gvfs r1685 - in trunk: . daemon
- From: alexl svn gnome org
- To: svn-commits-list gnome org
- Subject: gvfs r1685 - in trunk: . daemon
- Date: Thu, 27 Mar 2008 19:57:39 +0000 (GMT)
Author: alexl
Date: Thu Mar 27 19:57:39 2008
New Revision: 1685
URL: http://svn.gnome.org/viewvc/gvfs?rev=1685&view=rev
Log:
2008-03-27 Alexander Larsson <alexl redhat com>
* daemon/gvfsbackendsftp.c:
Handle all target exists errors correctly
in move. This should make us not silently
overwrite files.
* daemon/gvfsjobmove.[ch]:
Add g_vfs_job_move_progress_callback
Modified:
trunk/ChangeLog
trunk/daemon/gvfsbackendsftp.c
trunk/daemon/gvfsjobmove.c
trunk/daemon/gvfsjobmove.h
Modified: trunk/daemon/gvfsbackendsftp.c
==============================================================================
--- trunk/daemon/gvfsbackendsftp.c (original)
+++ trunk/daemon/gvfsbackendsftp.c Thu Mar 27 19:57:39 2008
@@ -48,6 +48,7 @@
#include "gvfsjobseekwrite.h"
#include "gvfsjobsetdisplayname.h"
#include "gvfsjobqueryinfo.h"
+#include "gvfsjobmove.h"
#include "gvfsjobdelete.h"
#include "gvfsjobqueryfsinfo.h"
#include "gvfsjobqueryattributes.h"
@@ -100,7 +101,7 @@
} MultiRequest;
struct _MultiReply {
- int reply_type;
+ int type;
GDataInputStream *data;
guint32 data_len;
@@ -1248,7 +1249,7 @@
reply = user_data;
request = reply->request;
- reply->reply_type = reply_type;
+ reply->type = reply_type;
reply->data = g_object_ref (reply_stream);
reply->data_len = len;
@@ -1613,19 +1614,16 @@
}
static gboolean
-result_from_status (GVfsJob *job,
- GDataInputStream *reply,
- int failure_error,
- int allowed_sftp_error)
+failure_from_status (GVfsJob *job,
+ GDataInputStream *reply,
+ int failure_error,
+ int allowed_sftp_error)
{
GError *error;
error = NULL;
if (error_from_status (job, reply, failure_error, allowed_sftp_error, &error))
- {
- g_vfs_job_succeeded (job);
- return TRUE;
- }
+ return TRUE;
else
{
g_vfs_job_failed_from_error (job, error);
@@ -1634,6 +1632,24 @@
return FALSE;
}
+
+static gboolean
+result_from_status (GVfsJob *job,
+ GDataInputStream *reply,
+ int failure_error,
+ int allowed_sftp_error)
+{
+ gboolean res;
+
+ res = failure_from_status (job, reply,
+ failure_error,
+ allowed_sftp_error);
+ if (res)
+ g_vfs_job_succeeded (job);
+
+ return res;
+}
+
static void
set_access_attributes (GFileInfo *info,
guint32 perm)
@@ -1929,7 +1945,6 @@
gpointer user_data)
{
SftpHandle *handle;
- GError *error;
if (g_vfs_job_is_finished (job))
{
@@ -1957,22 +1972,15 @@
if (reply_type == SSH_FXP_STATUS)
{
- error = NULL;
- if (error_from_status (job,
- reply,
- -1,
- SSH_FX_FAILURE,
- &error))
+ if (failure_from_status (job,
+ reply,
+ -1,
+ SSH_FX_FAILURE))
{
/* Unknown failure type, mark that we got this and
return result from stat result */
G_VFS_JOB(job)->backend_data = GINT_TO_POINTER (1);
}
- else
- {
- g_vfs_job_failed_from_error (job, error);
- g_error_free (error);
- }
return;
}
@@ -3236,7 +3244,6 @@
char *basename;
int i;
MultiReply *lstat_reply, *reply;
- GError *error;
GFileInfo *lstat_info;
GVfsJobQueryInfo *op_job;
@@ -3245,15 +3252,12 @@
i = 0;
lstat_reply = &replies[i++];
- if (lstat_reply->reply_type == SSH_FXP_STATUS)
+ if (lstat_reply->type == SSH_FXP_STATUS)
{
- error = NULL;
- error_from_status (job, lstat_reply->data, -1, -1, &error);
- g_vfs_job_failed_from_error (job, error);
- g_error_free (error);
- return;
+ result_from_status (job, lstat_reply->data, -1, -1);
+ return;
}
- else if (lstat_reply->reply_type != SSH_FXP_ATTRS)
+ else if (lstat_reply->type != SSH_FXP_ATTRS)
{
g_vfs_job_failed (job,
G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -3275,7 +3279,7 @@
/* Look at stat results */
reply = &replies[i++];
- if (reply->reply_type == SSH_FXP_ATTRS)
+ if (reply->type == SSH_FXP_ATTRS)
{
parse_attributes (backend, op_job->file_info, basename,
reply->data, op_job->attribute_matcher);
@@ -3305,7 +3309,7 @@
/* Look at readlink results */
reply = &replies[i++];
- if (reply->reply_type == SSH_FXP_NAME)
+ if (reply->type == SSH_FXP_NAME)
{
char *symlink_target;
guint32 count;
@@ -3370,14 +3374,153 @@
GVfsJob *job,
gpointer user_data)
{
+ goffset *file_size;
+
/* on any unknown error, return NOT_SUPPORTED to get the fallback implementation */
if (reply_type == SSH_FXP_STATUS)
- result_from_status (job, reply, G_IO_ERROR_NOT_SUPPORTED, -1);
+ {
+ if (failure_from_status (job, reply, G_IO_ERROR_NOT_SUPPORTED, -1))
+ {
+ /* Succeeded, report file size */
+ file_size = job->backend_data;
+ if (file_size != NULL)
+ g_vfs_job_move_progress_callback (*file_size, *file_size, job);
+ g_vfs_job_succeeded (job);
+ }
+ }
+ else
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid reply received"));
+}
+
+static void
+move_do_rename (GVfsBackendSftp *backend,
+ GVfsJob *job)
+{
+ GVfsJobMove *op_job;
+ GDataOutputStream *command;
+
+ op_job = G_VFS_JOB_MOVE (job);
+
+ command = new_command_stream (backend,
+ SSH_FXP_RENAME);
+ put_string (command, op_job->source);
+ put_string (command, op_job->destination);
+
+ queue_command_stream_and_free (backend, command, move_reply, G_VFS_JOB (job), NULL);
+}
+
+static void
+move_delete_target_reply (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ if (reply_type == SSH_FXP_STATUS)
+ {
+ if (failure_from_status (job, reply, -1, -1))
+ move_do_rename (backend, job);
+ }
else
g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Invalid reply received"));
}
+
+static void
+move_lstat_reply (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ GVfsJobMove *op_job;
+ gboolean destination_exist, source_is_dir, dest_is_dir;
+ GDataOutputStream *command;
+ GFileInfo *info;
+ goffset *file_size;
+
+ op_job = G_VFS_JOB_MOVE (job);
+
+ if (replies[0].type == SSH_FXP_STATUS)
+ {
+ result_from_status (job, replies[0].data, -1, -1);
+ return;
+ }
+ else if (replies[0].type != SSH_FXP_ATTRS)
+ {
+ g_vfs_job_failed (job,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid reply received"));
+ return;
+ }
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ replies[0].data, NULL);
+ source_is_dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ file_size = g_new (goffset, 1);
+ *file_size = g_file_info_get_size (info);
+ g_vfs_job_set_backend_data (G_VFS_JOB (job), file_size, g_free);
+ g_object_unref (info);
+
+ destination_exist = FALSE;
+ if (replies[1].type == SSH_FXP_ATTRS)
+ {
+ destination_exist = TRUE; /* Target file exists */
+
+ info = g_file_info_new ();
+ parse_attributes (backend, info, NULL,
+ replies[1].data, NULL);
+ dest_is_dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
+ g_object_unref (info);
+
+ if (op_job->flags & G_FILE_COPY_OVERWRITE)
+ {
+
+ /* Always fail on dirs, even with overwrite */
+ if (dest_is_dir)
+ {
+ if (source_is_dir)
+ g_vfs_job_failed (job,
+ G_IO_ERROR,
+ G_IO_ERROR_WOULD_MERGE,
+ _("Can't move directory over directory"));
+ else
+ g_vfs_job_failed (job,
+ G_IO_ERROR,
+ G_IO_ERROR_IS_DIRECTORY,
+ _("File is directory"));
+ return;
+ }
+ }
+ else
+ {
+ g_vfs_job_failed (G_VFS_JOB (job),
+ G_IO_ERROR,
+ G_IO_ERROR_EXISTS,
+ _("Target file already exists"));
+ return;
+ }
+ }
+
+ /* TODO: Check flags & G_FILE_COPY_BACKUP */
+
+ if (destination_exist && (op_job->flags & G_FILE_COPY_OVERWRITE))
+ {
+ command = new_command_stream (backend,
+ SSH_FXP_REMOVE);
+ put_string (command, op_job->destination);
+ queue_command_stream_and_free (backend, command, move_delete_target_reply, G_VFS_JOB (job), NULL);
+ return;
+ }
+
+ move_do_rename (backend, job);
+}
+
+
static gboolean
try_move (GVfsBackend *backend,
GVfsJobMove *job,
@@ -3389,16 +3532,20 @@
{
GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
GDataOutputStream *command;
-
- command = new_command_stream (op_backend,
- SSH_FXP_RENAME);
+ GDataOutputStream *commands[2];
+
+ command = commands[0] =
+ new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
put_string (command, source);
+
+ command = commands[1] =
+ new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
put_string (command, destination);
- /* This fails if the target exists, we then fallback to default implementation */
+ queue_command_streams_and_free (op_backend, commands, 2, move_lstat_reply, G_VFS_JOB (job), NULL);
- queue_command_stream_and_free (op_backend, command, move_reply, G_VFS_JOB (job), NULL);
-
return TRUE;
}
Modified: trunk/daemon/gvfsjobmove.c
==============================================================================
--- trunk/daemon/gvfsjobmove.c (original)
+++ trunk/daemon/gvfsjobmove.c Thu Mar 27 19:57:39 2008
@@ -122,12 +122,11 @@
return G_VFS_JOB (job);
}
-static void
-progress_callback (goffset current_num_bytes,
- goffset total_num_bytes,
- gpointer user_data)
+void
+g_vfs_job_move_progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ GVfsJob *job)
{
- GVfsJob *job = G_VFS_JOB (user_data);
GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
GVfsJobMove *op_job = G_VFS_JOB_MOVE (job);
dbus_uint64_t current_dbus, total_dbus;
@@ -175,7 +174,7 @@
op_job->source,
op_job->destination,
op_job->flags,
- progress_callback,
+ (GFileProgressCallback)g_vfs_job_move_progress_callback,
job);
}
@@ -193,7 +192,7 @@
op_job->source,
op_job->destination,
op_job->flags,
- progress_callback,
+ (GFileProgressCallback)g_vfs_job_move_progress_callback,
job);
}
Modified: trunk/daemon/gvfsjobmove.h
==============================================================================
--- trunk/daemon/gvfsjobmove.h (original)
+++ trunk/daemon/gvfsjobmove.h Thu Mar 27 19:57:39 2008
@@ -62,6 +62,10 @@
DBusMessage *message,
GVfsBackend *backend);
+void g_vfs_job_move_progress_callback (goffset current_num_bytes,
+ goffset total_num_bytes,
+ GVfsJob *job);
+
G_END_DECLS
#endif /* __G_VFS_JOB_MOVE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]