https://bugzilla.gnome.org/show_bug.cgi?id=527339 diff -urN gvfs-1.14.0.new/client/gdaemonfile.c gvfs-1.14.0/client/gdaemonfile.c --- gvfs-1.14.0.new/client/gdaemonfile.c 2012-09-30 22:04:15.383736541 +0200 +++ gvfs-1.14.0/client/gdaemonfile.c 2012-09-30 23:02:25.536442767 +0200 @@ -2679,6 +2679,51 @@ return TRUE; } +static gboolean +g_daemon_file_set_attributes_from_info (GFile *file, + GFileInfo *info, + GFileQueryInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + GVfsDBusMount *proxy; + char *path; + gboolean res; + GError *my_error; + + retry: + proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error); + if (proxy == NULL) + return FALSE; + + my_error = NULL; + res = gvfs_dbus_mount_call_set_attributes_from_info_sync (proxy, + path, + flags, + _g_dbus_append_file_info (info), + cancellable, + &my_error); + g_free (path); + + if (! res) + { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + _g_dbus_send_cancelled_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (proxy))); + else + if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY)) + { + g_clear_error (&my_error); + g_object_unref (proxy); + goto retry; + } + _g_propagate_error_stripped (error, my_error); + return FALSE; + } + + g_object_unref (proxy); + + return TRUE; +} typedef struct { @@ -3698,6 +3743,7 @@ iface->query_settable_attributes = g_daemon_file_query_settable_attributes; iface->query_writable_namespaces = g_daemon_file_query_writable_namespaces; iface->set_attribute = g_daemon_file_set_attribute; + iface->set_attributes_from_info = g_daemon_file_set_attributes_from_info; iface->make_symbolic_link = g_daemon_file_make_symbolic_link; iface->monitor_dir = g_daemon_file_monitor_dir; iface->monitor_file = g_daemon_file_monitor_file; diff -urN gvfs-1.14.0.new/common/org.gtk.vfs.xml gvfs-1.14.0/common/org.gtk.vfs.xml --- gvfs-1.14.0.new/common/org.gtk.vfs.xml 2012-09-30 22:04:15.377066577 +0200 +++ gvfs-1.14.0/common/org.gtk.vfs.xml 2012-09-30 22:56:26.665247761 +0200 @@ -314,6 +314,11 @@ + + + + + diff -urN gvfs-1.14.0.new/daemon/gvfsbackend.c gvfs-1.14.0/daemon/gvfsbackend.c --- gvfs-1.14.0.new/daemon/gvfsbackend.c 2012-09-30 22:04:15.393741487 +0200 +++ gvfs-1.14.0/daemon/gvfsbackend.c 2012-09-30 23:40:33.814046064 +0200 @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -271,6 +272,7 @@ g_signal_connect (skeleton, "handle-query-settable-attributes", G_CALLBACK (g_vfs_job_query_settable_attributes_new_handle), data); g_signal_connect (skeleton, "handle-query-writable-namespaces", G_CALLBACK (g_vfs_job_query_writable_namespaces_new_handle), data); g_signal_connect (skeleton, "handle-set-attribute", G_CALLBACK (g_vfs_job_set_attribute_new_handle), data); + g_signal_connect (skeleton, "handle-set-attributes-from-info", G_CALLBACK (g_vfs_job_set_attributes_from_info_new_handle), data); g_signal_connect (skeleton, "handle-poll-mountable", G_CALLBACK (g_vfs_job_poll_mountable_new_handle), data); g_signal_connect (skeleton, "handle-start-mountable", G_CALLBACK (g_vfs_job_start_mountable_new_handle), data); g_signal_connect (skeleton, "handle-stop-mountable", G_CALLBACK (g_vfs_job_stop_mountable_new_handle), data); diff -urN gvfs-1.14.0.new/daemon/gvfsbackend.h gvfs-1.14.0/daemon/gvfsbackend.h --- gvfs-1.14.0.new/daemon/gvfsbackend.h 2012-09-30 22:04:15.387071523 +0200 +++ gvfs-1.14.0/daemon/gvfsbackend.h 2012-09-30 23:08:49.801027687 +0200 @@ -72,6 +72,7 @@ typedef struct _GVfsJobPush GVfsJobPush; typedef struct _GVfsJobPull GVfsJobPull; typedef struct _GVfsJobSetAttribute GVfsJobSetAttribute; +typedef struct _GVfsJobSetAttributesFromInfo GVfsJobSetAttributesFromInfo; typedef struct _GVfsJobQueryAttributes GVfsJobQueryAttributes; typedef struct _GVfsJobCreateMonitor GVfsJobCreateMonitor; @@ -396,6 +397,17 @@ GFileAttributeType type, gpointer value_p, GFileQueryInfoFlags flags); + void (*set_attributes_from_info) (GVfsBackend *backend, + GVfsJobSetAttributesFromInfo *job, + const char *filename, + GFileInfo *info, + GFileQueryInfoFlags flags); + gboolean (*try_set_attributes_from_info) (GVfsBackend *backend, + GVfsJobSetAttributesFromInfo *job, + const char *filename, + GFileInfo *info, + GFileQueryInfoFlags flags); + void (*create_dir_monitor)(GVfsBackend *backend, GVfsJobCreateMonitor *job, const char *filename, diff -urN gvfs-1.14.0.new/daemon/gvfsbackendsftp.c gvfs-1.14.0/daemon/gvfsbackendsftp.c --- gvfs-1.14.0.new/daemon/gvfsbackendsftp.c 2012-09-30 22:04:15.390406505 +0200 +++ gvfs-1.14.0/daemon/gvfsbackendsftp.c 2012-09-30 23:48:52.948008785 +0200 @@ -4575,9 +4575,38 @@ g_file_attribute_info_list_add (list, G_FILE_ATTRIBUTE_UNIX_MODE, G_FILE_ATTRIBUTE_TYPE_UINT32, - G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE | G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); + /* G_FILE_INFO_COPY_WHEN_MOVED to ensure that this is copied when + G_FILE_COPY_ALL_METADATA flag is set, but is not copied by default */ + g_file_attribute_info_list_add (list, + G_FILE_ATTRIBUTE_TIME_ACCESS, + G_FILE_ATTRIBUTE_TYPE_UINT32, + G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); + g_file_attribute_info_list_add (list, + G_FILE_ATTRIBUTE_TIME_CHANGED, + G_FILE_ATTRIBUTE_TYPE_UINT32, + G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED); + /* do not make uid/gid settable: it will cause massive problems + when G_FILE_COPY_ALL_METADATA is set. */ + + g_vfs_job_query_attributes_set_list (job, list); + g_vfs_job_succeeded (G_VFS_JOB (job)); + g_file_attribute_info_list_unref (list); + return TRUE; +} + +static gboolean +try_query_writable_namespaces (GVfsBackend *backend, + GVfsJobQueryAttributes *job, + const char *filename) +{ + GFileAttributeInfoList *list; + + list = g_file_attribute_info_list_new (); + + /* generally, we don't have any writable namespaces */ + g_vfs_job_query_attributes_set_list (job, list); g_vfs_job_succeeded (G_VFS_JOB (job)); g_file_attribute_info_list_unref (list); @@ -4612,6 +4641,8 @@ GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend); GDataOutputStream *command; + /* atime and mtime must be set in a single sftp command. Therefore, to set them, + you must use try_set_attributes_from_info () */ if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) != 0) { g_vfs_job_failed (G_VFS_JOB (job), @@ -4640,6 +4671,103 @@ } static void +set_attributes_from_info_reply (GVfsBackendSftp *backend, + int reply_type, + GDataInputStream *reply, + guint32 len, + GVfsJob *job, + gpointer user_data) +{ + if (reply_type == SSH_FXP_STATUS) + result_from_status (job, reply, -1, -1); + else + g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Invalid reply received")); +} + +static gboolean +try_set_attributes_from_info (GVfsBackend *backend, + GVfsJobSetAttributesFromInfo *job, + const char *filename, + GFileInfo *info, + GFileQueryInfoFlags flags) +{ + GVfsBackendSftp *op_backend = G_VFS_BACKEND_SFTP (backend); + GDataOutputStream *command; + char **attributes; + int i; + guint64 tmp64; + guint32 sftp_attributes = 0, sftp_mode, sftp_atime, sftp_mtime; + gboolean is_atime_set = FALSE, is_mtime_set = FALSE; + + attributes = g_file_info_list_attributes (info, NULL); + for (i=0; attributes[i]; i++) + { + if (!strcmp (attributes[i], G_FILE_ATTRIBUTE_UNIX_MODE) ) + { + sftp_attributes |= SSH_FILEXFER_ATTR_PERMISSIONS; + sftp_mode = 0777 & g_file_info_get_attribute_uint32 (info, attributes[i]); + } + else if (!strcmp (attributes[i], G_FILE_ATTRIBUTE_TIME_ACCESS) ) + { + sftp_attributes |= SSH_FILEXFER_ATTR_ACMODTIME; + /* assume year < 2107 */ + sftp_atime = g_file_info_get_attribute_uint64 (info, attributes[i]); + is_atime_set = TRUE; + } + else if (!strcmp (attributes[i], G_FILE_ATTRIBUTE_TIME_CHANGED) ) + { + sftp_attributes |= SSH_FILEXFER_ATTR_ACMODTIME; + /* assume year < 2107 */ + sftp_mtime = g_file_info_get_attribute_uint64 (info, attributes[i]); + is_mtime_set = TRUE; + } + else + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Operation unsupported")); + } + g_strfreev (attributes); + + /* must set atime and mtime in a single command */ + if ( (is_atime_set && !is_mtime_set) || (is_mtime_set && !is_atime_set)) + { + sftp_attributes &= ~SSH_FILEXFER_ATTR_ACMODTIME; + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Operation unsupported")); + } + + if (sftp_attributes) + { + command = new_command_stream (op_backend,SSH_FXP_SETSTAT); + put_string (command, filename); + g_data_output_stream_put_uint32 (command, sftp_attributes, NULL, NULL); + + if (sftp_attributes & SSH_FILEXFER_ATTR_PERMISSIONS) + g_data_output_stream_put_uint32 (command, sftp_mode, NULL, NULL); + if (sftp_attributes & SSH_FILEXFER_ATTR_ACMODTIME) + { + g_data_output_stream_put_uint32 (command, sftp_atime, NULL, NULL); + g_data_output_stream_put_uint32 (command, sftp_mtime, NULL, NULL); + } + + queue_command_stream_and_free (op_backend, command, set_attributes_from_info_reply, G_VFS_JOB (job), NULL); + } + else + { + if (!i) + /* no attributes to set - return success */ + g_vfs_job_succeeded (G_VFS_JOB (job)); + else + g_vfs_job_failed (G_VFS_JOB (job), + G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Operation unsupported")); + } + return TRUE; +} + +static void g_vfs_backend_sftp_class_init (GVfsBackendSftpClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); @@ -4672,5 +4800,7 @@ backend_class->try_delete = try_delete; backend_class->try_set_display_name = try_set_display_name; backend_class->try_query_settable_attributes = try_query_settable_attributes; + backend_class->try_query_writable_namespaces = try_query_writable_namespaces; backend_class->try_set_attribute = try_set_attribute; + backend_class->try_set_attributes_from_info = try_set_attributes_from_info; backend_class->try_push = try_push; diff -urN gvfs-1.14.0.new/daemon/gvfsjobsetattributesfrominfo.c gvfs-1.14.0/daemon/gvfsjobsetattributesfrominfo.c --- gvfs-1.14.0.new/daemon/gvfsjobsetattributesfrominfo.c 1970-01-01 01:00:00.000000000 +0100 +++ gvfs-1.14.0/daemon/gvfsjobsetattributesfrominfo.c 2012-09-30 23:32:41.529938013 +0200 @@ -0,0 +1,190 @@ +/* GVFS - GNOME virtual filesystem layer + * + * Copyright (C) 2008 Alexandre Rostovtsev + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexandre Rostovtsev + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include "gvfsjobmove.h" +#include "gvfsdaemonprotocol.h" +#include "gvfsjobsetattribute.h" +#include "gvfsjobsetattributesfrominfo.h" + +G_DEFINE_TYPE (GVfsJobSetAttributesFromInfo, g_vfs_job_set_attributes_from_info, G_VFS_TYPE_JOB_DBUS) + +typedef struct _GVfsJobSetAttributesFromInfoPrivate GVfsJobSetAttributesFromInfoPrivate; +struct _GVfsJobSetAttributesFromInfoPrivate { + gboolean dispose_has_run; +}; + +#define G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO, GVfsJobSetAttributesFromInfoPrivate)) + +static void run (GVfsJob *job); +static gboolean try (GVfsJob *job); +static void create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation); + +static void +g_vfs_job_set_attributes_from_info_dispose (GObject *object) +{ + GVfsJobSetAttributesFromInfo *job; + GVfsJobSetAttributesFromInfoPrivate *priv; + + job = G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO (object); + priv = G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_GET_PRIVATE (object); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + g_object_unref (job->info); + + if (G_OBJECT_CLASS (g_vfs_job_set_attributes_from_info_parent_class)->dispose) + (*G_OBJECT_CLASS (g_vfs_job_set_attributes_from_info_parent_class)->dispose) (object); +} + +static void +g_vfs_job_set_attributes_from_info_finalize (GObject *object) +{ + GVfsJobSetAttributesFromInfo *job; + + job = G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO (object); + + g_free (job->filename); + + if (G_OBJECT_CLASS (g_vfs_job_set_attributes_from_info_parent_class)->finalize) + (*G_OBJECT_CLASS (g_vfs_job_set_attributes_from_info_parent_class)->finalize) (object); +} + +static void +g_vfs_job_set_attributes_from_info_class_init (GVfsJobSetAttributesFromInfoClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVfsJobClass *job_class = G_VFS_JOB_CLASS (klass); + GVfsJobDBusClass *job_dbus_class = G_VFS_JOB_DBUS_CLASS (klass); + + gobject_class->dispose = g_vfs_job_set_attributes_from_info_dispose; + gobject_class->finalize = g_vfs_job_set_attributes_from_info_finalize; + job_class->run = run; + job_class->try = try; + job_dbus_class->create_reply = create_reply; + + g_type_class_add_private (klass, sizeof (GVfsJobSetAttributesFromInfoPrivate)); +} + +static void +g_vfs_job_set_attributes_from_info_init (GVfsJobSetAttributesFromInfo *job) +{ + GVfsJobSetAttributesFromInfoPrivate *priv; + + job->info = NULL; + priv = G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_GET_PRIVATE (job); + priv->dispose_has_run = FALSE; +} + +gboolean +g_vfs_job_set_attributes_from_info_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const char *arg_path_data, + guint arg_flags, + GVariant *arg_info, + GVfsBackend *backend) +{ + GVfsJobSetAttributesFromInfo *job; + GFileInfo *info = NULL; + + if (g_vfs_backend_invocation_first_handler (object, invocation, backend)) + return TRUE; + + if ( !(info = _g_dbus_get_file_info (arg_info, NULL)) ) + { + g_dbus_method_invocation_return_error_literal (invocation, + G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + _("Invalid dbus message")); + return TRUE; + } + + job = g_object_new (G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO, + "object", object, + "invocation", invocation, + NULL); + + job->backend = backend; + job->filename = g_strdup (arg_path_data); + job->info = info; + job->flags = arg_flags; + + g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job)); + g_object_unref (job); + + return TRUE; +} + +static void +run (GVfsJob *job) +{ + GVfsJobSetAttributesFromInfo *op_job = G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO (job); + GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend); + + if (class->set_attributes_from_info == NULL) + { + /* TODO : try to fallback using class->set_attribute */ + g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Operation not supported by backend")); + return; + } + class->set_attributes_from_info (op_job->backend, op_job, op_job->filename, op_job->info, op_job->flags); +} + +static gboolean +try (GVfsJob *job) +{ + GVfsJobSetAttributesFromInfo *op_job = G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO (job); + GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend); + + if (class->try_set_attributes_from_info == NULL) + { + /* TODO : try to fallback using class->try_set_attribute */ + return FALSE; + } + + return class->try_set_attributes_from_info (op_job->backend, op_job, op_job->filename, op_job->info, op_job->flags); +} + +/* Might be called on an i/o thread */ +static void +create_reply (GVfsJob *job, + GVfsDBusMount *object, + GDBusMethodInvocation *invocation) +{ + gvfs_dbus_mount_complete_set_attributes_from_info (object, invocation); +} diff -urN gvfs-1.14.0.new/daemon/gvfsjobsetattributesfrominfo.h gvfs-1.14.0/daemon/gvfsjobsetattributesfrominfo.h --- gvfs-1.14.0.new/daemon/gvfsjobsetattributesfrominfo.h 1970-01-01 01:00:00.000000000 +0100 +++ gvfs-1.14.0/daemon/gvfsjobsetattributesfrominfo.h 2012-09-30 23:42:51.086635731 +0200 @@ -0,0 +1,75 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2006-2007 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexandre Rostovtsev + */ + +#ifndef __G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_H__ +#define __G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO \ + (g_vfs_job_set_attributes_from_info_get_type ()) +#define G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO(o) \ + (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO, GVfsJobSetAttributesFromInfo)) +#define G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_CLASS(k) \ + (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO, GVfsJobSetAttributesFromInfoClass)) +#define G_VFS_IS_JOB_SET_ATTRIBUTES_FROM_INFO(o) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO)) +#define G_VFS_IS_JOB_SET_ATTRIBUTES_FROM_INFO_CLASS(k) \ + (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO)) +#define G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_GET_CLASS(o) \ + (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTES_FROM_INFO, GVfsJobSetAttributesFromInfoClass)) + +typedef struct _GVfsJobSetAttributesFromInfoClass GVfsJobSetAttributesFromInfoClass; + +struct _GVfsJobSetAttributesFromInfo +{ + GVfsJobDBus parent_instance; + + GVfsBackend *backend; + + char *filename; + GFileInfo *info; + GFileQueryInfoFlags flags; +}; + +struct _GVfsJobSetAttributesFromInfoClass +{ + GVfsJobDBusClass parent_class; +}; + +GType g_vfs_job_set_attributes_from_info_get_type (void) G_GNUC_CONST; + +gboolean g_vfs_job_set_attributes_from_info_new_handle (GVfsDBusMount *object, + GDBusMethodInvocation *invocation, + const gchar *arg_path_data, + guint arg_flags, + GVariant *arg_info, + GVfsBackend *backend); + +G_END_DECLS + +#endif /* __G_VFS_JOB_SET_ATTRIBUTES_FROM_INFO_H__ */ diff -urN gvfs-1.14.0.new/daemon/Makefile.am gvfs-1.14.0/daemon/Makefile.am --- gvfs-1.14.0.new/daemon/Makefile.am 2012-09-30 22:04:15.400411451 +0200 +++ gvfs-1.14.0/daemon/Makefile.am 2012-09-30 23:39:57.067578418 +0200 @@ -181,6 +181,7 @@ gvfsjobmakedirectory.c gvfsjobmakedirectory.h \ gvfsjobmakesymlink.c gvfsjobmakesymlink.h \ gvfsjobsetattribute.c gvfsjobsetattribute.h \ + gvfsjobsetattributesfrominfo.c gvfsjobsetattributesfrominfo.h \ gvfsjobqueryattributes.c gvfsjobqueryattributes.h \ gvfsjobcreatemonitor.c gvfsjobcreatemonitor.h \ gvfskeyring.h gvfskeyring.c \