diff options
author | Carl-Anton Ingmarsson <ca.ingmarsson@gmail.com> | 2011-08-22 00:30:08 +0200 |
---|---|---|
committer | Christian Kellner <gicmo@gnome.org> | 2011-08-25 21:19:56 +0200 |
commit | e70e80d574505dbfeb89e31269cc00d8866bf122 (patch) | |
tree | 730bc6a84007b8406179fa9065e8fcf68b47395d | |
parent | 2411f18823d4c88a00c47ae549c4719ae27b84c9 (diff) | |
download | gvfs-e70e80d574505dbfeb89e31269cc00d8866bf122.tar.gz |
afp: add copy_file function wrapping FPCopyFile
-rw-r--r-- | daemon/gvfsafpconnection.h | 2 | ||||
-rw-r--r-- | daemon/gvfsbackendafp.c | 128 |
2 files changed, 129 insertions, 1 deletions
diff --git a/daemon/gvfsafpconnection.h b/daemon/gvfsafpconnection.h index 44cfb095..f5cde133 100644 --- a/daemon/gvfsafpconnection.h +++ b/daemon/gvfsafpconnection.h @@ -191,6 +191,7 @@ enum typedef enum { AFP_COMMAND_CLOSE_FORK = 4, + AFP_COMMAND_COPY_FILE = 5, AFP_COMMAND_CREATE_DIR = 6, AFP_COMMAND_CREATE_FILE = 7, AFP_COMMAND_DELETE = 8, @@ -227,6 +228,7 @@ typedef enum AFP_RESULT_AUTH_CONTINUE = -5001, AFP_RESULT_BAD_UAM = -5002, AFP_RESULT_CANT_MOVE = -5005, + AFP_RESULT_DENY_CONFLICT = -5006, AFP_RESULT_DIR_NOT_EMPTY = -5007, AFP_RESULT_DISK_FULL = -5008, AFP_RESULT_EOF_ERR = -5009, diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c index 8f0afc0f..f4a80c38 100644 --- a/daemon/gvfsbackendafp.c +++ b/daemon/gvfsbackendafp.c @@ -1517,10 +1517,136 @@ move_and_rename_finish (GVfsBackendAfp *afp_backend, return TRUE; } +static void +copy_file_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) +{ + GVfsAfpConnection *afp_conn = G_VFS_AFP_CONNECTION (source_object); + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + + GVfsAfpReply *reply; + GError *err = NULL; + + AfpResultCode res_code; + + reply = g_vfs_afp_connection_send_command_finish (afp_conn, res, &err); + if (!reply) + { + g_simple_async_result_take_error (simple, err); + goto done; + } + + res_code = g_vfs_afp_reply_get_result_code (reply); + g_object_unref (reply); + + if (res_code != AFP_RESULT_NO_ERROR) + { + switch (res_code) + { + case AFP_RESULT_ACCESS_DENIED: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, + _("Permission denied")); + break; + case AFP_RESULT_CALL_NOT_SUPPORTED: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Server doesn't support the FPCopyFile operation")); + break; + case AFP_RESULT_DENY_CONFLICT: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn't open source file as Read/DenyWrite")); + break; + case AFP_RESULT_DISK_FULL: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_NO_SPACE, + _("Not enough space on volume")); + break; + case AFP_RESULT_OBJECT_EXISTS: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_EXISTS, + _("Target file already exists")); + break; + case AFP_RESULT_OBJECT_NOT_FOUND: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + _("Source file and/or destination directory doesn't exist")); + break; + case AFP_RESULT_OBJECT_TYPE_ERR: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + _("Source file is a directory")); + break; + default: + g_simple_async_result_set_error (simple, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Got error code: %d from server"), res_code); + break; + } + } + +done: + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +copy_file (GVfsBackendAfp *afp_backend, + const char *source, + const char *destination, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GVfsAfpCommand *comm; + char *dirname, *basename; + GSimpleAsyncResult *simple; + + comm = g_vfs_afp_command_new (AFP_COMMAND_COPY_FILE); + /* pad byte */ + g_vfs_afp_command_put_byte (comm, 0); + + /* VolumeID */ + g_vfs_afp_command_put_uint16 (comm, afp_backend->volume_id); + + /* SourceDirectoryID 2 == / */ + g_vfs_afp_command_put_uint32 (comm, 2); + /* DestDirectoryID 2 == / */ + g_vfs_afp_command_put_uint32 (comm, 2); + + /* SourcePathname */ + put_pathname (comm, source); + + /* DestPathname */ + dirname = g_path_get_dirname (destination); + put_pathname (comm, dirname); + g_free (dirname); + + /* NewName */ + basename = g_path_get_basename (destination); + put_pathname (comm, basename); + g_free (basename); + + simple = g_simple_async_result_new (G_OBJECT (afp_backend), callback, + user_data, copy_file); + + g_vfs_afp_connection_send_command (afp_backend->server->conn, comm, NULL, + copy_file_cb, cancellable, simple); + g_object_unref (comm); +} + +static gboolean +copy_file_finish (GVfsBackendAfp *afp_backend, GAsyncResult *res, GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (afp_backend), + copy_file), + FALSE); + + simple = (GSimpleAsyncResult *)res; + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return TRUE; +} + /* * Backend code */ - static void move_move_and_rename_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { |