summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2011-11-22 23:46:10 +0100
committerCarl-Anton Ingmarsson <ca.ingmarsson@gmail.com>2012-01-22 09:47:27 +0100
commita1af02aee5d076e042502569d59d350d03839baf (patch)
tree00471f8f5b65cc020f08d656fea13e1d37703a6c
parent35cf2feab74059065b23073b8bb3bcd8a3786bbf (diff)
downloadgvfs-a1af02aee5d076e042502569d59d350d03839baf.tar.gz
afp: Add support for making backups when server has support for FPExchangeFiles
Instead of deleting the temporary file after doing the FPExchangeFiles call we rename the temporary file to "~filename" since it holds the old contents of the file.
-rw-r--r--daemon/gvfsbackendafp.c83
1 files changed, 63 insertions, 20 deletions
diff --git a/daemon/gvfsbackendafp.c b/daemon/gvfsbackendafp.c
index 796863a9..d35ee7a6 100644
--- a/daemon/gvfsbackendafp.c
+++ b/daemon/gvfsbackendafp.c
@@ -194,9 +194,11 @@ typedef struct
/* Used if type == AFP_HANDLE_TYPE_REPLACE_FILE_DIRECT */
gint64 size;
-
+
+ /* Used if type == AFP_HANDLE_TYPE_REPLACE_FILE_TEMP */
char *filename;
char *tmp_filename;
+ gboolean make_backup;
} AfpHandle;
static AfpHandle *
@@ -2676,20 +2678,49 @@ close_replace_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res, g
g_object_unref (info);
}
-
+
static void
-close_replace_close_fork_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+close_replace_delete_backup_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
AfpHandle *afp_handle = (AfpHandle *)user_data;
- /* Delete temporary file */
- delete (afp_backend, afp_handle->tmp_filename, NULL, NULL, NULL);
+ char *backup_name;
+
+ /* We ignore all errors and just try to rename the temporary file anyway */
+ backup_name = g_strconcat (afp_handle->filename, "~", NULL);
+ move_and_rename (afp_backend, afp_handle->tmp_filename, backup_name, NULL,
+ NULL, NULL);
afp_handle_free (afp_handle);
}
static void
+close_replace_close_fork_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+ GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (source_object);
+ AfpHandle *afp_handle = (AfpHandle *)user_data;
+
+ if (afp_handle->make_backup)
+ {
+ char *backup_name = g_strconcat (afp_handle->filename, "~", NULL);
+
+ /* Delete old backup */
+ delete (afp_backend, backup_name, NULL, close_replace_delete_backup_cb,
+ afp_handle);
+ g_free (backup_name);
+ }
+
+ else
+ {
+ /* Delete temporary file */
+ delete (afp_backend, afp_handle->tmp_filename, NULL, NULL, NULL);
+
+ afp_handle_free (afp_handle);
+ }
+}
+
+static void
close_replace_exchange_files_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
GVfsAfpConnection *afp_conn = G_VFS_AFP_CONNECTION (source_object);
@@ -2710,7 +2741,7 @@ close_replace_exchange_files_cb (GObject *source_object, GAsyncResult *res, gpoi
return;
}
- /* Close fork and remove the temporary file even if the exchange failed */
+ /* Close fork and remove/rename the temporary file even if the exchange failed */
close_fork (afp_backend, afp_handle->fork_refnum, G_VFS_JOB (job)->cancellable,
close_replace_close_fork_cb, job->handle);
@@ -3029,6 +3060,7 @@ replace_open_fork_cb (GObject *source_object, GAsyncResult *res, gpointer user_d
afp_handle->type = AFP_HANDLE_TYPE_REPLACE_FILE_TEMP;
afp_handle->filename = g_strdup (job->filename);
afp_handle->tmp_filename = g_strdup (tmp_filename);
+ afp_handle->make_backup = job->make_backup;
}
else
afp_handle->type = AFP_HANDLE_TYPE_REPLACE_FILE_DIRECT;
@@ -3060,9 +3092,19 @@ replace_create_tmp_file_cb (GObject *source_object, GAsyncResult *res, gpointer
* so we try to write directly to the file */
else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
{
- g_object_set_data (G_OBJECT (job), "TempFilename", NULL);
- open_fork (afp_backend, job->filename, AFP_ACCESS_MODE_WRITE_BIT, 0,
- G_VFS_JOB (job)->cancellable, replace_open_fork_cb, job);
+ /* FIXME: We don't support making backups when we can't use FPExchangeFiles */
+ if (job->make_backup)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("backups not supported"));
+ }
+ else
+ {
+ g_object_set_data (G_OBJECT (job), "TempFilename", NULL);
+ open_fork (afp_backend, job->filename, AFP_ACCESS_MODE_WRITE_BIT, 0,
+ G_VFS_JOB (job)->cancellable, replace_open_fork_cb, job);
+ }
}
else
@@ -3145,8 +3187,18 @@ replace_get_filedir_parms_cb (GObject *source_object, GAsyncResult *res, gpointe
{
if (afp_backend->vol_attrs_bitmap & AFP_VOLUME_ATTRIBUTES_BITMAP_NO_EXCHANGE_FILES)
{
- open_fork (afp_backend, job->filename, AFP_ACCESS_MODE_WRITE_BIT, 0,
- G_VFS_JOB (job)->cancellable, replace_open_fork_cb, job);
+ /* FIXME: We don't support making backups when we can't use FPExchangeFiles */
+ if (job->make_backup)
+ {
+ g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ _("backups not supported"));
+ }
+ else
+ {
+ open_fork (afp_backend, job->filename, AFP_ACCESS_MODE_WRITE_BIT, 0,
+ G_VFS_JOB (job)->cancellable, replace_open_fork_cb, job);
+ }
}
else
replace_create_tmp_file (afp_backend, job);
@@ -3165,15 +3217,6 @@ try_replace (GVfsBackend *backend,
{
GVfsBackendAfp *afp_backend = G_VFS_BACKEND_AFP (backend);
- if (make_backup)
- {
- /* FIXME: implement! */
- g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR,
- G_IO_ERROR_CANT_CREATE_BACKUP,
- _("backups not supported yet"));
- return TRUE;
- }
-
get_filedir_parms (afp_backend, filename, AFP_FILE_BITMAP_MOD_DATE_BIT, 0,
G_VFS_JOB (job)->cancellable, replace_get_filedir_parms_cb,
job);