summaryrefslogtreecommitdiff
path: root/daemon
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2008-03-27 12:39:26 +0000
committerAlexander Larsson <alexl@src.gnome.org>2008-03-27 12:39:26 +0000
commit69a6a91b73fd21bbc54a60b4c540952eb2856cbb (patch)
tree703edea61d60b1d31e57f2d1e1b62092fd47d40f /daemon
parent4a44c5740f71314430dbbe0163743a3909be6dc2 (diff)
downloadgvfs-69a6a91b73fd21bbc54a60b4c540952eb2856cbb.tar.gz
Introduce helpers for multi-request ops. Use it for query_info.
2008-03-27 Alexander Larsson <alexl@redhat.com> * daemon/gvfsbackendsftp.c: Introduce helpers for multi-request ops. Use it for query_info. svn path=/trunk/; revision=1684
Diffstat (limited to 'daemon')
-rw-r--r--daemon/gvfsbackendsftp.c343
1 files changed, 191 insertions, 152 deletions
diff --git a/daemon/gvfsbackendsftp.c b/daemon/gvfsbackendsftp.c
index 2573f634..631bdec6 100644
--- a/daemon/gvfsbackendsftp.c
+++ b/daemon/gvfsbackendsftp.c
@@ -75,13 +75,40 @@ typedef enum {
SFTP_VENDOR_SSH
} SFTPClientVendor;
+typedef struct _MultiReply MultiReply;
+
typedef void (*ReplyCallback) (GVfsBackendSftp *backend,
int reply_type,
GDataInputStream *reply,
guint32 len,
GVfsJob *job,
gpointer user_data);
-
+
+typedef void (*MultiReplyCallback) (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data);
+
+
+typedef struct {
+ MultiReply *replies;
+ int n_replies;
+ int n_outstanding;
+ gpointer user_data;
+ MultiReplyCallback callback;
+} MultiRequest;
+
+struct _MultiReply {
+ int reply_type;
+ GDataInputStream *data;
+ guint32 data_len;
+
+ MultiRequest *request;
+};
+
+
+
typedef struct {
guchar *data;
gsize size;
@@ -1205,6 +1232,85 @@ queue_command_stream_and_free (GVfsBackendSftp *backend,
queue_command_buffer (backend, buffer);
}
+
+static void
+multi_request_cb (GVfsBackendSftp *backend,
+ int reply_type,
+ GDataInputStream *reply_stream,
+ guint32 len,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ MultiReply *reply;
+ MultiRequest *request;
+ int i;
+
+ reply = user_data;
+ request = reply->request;
+
+ reply->reply_type = reply_type;
+ reply->data = g_object_ref (reply_stream);
+ reply->data_len = len;
+
+ if (--request->n_outstanding == 0)
+ {
+ /* Call callback */
+ if (request->callback != NULL)
+ (request->callback) (backend,
+ request->replies,
+ request->n_replies,
+ job,
+ request->user_data);
+
+ /* Free request data */
+
+ for (i = 0; i < request->n_replies; i++)
+ {
+ reply = &request->replies[i];
+ if (reply->data)
+ g_object_unref (reply->data);
+ }
+ g_free (request->replies);
+
+ g_free (request);
+
+ }
+}
+
+static void
+queue_command_streams_and_free (GVfsBackendSftp *backend,
+ GDataOutputStream **commands,
+ int n_commands,
+ MultiReplyCallback callback,
+ GVfsJob *job,
+ gpointer user_data)
+{
+ MultiRequest *data;
+ MultiReply *reply;
+
+ int i;
+
+ data = g_new0 (MultiRequest, 1);
+
+ data->user_data = user_data;
+ data->n_replies = n_commands;
+ data->n_outstanding = n_commands;
+ data->replies = g_new0 (MultiReply, n_commands);
+ data->callback = callback;
+
+ for (i = 0; i < n_commands; i++)
+ {
+ reply = &data->replies[i];
+ reply->request = data;
+ queue_command_stream_and_free (backend,
+ commands[i],
+ multi_request_cb,
+ job,
+ reply);
+ }
+}
+
+
static gboolean
get_uid_sync (GVfsBackendSftp *backend)
{
@@ -3120,162 +3226,98 @@ try_enumerate (GVfsBackend *backend,
return TRUE;
}
-typedef struct {
- GFileInfo *lstat_info;
- GError *lstat_error;
- GFileInfo *stat_info;
- GError *stat_error;
- char *symlink_target;
- int cb_count;
-} QueryInfoData;
-
-static void
-query_info_data_free (QueryInfoData *data)
-{
- if (data->lstat_info)
- g_object_unref (data->lstat_info);
- if (data->lstat_error)
- g_error_free (data->lstat_error);
- if (data->stat_info)
- g_object_unref (data->stat_info);
- if (data->stat_error)
- g_error_free (data->stat_error);
-
- g_free (data->symlink_target);
-
- g_slice_free (QueryInfoData, data);
-}
-
static void
-query_info_finish (GVfsBackendSftp *backend,
- GVfsJob *job)
+query_info_reply (GVfsBackendSftp *backend,
+ MultiReply *replies,
+ int n_replies,
+ GVfsJob *job,
+ gpointer user_data)
{
+ char *basename;
+ int i;
+ MultiReply *lstat_reply, *reply;
+ GError *error;
+ GFileInfo *lstat_info;
GVfsJobQueryInfo *op_job;
- QueryInfoData *data;
- data = job->backend_data;
+ op_job = G_VFS_JOB_QUERY_INFO (job);
+
+ i = 0;
+ lstat_reply = &replies[i++];
- if (data->lstat_error)
+ if (lstat_reply->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;
+ }
+ else if (lstat_reply->reply_type != SSH_FXP_ATTRS)
{
- /* This failed, file must really not exist or something bad happened */
- g_vfs_job_failed_from_error (job, data->lstat_error);
+ g_vfs_job_failed (job,
+ G_IO_ERROR, G_IO_ERROR_FAILED,
+ "%s", _("Invalid reply received"));
return;
}
- op_job = G_VFS_JOB_QUERY_INFO (job);
+ basename = NULL;
+ if (strcmp (op_job->filename, "/") != 0)
+ basename = g_path_get_basename (op_job->filename);
+
if (op_job->flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS)
{
- g_file_info_copy_into (data->lstat_info,
- op_job->file_info);
+ parse_attributes (backend, op_job->file_info, basename,
+ lstat_reply->data, op_job->attribute_matcher);
}
else
{
- if (data->stat_info != NULL)
+ /* Look at stat results */
+ reply = &replies[i++];
+
+ if (reply->reply_type == SSH_FXP_ATTRS)
{
- g_file_info_copy_into (data->stat_info,
- op_job->file_info);
- if (data->lstat_info &&
- g_file_info_get_is_symlink (data->lstat_info))
+ parse_attributes (backend, op_job->file_info, basename,
+ reply->data, op_job->attribute_matcher);
+
+
+ lstat_info = g_file_info_new ();
+ parse_attributes (backend, lstat_info, basename,
+ lstat_reply->data, op_job->attribute_matcher);
+ if (g_file_info_get_is_symlink (lstat_info))
g_file_info_set_is_symlink (op_job->file_info, TRUE);
+ g_object_unref (lstat_info);
}
- else /* Broken symlink: */
- g_file_info_copy_into (data->lstat_info,
- op_job->file_info);
- }
-
- if (data->symlink_target)
- g_file_info_set_symlink_target (op_job->file_info, data->symlink_target);
-
- g_vfs_job_succeeded (G_VFS_JOB (job));
-}
-
-static void
-query_info_stat_reply (GVfsBackendSftp *backend,
- int reply_type,
- GDataInputStream *reply,
- guint32 len,
- GVfsJob *job,
- gpointer user_data)
-{
- char *basename;
- QueryInfoData *data;
-
- data = job->backend_data;
-
- if (reply_type == SSH_FXP_STATUS)
- error_from_status (job, reply, -1, -1, &data->stat_error);
- else if (reply_type != SSH_FXP_ATTRS)
- g_set_error (&data->stat_error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "%s", _("Invalid reply received"));
- else
- {
- data->stat_info = g_file_info_new ();
- basename = NULL;
- if (strcmp (G_VFS_JOB_QUERY_INFO (job)->filename, "/") != 0)
- basename = g_path_get_basename (G_VFS_JOB_QUERY_INFO (job)->filename);
- parse_attributes (backend, data->stat_info, basename,
- reply, G_VFS_JOB_QUERY_INFO (job)->attribute_matcher);
- g_free (basename);
+ else
+ {
+ /* Broken symlink, use lstat data */
+ parse_attributes (backend, op_job->file_info, basename,
+ lstat_reply->data, op_job->attribute_matcher);
+ }
+
}
+
+ g_free (basename);
- if (--data->cb_count == 0)
- query_info_finish (backend, job);
-}
-
-static void
-query_info_lstat_reply (GVfsBackendSftp *backend,
- int reply_type,
- GDataInputStream *reply,
- guint32 len,
- GVfsJob *job,
- gpointer user_data)
-{
- char *basename;
- QueryInfoData *data;
-
- data = job->backend_data;
-
- if (reply_type == SSH_FXP_STATUS)
- error_from_status (job, reply, -1, -1, &data->lstat_error);
- else if (reply_type != SSH_FXP_ATTRS)
- g_set_error (&data->lstat_error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "%s", _("Invalid reply received"));
- else
+ if (g_file_attribute_matcher_matches (op_job->attribute_matcher,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
{
- data->lstat_info = g_file_info_new ();
- basename = NULL;
- if (strcmp (G_VFS_JOB_QUERY_INFO (job)->filename, "/") != 0)
- basename = g_path_get_basename (G_VFS_JOB_QUERY_INFO (job)->filename);
- parse_attributes (backend, data->lstat_info, basename,
- reply, G_VFS_JOB_QUERY_INFO (job)->attribute_matcher);
- g_free (basename);
- }
-
- if (--data->cb_count == 0)
- query_info_finish (backend, job);
-}
-
-static void
-query_info_readlink_reply (GVfsBackendSftp *backend,
- int reply_type,
- GDataInputStream *reply,
- guint32 len,
- GVfsJob *job,
- gpointer user_data)
-{
- QueryInfoData *data;
- guint32 count;
-
- data = job->backend_data;
+ /* Look at readlink results */
+ reply = &replies[i++];
- if (reply_type == SSH_FXP_NAME)
- {
- count = g_data_input_stream_read_uint32 (reply, NULL, NULL);
- data->symlink_target = read_string (reply, NULL);
+ if (reply->reply_type == SSH_FXP_NAME)
+ {
+ char *symlink_target;
+ guint32 count;
+
+ count = g_data_input_stream_read_uint32 (reply->data, NULL, NULL);
+ symlink_target = read_string (reply->data, NULL);
+ g_file_info_set_symlink_target (op_job->file_info, symlink_target);
+ g_free (symlink_target);
+ }
}
- if (--data->cb_count == 0)
- query_info_finish (backend, job);
+ g_vfs_job_succeeded (G_VFS_JOB (job));
}
static gboolean
@@ -3287,38 +3329,35 @@ try_query_info (GVfsBackend *backend,
GFileAttributeMatcher *matcher)
{
GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend);
+ GDataOutputStream *commands[3];
GDataOutputStream *command;
- QueryInfoData *data;
+ int n_commands;
- data = g_slice_new0 (QueryInfoData);
- g_vfs_job_set_backend_data (G_VFS_JOB (job), data, (GDestroyNotify)query_info_data_free);
+ n_commands = 0;
- data->cb_count = 1;
- command = new_command_stream (op_backend,
- SSH_FXP_LSTAT);
+ command = commands[n_commands++] =
+ new_command_stream (op_backend,
+ SSH_FXP_LSTAT);
put_string (command, filename);
- queue_command_stream_and_free (op_backend, command, query_info_lstat_reply, G_VFS_JOB (job), NULL);
-
+
if (! (job->flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))
{
- data->cb_count++;
-
- command = new_command_stream (op_backend,
- SSH_FXP_STAT);
+ command = commands[n_commands++] =
+ new_command_stream (op_backend,
+ SSH_FXP_STAT);
put_string (command, filename);
- queue_command_stream_and_free (op_backend, command, query_info_stat_reply, G_VFS_JOB (job), NULL);
}
if (g_file_attribute_matcher_matches (job->attribute_matcher,
G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
{
- data->cb_count++;
-
- command = new_command_stream (op_backend,
- SSH_FXP_READLINK);
+ command = commands[n_commands++] =
+ new_command_stream (op_backend,
+ SSH_FXP_READLINK);
put_string (command, filename);
- queue_command_stream_and_free (op_backend, command, query_info_readlink_reply, G_VFS_JOB (job), NULL);
}
+
+ queue_command_streams_and_free (op_backend, commands, n_commands, query_info_reply, G_VFS_JOB (job), NULL);
return TRUE;
}