diff options
Diffstat (limited to 'gnome-2-24/daemon/gvfsbackendobexftp.c')
-rw-r--r-- | gnome-2-24/daemon/gvfsbackendobexftp.c | 1489 |
1 files changed, 0 insertions, 1489 deletions
diff --git a/gnome-2-24/daemon/gvfsbackendobexftp.c b/gnome-2-24/daemon/gvfsbackendobexftp.c deleted file mode 100644 index 23bea15f..00000000 --- a/gnome-2-24/daemon/gvfsbackendobexftp.c +++ /dev/null @@ -1,1489 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2006-2008 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Bastien Nocera <hadess@hadess.net> - */ - -#include <config.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> - -#include <glib/gstdio.h> -#include <glib/gi18n.h> -#include <gio/gio.h> -#include <dbus/dbus-glib.h> -#include <bluetooth/bluetooth.h> - -#include "gvfsbackendobexftp.h" -#include "gvfsbackendobexftp-fl-parser.h" -#include "gvfsbackendobexftp-cap-parser.h" -#include "obexftp-marshal.h" - -#include "gvfsjobopenforread.h" -#include "gvfsjobread.h" -#include "gvfsjobseekread.h" -#include "gvfsjobmount.h" -#include "gvfsjobopenforwrite.h" -#include "gvfsjobwrite.h" -#include "gvfsjobclosewrite.h" -#include "gvfsjobseekwrite.h" -#include "gvfsjobsetdisplayname.h" -#include "gvfsjobqueryinfo.h" -#include "gvfsjobqueryfsinfo.h" -#include "gvfsjobqueryattributes.h" -#include "gvfsjobenumerate.h" -#include "gvfsdaemonprotocol.h" - -#define BDADDR_LEN 17 - -#define ASYNC_SUCCESS 1 -#define ASYNC_PENDING 0 -#define ASYNC_ERROR -1 - -#define CACHE_LIFESPAN 3 - -struct _GVfsBackendObexftp -{ - GVfsBackend parent_instance; - - char *display_name; - char *bdaddr; - guint type; - - DBusGConnection *connection; - DBusGProxy *manager_proxy; - DBusGProxy *session_proxy; - - /* Use for the async notifications and errors */ - GCond *cond; - GMutex *mutex; - int status; - gboolean doing_io; - GError *error; - - /* Folders listing cache */ - char *files_listing; - char *directory; - time_t time_captured; -}; - -typedef struct { - char *source; - goffset size; - int fd; -} ObexFTPOpenHandle; - -G_DEFINE_TYPE (GVfsBackendObexftp, g_vfs_backend_obexftp, G_VFS_TYPE_BACKEND); - -/* This should all live in bluez-gnome, and we - * should depend on it */ -enum { - BLUETOOTH_TYPE_ANY = 1, - BLUETOOTH_TYPE_PHONE = 1 << 1, - BLUETOOTH_TYPE_MODEM = 1 << 2, - BLUETOOTH_TYPE_COMPUTER = 1 << 3, - BLUETOOTH_TYPE_NETWORK = 1 << 4, - BLUETOOTH_TYPE_HEADSET = 1 << 5, - BLUETOOTH_TYPE_KEYBOARD = 1 << 6, - BLUETOOTH_TYPE_MOUSE = 1 << 7, - BLUETOOTH_TYPE_CAMERA = 1 << 8, - BLUETOOTH_TYPE_PRINTER = 1 << 9 -}; - -static const char * -_get_icon_from_type (guint type) -{ - switch (type) - { - case BLUETOOTH_TYPE_PHONE: - return "phone"; - break; - case BLUETOOTH_TYPE_MODEM: - return "modem"; - break; - case BLUETOOTH_TYPE_COMPUTER: - return "network-server"; - break; - case BLUETOOTH_TYPE_NETWORK: - return "network-wireless"; - break; - case BLUETOOTH_TYPE_HEADSET: - return "stock_headphones"; - break; - case BLUETOOTH_TYPE_KEYBOARD: - return "input-keyboard"; - break; - case BLUETOOTH_TYPE_MOUSE: - return "input-mouse"; - break; - case BLUETOOTH_TYPE_CAMERA: - return "camera-photo"; - break; - case BLUETOOTH_TYPE_PRINTER: - return "printer"; - break; - default: - return "bluetooth"; - break; - } -} - -static int -_get_type_from_class (guint class) -{ - switch ((class & 0x1f00) >> 8) - { - case 0x01: - return BLUETOOTH_TYPE_COMPUTER; - case 0x02: - switch ((class & 0xfc) >> 2) - { - case 0x01: - case 0x02: - case 0x03: - case 0x05: - return BLUETOOTH_TYPE_PHONE; - case 0x04: - return BLUETOOTH_TYPE_MODEM; - } - break; - case 0x03: - return BLUETOOTH_TYPE_NETWORK; - case 0x04: - switch ((class & 0xfc) >> 2) - { - case 0x01: - return BLUETOOTH_TYPE_HEADSET; - } - break; - case 0x05: - switch ((class & 0xc0) >> 6) - { - case 0x01: - return BLUETOOTH_TYPE_KEYBOARD; - case 0x02: - return BLUETOOTH_TYPE_MOUSE; - } - break; - case 0x06: - if (class & 0x80) - return BLUETOOTH_TYPE_PRINTER; - if (class & 0x20) - return BLUETOOTH_TYPE_CAMERA; - break; - } - - return BLUETOOTH_TYPE_ANY; -} - -/* Used to detect broken listings from - * old Nokia 3650s */ -static gboolean -_is_nokia_3650 (const char *bdaddr) -{ - /* Don't ask, Nokia seem to use a Bluetooth - * HCI from Murata */ - return g_str_has_prefix(bdaddr, "00:60:57"); -} - -static gchar * -_get_device_properties (const char *bdaddr, guint32 *type) -{ - DBusGConnection *connection; - DBusGProxy *manager; - gchar *name, **adapters; - guint i; - - name = NULL; - - connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); - if (connection == NULL) - return NULL; - - manager = dbus_g_proxy_new_for_name (connection, "org.bluez", - "/org/bluez", "org.bluez.Manager"); - if (manager == NULL) - { - dbus_g_connection_unref (connection); - return NULL; - } - - if (dbus_g_proxy_call (manager, "ListAdapters", NULL, G_TYPE_INVALID, G_TYPE_STRV, &adapters, G_TYPE_INVALID) == FALSE) - { - g_object_unref (manager); - dbus_g_connection_unref (connection); - return NULL; - } - - for (i = 0; adapters[i] != NULL; i++) - { - DBusGProxy *adapter; - - adapter = dbus_g_proxy_new_for_name (connection, "org.bluez", - adapters[i], "org.bluez.Adapter"); - if (dbus_g_proxy_call (adapter, "GetRemoteName", NULL, - G_TYPE_STRING, bdaddr, G_TYPE_INVALID, - G_TYPE_STRING, &name, G_TYPE_INVALID) != FALSE) - { - if (name != NULL && name[0] != '\0') - { - guint32 class; - - if (dbus_g_proxy_call(adapter, "GetRemoteClass", NULL, - G_TYPE_STRING, bdaddr, G_TYPE_INVALID, - G_TYPE_UINT, &class, G_TYPE_INVALID) != FALSE) - { - *type = _get_type_from_class (class); - } - else - { - *type = BLUETOOTH_TYPE_ANY; - } - g_object_unref (adapter); - break; - } - } - g_object_unref (adapter); - } - - g_object_unref (manager); - dbus_g_connection_unref (connection); - - return name; -} - -static void -g_vfs_backend_obexftp_finalize (GObject *object) -{ - GVfsBackendObexftp *backend; - - backend = G_VFS_BACKEND_OBEXFTP (object); - - g_free (backend->display_name); - g_free (backend->bdaddr); - g_free (backend->files_listing); - g_free (backend->directory); - - if (backend->session_proxy != NULL) - g_object_unref (backend->session_proxy); - g_mutex_free (backend->mutex); - g_cond_free (backend->cond); - - if (G_OBJECT_CLASS (g_vfs_backend_obexftp_parent_class)->finalize) - (*G_OBJECT_CLASS (g_vfs_backend_obexftp_parent_class)->finalize) (object); -} - -static void -g_vfs_backend_obexftp_init (GVfsBackendObexftp *backend) -{ - GError *err = NULL; - - backend->connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err); - if (backend->connection == NULL) { - g_printerr ("Connecting to session bus failed: %s\n", err->message); - g_error_free (err); - return; - } - - backend->mutex = g_mutex_new (); - backend->cond = g_cond_new (); - backend->manager_proxy = dbus_g_proxy_new_for_name (backend->connection, - "org.openobex", - "/org/openobex", - "org.openobex.Manager"); -} - -static gboolean -_change_directory (GVfsBackendObexftp *op_backend, - const char *filename, - GError **error) -{ - char *current_path, **req_components; - guint i; - - if (dbus_g_proxy_call (op_backend->session_proxy, "GetCurrentPath", error, - G_TYPE_INVALID, - G_TYPE_STRING, ¤t_path, G_TYPE_INVALID) == FALSE) - { - g_message ("GetCurrentPath failed"); - return FALSE; - } - - if (strcmp (filename, current_path) == 0) - { - g_free (current_path); - return TRUE; - } - - /* Are we already at the root? */ - if (strcmp (current_path, "/") != 0) - { - if (dbus_g_proxy_call (op_backend->session_proxy, "ChangeCurrentFolderToRoot", error, - G_TYPE_INVALID, - G_TYPE_INVALID) == FALSE) - { - g_message ("ChangeCurrentFolderToRoot failed"); - //FIXME change the retval from org.openobex.Error.NotAuthorized to - //no such file or directory - return FALSE; - } - } - g_free (current_path); - - /* If we asked for the root, we're done */ - if (strcmp (filename, "/") == 0) - return TRUE; - - req_components = g_strsplit (filename, "/", -1); - for (i = 0; req_components[i] != NULL; i++) - { - if (*req_components[i] == '\0') - continue; - if (dbus_g_proxy_call (op_backend->session_proxy, "ChangeCurrentFolder", error, - G_TYPE_STRING, req_components[i], G_TYPE_INVALID, - G_TYPE_INVALID) == FALSE) - { - g_message ("ChangeCurrentFolder failed"); - g_strfreev (req_components); - return FALSE; - } - } - - g_strfreev (req_components); - - return TRUE; -} - -static gboolean -_retrieve_folder_listing (GVfsBackend *backend, - const char *filename, - char **files, - GError **error) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - time_t current; - - current = time (NULL); - - if (op_backend->directory != NULL && - strcmp (op_backend->directory, filename) == 0 && - op_backend->time_captured > current - CACHE_LIFESPAN) - { - *files = g_strdup (op_backend->files_listing); - return TRUE; - } - else - { - g_free (op_backend->directory); - op_backend->directory = NULL; - g_free (op_backend->files_listing); - op_backend->files_listing = NULL; - } - - if (dbus_g_proxy_call (op_backend->session_proxy, "RetrieveFolderListing", error, - G_TYPE_INVALID, - G_TYPE_STRING, files, G_TYPE_INVALID) == FALSE) - { - return FALSE; - } - - op_backend->directory = g_strdup (filename); - op_backend->files_listing = g_strdup (*files); - op_backend->time_captured = time (NULL); - - return TRUE; -} - -static gboolean -_query_file_info_helper (GVfsBackend *backend, - const char *filename, - GFileInfo *info, - GError **error) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - char *parent, *basename, *files; - GList *elements, *l; - gboolean found; - - g_print ("+ _query_file_info_helper, filename: %s\n", filename); - - if (strcmp (filename, "/") == 0) - { - char *display; - - /* That happens when you want '/' - * and we don't have any info about it :( */ - g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); - g_file_info_set_content_type (info, "inode/directory"); - g_file_info_set_name (info, "/"); - g_vfs_backend_set_icon_name (backend, - _get_icon_from_type (op_backend->type)); - display = g_strdup_printf (_("%s on %s"), "/", op_backend->display_name); - g_file_info_set_display_name (info, display); - g_free (display); - return TRUE; - } - - parent = g_path_get_dirname (filename); - if (_change_directory (op_backend, parent, error) == FALSE) - { - g_free (parent); - return FALSE; - } - - files = NULL; - if (_retrieve_folder_listing (backend, parent, &files, error) == FALSE) - { - g_free (parent); - return FALSE; - } - - g_free (parent); - - if (gvfsbackendobexftp_fl_parser_parse (files, strlen (files), &elements, error) == FALSE) - { - g_free (files); - return FALSE; - } - g_free (files); - - basename = g_path_get_basename (filename); - found = FALSE; - - for (l = elements; l != NULL; l = l->next) - { - if (strcmp (basename, g_file_info_get_name (l->data)) == 0) - { - g_file_info_copy_into (l->data, info); - found = TRUE; - break; - } - } - - if (found == FALSE) - { - g_set_error_literal (error, G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - g_strerror (ENOENT)); - } - - g_free (basename); - g_list_foreach (elements, (GFunc)g_object_unref, NULL); - g_list_free (elements); - - g_print ("- _query_file_info_helper\n"); - - return found; -} - -static void -error_occurred_cb (DBusGProxy *proxy, const gchar *error_name, const gchar *error_message, gpointer user_data) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data); - - g_message("ErrorOccurred"); - g_message("Error name: %s", error_name); - g_message("Error message: %s", error_message); - - if (strcmp (error_name, "org.openobex.Error.LinkError") == 0) - { - g_message ("link lost to remote device"); - _exit (1); - } - - /* Something is waiting on us */ - g_mutex_lock (op_backend->mutex); - if (op_backend->doing_io) - { - op_backend->status = ASYNC_ERROR; - op_backend->error = g_error_new_literal (DBUS_GERROR, - DBUS_GERROR_REMOTE_EXCEPTION, - error_message); - g_cond_signal (op_backend->cond); - g_mutex_unlock (op_backend->mutex); - return; - } - g_mutex_unlock (op_backend->mutex); - - g_message ("Unhandled error, file a bug"); - _exit (1); -} - -static void -cancelled_cb (DBusGProxy *proxy, gpointer user_data) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data); - - g_message ("transfer got cancelled"); - - g_mutex_lock (op_backend->mutex); - op_backend->status = ASYNC_ERROR; - g_cond_signal (op_backend->cond); - g_mutex_unlock (op_backend->mutex); -} - -static void -disconnected_cb (DBusGProxy *proxy, gpointer user_data) -{ - g_message ("disconnected_cb"); - - _exit (1); -} - -static void -closed_cb (DBusGProxy *proxy, gpointer user_data) -{ - g_message ("closed_cb"); - - _exit (1); -} - -static int -is_connected (DBusGProxy *session_proxy, GVfsJob *job) -{ - GError *error = NULL; - gboolean connected; - - if (dbus_g_proxy_call (session_proxy, "IsConnected", &error, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &connected, G_TYPE_INVALID) == FALSE) - { - g_vfs_job_failed_from_error (job, error); - g_error_free (error); - return -1; - } - - return connected; -} - -static void -do_mount (GVfsBackend *backend, - GVfsJobMount *job, - GMountSpec *mount_spec, - GMountSource *mount_source, - gboolean is_automount) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - const char *device; - GError *error = NULL; - const gchar *path = NULL; - char *server; - GMountSpec *obexftp_mount_spec; - gboolean connected; - - g_print ("+ do_mount\n"); - - device = g_mount_spec_get (mount_spec, "host"); - - if (device == NULL || strlen (device) != BDADDR_LEN + 2) - { - g_vfs_job_failed (G_VFS_JOB (job), - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Invalid mount spec")); - return; - } - - /* Strip the brackets */ - op_backend->bdaddr = g_strndup (device + 1, 17); - if (bachk (op_backend->bdaddr) < 0) - { - g_free (op_backend->bdaddr); - g_vfs_job_failed (G_VFS_JOB (job), - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Invalid mount spec")); - return; - } - - /* FIXME, Have a way for the mount to be cancelled, see: - * http://bugs.muiline.com/view.php?id=51 */ - - if (dbus_g_proxy_call (op_backend->manager_proxy, "CreateBluetoothSession", &error, - G_TYPE_STRING, op_backend->bdaddr, G_TYPE_STRING, "ftp", G_TYPE_INVALID, - DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID) == FALSE) - { - g_free (op_backend->bdaddr); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - g_vfs_job_set_backend_data (G_VFS_JOB (job), backend, NULL); - g_print (" do_mount: %s mounted\n", op_backend->bdaddr); - - op_backend->session_proxy = dbus_g_proxy_new_for_name (op_backend->connection, - "org.openobex", - path, - "org.openobex.Session"); - - op_backend->display_name = _get_device_properties (op_backend->bdaddr, &op_backend->type); - if (!op_backend->display_name) - op_backend->display_name = g_strdup (op_backend->bdaddr); - - g_vfs_backend_set_display_name (G_VFS_BACKEND (op_backend), - op_backend->display_name); - g_vfs_backend_set_icon_name (G_VFS_BACKEND (op_backend), - _get_icon_from_type (op_backend->type)); - - obexftp_mount_spec = g_mount_spec_new ("obex"); - server = g_strdup_printf ("[%s]", op_backend->bdaddr); - g_mount_spec_set (obexftp_mount_spec, "host", server); - g_free (server); - g_vfs_backend_set_mount_spec (G_VFS_BACKEND (op_backend), obexftp_mount_spec); - g_mount_spec_unref (obexftp_mount_spec); - - dbus_g_proxy_add_signal(op_backend->session_proxy, "ErrorOccurred", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(op_backend->session_proxy, "ErrorOccurred", - G_CALLBACK(error_occurred_cb), op_backend, NULL); - - dbus_g_proxy_add_signal(op_backend->session_proxy, "Cancelled", - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(op_backend->session_proxy, "Cancelled", - G_CALLBACK(cancelled_cb), op_backend, NULL); - - dbus_g_proxy_add_signal(op_backend->session_proxy, "Disconnected", - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(op_backend->session_proxy, "Disconnected", - G_CALLBACK(disconnected_cb), op_backend, NULL); - - dbus_g_proxy_add_signal(op_backend->session_proxy, "Closed", - G_TYPE_INVALID); - dbus_g_proxy_connect_signal(op_backend->session_proxy, "Closed", - G_CALLBACK(closed_cb), op_backend, NULL); - - dbus_g_proxy_add_signal(op_backend->session_proxy, "TransferStarted", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID); - - /* Now wait until the device is connected */ - connected = is_connected (op_backend->session_proxy, G_VFS_JOB (job)); - while (connected == FALSE) - { - g_usleep (G_USEC_PER_SEC / 100); - connected = is_connected (op_backend->session_proxy, G_VFS_JOB (job)); - } - - if (connected < 0) - { - g_message ("mount failed, didn't connect"); - - g_free (op_backend->display_name); - op_backend->display_name = NULL; - g_free (op_backend->bdaddr); - op_backend->bdaddr = NULL; - g_object_unref (op_backend->session_proxy); - op_backend->session_proxy = NULL; - - g_vfs_job_failed (G_VFS_JOB (job), - G_IO_ERROR, G_IO_ERROR_BUSY, - _("Connection to the device lost")); - return; - } - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_print ("- do_mount\n"); -} - -static void -transfer_started_cb (DBusGProxy *proxy, const gchar *filename, - const gchar *local_path, guint64 byte_count, gpointer user_data) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (user_data); - - g_message ("transfer of %s to %s started", filename, local_path); - - g_mutex_lock (op_backend->mutex); - op_backend->status = ASYNC_SUCCESS; - g_cond_signal (op_backend->cond); - g_mutex_unlock (op_backend->mutex); -} - -static void -do_open_for_read (GVfsBackend *backend, - GVfsJobOpenForRead *job, - const char *filename) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - GError *error = NULL; - ObexFTPOpenHandle *handle; - char *target, *basename; - GFileInfo *info; - goffset size; - int fd, success; - - g_print ("+ do_open_for_read, filename: %s\n", filename); - - g_mutex_lock (op_backend->mutex); - op_backend->doing_io = TRUE; - - /* Change into the directory and cache the file size */ - info = g_file_info_new (); - if (_query_file_info_helper (backend, filename, info, &error) == FALSE) - { - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - g_object_unref (info); - return; - } - /* If we're trying to open a directory for reading, exit out */ - if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) - { - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_IS_DIRECTORY, - _("Can't open directory")); - g_object_unref (info); - return; - } - - size = g_file_info_get_size (info); - g_object_unref (info); - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return; - } - - fd = g_file_open_tmp ("gvfsobexftp-tmp-XXXXXX", - &target, &error); - if (fd < 0) - { - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return; - } - - op_backend->status = ASYNC_PENDING; - - dbus_g_proxy_connect_signal(op_backend->session_proxy, "TransferStarted", - G_CALLBACK(transfer_started_cb), op_backend, NULL); - - basename = g_path_get_basename (filename); - if (dbus_g_proxy_call (op_backend->session_proxy, "CopyRemoteFile", &error, - G_TYPE_STRING, basename, - G_TYPE_STRING, target, - G_TYPE_INVALID, - G_TYPE_INVALID) == FALSE) - { - g_message ("CopyRemoteFile failed"); - - g_free (basename); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - - dbus_g_proxy_disconnect_signal(op_backend->session_proxy, "TransferStarted", - G_CALLBACK(transfer_started_cb), op_backend); - - /* Close the target */ - g_unlink (target); - g_free (target); - close (fd); - - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - return; - } - - /* Wait for TransferStarted or ErrorOccurred to have happened */ - while (op_backend->status == ASYNC_PENDING) - g_cond_wait (op_backend->cond, op_backend->mutex); - success = op_backend->status; - dbus_g_proxy_disconnect_signal(op_backend->session_proxy, "TransferStarted", - G_CALLBACK(transfer_started_cb), op_backend); - - /* We either got success or an async error */ - g_assert (success != ASYNC_PENDING); - - g_message ("filename: %s (%s) copying to %s (retval %d)", filename, basename, target, success); - g_free (basename); - - g_unlink (target); - g_free (target); - op_backend->status = ASYNC_PENDING; - - if (success == ASYNC_ERROR) - { - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); - close (fd); - g_vfs_job_failed_from_error (G_VFS_JOB (job), - op_backend->error); - g_error_free (op_backend->error); - op_backend->error = NULL; - return; - } - - handle = g_new0 (ObexFTPOpenHandle, 1); - handle->source = g_strdup (filename); - handle->fd = fd; - handle->size = size; - g_vfs_job_open_for_read_set_handle (job, handle); - - g_print ("- do_open_for_read, filename: %s\n", filename); - - g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), FALSE); - g_vfs_job_succeeded (G_VFS_JOB (job)); - - op_backend->doing_io = FALSE; - g_mutex_unlock (op_backend->mutex); -} - -static int -is_busy (DBusGProxy *session_proxy, GVfsJob *job) -{ - GError *error = NULL; - gboolean busy; - - if (dbus_g_proxy_call (session_proxy, "IsBusy", &error, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &busy, G_TYPE_INVALID) == FALSE) - { - g_vfs_job_failed_from_error (job, error); - g_error_free (error); - return -1; - } - - return busy; -} - -static void -do_read (GVfsBackend *backend, - GVfsJobRead *job, - GVfsBackendHandle handle, - char *buffer, - gsize bytes_requested) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - ObexFTPOpenHandle *backend_handle = (ObexFTPOpenHandle *) handle; - ssize_t bytes_read = 0; - gboolean busy = TRUE; - - while (bytes_read == 0 && busy != FALSE) - { - bytes_read = read (backend_handle->fd, buffer, bytes_requested); - if (bytes_read != 0) - break; - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return; - } - - busy = is_busy (op_backend->session_proxy, G_VFS_JOB (job)); - if (busy < 0) - return; - - g_usleep (G_USEC_PER_SEC / 100); - } - - if (bytes_read < 0) - { - g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno); - } - else if (bytes_read == 0) - { - g_vfs_job_read_set_size (job, 0); - g_vfs_job_succeeded (G_VFS_JOB (job)); - } - else - { - g_vfs_job_read_set_size (job, bytes_read); - g_vfs_job_succeeded (G_VFS_JOB (job)); - } -} - -static void -do_close_read (GVfsBackend *backend, - GVfsJobCloseRead *job, - GVfsBackendHandle handle) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - ObexFTPOpenHandle *backend_handle = (ObexFTPOpenHandle *) handle; - int busy; - - g_print ("+ do_close_read\n"); - - busy = is_busy (op_backend->session_proxy, G_VFS_JOB (job)); - if (busy < 0) { - g_message ("busy error"); - return; - } - - g_mutex_lock (op_backend->mutex); - - if (busy > 0) - { - op_backend->status = ASYNC_PENDING; - - if (dbus_g_proxy_call (op_backend->session_proxy, "Cancel", NULL, - G_TYPE_INVALID, G_TYPE_INVALID) != FALSE) - { - while (op_backend->status == ASYNC_PENDING) - g_cond_wait (op_backend->cond, op_backend->mutex); - } - } - - g_mutex_unlock (op_backend->mutex); - - close (backend_handle->fd); - g_free (backend_handle->source); - g_free (backend_handle); - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_print ("- do_close_read\n"); -} - -static void -do_query_info (GVfsBackend *backend, - GVfsJobQueryInfo *job, - const char *filename, - GFileQueryInfoFlags flags, - GFileInfo *info, - GFileAttributeMatcher *matcher) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - GError *error = NULL; - - g_print ("+ do_query_info, filename: %s\n", filename); - - g_mutex_lock (op_backend->mutex); - - if (_query_file_info_helper (backend, filename, info, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - g_mutex_unlock (op_backend->mutex); - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_print ("- do_query_info\n"); - - return; -} - -static void -do_query_fs_info (GVfsBackend *backend, - GVfsJobQueryFsInfo *job, - const char *filename, - GFileInfo *info, - GFileAttributeMatcher *attribute_matcher) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - OvuCaps *caps; - OvuCapsMemory *memory; - GError *error = NULL; - char *caps_str; - const char *mem_type; - GList *l; - gboolean has_free_memory; - - g_print ("+ do_query_fs_info, filename: %s\n", filename); - - g_mutex_lock (op_backend->mutex); - - /* Get the capabilities */ - if (dbus_g_proxy_call (op_backend->session_proxy, "GetCapability", &error, - G_TYPE_INVALID, - G_TYPE_STRING, &caps_str, G_TYPE_INVALID) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - g_free (caps_str); - return; - } - - /* No caps from the server? */ - if (caps_str == NULL) - { - /* Best effort, don't error out */ - g_mutex_unlock (op_backend->mutex); - g_vfs_job_succeeded (G_VFS_JOB (job)); - return; - } - - caps = ovu_caps_parser_parse (caps_str, strlen (caps_str), &error); - g_free (caps_str); - if (caps == NULL) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - /* Check whether we have no free space available */ - has_free_memory = FALSE; - for (l = ovu_caps_get_memory_entries (caps); l != NULL; l = l->next) - { - if (ovu_caps_memory_has_free (l->data) != FALSE) - { - has_free_memory = TRUE; - break; - } - } - if (has_free_memory == FALSE) - { - g_mutex_unlock (op_backend->mutex); - /* Best effort, don't error out */ - g_vfs_job_succeeded (G_VFS_JOB (job)); - return; - } - - /* Check whether we have only one memory type */ - l = ovu_caps_get_memory_entries (caps); - if (g_list_length (l) == 1) - { - memory = l->data; - goto set_info_from_memory; - } - - if (_query_file_info_helper (backend, filename, info, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - ovu_caps_free (caps); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - ovu_caps_free (caps); - return; - } - - mem_type = NULL; - if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_UNIX_RDEV) != FALSE) - { - guint rdev; - rdev = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV); - mem_type = om_mem_type_id_to_string (rdev); - } - memory = ovu_caps_get_memory_type (caps, mem_type); - -set_info_from_memory: - if (memory != NULL && ovu_caps_memory_has_free (memory) != FALSE) - { - g_file_info_set_attribute_uint64 (info, - G_FILE_ATTRIBUTE_FILESYSTEM_FREE, - ovu_caps_memory_get_free (memory)); - if (ovu_caps_memory_has_used (memory) != FALSE) - { - g_file_info_set_attribute_uint64 (info, - G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, - ovu_caps_memory_get_free (memory) - + ovu_caps_memory_get_used (memory)); - } - } - ovu_caps_free (caps); - - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "obexftp"); - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_mutex_unlock (op_backend->mutex); - - g_print ("- do_query_fs_info\n"); -} - -static void -do_enumerate (GVfsBackend *backend, - GVfsJobEnumerate *job, - const char *filename, - GFileAttributeMatcher *matcher, - GFileQueryInfoFlags flags) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - GError *error = NULL; - char *files; - GList *elements = NULL; - - g_print ("+ do_enumerate, filename: %s\n", filename); - - g_mutex_lock (op_backend->mutex); - - if (_change_directory (op_backend, filename, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - files = NULL; - if (_retrieve_folder_listing (backend, filename, &files, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - if (gvfsbackendobexftp_fl_parser_parse (files, strlen (files), &elements, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - /* See http://web.archive.org/web/20070826221251/http://docs.kde.org/development/en/extragear-pim/kdebluetooth/components.kio_obex.html#devices - * for the reasoning */ - if (strstr (files, "SYSTEM\"obex-folder-listing.dtd") != NULL && _is_nokia_3650 (op_backend->bdaddr)) - { - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - _("Device requires a software update")); - } - else - { - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - } - g_message ("gvfsbackendobexftp_fl_parser_parse failed"); - g_free (files); - g_error_free (error); - return; - } - g_free (files); - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_vfs_job_enumerate_add_infos (job, elements); - - g_list_foreach (elements, (GFunc)g_object_unref, NULL); - g_list_free (elements); - g_vfs_job_enumerate_done (job); - - g_mutex_unlock (op_backend->mutex); - - g_print ("- do_enumerate\n"); -} - -static void -do_delete (GVfsBackend *backend, - GVfsJobDelete *job, - const char *filename) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - char *basename, *parent; - GError *error = NULL; - GFileInfo *info; - - g_print ("+ do_delete, filename: %s\n", filename); - - g_mutex_lock (op_backend->mutex); - - /* Check whether we have a directory */ - info = g_file_info_new (); - if (_query_file_info_helper (backend, filename, info, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - g_object_unref (info); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - g_object_unref (info); - return; - } - - /* Get the listing of the directory, and abort if it's not empty */ - if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) - { - GList *elements; - char *files; - guint len; - - g_object_unref (info); - - if (_change_directory (op_backend, filename, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return; - } - - files = NULL; - if (_retrieve_folder_listing (backend, filename, &files, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - if (gvfsbackendobexftp_fl_parser_parse (files, strlen (files), &elements, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_message ("gvfsbackendobexftp_fl_parser_parse failed"); - g_free (files); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - g_free (files); - - len = g_list_length (elements); - g_list_foreach (elements, (GFunc)g_object_unref, NULL); - g_list_free (elements); - - if (len != 0) - { - g_mutex_unlock (op_backend->mutex); - g_set_error_literal (&error, G_IO_ERROR, - G_IO_ERROR_NOT_EMPTY, - g_strerror (ENOTEMPTY)); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - } - else - { - g_object_unref (info); - } - - basename = g_path_get_basename (filename); - if (strcmp (basename, G_DIR_SEPARATOR_S) == 0 - || strcmp (basename, ".") == 0) - { - g_mutex_unlock (op_backend->mutex); - g_free (basename); - g_vfs_job_failed_from_errno (G_VFS_JOB (job), EPERM); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - g_free (basename); - return; - } - - parent = g_path_get_dirname (filename); - if (_change_directory (op_backend, parent, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_free (basename); - g_free (parent); - g_error_free (error); - return; - } - g_free (parent); - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - g_free (basename); - return; - } - - if (dbus_g_proxy_call (op_backend->session_proxy, "DeleteRemoteFile", &error, - G_TYPE_STRING, basename, G_TYPE_INVALID, - G_TYPE_INVALID) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - g_free (basename); - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_mutex_unlock (op_backend->mutex); - - g_print ("- do_delete\n"); -} - -static void -do_make_directory (GVfsBackend *backend, - GVfsJobMakeDirectory *job, - const char *filename) -{ - GVfsBackendObexftp *op_backend = G_VFS_BACKEND_OBEXFTP (backend); - char *basename, *parent; - GError *error = NULL; - GFileInfo *info; - - g_print ("+ do_make_directory, filename: %s\n", filename); - - g_mutex_lock (op_backend->mutex); - - /* Check if the folder already exists */ - info = g_file_info_new (); - if (_query_file_info_helper (backend, filename, info, &error) != FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_object_unref (info); - g_vfs_job_failed_from_errno (G_VFS_JOB (job), EEXIST); - return; - } - g_object_unref (info); - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return; - } - - parent = g_path_get_dirname (filename); - if (_change_directory (op_backend, parent, &error) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - g_free (parent); - - if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, - G_IO_ERROR_CANCELLED, - _("Operation was cancelled")); - return; - } - - basename = g_path_get_basename (filename); - if (dbus_g_proxy_call (op_backend->session_proxy, "CreateFolder", &error, - G_TYPE_STRING, basename, G_TYPE_INVALID, - G_TYPE_INVALID) == FALSE) - { - g_mutex_unlock (op_backend->mutex); - g_vfs_job_failed_from_error (G_VFS_JOB (job), error); - g_error_free (error); - return; - } - g_free (basename); - - g_vfs_job_succeeded (G_VFS_JOB (job)); - - g_mutex_unlock (op_backend->mutex); - - g_print ("+ do_make_directory\n"); -} - -static void -g_vfs_backend_obexftp_class_init (GVfsBackendObexftpClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass); - - gobject_class->finalize = g_vfs_backend_obexftp_finalize; - - backend_class->mount = do_mount; - backend_class->open_for_read = do_open_for_read; - backend_class->read = do_read; - backend_class->close_read = do_close_read; - backend_class->query_info = do_query_info; - backend_class->query_fs_info = do_query_fs_info; - backend_class->enumerate = do_enumerate; - backend_class->delete = do_delete; - backend_class->make_directory = do_make_directory; - - /* ErrorOccurred */ - dbus_g_object_register_marshaller (obexftp_marshal_VOID__STRING_STRING, - G_TYPE_NONE, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_INVALID); - /* TransferStarted */ - dbus_g_object_register_marshaller(obexftp_marshal_VOID__STRING_STRING_UINT64, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID); -} - -/* - * vim: sw=2 ts=8 cindent expandtab cinoptions=f0,>4,n2,{2,(0,^-2,t0 ai - */ |