summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/gdaemonfile.c16
-rw-r--r--client/gvfsdaemondbus.c146
-rw-r--r--common/gvfsdaemonprotocol.c212
-rw-r--r--common/gvfsdaemonprotocol.h39
-rw-r--r--daemon/Makefile.am1
-rw-r--r--daemon/gvfsbackend.c5
-rw-r--r--daemon/gvfsbackend.h19
-rw-r--r--daemon/gvfsjobenumerate.c4
-rw-r--r--daemon/gvfsjobgetfsinfo.c4
-rw-r--r--daemon/gvfsjobgetinfo.c2
-rw-r--r--daemon/gvfsjobsetattribute.c171
-rw-r--r--daemon/gvfsjobsetattribute.h46
12 files changed, 480 insertions, 185 deletions
diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c
index f55b7779..664cd6e8 100644
--- a/client/gdaemonfile.c
+++ b/client/gdaemonfile.c
@@ -1319,7 +1319,6 @@ g_daemon_file_set_attribute (GFile *file,
GCancellable *cancellable,
GError **error)
{
-#if 0
GDaemonFile *daemon_file;
DBusMessage *message, *reply;
DBusMessageIter iter;
@@ -1338,20 +1337,17 @@ g_daemon_file_set_attribute (GFile *file,
DBUS_TYPE_UINT32,
&flags_dbus);
+ _g_dbus_append_file_attribute (&iter, attribute, type, value_ptr);
+
+ reply = _g_vfs_daemon_call_sync (message,
+ NULL,
+ NULL, NULL, NULL,
+ cancellable, error);
- reply = do_sync_path_call (file,
- G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE,
- NULL, cancellable, error,
- DBUS_TYPE_STRING, &attribute,
- DBUS_TYPE_UINT, &type,
- DBUS_TYPE_UINT32, &flags_dbus,
- g_dbus_type_from_file_attribute_type (type), &value,
- 0);
if (reply == NULL)
return FALSE;
dbus_message_unref (reply);
-#endif
return TRUE;
}
diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c
index 3b0975f2..50b32086 100644
--- a/client/gvfsdaemondbus.c
+++ b/client/gvfsdaemondbus.c
@@ -915,149 +915,3 @@ _g_dbus_connection_get_sync (const char *dbus_id,
return connection;
}
-
-/**************************************************************************
- * GFileInfo demarshaller *
- *************************************************************************/
-
-
-GFileInfo *
-_g_dbus_get_file_info (DBusMessageIter *iter,
- GError **error)
-{
- GFileInfo *info;
- DBusMessageIter struct_iter, array_iter, inner_struct_iter, variant_iter, cstring_iter, obj_iter;
- const char *attribute;
-
- info = g_file_info_new ();
-
- if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
- goto error;
-
- dbus_message_iter_recurse (iter, &struct_iter);
-
- if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY)
- goto error;
-
- dbus_message_iter_recurse (&struct_iter, &array_iter);
-
- while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
- {
- char *str;
- char **strs;
- int n_elements;
- guint32 v_uint32;
- gint32 v_int32;
- guint64 v_uint64;
- gint64 v_int64;
- guint32 obj_type;
- GObject *obj;
-
- dbus_message_iter_recurse (&array_iter, &inner_struct_iter);
-
- if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING)
- goto error;
-
- dbus_message_iter_get_basic (&inner_struct_iter, &attribute);
- dbus_message_iter_next (&inner_struct_iter);
-
- if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT)
- goto error;
-
- dbus_message_iter_recurse (&inner_struct_iter, &variant_iter);
-
- switch (dbus_message_iter_get_arg_type (&variant_iter))
- {
- case DBUS_TYPE_STRING:
- dbus_message_iter_get_basic (&variant_iter, &str);
- g_file_info_set_attribute_string (info, attribute, str);
- break;
- case DBUS_TYPE_ARRAY:
- if (dbus_message_iter_get_element_type (&variant_iter) != DBUS_TYPE_BYTE)
- goto error;
-
- dbus_message_iter_recurse (&variant_iter, &cstring_iter);
- dbus_message_iter_get_fixed_array (&cstring_iter,
- &str, &n_elements);
- str = g_strndup (str, n_elements);
- g_file_info_set_attribute_byte_string (info, attribute, str);
- g_free (str);
- break;
- case DBUS_TYPE_UINT32:
- dbus_message_iter_get_basic (&variant_iter, &v_uint32);
- g_file_info_set_attribute_uint32 (info, attribute, v_uint32);
- break;
- case DBUS_TYPE_INT32:
- dbus_message_iter_get_basic (&variant_iter, &v_int32);
- g_file_info_set_attribute_int32 (info, attribute, v_int32);
- break;
- case DBUS_TYPE_UINT64:
- dbus_message_iter_get_basic (&variant_iter, &v_uint64);
- g_file_info_set_attribute_uint64 (info, attribute, v_uint64);
- break;
- case DBUS_TYPE_INT64:
- dbus_message_iter_get_basic (&variant_iter, &v_int64);
- g_file_info_set_attribute_int64 (info, attribute, v_int64);
- break;
- case DBUS_TYPE_STRUCT:
- dbus_message_iter_recurse (&variant_iter, &obj_iter);
- if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32)
- goto error;
-
- dbus_message_iter_get_basic (&obj_iter, &obj_type);
- obj = NULL;
- /* 0 == NULL */
- if (obj_type == 1)
- {
- /* G_THEMED_ICON */
- if (_g_dbus_message_iter_get_args (&obj_iter,
- NULL,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
- &strs, &n_elements, 0))
- {
- obj = G_OBJECT (g_themed_icon_new_from_names (strs, -1));
- dbus_free_string_array (strs);
- }
- }
- else if (obj_type == 2)
- {
- /* G_FILE_ICON, w/ local file */
- if (_g_dbus_message_iter_get_args (&obj_iter,
- NULL,
- G_DBUS_TYPE_CSTRING, &str,
- 0))
- {
- GFile *file = g_file_get_for_path (str);
- obj = G_OBJECT (g_file_icon_new (file));
- g_free (str);
- }
- }
- else
- {
- /* NULL (or unsupported) */
- if (obj_type != 0)
- g_warning ("Unsupported object type in file attribute");
- }
-
- g_file_info_set_attribute_object (info, attribute, obj);
-
- if (obj)
- g_object_unref (obj);
-
- break;
- default:
- goto error;
- }
-
- dbus_message_iter_next (&array_iter);
- }
-
- dbus_message_iter_next (iter);
- return info;
-
- error:
- g_object_unref (info);
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Invalid file info format"));
- return NULL;
-}
diff --git a/common/gvfsdaemonprotocol.c b/common/gvfsdaemonprotocol.c
index b52790d6..29663534 100644
--- a/common/gvfsdaemonprotocol.c
+++ b/common/gvfsdaemonprotocol.c
@@ -1,5 +1,8 @@
+#include <config.h>
+
#include <glib-object.h>
#include <dbus/dbus.h>
+#include <glib/gi18n-lib.h>
#include <gvfsdaemonprotocol.h>
#include <gdbusutils.h>
#include <gio/gthemedicon.h>
@@ -7,7 +10,7 @@
#include <gio/glocalfile.h>
gchar *
-g_dbus_type_from_file_attribute_type (GFileAttributeType type)
+_g_dbus_type_from_file_attribute_type (GFileAttributeType type)
{
char *dbus_type;
@@ -49,16 +52,12 @@ append_file_attribute (DBusMessageIter *iter,
GFileAttributeType type,
gconstpointer value)
{
- DBusMessageIter struct_iter, variant_iter, array_iter, inner_struct_iter, obj_struct_iter;
+ DBusMessageIter variant_iter, inner_struct_iter, obj_struct_iter;
char *dbus_type;
guint32 v_uint32;
- gint32 v_int32;
- guint64 v_uint64;
- gint64 v_int64;
- const char *str = NULL;
GObject *obj = NULL;
- dbus_type = g_dbus_type_from_file_attribute_type (type);
+ dbus_type = _g_dbus_type_from_file_attribute_type (type);
if (!dbus_message_iter_open_container (iter,
DBUS_TYPE_STRUCT,
@@ -72,7 +71,6 @@ append_file_attribute (DBusMessageIter *iter,
&attribute))
_g_dbus_oom ();
-
if (!dbus_message_iter_open_container (&inner_struct_iter,
DBUS_TYPE_VARIANT,
dbus_type,
@@ -196,17 +194,17 @@ append_file_attribute (DBusMessageIter *iter,
}
void
-g_dbus_append_file_attribute (DBusMessageIter *iter,
- const char *attribute,
- GFileAttributeType type,
- gconstpointer value)
+_g_dbus_append_file_attribute (DBusMessageIter *iter,
+ const char *attribute,
+ GFileAttributeType type,
+ gconstpointer value)
{
append_file_attribute (iter, attribute, type, value);
}
void
-g_dbus_append_file_info (DBusMessageIter *iter,
- GFileInfo *info)
+_g_dbus_append_file_info (DBusMessageIter *iter,
+ GFileInfo *info)
{
DBusMessageIter struct_iter, array_iter;
char **attributes;
@@ -298,3 +296,189 @@ g_dbus_append_file_info (DBusMessageIter *iter,
if (!dbus_message_iter_close_container (iter, &struct_iter))
_g_dbus_oom ();
}
+
+gboolean
+_g_dbus_get_file_attribute (DBusMessageIter *iter,
+ gchar **attribute,
+ GFileAttributeType *type,
+ GFileAttributeValue *value)
+{
+ char *str;
+ char **strs;
+ int n_elements;
+ DBusMessageIter inner_struct_iter, variant_iter, cstring_iter, obj_iter;
+ const gchar *attribute_temp;
+
+ dbus_message_iter_recurse (iter, &inner_struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING)
+ goto error;
+
+ dbus_message_iter_get_basic (&inner_struct_iter, &attribute_temp);
+ *attribute = g_strdup (attribute_temp);
+
+ dbus_message_iter_next (&inner_struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT)
+ goto error;
+
+ dbus_message_iter_recurse (&inner_struct_iter, &variant_iter);
+
+ switch (dbus_message_iter_get_arg_type (&variant_iter))
+ {
+ case DBUS_TYPE_STRING:
+ dbus_message_iter_get_basic (&variant_iter, &value->v.v_str);
+ *type = G_FILE_ATTRIBUTE_TYPE_STRING;
+ break;
+ case DBUS_TYPE_ARRAY:
+ if (dbus_message_iter_get_element_type (&variant_iter) != DBUS_TYPE_BYTE)
+ goto error;
+
+ *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
+
+ dbus_message_iter_recurse (&variant_iter, &cstring_iter);
+ dbus_message_iter_get_fixed_array (&cstring_iter,
+ &str, &n_elements);
+ value->v.v_str = g_strndup (str, n_elements);
+ break;
+ case DBUS_TYPE_UINT32:
+ dbus_message_iter_get_basic (&variant_iter, &value->v.v_uint32);
+ *type = G_FILE_ATTRIBUTE_TYPE_UINT32;
+ break;
+ case DBUS_TYPE_INT32:
+ dbus_message_iter_get_basic (&variant_iter, &value->v.v_int32);
+ *type = G_FILE_ATTRIBUTE_TYPE_INT32;
+ break;
+ case DBUS_TYPE_UINT64:
+ dbus_message_iter_get_basic (&variant_iter, &value->v.v_uint64);
+ *type = G_FILE_ATTRIBUTE_TYPE_UINT64;
+ break;
+ case DBUS_TYPE_INT64:
+ dbus_message_iter_get_basic (&variant_iter, &value->v.v_int64);
+ *type = G_FILE_ATTRIBUTE_TYPE_INT64;
+ break;
+ case DBUS_TYPE_STRUCT:
+ dbus_message_iter_recurse (&variant_iter, &obj_iter);
+ if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32)
+ goto error;
+
+ *type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
+
+ dbus_message_iter_get_basic (&obj_iter, &value->obj_type);
+ value->v.v_obj = NULL;
+ /* 0 == NULL */
+ if (value->obj_type == 1)
+ {
+ /* G_THEMED_ICON */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
+ &strs, &n_elements, 0))
+ {
+ value->v.v_obj = G_OBJECT (g_themed_icon_new_from_names (strs, -1));
+ dbus_free_string_array (strs);
+ }
+ }
+ else if (value->obj_type == 2)
+ {
+ /* G_FILE_ICON, w/ local file */
+ if (_g_dbus_message_iter_get_args (&obj_iter,
+ NULL,
+ G_DBUS_TYPE_CSTRING, &str,
+ 0))
+ {
+ GFile *file = g_file_get_for_path (str);
+ value->v.v_obj = G_OBJECT (g_file_icon_new (file));
+ g_free (str);
+ }
+ }
+ else
+ {
+ /* NULL (or unsupported) */
+ if (value->obj_type != 0)
+ g_warning ("Unsupported object type in file attribute");
+ }
+ break;
+ default:
+ goto error;
+ }
+
+ return TRUE;
+
+ error:
+ return FALSE;
+}
+
+GFileInfo *
+_g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error)
+{
+ GFileInfo *info;
+ DBusMessageIter struct_iter, array_iter;
+ gchar *attribute;
+
+ info = g_file_info_new ();
+
+ if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+ goto error;
+
+ dbus_message_iter_recurse (iter, &struct_iter);
+
+ if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY)
+ goto error;
+
+ dbus_message_iter_recurse (&struct_iter, &array_iter);
+
+ while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+ {
+ GFileAttributeType type;
+ GFileAttributeValue value;
+
+ if (!_g_dbus_get_file_attribute (&array_iter, &attribute, &type, &value))
+ goto error;
+
+ switch (type)
+ {
+ case G_FILE_ATTRIBUTE_TYPE_STRING:
+ g_file_info_set_attribute_string (info, attribute, value.v.v_str);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
+ g_file_info_set_attribute_byte_string (info, attribute, value.v.v_str);
+ g_free (value.v.v_str);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT32:
+ g_file_info_set_attribute_uint32 (info, attribute, value.v.v_uint32);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT32:
+ g_file_info_set_attribute_int32 (info, attribute, value.v.v_int32);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_UINT64:
+ g_file_info_set_attribute_uint64 (info, attribute, value.v.v_uint64);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_INT64:
+ g_file_info_set_attribute_int64 (info, attribute, value.v.v_int64);
+ break;
+ case G_FILE_ATTRIBUTE_TYPE_OBJECT:
+ g_file_info_set_attribute_object (info, attribute, value.v.v_obj);
+ if (value.v.v_obj)
+ g_object_unref (value.v.v_obj);
+ break;
+ default:
+ g_assert_not_reached ();
+ continue;
+ }
+
+ g_free (attribute);
+
+ dbus_message_iter_next (&array_iter);
+ }
+
+ dbus_message_iter_next (iter);
+ return info;
+
+ error:
+ g_object_unref (info);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ _("Invalid file info format"));
+ return NULL;
+}
diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h
index 5d39dd36..b4d65dcf 100644
--- a/common/gvfsdaemonprotocol.h
+++ b/common/gvfsdaemonprotocol.h
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
#define G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY "MakeDirectory"
#define G_VFS_DBUS_MOUNT_OP_COPY "Copy"
#define G_VFS_DBUS_MOUNT_OP_MOVE "Move"
+#define G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE "SetAttribute"
/* Progress callback interface for copy and move */
#define G_VFS_DBUS_PROGRESS_INTERFACE "org.gtk.vfs.Progress"
@@ -72,6 +73,23 @@ G_BEGIN_DECLS
/* Normal ops are faster, one minute timeout */
#define G_VFS_DBUS_TIMEOUT_MSECS (1000*60)
+typedef struct
+{
+ union
+ {
+ guint32 v_uint32;
+ gint32 v_int32;
+ guint64 v_uint64;
+ gint64 v_int64;
+ gchar *v_str;
+ GObject *v_obj;
+ }
+ v;
+
+ guint32 obj_type;
+}
+GFileAttributeValue;
+
typedef struct {
guint32 command;
guint32 seq_nr;
@@ -129,14 +147,19 @@ typedef struct {
DBUS_STRUCT_END_CHAR_AS_STRING
-char *g_dbus_get_file_info_signature (void);
-gchar *g_dbus_type_from_file_attribute_type (GFileAttributeType type);
-void g_dbus_append_file_attribute (DBusMessageIter *iter,
- const char *attribute,
- GFileAttributeType type,
- gconstpointer value);
-void g_dbus_append_file_info (DBusMessageIter *iter,
- GFileInfo *file_info);
+gchar *_g_dbus_type_from_file_attribute_type (GFileAttributeType type);
+void _g_dbus_append_file_attribute (DBusMessageIter *iter,
+ const char *attribute,
+ GFileAttributeType type,
+ gconstpointer value);
+void _g_dbus_append_file_info (DBusMessageIter *iter,
+ GFileInfo *file_info);
+gboolean _g_dbus_get_file_attribute (DBusMessageIter *iter,
+ gchar **attribute,
+ GFileAttributeType *type,
+ GFileAttributeValue *value);
+GFileInfo *_g_dbus_get_file_info (DBusMessageIter *iter,
+ GError **error);
G_END_DECLS
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 7e01b13b..c7452bf1 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -77,6 +77,7 @@ libdaemon_la_SOURCES = \
gvfsjobcopy.c gvfsjobcopy.h \
gvfsjobmove.c gvfsjobmove.h \
gvfsjobmakedirectory.c gvfsjobmakedirectory.h \
+ gvfsjobsetattribute.c gvfsjobsetattribute.h \
dbus-gmain.h dbus-gmain.c \
$(NULL)
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
index 49131e5d..55a2d82f 100644
--- a/daemon/gvfsbackend.c
+++ b/daemon/gvfsbackend.c
@@ -24,6 +24,7 @@
#include <gvfsjobmakedirectory.h>
#include <gvfsjobcopy.h>
#include <gvfsjobmove.h>
+#include <gvfsjobsetattribute.h>
#include <gdbusutils.h>
enum {
@@ -311,6 +312,10 @@ backend_dbus_handler (DBusConnection *connection,
G_VFS_DBUS_MOUNT_INTERFACE,
G_VFS_DBUS_MOUNT_OP_MOVE))
job = g_vfs_job_move_new (connection, message, backend);
+ else if (dbus_message_is_method_call (message,
+ G_VFS_DBUS_MOUNT_INTERFACE,
+ G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE))
+ job = g_vfs_job_set_attribute_new (connection, message, backend);
if (job)
{
diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h
index e4b99f68..cc0aece0 100644
--- a/daemon/gvfsbackend.h
+++ b/daemon/gvfsbackend.h
@@ -42,6 +42,7 @@ typedef struct _GVfsJobDelete GVfsJobDelete;
typedef struct _GVfsJobMakeDirectory GVfsJobMakeDirectory;
typedef struct _GVfsJobCopy GVfsJobCopy;
typedef struct _GVfsJobMove GVfsJobMove;
+typedef struct _GVfsJobSetAttribute GVfsJobSetAttribute;
typedef gpointer GVfsBackendHandle;
@@ -213,10 +214,10 @@ struct _GVfsBackendClass
GVfsJobTrash *job,
const char *filename);
void (*make_directory) (GVfsBackend *backend,
- GVfsJobMakeDirectory *make_directory,
+ GVfsJobMakeDirectory *job,
const char *filename);
gboolean (*try_make_directory)(GVfsBackend *backend,
- GVfsJobMakeDirectory *make_directory,
+ GVfsJobMakeDirectory *job,
const char *filename);
void (*copy) (GVfsBackend *backend,
GVfsJobCopy *job,
@@ -246,6 +247,20 @@ struct _GVfsBackendClass
GFileCopyFlags flags,
GFileProgressCallback progress_callback,
gpointer progress_callback_data);
+ void (*set_attribute) (GVfsBackend *backend,
+ GVfsJobSetAttribute *set_attribute,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gconstpointer value_ptr,
+ GFileGetInfoFlags flags);
+ gboolean (*try_set_attribute) (GVfsBackend *backend,
+ GVfsJobSetAttribute *set_attribute,
+ const char *filename,
+ const char *attribute,
+ GFileAttributeType type,
+ gconstpointer value_ptr,
+ GFileGetInfoFlags flags);
};
GType g_vfs_backend_get_type (void) G_GNUC_CONST;
diff --git a/daemon/gvfsjobenumerate.c b/daemon/gvfsjobenumerate.c
index c36bd798..b29d9fd1 100644
--- a/daemon/gvfsjobenumerate.c
+++ b/daemon/gvfsjobenumerate.c
@@ -130,8 +130,8 @@ g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job,
num = 0;
while (infos != NULL)
{
- g_dbus_append_file_info (&array_iter,
- infos->data);
+ _g_dbus_append_file_info (&array_iter,
+ infos->data);
infos = infos->next;
if (++num > 100)
break;
diff --git a/daemon/gvfsjobgetfsinfo.c b/daemon/gvfsjobgetfsinfo.c
index 9cb17d7e..ae1c80dd 100644
--- a/daemon/gvfsjobgetfsinfo.c
+++ b/daemon/gvfsjobgetfsinfo.c
@@ -150,8 +150,8 @@ create_reply (GVfsJob *job,
dbus_message_iter_init_append (reply, &iter);
- g_dbus_append_file_info (&iter,
- op_job->file_info);
+ _g_dbus_append_file_info (&iter,
+ op_job->file_info);
return reply;
}
diff --git a/daemon/gvfsjobgetinfo.c b/daemon/gvfsjobgetinfo.c
index 1f935de7..94d0ef87 100644
--- a/daemon/gvfsjobgetinfo.c
+++ b/daemon/gvfsjobgetinfo.c
@@ -156,7 +156,7 @@ create_reply (GVfsJob *job,
dbus_message_iter_init_append (reply, &iter);
- g_dbus_append_file_info (&iter,
+ _g_dbus_append_file_info (&iter,
op_job->file_info);
return reply;
diff --git a/daemon/gvfsjobsetattribute.c b/daemon/gvfsjobsetattribute.c
new file mode 100644
index 00000000..52e22a84
--- /dev/null
+++ b/daemon/gvfsjobsetattribute.c
@@ -0,0 +1,171 @@
+#include <config.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <glib/gi18n.h>
+#include "gvfsjobmove.h"
+#include "gdbusutils.h"
+#include "gvfsdaemonprotocol.h"
+#include "gvfsjobsetattribute.h"
+
+G_DEFINE_TYPE (GVfsJobSetAttribute, g_vfs_job_set_attribute, G_VFS_TYPE_JOB_DBUS);
+
+static void run (GVfsJob *job);
+static gboolean try (GVfsJob *job);
+static DBusMessage *create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message);
+
+static void
+g_vfs_job_set_attribute_finalize (GObject *object)
+{
+ GVfsJobSetAttribute *job;
+
+ job = G_VFS_JOB_SET_ATTRIBUTE (object);
+
+ g_free (job->filename);
+ g_free (job->attribute);
+
+ if (G_OBJECT_CLASS (g_vfs_job_set_attribute_parent_class)->finalize)
+ (*G_OBJECT_CLASS (g_vfs_job_set_attribute_parent_class)->finalize) (object);
+}
+
+static void
+g_vfs_job_set_attribute_class_init (GVfsJobSetAttributeClass *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->finalize = g_vfs_job_set_attribute_finalize;
+ job_class->run = run;
+ job_class->try = try;
+ job_dbus_class->create_reply = create_reply;
+}
+
+static void
+g_vfs_job_set_attribute_init (GVfsJobSetAttribute *job)
+{
+}
+
+GVfsJob *
+g_vfs_job_set_attribute_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend)
+{
+ GVfsJobSetAttribute *job;
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ DBusError derror;
+ const gchar *filename = NULL;
+ gint filename_len;
+ GFileAttributeType type;
+ GFileAttributeValue value;
+ GFileGetInfoFlags flags;
+ gchar *attribute;
+ dbus_uint32_t flags_u32 = 0;
+
+ dbus_error_init (&derror);
+
+ dbus_message_iter_init (message, &iter);
+
+ if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY &&
+ dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_BYTE)
+ {
+ dbus_message_iter_recurse (&iter, &array_iter);
+ dbus_message_iter_get_fixed_array (&array_iter, &filename, &filename_len);
+ }
+
+ dbus_message_iter_next (&iter);
+
+ if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32)
+ {
+ dbus_message_iter_get_basic (&iter, &flags_u32);
+ dbus_message_iter_next (&iter);
+ }
+
+ flags = flags_u32;
+
+ if (!(filename && _g_dbus_get_file_attribute (&iter, &attribute, &type, &value)))
+ {
+ reply = dbus_message_new_error (message,
+ DBUS_ERROR_FAILED,
+ _("Failed to demarshal message"));
+ dbus_error_free (&derror);
+
+ dbus_connection_send (connection, reply, NULL);
+ return NULL;
+ }
+
+ job = g_object_new (G_VFS_TYPE_JOB_SET_ATTRIBUTE,
+ "message", message,
+ "connection", connection,
+ NULL);
+
+ job->backend = backend;
+ job->filename = g_strndup (filename, filename_len);
+ job->attribute = attribute;
+ job->type = type;
+ job->value = value;
+ job->flags = flags;
+
+ return G_VFS_JOB (job);
+}
+
+static void
+run (GVfsJob *job)
+{
+ GVfsJobSetAttribute *op_job = G_VFS_JOB_SET_ATTRIBUTE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->set_attribute == NULL)
+ {
+ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Operation not supported by backend"));
+ return;
+ }
+
+ class->set_attribute (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->attribute,
+ op_job->type,
+ &op_job->value,
+ op_job->flags);
+}
+
+static gboolean
+try (GVfsJob *job)
+{
+ GVfsJobSetAttribute *op_job = G_VFS_JOB_SET_ATTRIBUTE (job);
+ GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
+
+ if (class->try_set_attribute == NULL)
+ return FALSE;
+
+ return class->try_set_attribute (op_job->backend,
+ op_job,
+ op_job->filename,
+ op_job->attribute,
+ op_job->type,
+ &op_job->value,
+ op_job->flags);
+}
+
+/* Might be called on an i/o thread */
+static DBusMessage *
+create_reply (GVfsJob *job,
+ DBusConnection *connection,
+ DBusMessage *message)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return (message);
+
+ return reply;
+}
diff --git a/daemon/gvfsjobsetattribute.h b/daemon/gvfsjobsetattribute.h
new file mode 100644
index 00000000..ad0e9d58
--- /dev/null
+++ b/daemon/gvfsjobsetattribute.h
@@ -0,0 +1,46 @@
+#ifndef __G_VFS_JOB_SET_ATTRIBUTE_H__
+#define __G_VFS_JOB_SET_ATTRIBUTE_H__
+
+#include <gio/gfileinfo.h>
+#include <gvfsjob.h>
+#include <gvfsjobdbus.h>
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_JOB_SET_ATTRIBUTE (g_vfs_job_set_attribute_get_type ())
+#define G_VFS_JOB_SET_ATTRIBUTE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTE, GVfsJobSetAttribute))
+#define G_VFS_JOB_SET_ATTRIBUTE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_VFS_TYPE_JOB_SET_ATTRIBUTE, GVfsJobSetAttributeClass))
+#define G_VFS_IS_JOB_SET_ATTRIBUTE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTE))
+#define G_VFS_IS_JOB_SET_ATTRIBUTE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_VFS_TYPE_JOB_SET_ATTRIBUTE))
+#define G_VFS_JOB_SET_ATTRIBUTE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_VFS_TYPE_JOB_SET_ATTRIBUTE, GVfsJobSetAttributeClass))
+
+typedef struct _GVfsJobSetAttributeClass GVfsJobSetAttributeClass;
+
+struct _GVfsJobSetAttribute
+{
+ GVfsJobDBus parent_instance;
+
+ GVfsBackend *backend;
+
+ char *filename;
+ char *attribute;
+ GFileAttributeType type;
+ GFileAttributeValue value;
+ GFileGetInfoFlags flags;
+};
+
+struct _GVfsJobSetAttributeClass
+{
+ GVfsJobDBusClass parent_class;
+};
+
+GType g_vfs_job_set_attribute_get_type (void) G_GNUC_CONST;
+
+GVfsJob *g_vfs_job_set_attribute_new (DBusConnection *connection,
+ DBusMessage *message,
+ GVfsBackend *backend);
+
+G_END_DECLS
+
+#endif /* __G_VFS_JOB_SET_ATTRIBUTE_H__ */