diff options
author | Alexander Larsson <alexl@redhat.com> | 2009-03-23 13:41:27 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2009-03-23 13:41:27 +0000 |
commit | b524a6fd69ff7c26c71a5a0665e4ea49c3f06294 (patch) | |
tree | 8a8986098b616a5a66e13e0e241bf23a483e726a /daemon/gvfsbackendsftp.c | |
parent | f205f6cfa56dbbc2dac6390bf4cd640ebfe6155c (diff) | |
download | gvfs-b524a6fd69ff7c26c71a5a0665e4ea49c3f06294.tar.gz |
Fix various error cases to return right error: Append to existing
2009-03-23 Alexander Larsson <alexl@redhat.com>
* daemon/gvfsbackendsftp.c:
Fix various error cases to return right error:
Append to existing directory
replace existing directory
enumerate non-directory
svn path=/trunk/; revision=2347
Diffstat (limited to 'daemon/gvfsbackendsftp.c')
-rw-r--r-- | daemon/gvfsbackendsftp.c | 244 |
1 files changed, 224 insertions, 20 deletions
diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c index 965eda23..b78f2438 100644 --- a/daemon/gvfsbackendsftp.c +++ b/daemon/gvfsbackendsftp.c @@ -1647,22 +1647,38 @@ io_error_code_for_sftp_error (guint32 code, int failure_error) return error_code; } +static char * +error_message (GIOErrorEnum error) +{ + switch (error) + { + case G_IO_ERROR_NOT_EMPTY: + return _("Directory not empty"); + case G_IO_ERROR_EXISTS: + return _("Target file exists"); + case G_IO_ERROR_NOT_SUPPORTED: + return _("Operation unsupported"); + case G_IO_ERROR_PERMISSION_DENIED: + return _("Permission denied"); + case G_IO_ERROR_NOT_FOUND: + return _("No such file or directory"); + default: + return "Unknown reason"; + } +} + static gboolean -error_from_status (GVfsJob *job, - GDataInputStream *reply, - int failure_error, - int allowed_sftp_error, - GError **error) +error_from_status_code (GVfsJob *job, + guint32 code, + int failure_error, + int allowed_sftp_error, + GError **error) { - guint32 code; gint error_code; - char *message; - + if (failure_error == -1) failure_error = G_IO_ERROR_FAILED; - code = g_data_input_stream_read_uint32 (reply, NULL, NULL); - if (code == SSH_FX_OK || (allowed_sftp_error != -1 && code == allowed_sftp_error)) @@ -1671,18 +1687,67 @@ error_from_status (GVfsJob *job, if (error) { error_code = io_error_code_for_sftp_error (code, failure_error); - message = read_string (reply, NULL); - if (message == NULL) - message = g_strdup ("Unknown reason"); - - *error = g_error_new_literal (G_IO_ERROR, error_code, message); - g_free (message); + *error = g_error_new_literal (G_IO_ERROR, error_code, + error_message (error_code)); } return FALSE; } static gboolean +failure_from_status_code (GVfsJob *job, + guint32 code, + int failure_error, + int allowed_sftp_error) +{ + GError *error; + + error = NULL; + if (error_from_status_code (job, code, failure_error, allowed_sftp_error, &error)) + return TRUE; + else + { + g_vfs_job_failed_from_error (job, error); + g_error_free (error); + } + return FALSE; +} + +static gboolean +result_from_status_code (GVfsJob *job, + guint32 code, + int failure_error, + int allowed_sftp_error) +{ + gboolean res; + + res = failure_from_status_code (job, code, + failure_error, + allowed_sftp_error); + if (res) + g_vfs_job_succeeded (job); + + return res; +} + + +static gboolean +error_from_status (GVfsJob *job, + GDataInputStream *reply, + int failure_error, + int allowed_sftp_error, + GError **error) +{ + guint32 code; + + code = g_data_input_stream_read_uint32 (reply, NULL, NULL); + + return error_from_status_code (job, code, + failure_error, allowed_sftp_error, + error); +} + +static gboolean failure_from_status (GVfsJob *job, GDataInputStream *reply, int failure_error, @@ -1701,7 +1766,6 @@ failure_from_status (GVfsJob *job, return FALSE; } - static gboolean result_from_status (GVfsJob *job, GDataInputStream *reply, @@ -1719,6 +1783,89 @@ result_from_status (GVfsJob *job, return res; } + + +typedef struct _ErrorFromStatData ErrorFromStatData; + +typedef void (*ErrorFromStatCallback) (GVfsBackendSftp *backend, + GVfsJob *job, + gint original_error, + gint stat_error, + GFileInfo *info, + gpointer user_data); + + +struct _ErrorFromStatData { + gint original_error; + ErrorFromStatCallback callback; + gpointer user_data; +}; + +static void +error_from_lstat_reply (GVfsBackendSftp *backend, + int reply_type, + GDataInputStream *reply, + guint32 len, + GVfsJob *job, + gpointer user_data) +{ + ErrorFromStatData *data = user_data; + GFileInfo *info; + gint stat_error; + + stat_error = 0; + info = NULL; + if (reply_type == SSH_FXP_STATUS) + stat_error = g_data_input_stream_read_uint32 (reply, NULL, NULL); + else if (reply_type == SSH_FXP_ATTRS) + { + info = g_file_info_new (); + parse_attributes (backend, + info, + NULL, + reply, + NULL); + } + else + { + g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid reply received")); + goto out; + } + + data->callback (backend, job, + data->original_error, + stat_error, + info, + data->user_data); + + out: + g_slice_free (ErrorFromStatData, data); +} + +static void +error_from_lstat (GVfsBackendSftp *backend, + GVfsJob *job, + GDataInputStream *original_reply, + const char *path, + ErrorFromStatCallback callback, + gpointer user_data) +{ + GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend); + GDataOutputStream *command; + ErrorFromStatData *data; + + command = new_command_stream (op_backend, SSH_FXP_LSTAT); + put_string (command, path); + + data = g_slice_new (ErrorFromStatData); + data->original_error = g_data_input_stream_read_uint32 (original_reply, NULL, NULL); + data->callback = callback; + data->user_data = user_data; + queue_command_stream_and_free (op_backend, command, error_from_lstat_reply, + G_VFS_JOB (job), data); +} + static void set_access_attributes (GFileInfo *info, guint32 perm) @@ -2635,6 +2782,26 @@ try_create (GVfsBackend *backend, } static void +append_to_error (GVfsBackendSftp *backend, + GVfsJob *job, + gint original_error, + gint stat_error, + GFileInfo *info, + gpointer user_data) +{ + if ((original_error == SSH_FX_FAILURE) && + info != NULL && + g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + _("File is directory")); + return; + } + + result_from_status_code (job, original_error, -1, -1); +} + +static void append_to_reply (GVfsBackendSftp *backend, int reply_type, GDataInputStream *reply, @@ -2646,7 +2813,10 @@ append_to_reply (GVfsBackendSftp *backend, if (reply_type == SSH_FXP_STATUS) { - result_from_status (job, reply, -1, -1); + error_from_lstat (backend, job, reply, + G_VFS_JOB_OPEN_FOR_WRITE (job)->filename, + append_to_error, + NULL); return; } @@ -2953,6 +3123,14 @@ replace_stat_reply (GVfsBackendSftp *backend, parse_attributes (backend, info, NULL, reply, NULL); + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + { + g_object_unref (info); + g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, + _("File is directory")); + return; + } + if (op_job->etag != NULL) { current_etag = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE); @@ -3024,7 +3202,7 @@ replace_exclusive_reply (GVfsBackendSftp *backend, /* Replace existing file code: */ command = new_command_stream (backend, - SSH_FXP_STAT); + SSH_FXP_LSTAT); put_string (command, op_job->filename); queue_command_stream_and_free (backend, command, replace_stat_reply, G_VFS_JOB (job), NULL); } @@ -3400,6 +3578,29 @@ read_dir_reply (GVfsBackendSftp *backend, } static void +open_dir_error (GVfsBackendSftp *backend, + GVfsJob *job, + gint original_error, + gint stat_error, + GFileInfo *info, + gpointer user_data) +{ + if ((original_error == SSH_FX_FAILURE || + original_error == SSH_FX_NO_SUCH_FILE) && + info != NULL && + g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) + { + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, + G_IO_ERROR_NOT_DIRECTORY, + _("The file is not a directory")); + return; + } + + result_from_status_code (job, original_error, -1, -1); +} + +static void open_dir_reply (GVfsBackendSftp *backend, int reply_type, GDataInputStream *reply, @@ -3415,7 +3616,10 @@ open_dir_reply (GVfsBackendSftp *backend, if (reply_type == SSH_FXP_STATUS) { - result_from_status (job, reply, -1, -1); + error_from_lstat (backend, job, reply, + G_VFS_JOB_ENUMERATE (job)->filename, + open_dir_error, + NULL); return; } |