diff options
36 files changed, 1627 insertions, 1257 deletions
diff --git a/client/gfiledaemon.c b/client/gfiledaemon.c index e19581d7..18648128 100644 --- a/client/gfiledaemon.c +++ b/client/gfiledaemon.c @@ -370,16 +370,13 @@ do_async_path_call (GFile *file, static GFileEnumerator * g_file_daemon_enumerate_children (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { DBusMessage *reply; - guint32 requested_32; - dbus_bool_t follow_symlinks_dbus; - DBusMessageIter iter; + dbus_uint32_t flags_dbus; char *obj_path; GFileEnumeratorDaemon *enumerator; DBusConnection *connection; @@ -387,17 +384,15 @@ g_file_daemon_enumerate_children (GFile *file, enumerator = g_file_enumerator_daemon_new (); obj_path = g_file_enumerator_daemon_get_object_path (enumerator); - requested_32 = (guint32)requested; if (attributes == NULL) attributes = ""; - follow_symlinks_dbus = follow_symlinks; + flags_dbus = flags; reply = do_sync_path_call (file, G_VFS_DBUS_OP_ENUMERATE, &connection, cancellable, error, DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_UINT32, &requested_32, DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_BOOLEAN, &follow_symlinks_dbus, + DBUS_TYPE_UINT32, &flags_dbus, 0); g_free (obj_path); @@ -405,19 +400,9 @@ g_file_daemon_enumerate_children (GFile *file, if (reply == NULL) goto error; - if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)) - { - g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO, - _("Invalid return value from Enumerate")); - goto error; - } - - dbus_message_iter_get_basic (&iter, &requested_32); dbus_message_unref (reply); g_file_enumerator_daemon_set_sync_connection (enumerator, connection); - g_file_enumerator_daemon_set_request_flags (enumerator, requested_32); return G_FILE_ENUMERATOR (enumerator); @@ -430,28 +415,24 @@ g_file_daemon_enumerate_children (GFile *file, static GFileInfo * g_file_daemon_get_info (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { DBusMessage *reply; - guint32 requested_32; - dbus_bool_t follow_symlinks_dbus; + dbus_uint32_t flags_dbus; DBusMessageIter iter; GFileInfo *info; - requested_32 = (guint32)requested; if (attributes == NULL) attributes = ""; - follow_symlinks_dbus = follow_symlinks; + flags_dbus = flags; reply = do_sync_path_call (file, G_VFS_DBUS_OP_GET_INFO, NULL, cancellable, error, - DBUS_TYPE_UINT32, &requested_32, DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_BOOLEAN, &follow_symlinks_dbus, + DBUS_TYPE_UINT32, &flags, 0); if (reply == NULL) return NULL; @@ -459,19 +440,14 @@ g_file_daemon_get_info (GFile *file, info = NULL; if (!dbus_message_iter_init (reply, &iter) || - (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)) + (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT)) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_IO, _("Invalid return value from get_info")); goto out; } - dbus_message_iter_get_basic (&iter, &requested_32); - - if (!dbus_message_iter_next (&iter)) - goto out; - - info = _g_dbus_get_file_info (&iter, requested_32, error); + info = _g_dbus_get_file_info (&iter, error); out: dbus_message_unref (reply); diff --git a/client/gfiledaemonlocal.c b/client/gfiledaemonlocal.c index 79152e02..d4cd5ebe 100644 --- a/client/gfiledaemonlocal.c +++ b/client/gfiledaemonlocal.c @@ -114,27 +114,25 @@ g_file_daemon_local_get_child (GFile *file, static GFileEnumerator * g_file_daemon_local_enumerate_children (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { return g_file_enumerate_children (G_FILE_DAEMON_LOCAL (file)->wrapped, - requested, attributes, follow_symlinks, + attributes, flags, cancellable, error); } static GFileInfo * g_file_daemon_local_get_info (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { return g_file_get_info (G_FILE_DAEMON_LOCAL (file)->wrapped, - requested, attributes, follow_symlinks, + attributes, flags, cancellable, error); } diff --git a/client/gfileenumeratordaemon.c b/client/gfileenumeratordaemon.c index 277b106e..b7505a73 100644 --- a/client/gfileenumeratordaemon.c +++ b/client/gfileenumeratordaemon.c @@ -22,7 +22,6 @@ struct _GFileEnumeratorDaemon gint id; DBusConnection *sync_connection; - GFileInfoRequestFlags request_flags; /* protected by infos lock */ GList *infos; @@ -131,7 +130,7 @@ g_file_enumerator_daemon_dbus_filter (DBusConnection *connection, while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) { - info = _g_dbus_get_file_info (&array_iter, enumerator->request_flags, NULL); + info = _g_dbus_get_file_info (&array_iter, NULL); if (info) g_assert (G_IS_FILE_INFO (info)); @@ -165,13 +164,6 @@ g_file_enumerator_daemon_set_sync_connection (GFileEnumeratorDaemon *enumerator, enumerator->sync_connection = dbus_connection_ref (connection); } -void -g_file_enumerator_daemon_set_request_flags (GFileEnumeratorDaemon *enumerator, - GFileInfoRequestFlags flags) -{ - enumerator->request_flags = flags; -} - static GFileInfo * g_file_enumerator_daemon_next_file (GFileEnumerator *enumerator, GCancellable *cancellable, diff --git a/client/gfileenumeratordaemon.h b/client/gfileenumeratordaemon.h index 759f56e9..bdaeaee6 100644 --- a/client/gfileenumeratordaemon.h +++ b/client/gfileenumeratordaemon.h @@ -29,8 +29,6 @@ GFileEnumeratorDaemon *g_file_enumerator_daemon_new (void); char * g_file_enumerator_daemon_get_object_path (GFileEnumeratorDaemon *enumerator); void g_file_enumerator_daemon_set_sync_connection (GFileEnumeratorDaemon *enumerator, DBusConnection *connection); -void g_file_enumerator_daemon_set_request_flags (GFileEnumeratorDaemon *enumerator, - GFileInfoRequestFlags flags); G_END_DECLS diff --git a/client/gfileinputstreamdaemon.c b/client/gfileinputstreamdaemon.c index d336da4f..89805758 100644 --- a/client/gfileinputstreamdaemon.c +++ b/client/gfileinputstreamdaemon.c @@ -156,7 +156,6 @@ static gboolean g_file_input_stream_daemon_close (GInputStream GCancellable *cancellable, GError **error); static GFileInfo *g_file_input_stream_daemon_get_file_info (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); @@ -1180,7 +1179,6 @@ g_file_input_stream_daemon_seek (GFileInputStream *stream, static GFileInfo * g_file_input_stream_daemon_get_file_info (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error) diff --git a/client/gfileoutputstreamdaemon.c b/client/gfileoutputstreamdaemon.c index 9e5c51c5..a1ea91c4 100644 --- a/client/gfileoutputstreamdaemon.c +++ b/client/gfileoutputstreamdaemon.c @@ -136,7 +136,6 @@ static gboolean g_file_output_stream_daemon_close (GOutputStream GCancellable *cancellable, GError **error); static GFileInfo *g_file_output_stream_daemon_get_file_info (GFileOutputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); @@ -936,10 +935,9 @@ g_file_output_stream_daemon_seek (GFileOutputStream *stream, static GFileInfo * g_file_output_stream_daemon_get_file_info (GFileOutputStream *stream, - GFileInfoRequestFlags requested, - char *attributes, - GCancellable *cancellable, - GError **error) + char *attributes, + GCancellable *cancellable, + GError **error) { GFileOutputStreamDaemon *file; diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c index bdeabad2..64041f12 100644 --- a/client/gvfsdaemondbus.c +++ b/client/gvfsdaemondbus.c @@ -901,11 +901,11 @@ _g_dbus_connection_get_sync (const char *dbus_id, GFileInfo * _g_dbus_get_file_info (DBusMessageIter *iter, - GFileInfoRequestFlags requested, GError **error) { GFileInfo *info; - DBusMessageIter struct_iter, array_iter; + DBusMessageIter struct_iter, array_iter, inner_struct_iter, variant_iter, cstring_iter; + const char *attribute; info = g_file_info_new (); @@ -914,177 +914,73 @@ _g_dbus_get_file_info (DBusMessageIter *iter, dbus_message_iter_recurse (iter, &struct_iter); - if (requested & G_FILE_INFO_FILE_TYPE) - { - guint16 type; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_UINT16) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &type); - - g_file_info_set_file_type (info, type); - - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_NAME) - { - char *str; - const char *data; - int len; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type (&struct_iter) != DBUS_TYPE_BYTE) - goto error; - - dbus_message_iter_recurse (&struct_iter, &array_iter); - dbus_message_iter_get_fixed_array (&array_iter, &data, &len); - str = g_strndup (data, len); - g_file_info_set_name (info, str); - g_free (str); - - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_DISPLAY_NAME) - { - const char *str; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_STRING) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &str); - - g_file_info_set_display_name (info, str); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_EDIT_NAME) - { - const char *str; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_STRING) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &str); - - g_file_info_set_edit_name (info, str); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_ICON) - { - const char *str; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_STRING) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &str); - - g_file_info_set_icon (info, str); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_MIME_TYPE) - { - const char *str; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_STRING) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &str); - - g_file_info_set_mime_type (info, str); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_SIZE) - { - guint64 size; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_UINT64) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &size); - - g_file_info_set_size (info, size); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_MODIFICATION_TIME) - { - guint64 time; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_UINT64) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &time); - - g_file_info_set_modification_time (info, time); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_ACCESS_RIGHTS) - { - guint32 rights; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_UINT32) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &rights); - - g_file_info_set_access_rights (info, rights); - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_STAT_INFO) - { - guint32 tmp; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_UINT32) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &tmp); - - /* TODO: implement statinfo */ - dbus_message_iter_next (&struct_iter); - } + if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY) + goto error; + + dbus_message_iter_recurse (&struct_iter, &array_iter); - if (requested & G_FILE_INFO_SYMLINK_TARGET) + while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT) { char *str; - const char *data; - int len; - - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type (&struct_iter) != DBUS_TYPE_BYTE) - goto error; - - dbus_message_iter_recurse (&struct_iter, &array_iter); - dbus_message_iter_get_fixed_array (&array_iter, &data, &len); - str = g_strndup (data, len); - g_file_info_set_symlink_target (info, str); - g_free (str); - - dbus_message_iter_next (&struct_iter); - } - - if (requested & G_FILE_INFO_IS_HIDDEN) - { - dbus_bool_t is_hidden; + int n_elements; + guint32 v_uint32; + gint32 v_int32; + guint64 v_uint64; + gint64 v_int64; - if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_BOOLEAN) - goto error; - - dbus_message_iter_get_basic (&struct_iter, &is_hidden); + dbus_message_iter_recurse (&array_iter, &inner_struct_iter); - g_file_info_set_is_hidden (info, is_hidden); - dbus_message_iter_next (&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; + default: + goto error; + } + + dbus_message_iter_next (&array_iter); } - /* TODO: Attributes */ - dbus_message_iter_next (iter); return info; diff --git a/client/gvfsdaemondbus.h b/client/gvfsdaemondbus.h index 711e8042..2fb82452 100644 --- a/client/gvfsdaemondbus.h +++ b/client/gvfsdaemondbus.h @@ -39,7 +39,6 @@ DBusMessage *_g_vfs_daemon_call_sync (DBusMessage GCancellable *cancellable, GError **error); GFileInfo * _g_dbus_get_file_info (DBusMessageIter *iter, - GFileInfoRequestFlags requested, GError **error); diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h index 24f43cb0..e085e49e 100644 --- a/common/gvfsdaemonprotocol.h +++ b/common/gvfsdaemonprotocol.h @@ -83,9 +83,21 @@ typedef struct { #define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_WRITTEN 3 #define G_VFS_DAEMON_SOCKET_PROTOCOL_REPLY_CLOSED 4 -char *g_dbus_get_file_info_signature (GFileInfoRequestFlags requested); +#define G_FILE_INFO_INNER_TYPE_AS_STRING \ + DBUS_TYPE_ARRAY_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_VARIANT_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + +#define G_FILE_INFO_TYPE_AS_STRING \ + DBUS_STRUCT_BEGIN_CHAR_AS_STRING \ + G_FILE_INFO_INNER_TYPE_AS_STRING \ + DBUS_STRUCT_END_CHAR_AS_STRING + + +char *g_dbus_get_file_info_signature (void); void g_dbus_append_file_info (DBusMessageIter *iter, - GFileInfoRequestFlags requested, GFileInfo *file_info); G_END_DECLS diff --git a/configure.ac b/configure.ac index fec7e588..d63a22e9 100644 --- a/configure.ac +++ b/configure.ac @@ -22,6 +22,16 @@ AC_TYPE_SIGNAL AC_TYPE_SIZE_T AC_TYPE_UID_T +AH_VERBATIM([_GNU_SOURCE], +[/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif]) + +saved_CFLAGS=$CFLAGS +AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec, struct stat.st_atimensec, struct stat.st_atim.tv_nsec, struct stat.st_ctimensec, struct stat.st_ctim.tv_nsec]) +CFLAGS=$saved_CFLAGS + GTK_DOC_CHECK DISTCHECK_CONFIGURE_FLAGS="--enable-gtk-doc" AC_SUBST(DISTCHECK_CONFIGURE_FLAGS) diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h index cd5ab4d1..58a81052 100644 --- a/daemon/gvfsbackend.h +++ b/daemon/gvfsbackend.h @@ -4,6 +4,7 @@ #include <dbus/dbus.h> #include <gio/gvfstypes.h> #include <gio/gfileinfo.h> +#include <gio/gfile.h> #include <gvfsdaemon.h> #include <gvfsjob.h> #include <gmountspec.h> @@ -148,27 +149,23 @@ struct _GVfsBackendClass void (*get_info) (GVfsBackend *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks); + GFileGetInfoFlags flags); gboolean (*try_get_info) (GVfsBackend *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks); + GFileGetInfoFlags flags); void (*enumerate) (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks); + GFileGetInfoFlags flags); gboolean (*try_enumerate) (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks); + GFileGetInfoFlags flags); }; GType g_vfs_backend_get_type (void) G_GNUC_CONST; diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c index 3ead85ec..c94f72ee 100644 --- a/daemon/gvfsbackendsmb.c +++ b/daemon/gvfsbackendsmb.c @@ -1075,15 +1075,73 @@ do_close_write (GVfsBackend *backend, } static void +set_info_from_stat (GFileInfo *info, struct stat *statbuf) +{ + GFileType file_type; + GTimeVal t; + + file_type = G_FILE_TYPE_UNKNOWN; + + if (S_ISREG (statbuf->st_mode)) + file_type = G_FILE_TYPE_REGULAR; + else if (S_ISDIR (statbuf->st_mode)) + file_type = G_FILE_TYPE_DIRECTORY; + else if (S_ISCHR (statbuf->st_mode) || + S_ISBLK (statbuf->st_mode) || + S_ISFIFO (statbuf->st_mode) +#ifdef S_ISSOCK + || S_ISSOCK (statbuf->st_mode) +#endif + ) + file_type = G_FILE_TYPE_SPECIAL; + else if (S_ISLNK (statbuf->st_mode)) + file_type = G_FILE_TYPE_SYMBOLIC_LINK; + + g_file_info_set_file_type (info, file_type); + g_file_info_set_size (info, statbuf->st_size); + + t.tv_sec = statbuf->st_mtime; +#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) + t.tv_usec = statbuf->st_mtimensec / 1000; +#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) + t.tv_usec = statbuf->st_mtim.tv_nsec / 1000; +#else + t.tv_usec = 0; +#endif + g_file_info_set_modification_time (info, &t); + + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE, statbuf->st_dev); + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE, statbuf->st_ino); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, statbuf->st_mode); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_NLINK, statbuf->st_nlink); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, statbuf->st_uid); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, statbuf->st_uid); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV, statbuf->st_rdev); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE, statbuf->st_blksize); + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_BLOCKS, statbuf->st_blocks); + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_ATIME, statbuf->st_atime); +#if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_ATIME_USEC, statbuf->st_atimensec / 1000); +#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_ATIME_USEC, statbuf->st_atim.tv_nsec / 1000); +#endif + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_CTIME, statbuf->st_ctime); +#if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_CTIME_USEC, statbuf->st_ctimensec / 1000); +#elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_CTIME_USEC, statbuf->st_ctim.tv_nsec / 1000); +#endif +} + +static void do_get_info (GVfsBackend *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend); - struct stat st; + struct stat st = {0}; char *uri; int res; GFileInfo *info; @@ -1095,9 +1153,9 @@ do_get_info (GVfsBackend *backend, if (res == 0) { info = g_file_info_new (); - g_file_info_set_from_stat (info, requested, &st); + set_info_from_stat (info, &st); - g_vfs_job_get_info_set_info (job, requested & ~(G_FILE_INFO_DISPLAY_NAME|G_FILE_INFO_EDIT_NAME), info); + g_vfs_job_get_info_set_info (job, info); g_vfs_job_succeeded (G_VFS_JOB (job)); g_object_unref (info); } @@ -1109,9 +1167,8 @@ static void do_enumerate (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend); struct stat st; @@ -1137,8 +1194,6 @@ do_enumerate (GVfsBackend *backend, goto error; } - /* TODO: limit requested to what we support */ - g_vfs_job_enumerate_set_result (job, requested); g_vfs_job_succeeded (G_VFS_JOB (job)); if (uri->str[uri->len - 1] != '/') @@ -1177,10 +1232,9 @@ do_enumerate (GVfsBackend *backend, if (stat_res == 0) { info = g_file_info_new (); - if (requested & G_FILE_INFO_NAME) - g_file_info_set_name (info, dirp->name); + g_file_info_set_name (info, dirp->name); - g_file_info_set_from_stat (info, requested, &st); + set_info_from_stat (info, &st); files = g_list_prepend (files, info); } } diff --git a/daemon/gvfsbackendsmbbrowse.c b/daemon/gvfsbackendsmbbrowse.c index 68efba2f..ab8a493e 100644 --- a/daemon/gvfsbackendsmbbrowse.c +++ b/daemon/gvfsbackendsmbbrowse.c @@ -694,7 +694,6 @@ static void run_get_info (GVfsBackendSmbBrowse *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes) { GFileInfo *info; @@ -710,14 +709,15 @@ run_get_info (GVfsBackendSmbBrowse *backend, info = g_file_info_new (); g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE); g_file_info_set_name (info, entry->name); - g_file_info_set_attribute (info, "smb:comment", entry->comment); + /* TODO: Is this always UTF8? */ + g_file_info_set_attribute_string (info, "smb:comment", entry->comment); } g_mutex_unlock (backend->entries_lock); if (info) { - g_vfs_job_get_info_set_info (job, requested & ~(G_FILE_INFO_DISPLAY_NAME|G_FILE_INFO_EDIT_NAME), info); + g_vfs_job_get_info_set_info (job, info); g_vfs_job_succeeded (G_VFS_JOB (job)); g_object_unref (info); } @@ -733,15 +733,14 @@ static void do_get_info (GVfsBackend *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend); update_cache (op_backend); - run_get_info (op_backend, job, filename, requested, attributes); + run_get_info (op_backend, job, filename, attributes); } @@ -749,9 +748,8 @@ static gboolean try_get_info (GVfsBackend *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend); @@ -760,7 +758,7 @@ try_get_info (GVfsBackend *backend, GFileInfo *info = g_file_info_new (); g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); g_file_info_set_name (info, "/"); - g_vfs_job_get_info_set_info (job, requested & ~(G_FILE_INFO_DISPLAY_NAME|G_FILE_INFO_EDIT_NAME), info); + g_vfs_job_get_info_set_info (job, info); g_vfs_job_succeeded (G_VFS_JOB (job)); g_object_unref (info); @@ -770,7 +768,7 @@ try_get_info (GVfsBackend *backend, if (cache_needs_updating (op_backend)) return FALSE; - run_get_info (op_backend, job, filename, requested, attributes); + run_get_info (op_backend, job, filename, attributes); return TRUE; } @@ -779,7 +777,6 @@ static void run_enumerate (GVfsBackendSmbBrowse *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes) { GList *files, *l; @@ -799,7 +796,6 @@ run_enumerate (GVfsBackendSmbBrowse *backend, } /* TODO: limit requested to what we support */ - g_vfs_job_enumerate_set_result (job, requested); g_vfs_job_succeeded (G_VFS_JOB (job)); files = NULL; @@ -810,9 +806,9 @@ run_enumerate (GVfsBackendSmbBrowse *backend, info = g_file_info_new (); g_file_info_set_file_type (info, G_FILE_TYPE_MOUNTABLE); - if (requested & G_FILE_INFO_NAME) - g_file_info_set_name (info, entry->name); - g_file_info_set_attribute (info, "smb:comment", entry->comment); + g_file_info_set_name (info, entry->name); + /* TODO: Is this always in utf8??? */ + g_file_info_set_attribute_string (info, "smb:comment", entry->comment); files = g_list_prepend (files, info); } @@ -831,31 +827,29 @@ static void do_enumerate (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend); update_cache (op_backend); - run_enumerate (op_backend, job, filename, requested, attributes); + run_enumerate (op_backend, job, filename, attributes); } static gboolean try_enumerate (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GVfsBackendSmbBrowse *op_backend = G_VFS_BACKEND_SMB_BROWSE (backend); if (cache_needs_updating (op_backend)) return FALSE; - run_enumerate (op_backend, job, filename, requested, attributes); + run_enumerate (op_backend, job, filename, attributes); return TRUE; } diff --git a/daemon/gvfsbackendtest.c b/daemon/gvfsbackendtest.c index a6088736..a8df65ed 100644 --- a/daemon/gvfsbackendtest.c +++ b/daemon/gvfsbackendtest.c @@ -245,9 +245,8 @@ static void do_get_info (GVfsBackend *backend, GVfsJobGetInfo *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GFile *file; GFileInfo *info; @@ -258,12 +257,12 @@ do_get_info (GVfsBackend *backend, file = g_file_local_new (filename); error = NULL; - info = g_file_get_info (file, requested, attributes, follow_symlinks, + info = g_file_get_info (file, attributes, flags, NULL, &error); if (info) { - g_vfs_job_get_info_set_info (job, requested, info); + g_vfs_job_get_info_set_info (job, info); g_vfs_job_succeeded (G_VFS_JOB (job)); } else @@ -277,16 +276,14 @@ static gboolean try_enumerate (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks) + GFileGetInfoFlags flags) { GFileInfo *info1, *info2;; GList *l; g_print ("try_enumerate (%s)\n", filename); - g_vfs_job_enumerate_set_result (job, requested); g_vfs_job_succeeded (G_VFS_JOB (job)); info1 = g_file_info_new (); diff --git a/daemon/gvfsdaemonprotocol.c b/daemon/gvfsdaemonprotocol.c index 3058b670..e1b24c3b 100644 --- a/daemon/gvfsdaemonprotocol.c +++ b/daemon/gvfsdaemonprotocol.c @@ -3,207 +3,122 @@ #include <gvfsdaemonprotocol.h> #include <gdbusutils.h> -char * -g_dbus_get_file_info_signature (GFileInfoRequestFlags requested) -{ - GString *str; - - str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING); - - - if (requested & G_FILE_INFO_FILE_TYPE) - { - g_string_append_c (str, DBUS_TYPE_UINT16); - } - - if (requested & G_FILE_INFO_NAME) - { - g_string_append (str, DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING); - } - - if (requested & G_FILE_INFO_DISPLAY_NAME) - { - g_string_append_c (str, DBUS_TYPE_STRING); - } - - if (requested & G_FILE_INFO_EDIT_NAME) - { - g_string_append_c (str, DBUS_TYPE_STRING); - } - - if (requested & G_FILE_INFO_ICON) - { - g_string_append_c (str, DBUS_TYPE_STRING); - } - - if (requested & G_FILE_INFO_MIME_TYPE) - { - g_string_append_c (str, DBUS_TYPE_STRING); - } - - if (requested & G_FILE_INFO_SIZE) - { - g_string_append_c (str, DBUS_TYPE_UINT64); - } - - if (requested & G_FILE_INFO_MODIFICATION_TIME) - { - g_string_append_c (str, DBUS_TYPE_UINT64); - } - - if (requested & G_FILE_INFO_ACCESS_RIGHTS) - { - g_string_append_c (str, DBUS_TYPE_UINT32); - } - - if (requested & G_FILE_INFO_STAT_INFO) - { - g_string_append_c (str, DBUS_TYPE_UINT32); /* TODO: struct */ - } - - if (requested & G_FILE_INFO_SYMLINK_TARGET) - { - g_string_append (str, DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING); - } - - if (requested & G_FILE_INFO_IS_HIDDEN) - { - g_string_append_c (str, DBUS_TYPE_BOOLEAN); - } - - - /* TODO: Attributes */ - - g_string_append_c (str, DBUS_STRUCT_END_CHAR); - - return g_string_free (str, FALSE); -} - void g_dbus_append_file_info (DBusMessageIter *iter, - GFileInfoRequestFlags requested, GFileInfo *info) { - DBusMessageIter struct_iter; - char *sig; + DBusMessageIter struct_iter, variant_iter, array_iter, inner_struct_iter; + char **attributes; + int i; + + attributes = g_file_info_list_attributes (info, NULL); - sig = g_dbus_get_file_info_signature (requested); if (!dbus_message_iter_open_container (iter, DBUS_TYPE_STRUCT, - sig, + G_FILE_INFO_INNER_TYPE_AS_STRING, &struct_iter)) _g_dbus_oom (); - g_free (sig); - if (requested & G_FILE_INFO_FILE_TYPE) - { - guint16 type = g_file_info_get_file_type (info); - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT16, - &type)) - _g_dbus_oom (); - } - if (requested & G_FILE_INFO_NAME) - { - _g_dbus_message_iter_append_cstring (&struct_iter, - g_file_info_get_name (info)); - } + if (!dbus_message_iter_open_container (&struct_iter, + DBUS_TYPE_ARRAY, + DBUS_STRUCT_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_STRUCT_END_CHAR_AS_STRING, + &array_iter)) + _g_dbus_oom (); - if (requested & G_FILE_INFO_DISPLAY_NAME) - { - const char *str = g_file_info_get_display_name (info); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &str)) + for (i = 0; attributes[i] != NULL; i++) + { + GFileAttributeType type; + char *dbus_type; + void *value; + const char *str; + guint32 v_uint32; + gint32 v_int32; + guint64 v_uint64; + gint64 v_int64; + + type = g_file_info_get_attribute_type (info, attributes[i]); + switch (type) + { + case G_FILE_ATTRIBUTE_TYPE_STRING: + dbus_type = DBUS_TYPE_STRING_AS_STRING; + str = g_file_info_get_attribute_string (info, attributes[i]); + value = &str; + break; + case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: + dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING; + str = g_file_info_get_attribute_byte_string (info, attributes[i]); + value = &str; + break; + case G_FILE_ATTRIBUTE_TYPE_UINT32: + dbus_type = DBUS_TYPE_UINT32_AS_STRING; + v_uint32 = g_file_info_get_attribute_uint32 (info, attributes[i]); + value = &v_uint32; + break; + case G_FILE_ATTRIBUTE_TYPE_INT32: + dbus_type = DBUS_TYPE_INT32_AS_STRING; + v_int32 = g_file_info_get_attribute_int32 (info, attributes[i]); + value = &v_int32; + break; + case G_FILE_ATTRIBUTE_TYPE_UINT64: + dbus_type = DBUS_TYPE_UINT64_AS_STRING; + v_uint64 = g_file_info_get_attribute_uint64 (info, attributes[i]); + value = &v_uint64; + break; + case G_FILE_ATTRIBUTE_TYPE_INT64: + dbus_type = DBUS_TYPE_INT64_AS_STRING; + v_int64 = g_file_info_get_attribute_int64 (info, attributes[i]); + value = &v_int64; + break; + default: + g_warning ("Invalid attribute type %s=%d, ignoring\n", attributes[i], type); + continue; + } + + if (!dbus_message_iter_open_container (&array_iter, + DBUS_TYPE_STRUCT, + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING, + &inner_struct_iter)) _g_dbus_oom (); - } - if (requested & G_FILE_INFO_EDIT_NAME) - { - const char *str = g_file_info_get_edit_name (info); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &str)) - _g_dbus_oom (); - } - if (requested & G_FILE_INFO_ICON) - { - const char *str = g_file_info_get_icon (info); - - if (!dbus_message_iter_append_basic (&struct_iter, + if (!dbus_message_iter_append_basic (&inner_struct_iter, DBUS_TYPE_STRING, - &str)) + &attributes[i])) _g_dbus_oom (); - } - if (requested & G_FILE_INFO_MIME_TYPE) - { - const char *str = g_file_info_get_mime_type (info); - - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_STRING, - &str)) - _g_dbus_oom (); - } - if (requested & G_FILE_INFO_SIZE) - { - guint64 size = g_file_info_get_size (info); - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT64, - &size)) - _g_dbus_oom (); - } - - if (requested & G_FILE_INFO_MODIFICATION_TIME) - { - guint64 time = g_file_info_get_modification_time (info); - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT64, - &time)) + if (!dbus_message_iter_open_container (&inner_struct_iter, + DBUS_TYPE_VARIANT, + dbus_type, + &variant_iter)) _g_dbus_oom (); - } - if (requested & G_FILE_INFO_ACCESS_RIGHTS) - { - guint32 rights = g_file_info_get_access_rights (info); - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT32, - &rights)) - _g_dbus_oom (); - } - - if (requested & G_FILE_INFO_STAT_INFO) - { - /* TODO: implement statinfo */ - guint32 tmp = 0; - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_UINT32, - &tmp)) + if (dbus_type[0] == DBUS_TYPE_ARRAY) + _g_dbus_message_iter_append_cstring (&variant_iter, *(char **)value); + else + { + if (!dbus_message_iter_append_basic (&variant_iter, + dbus_type[0], value)) + _g_dbus_oom (); + } + + if (!dbus_message_iter_close_container (&inner_struct_iter, &variant_iter)) _g_dbus_oom (); - } - - if (requested & G_FILE_INFO_SYMLINK_TARGET) - { - _g_dbus_message_iter_append_cstring (&struct_iter, - g_file_info_get_symlink_target (info)); - } - - if (requested & G_FILE_INFO_IS_HIDDEN) - { - dbus_bool_t is_hidden = g_file_info_get_is_hidden (info); - if (!dbus_message_iter_append_basic (&struct_iter, - DBUS_TYPE_BOOLEAN, - &is_hidden)) + + if (!dbus_message_iter_close_container (&array_iter, &inner_struct_iter)) _g_dbus_oom (); } - /* TODO: Attributes */ + g_strfreev (attributes); + if (!dbus_message_iter_close_container (&struct_iter, &array_iter)) + _g_dbus_oom (); + if (!dbus_message_iter_close_container (iter, &struct_iter)) _g_dbus_oom (); } diff --git a/daemon/gvfsjobenumerate.c b/daemon/gvfsjobenumerate.c index f2976dbd..5090eb1c 100644 --- a/daemon/gvfsjobenumerate.c +++ b/daemon/gvfsjobenumerate.c @@ -66,18 +66,16 @@ g_vfs_job_enumerate_new (DBusConnection *connection, int path_len; const char *obj_path; const char *path_data; - guint32 requested; char *attributes; - dbus_bool_t follow_symlinks; + dbus_uint32_t flags; dbus_error_init (&derror); if (!dbus_message_get_args (message, &derror, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &path_data, &path_len, DBUS_TYPE_STRING, &obj_path, - DBUS_TYPE_UINT32, &requested, DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_BOOLEAN, &follow_symlinks, + DBUS_TYPE_UINT32, &flags, 0)) { reply = dbus_message_new_error (message, @@ -97,28 +95,18 @@ g_vfs_job_enumerate_new (DBusConnection *connection, job->object_path = g_strdup (obj_path); job->filename = g_strndup (path_data, path_len); job->backend = backend; - job->requested = requested; job->attributes = g_strdup (attributes); - job->follow_symlinks = follow_symlinks; + job->flags = flags; return G_VFS_JOB (job); } - -void -g_vfs_job_enumerate_set_result (GVfsJobEnumerate *job, - GFileInfoRequestFlags requested_result) -{ - job->requested_result = requested_result; -} - void g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job, GList *infos) { DBusMessage *message, *orig_message; DBusMessageIter iter, array_iter; - char *sig; int num; restart: @@ -133,20 +121,16 @@ g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job, dbus_message_iter_init_append (message, &iter); - sig = g_dbus_get_file_info_signature (job->requested_result); - if (!dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, sig, + DBUS_TYPE_ARRAY, + G_FILE_INFO_TYPE_AS_STRING, &array_iter)) _g_dbus_oom (); - g_free (sig); - num = 0; while (infos != NULL) { g_dbus_append_file_info (&array_iter, - job->requested_result, infos->data); infos = infos->next; if (++num > 100) @@ -195,9 +179,8 @@ run (GVfsJob *job) class->enumerate (op_job->backend, op_job, op_job->filename, - op_job->requested, op_job->attributes, - op_job->follow_symlinks); + op_job->flags); } static gboolean @@ -212,9 +195,8 @@ try (GVfsJob *job) return class->try_enumerate (op_job->backend, op_job, op_job->filename, - op_job->requested, op_job->attributes, - op_job->follow_symlinks); + op_job->flags); } static void @@ -249,20 +231,9 @@ create_reply (GVfsJob *job, DBusConnection *connection, DBusMessage *message) { - GVfsJobEnumerate *op_job = G_VFS_JOB_ENUMERATE (job); DBusMessage *reply; - DBusMessageIter iter; - guint32 requested_32; reply = dbus_message_new_method_return (message); - dbus_message_iter_init_append (reply, &iter); - - requested_32 = op_job->requested_result; - if (!dbus_message_iter_append_basic (&iter, - DBUS_TYPE_UINT32, - &requested_32)) - _g_dbus_oom (); - return reply; } diff --git a/daemon/gvfsjobenumerate.h b/daemon/gvfsjobenumerate.h index 360c1549..7080bac2 100644 --- a/daemon/gvfsjobenumerate.h +++ b/daemon/gvfsjobenumerate.h @@ -24,11 +24,9 @@ struct _GVfsJobEnumerate GVfsBackend *backend; char *filename; char *object_path; - GFileInfoRequestFlags requested; char *attributes; - gboolean follow_symlinks; + GFileGetInfoFlags flags; - GFileInfoRequestFlags requested_result; }; struct _GVfsJobEnumerateClass @@ -41,8 +39,6 @@ GType g_vfs_job_enumerate_get_type (void) G_GNUC_CONST; GVfsJob *g_vfs_job_enumerate_new (DBusConnection *connection, DBusMessage *message, GVfsBackend *backend); -void g_vfs_job_enumerate_set_result (GVfsJobEnumerate *job, - GFileInfoRequestFlags requested_result); void g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job, GList *info); void g_vfs_job_enumerate_done (GVfsJobEnumerate *job); diff --git a/daemon/gvfsjobgetinfo.c b/daemon/gvfsjobgetinfo.c index 57db3cce..64aae474 100644 --- a/daemon/gvfsjobgetinfo.c +++ b/daemon/gvfsjobgetinfo.c @@ -65,17 +65,15 @@ g_vfs_job_get_info_new (DBusConnection *connection, DBusError derror; int path_len; const char *path_data; - guint32 requested; char *attributes; - dbus_bool_t follow_symlinks; + dbus_uint32_t flags; dbus_error_init (&derror); if (!dbus_message_get_args (message, &derror, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &path_data, &path_len, - DBUS_TYPE_UINT32, &requested, DBUS_TYPE_STRING, &attributes, - DBUS_TYPE_BOOLEAN, &follow_symlinks, + DBUS_TYPE_UINT32, &flags, 0)) { reply = dbus_message_new_error (message, @@ -94,9 +92,8 @@ g_vfs_job_get_info_new (DBusConnection *connection, job->filename = g_strndup (path_data, path_len); job->backend = backend; - job->requested = requested; job->attributes = g_strdup (attributes); - job->follow_symlinks = follow_symlinks; + job->flags = flags; return G_VFS_JOB (job); } @@ -110,9 +107,8 @@ run (GVfsJob *job) class->get_info (op_job->backend, op_job, op_job->filename, - op_job->requested, op_job->attributes, - op_job->follow_symlinks); + op_job->flags); } static gboolean @@ -127,17 +123,14 @@ try (GVfsJob *job) return class->try_get_info (op_job->backend, op_job, op_job->filename, - op_job->requested, op_job->attributes, - op_job->follow_symlinks); + op_job->flags); } void g_vfs_job_get_info_set_info (GVfsJobGetInfo *job, - GFileInfoRequestFlags requested_result, GFileInfo *file_info) { - job->requested_result = requested_result; job->file_info = g_object_ref (file_info); } @@ -150,20 +143,12 @@ create_reply (GVfsJob *job, GVfsJobGetInfo *op_job = G_VFS_JOB_GET_INFO (job); DBusMessage *reply; DBusMessageIter iter; - guint32 requested_32; reply = dbus_message_new_method_return (message); dbus_message_iter_init_append (reply, &iter); - requested_32 = op_job->requested_result; - if (!dbus_message_iter_append_basic (&iter, - DBUS_TYPE_UINT32, - &requested_32)) - _g_dbus_oom (); - g_dbus_append_file_info (&iter, - op_job->requested_result, op_job->file_info); return reply; diff --git a/daemon/gvfsjobgetinfo.h b/daemon/gvfsjobgetinfo.h index 9d1df88b..0d0636f1 100644 --- a/daemon/gvfsjobgetinfo.h +++ b/daemon/gvfsjobgetinfo.h @@ -23,11 +23,9 @@ struct _GVfsJobGetInfo GVfsBackend *backend; char *filename; - GFileInfoRequestFlags requested; char *attributes; - gboolean follow_symlinks; + GFileGetInfoFlags flags; - GFileInfoRequestFlags requested_result; GFileInfo *file_info; }; @@ -42,7 +40,6 @@ GVfsJob *g_vfs_job_get_info_new (DBusConnection *connection, DBusMessage *message, GVfsBackend *backend); void g_vfs_job_get_info_set_info (GVfsJobGetInfo *job, - GFileInfoRequestFlags requested_result, GFileInfo *file_info); G_END_DECLS diff --git a/gio/gfile.c b/gio/gfile.c index 1fbb52fb..13ccef6b 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -137,9 +137,8 @@ g_file_get_child (GFile *file, GFileEnumerator * g_file_enumerate_children (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) @@ -148,15 +147,14 @@ g_file_enumerate_children (GFile *file, iface = G_FILE_GET_IFACE (file); - return (* iface->enumerate_children) (file, requested, attributes, follow_symlinks, + return (* iface->enumerate_children) (file, attributes, flags, cancellable, error); } GFileInfo * g_file_get_info (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { @@ -164,7 +162,7 @@ g_file_get_info (GFile *file, iface = G_FILE_GET_IFACE (file); - return (* iface->get_info) (file, requested, attributes, follow_symlinks, cancellable, error); + return (* iface->get_info) (file, attributes, flags, cancellable, error); } GFileInputStream * diff --git a/gio/gfile.h b/gio/gfile.h index 66593e5a..7e065979 100644 --- a/gio/gfile.h +++ b/gio/gfile.h @@ -15,6 +15,10 @@ G_BEGIN_DECLS #define G_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_FILE)) #define G_FILE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_FILE, GFileIface)) +typedef enum { + G_FILE_GET_INFO_NOFOLLOW_SYMLINKS = (1<<0) +} GFileGetInfoFlags; + typedef struct _GFile GFile; /* Dummy typedef */ typedef struct _GFileIface GFileIface; @@ -39,15 +43,13 @@ struct _GFileIface GFile * (*get_child) (GFile *file, const char *name); GFileEnumerator * (*enumerate_children) (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error); GFileInfo * (*get_info) (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error); /* (*get_info_async) (GFile *file.. */ @@ -93,15 +95,13 @@ GFile * g_file_get_parent (GFile *file); GFile * g_file_get_child (GFile *file, const char *name); GFileEnumerator * g_file_enumerate_children (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error); GFileInfo * g_file_get_info (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error); GFileInputStream * g_file_read (GFile *file, diff --git a/gio/gfileenumeratorlocal.c b/gio/gfileenumeratorlocal.c index 04d8d811..0acb4727 100644 --- a/gio/gfileenumeratorlocal.c +++ b/gio/gfileenumeratorlocal.c @@ -19,8 +19,9 @@ struct _GFileEnumeratorLocal GFileAttributeMatcher *matcher; GDir *dir; char *filename; - GFileInfoRequestFlags requested; char *attributes; + GFileGetInfoFlags flags; + gboolean follow_symlinks; }; @@ -73,9 +74,8 @@ g_file_enumerator_local_init (GFileEnumeratorLocal *local) GFileEnumerator * g_file_enumerator_local_new (const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { @@ -90,9 +90,8 @@ g_file_enumerator_local_new (const char *filename, local->dir = dir; local->filename = g_strdup (filename); - local->requested = requested; local->matcher = g_file_attribute_matcher_new (attributes); - local->follow_symlinks = follow_symlinks; + local->flags = flags; return G_FILE_ENUMERATOR (local); } @@ -116,9 +115,8 @@ g_file_enumerator_local_next_file (GFileEnumerator *enumerator, path = g_build_filename (local->filename, filename, NULL); info = g_file_info_local_get (filename, path, - local->requested, local->matcher, - local->follow_symlinks, + local->flags, &my_error); g_free (path); diff --git a/gio/gfileenumeratorlocal.h b/gio/gfileenumeratorlocal.h index 4bf8051b..c7a8d117 100644 --- a/gio/gfileenumeratorlocal.h +++ b/gio/gfileenumeratorlocal.h @@ -3,6 +3,7 @@ #include <gfileenumerator.h> #include <gfileinfo.h> +#include <gfile.h> G_BEGIN_DECLS @@ -27,9 +28,8 @@ struct _GFileEnumeratorLocalClass GType g_file_enumerator_local_get_type (void) G_GNUC_CONST; GFileEnumerator *g_file_enumerator_local_new (const char *filename, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error); diff --git a/gio/gfileinfo.c b/gio/gfileinfo.c index 4a39da57..ee475aa1 100644 --- a/gio/gfileinfo.c +++ b/gio/gfileinfo.c @@ -6,58 +6,178 @@ #include "gfileinfo.h" #include <glib/gi18n-lib.h> -G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT); - typedef struct { - GQuark namespace_q; - GQuark attribute_q; /* full namespace:attribute form */ - char *value; -} GFileAttributeInternal; - - -struct _GFileInfoPrivate { - GFileType file_type; - char *name; - char *display_name; - char *edit_name; - char *icon; - GQuark mime_type_q; - goffset size; - time_t mtime; - GFileAccessRights access_rights; - struct stat *stat_info; - char *symlink_target; + guint32 attribute; + GFileAttributeType type; + union { + gint32 int32; + guint32 uint32; + gint64 int64; + guint64 uint64; + char *string; + GQuark quark; + } value; +} GFileAttributeValue; + +struct _GFileInfo +{ + GObject parent_instance; + GArray *attributes; - guint is_hidden : 1; }; -static void -g_file_info_finalize (GObject *object) +G_DEFINE_TYPE (GFileInfo, g_file_info, G_TYPE_OBJECT); + +typedef struct { + guint32 id; + guint32 attribute_id_counter; +} NSInfo; + +G_LOCK_DEFINE_STATIC (attribute_hash); +static int namespace_id_counter = 0; +static GHashTable *ns_hash = NULL; +static GHashTable *attribute_hash = NULL; +static char ***attributes = NULL; + +/* Attribute ids are 32bit, we split it up like this: + * |------------|--------------------| + * 12 bit 20 bit + * namespace attribute id + * + * This way the attributes gets sorted in namespace order + */ + +#define NS_POS 20 +#define NS_MASK ((guint32)((1<<12) - 1)) +#define ID_POS 0 +#define ID_MASK ((guint32)((1<<20) - 1)) + +#define GET_NS(_attr_id) \ + (((guint32) (_attr_id) >> NS_POS) & NS_MASK) +#define GET_ID(_attr_id) \ + (((guint32)(_attr_id) >> ID_POS) & ID_MASK) + +#define MAKE_ATTR_ID(_ns, _id) \ + ( ((((guint32) _ns) & NS_MASK) << NS_POS) | \ + ((((guint32) _id) & ID_MASK) << ID_POS) ) + +static NSInfo * +_lookup_namespace (const char *namespace) { - GFileInfo *info; - GFileInfoPrivate *priv; - GFileAttributeInternal *internal; - GArray *attrs; - int i; + NSInfo *ns_info; + + ns_info = g_hash_table_lookup (ns_hash, namespace); + if (ns_info == NULL) + { + ns_info = g_new0 (NSInfo, 1); + ns_info->id = ++namespace_id_counter; + g_hash_table_insert (ns_hash, g_strdup (namespace), ns_info); + attributes = g_realloc (attributes, (ns_info->id + 1) * sizeof (char **)); + attributes[ns_info->id] = NULL; + } + return ns_info; +} - info = G_FILE_INFO (object); +static guint32 +lookup_namespace (const char *namespace) +{ + NSInfo *ns_info; + guint32 id; + + G_LOCK (attribute_hash); + + if (attribute_hash == NULL) + { + ns_hash = g_hash_table_new (g_str_hash, g_str_equal); + attribute_hash = g_hash_table_new (g_str_hash, g_str_equal); + } + + ns_info = _lookup_namespace (namespace); + id = 0; + if (ns_info) + id = ns_info->id; + + G_UNLOCK (attribute_hash); - priv = info->priv; + return id; +} + + +static char * +get_attribute_for_id (int attribute) +{ + char *s; + G_LOCK (attribute_hash); + s = attributes[GET_NS(attribute)][GET_ID(attribute)]; + G_UNLOCK (attribute_hash); + return s; +} + +static guint32 +lookup_attribute (const char *attribute) +{ + guint32 attr_id, id; + char *ns; + const char *colon; + NSInfo *ns_info; - g_free (priv->name); - g_free (priv->display_name); - g_free (priv->icon); - g_free (priv->stat_info); - g_free (priv->symlink_target); + G_LOCK (attribute_hash); + if (attribute_hash == NULL) + { + ns_hash = g_hash_table_new (g_str_hash, g_str_equal); + attribute_hash = g_hash_table_new (g_str_hash, g_str_equal); + } - attrs = info->priv->attributes; - for (i = 0; i < attrs->len; i++) + attr_id = GPOINTER_TO_UINT (g_hash_table_lookup (attribute_hash, attribute)); + + if (attr_id != 0) { - internal = &g_array_index (attrs, GFileAttributeInternal, i); - g_free (internal->value); + G_UNLOCK (attribute_hash); + return attr_id; } + + colon = strchr (attribute, ':'); + if (colon) + ns = g_strndup (attribute, colon - attribute); + else + ns = g_strdup (""); + + ns_info = _lookup_namespace (ns); + g_free (ns); + + id = ++ns_info->attribute_id_counter; + attributes[ns_info->id] = g_realloc (attributes[ns_info->id], (id + 1) * sizeof (char *)); + attributes[ns_info->id][id] = g_strdup (attribute); - g_array_free (priv->attributes, TRUE); + attr_id = MAKE_ATTR_ID (ns_info->id, id); + + g_hash_table_insert (attribute_hash, attributes[ns_info->id][id], GUINT_TO_POINTER (attr_id)); + + G_UNLOCK (attribute_hash); + + return attr_id; +} + +static void +free_attribute_value (GFileAttributeValue *value) +{ + if (value->type == G_FILE_ATTRIBUTE_TYPE_STRING) + g_free (value->value.string); +} + +static void +g_file_info_finalize (GObject *object) +{ + GFileInfo *info; + int i; + GFileAttributeValue *values; + + info = G_FILE_INFO (object); + + values = (GFileAttributeValue *)info->attributes->data; + for (i = 0; i < info->attributes->len; i++) + free_attribute_value (&values[i]); + g_array_free (info->attributes, TRUE); if (G_OBJECT_CLASS (g_file_info_parent_class)->finalize) (*G_OBJECT_CLASS (g_file_info_parent_class)->finalize) (object); @@ -68,21 +188,14 @@ g_file_info_class_init (GFileInfoClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (GFileInfoPrivate)); - gobject_class->finalize = g_file_info_finalize; } static void g_file_info_init (GFileInfo *info) { - info->priv = G_TYPE_INSTANCE_GET_PRIVATE (info, - G_TYPE_FILE_INFO, - GFileInfoPrivate); - - info->priv->attributes = g_array_new (FALSE, - FALSE, - sizeof (GFileAttributeInternal)); + info->attributes = g_array_new (FALSE, FALSE, + sizeof (GFileAttributeValue)); } GFileInfo * @@ -91,523 +204,917 @@ g_file_info_new (void) return g_object_new (G_TYPE_FILE_INFO, NULL); } -GFileType -g_file_info_get_file_type (GFileInfo *info) +GFileInfo * +g_file_info_copy (GFileInfo *other) { - return info->priv->file_type; + GFileInfo *new; + + new = g_file_info_new (); + g_array_append_vals (new->attributes, + other->attributes->data, + other->attributes->len); + + return new; } -const char * -g_file_info_get_name (GFileInfo *info) +static int +g_file_info_find_place (GFileInfo *info, + guint32 attribute) { - return info->priv->name; + int min, max, med; + GFileAttributeValue *values; + /* Binary search for the place where attribute would be, if its + in the array */ + + min = 0; + max = info->attributes->len; + + values = (GFileAttributeValue *)info->attributes->data; + + while (min < max) + { + med = min + (max - min) / 2; + if (values[med].attribute == attribute) + { + min = med; + break; + } + else if (values[med].attribute < attribute) + min = med + 1; + else /* values[med].attribute > attribute */ + max = med; + } + + return min; } -const char * -g_file_info_get_display_name (GFileInfo *info) + +static GFileAttributeValue * +g_file_info_find_value (GFileInfo *info, + guint32 attr_id) { - return info->priv->display_name; + GFileAttributeValue *values; + int i; + + i = g_file_info_find_place (info, attr_id); + values = (GFileAttributeValue *)info->attributes->data; + if (i < info->attributes->len && + values[i].attribute == attr_id) + return &values[i]; + + return NULL; } -const char * -g_file_info_get_edit_name (GFileInfo *info) +static GFileAttributeValue * +g_file_info_find_value_by_name (GFileInfo *info, + const char *attribute) { - return info->priv->edit_name; + guint32 attr_id; + + attr_id = lookup_attribute (attribute); + return g_file_info_find_value (info, attr_id); } -const char * -g_file_info_get_icon (GFileInfo *info) + +gboolean +g_file_info_has_attribute (GFileInfo *info, + const char *attribute) { - return info->priv->icon; + GFileAttributeValue *value; + + value = g_file_info_find_value_by_name (info, attribute); + return value != NULL; } -const char * -g_file_info_get_mime_type (GFileInfo *info) +char ** +g_file_info_list_attributes (GFileInfo *info, + const char *name_space) { - return g_quark_to_string (info->priv->mime_type_q); + GPtrArray *names; + GFileAttributeValue *values; + guint32 attribute; + int i; + + names = g_ptr_array_new (); + values = (GFileAttributeValue *)info->attributes->data; + for (i = 0; i < info->attributes->len; i++) + { + attribute = values[i].attribute; + g_ptr_array_add (names, g_strdup (get_attribute_for_id (attribute))); + } + + /* NULL terminate */ + g_ptr_array_add (names, NULL); + + return (char **)g_ptr_array_free (names, FALSE); } -GQuark -g_file_info_get_mime_type_quark (GFileInfo *info) + +GFileAttributeType +g_file_info_get_attribute_type (GFileInfo *info, + const char *attribute) { - return info->priv->mime_type_q; + GFileAttributeValue *value; + + value = g_file_info_find_value_by_name (info, attribute); + if (value) + return value->type; + else + return G_FILE_ATTRIBUTE_TYPE_INVALID; } -goffset -g_file_info_get_size (GFileInfo *info) +void +g_file_info_remove_attribute (GFileInfo *info, + const char *attribute) { - return info->priv->size; -} + + guint32 attr_id; + GFileAttributeValue *values; + int i; + + attr_id = lookup_attribute (attribute); -time_t -g_file_info_get_modification_time (GFileInfo *info) + i = g_file_info_find_place (info, attr_id); + values = (GFileAttributeValue *)info->attributes->data; + if (i < info->attributes->len && + values[i].attribute == attr_id) + { + free_attribute_value (&values[i]); + g_array_remove_index (info->attributes, i); + } +} + +static gboolean +valid_char (char c) { - return info->priv->mtime; + return c >= 32 && c <= 126 && c != '\\'; } -const char * -g_file_info_get_symlink_target (GFileInfo *info) +static char * +escape_byte_string (const char *str) { - return info->priv->symlink_target; + size_t len; + int num_invalid, i; + char *escaped_val, *p; + unsigned char c; + char *hex_digits = "0123456789abcdef"; + + len = strlen (str); + + num_invalid = 0; + for (i = 0; i < len; i++) + { + if (!valid_char (str[i])) + num_invalid++; + } + + if (num_invalid == 0) + return g_strdup (str); + else + { + escaped_val = g_malloc (len + num_invalid*3 + 1); + + p = escaped_val; + for (i = 0; i < len; i++) + { + c = str[i]; + if (valid_char (c)) + *p++ = c; + else + { + *p++ = '\\'; + *p++ = 'x'; + *p++ = hex_digits[(c >> 8) & 0xf]; + *p++ = hex_digits[c & 0xf]; + } + } + *p++ = 0; + return escaped_val; + } } -GFileAccessRights -g_file_info_get_access_rights (GFileInfo *info) + +char * +g_file_info_get_attribute_as_string (GFileInfo *info, + const char *attribute) { - return info->priv->access_rights; + GFileAttributeValue *value; + char *str; + + value = g_file_info_find_value_by_name (info, attribute); + + if (value == NULL) + return NULL; + + switch (value->type) + { + case G_FILE_ATTRIBUTE_TYPE_STRING: + str = g_strdup (value->value.string); + break; + case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: + str = escape_byte_string (value->value.string); + break; + case G_FILE_ATTRIBUTE_TYPE_UINT32: + str = g_strdup_printf ("%u", (unsigned int)value->value.uint32); + break; + case G_FILE_ATTRIBUTE_TYPE_INT32: + str = g_strdup_printf ("%i", (int)value->value.int32); + break; + case G_FILE_ATTRIBUTE_TYPE_UINT64: + str = g_strdup_printf ("%"G_GUINT64_FORMAT, value->value.uint64); + break; + case G_FILE_ATTRIBUTE_TYPE_INT64: + str = g_strdup_printf ("%"G_GINT64_FORMAT, value->value.int64); + break; + default: + g_warning ("Invalid type in GFileInfo attribute"); + str = g_strdup (""); + break; + } + + return str; } -gboolean -g_file_info_can_read (GFileInfo *info) +static char * +get_string (GFileAttributeValue *value) { - return info->priv->access_rights & G_FILE_ACCESS_CAN_READ; + if (value == NULL || value->type != G_FILE_ATTRIBUTE_TYPE_STRING) + { + if (value != NULL) + g_warning ("Invalid type in GFileInfo attribute"); + return NULL; + } + return value->value.string; } -gboolean -g_file_info_can_write (GFileInfo *info) +static char * +get_byte_string (GFileAttributeValue *value) { - return info->priv->access_rights & G_FILE_ACCESS_CAN_WRITE; + if (value == NULL || value->type != G_FILE_ATTRIBUTE_TYPE_BYTE_STRING) + { + if (value != NULL) + g_warning ("Invalid type in GFileInfo attribute"); + return NULL; + } + return value->value.string; } -gboolean -g_file_info_can_delete (GFileInfo *info) +static guint32 +get_uint32 (GFileAttributeValue *value) { - return info->priv->access_rights & G_FILE_ACCESS_CAN_DELETE; + if (value == NULL || value->type != G_FILE_ATTRIBUTE_TYPE_UINT32) + { + if (value != NULL) + g_warning ("Invalid type in GFileInfo attribute"); + return 0; + } + return value->value.uint32; } -gboolean -g_file_info_can_rename (GFileInfo *info) +static gint32 +get_int32 (GFileAttributeValue *value) { - return info->priv->access_rights & G_FILE_ACCESS_CAN_RENAME; + if (value == NULL || value->type != G_FILE_ATTRIBUTE_TYPE_INT32) + { + if (value != NULL) + g_warning ("Invalid type in GFileInfo attribute"); + return 0; + } + return value->value.int32; } -gboolean -g_file_info_get_is_hidden (GFileInfo *info) +static guint64 +get_uint64 (GFileAttributeValue *value) { - return info->priv->is_hidden; + if (value == NULL || value->type != G_FILE_ATTRIBUTE_TYPE_UINT64) + { + if (value != NULL) + g_warning ("Invalid type in GFileInfo attribute"); + return 0; + } + return value->value.uint64; } -const struct stat * -g_file_info_get_stat_info (GFileInfo *info) +static gint64 +get_int64 (GFileAttributeValue *value) { - return info->priv->stat_info; + if (value == NULL || value->type != G_FILE_ATTRIBUTE_TYPE_INT64) + { + if (value != NULL) + g_warning ("Invalid type in GFileInfo attribute"); + return 0; + } + return value->value.int64; } const char * -g_file_info_get_attribute (GFileInfo *info, - const char *attribute) +g_file_info_get_attribute_string (GFileInfo *info, + const char *attribute) { - GFileAttributeInternal *internal; - GQuark attr_q; - GArray *attrs; - int i; - - attr_q = g_quark_try_string (attribute); - if (attr_q == 0) - return NULL; + GFileAttributeValue *value; - attrs = info->priv->attributes; - for (i = 0; i < attrs->len; i++) - { - internal = &g_array_index (attrs, GFileAttributeInternal, i); - if (internal->attribute_q == attr_q) - return internal->value; - } - - return NULL; + value = g_file_info_find_value_by_name (info, attribute); + return get_string (value); } - -GFileAttribute * -g_file_info_get_attributes (GFileInfo *info, - const char *namespace, - int *n_attributes) + +const char * +g_file_info_get_attribute_byte_string (GFileInfo *info, + const char *attribute) { - GFileAttributeInternal *internal; - GQuark namespace_q; - GArray *attrs; - GArray *result; - int i; + GFileAttributeValue *value; - *n_attributes = 0; - - namespace_q = g_quark_try_string (namespace); - if (namespace_q == 0) - return NULL; + value = g_file_info_find_value_by_name (info, attribute); + return get_byte_string (value); +} - result = g_array_new (FALSE, FALSE, sizeof (GFileAttribute)); - - attrs = info->priv->attributes; - for (i = 0; i < attrs->len; i++) - { - internal = &g_array_index (attrs, GFileAttributeInternal, i); - - if (internal->namespace_q == namespace_q) - { - GFileAttribute attr; - attr.attribute = g_quark_to_string (internal->attribute_q); - attr.value = internal->value; - g_array_append_val (result, attr); - } - } +guint32 +g_file_info_get_attribute_uint32 (GFileInfo *info, + const char *attribute) +{ + GFileAttributeValue *value; + value = g_file_info_find_value_by_name (info, attribute); + return get_uint32 (value); +} - *n_attributes = result->len; +gint32 +g_file_info_get_attribute_int32 (GFileInfo *info, + const char *attribute) +{ + GFileAttributeValue *value; - if (result->len == 0) - { - g_array_free (result, TRUE); - return NULL; - } + value = g_file_info_find_value_by_name (info, attribute); + return get_int32 (value); +} + +guint64 +g_file_info_get_attribute_uint64 (GFileInfo *info, + const char *attribute) +{ + GFileAttributeValue *value; - return (GFileAttribute *)g_array_free (result, FALSE); + value = g_file_info_find_value_by_name (info, attribute); + return get_uint64 (value); } - -GFileAttribute * -g_file_info_get_all_attributes (GFileInfo *info, - int *n_attributes) + +gint64 +g_file_info_get_attribute_int64 (GFileInfo *info, + const char *attribute) { - GFileAttributeInternal *internal; - GArray *attrs; - GArray *result; + GFileAttributeValue *value; + + value = g_file_info_find_value_by_name (info, attribute); + return get_int64 (value); +} + +static GFileAttributeValue * +g_file_info_create_value (GFileInfo *info, + guint32 attr_id) +{ + GFileAttributeValue *values; + GFileAttributeValue value; int i; - *n_attributes = 0; - - result = g_array_new (FALSE, FALSE, sizeof (GFileAttribute)); + i = g_file_info_find_place (info, attr_id); - attrs = info->priv->attributes; - for (i = 0; i < attrs->len; i++) + values = (GFileAttributeValue *)info->attributes->data; + if (i < info->attributes->len && + values[i].attribute == attr_id) + return &values[i]; + else { - GFileAttribute attr; - internal = &g_array_index (attrs, GFileAttributeInternal, i); - - attr.attribute = g_quark_to_string (internal->attribute_q); - attr.value = internal->value; - g_array_append_val (result, attr); + value.attribute = attr_id; + value.type = G_FILE_ATTRIBUTE_TYPE_INVALID; + g_array_insert_val (info->attributes, i , value); + + values = (GFileAttributeValue *)info->attributes->data; + return &values[i]; } +} - *n_attributes = result->len; +static GFileAttributeValue * +g_file_info_create_value_by_name (GFileInfo *info, + const char *attribute) +{ + guint32 attr_id; - if (result->len == 0) - { - g_array_free (result, TRUE); - return NULL; - } + attr_id = lookup_attribute (attribute); - return (GFileAttribute *)g_array_free (result, FALSE); -} + return g_file_info_create_value (info, attr_id); +} -void -g_file_info_set_file_type (GFileInfo *info, - GFileType file_type) +static void +set_string (GFileAttributeValue *value, const char *string) { - info->priv->file_type = file_type; + free_attribute_value (value); + value->type = G_FILE_ATTRIBUTE_TYPE_STRING; + value->value.string = g_strdup (string); } - -void -g_file_info_set_name (GFileInfo *info, - const char *name) + +static void +set_byte_string (GFileAttributeValue *value, const char *string) { - g_free (info->priv->name); - info->priv->name = g_strdup (name); + free_attribute_value (value); + value->type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING; + value->value.string = g_strdup (string); } -void -g_file_info_set_display_name (GFileInfo *info, - const char *display_name) +static void +set_uint32 (GFileAttributeValue *value, guint32 val) { - g_free (info->priv->display_name); - info->priv->display_name = g_strdup (display_name); + free_attribute_value (value); + value->type = G_FILE_ATTRIBUTE_TYPE_UINT32; + value->value.uint32 = val; +} + +static void +set_int32 (GFileAttributeValue *value, gint32 val) +{ + free_attribute_value (value); + value->type = G_FILE_ATTRIBUTE_TYPE_INT32; + value->value.int32 = val; +} + +static void +set_uint64 (GFileAttributeValue *value, guint64 val) +{ + free_attribute_value (value); + value->type = G_FILE_ATTRIBUTE_TYPE_UINT64; + value->value.uint64 = val; +} + +static void +set_int64 (GFileAttributeValue *value, gint64 val) +{ + free_attribute_value (value); + value->type = G_FILE_ATTRIBUTE_TYPE_INT64; + value->value.int64 = val; } void -g_file_info_set_edit_name (GFileInfo *info, - const char *edit_name) +g_file_info_set_attribute_string (GFileInfo *info, + const char *attribute, + const char *attr_value) { - g_free (info->priv->edit_name); - info->priv->edit_name = g_strdup (edit_name); + GFileAttributeValue *value; + + value = g_file_info_create_value_by_name (info, attribute); + set_string (value, attr_value); } void -g_file_info_set_icon (GFileInfo *info, - const char *icon) +g_file_info_set_attribute_byte_string (GFileInfo *info, + const char *attribute, + const char *attr_value) { - g_free (info->priv->icon); - info->priv->icon = g_strdup (icon); + GFileAttributeValue *value; + + value = g_file_info_create_value_by_name (info, attribute); + set_byte_string (value, attr_value); } void -g_file_info_set_mime_type (GFileInfo *info, - const char *mime_type) +g_file_info_set_attribute_uint32 (GFileInfo *info, + const char *attribute, + guint32 attr_value) { - info->priv->mime_type_q = g_quark_from_string (mime_type); + GFileAttributeValue *value; + + value = g_file_info_create_value_by_name (info, attribute); + set_uint32 (value, attr_value); } void -g_file_info_set_size (GFileInfo *info, - goffset size) +g_file_info_set_attribute_int32 (GFileInfo *info, + const char *attribute, + gint32 attr_value) { - info->priv->size = size; + GFileAttributeValue *value; + + value = g_file_info_create_value_by_name (info, attribute); + set_int32 (value, attr_value); } void -g_file_info_set_modification_time (GFileInfo *info, - time_t mtime) +g_file_info_set_attribute_uint64 (GFileInfo *info, + const char *attribute, + guint64 attr_value) { - info->priv->mtime = mtime; + GFileAttributeValue *value; + + value = g_file_info_create_value_by_name (info, attribute); + set_uint64 (value, attr_value); } void -g_file_info_set_symlink_target (GFileInfo *info, - const char *link_target) +g_file_info_set_attribute_int64 (GFileInfo *info, + const char *attribute, + gint64 attr_value) { - g_free (info->priv->symlink_target); - info->priv->symlink_target = g_strdup (link_target); + GFileAttributeValue *value; + + value = g_file_info_create_value_by_name (info, attribute); + set_int64 (value, attr_value); } + +/* Helper getters */ +GFileType +g_file_info_get_file_type (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; -void -g_file_info_set_access_rights (GFileInfo *info, - GFileAccessRights access_rights) + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_TYPE); + + value = g_file_info_find_value (info, attr); + return (GFileType)get_uint32 (value); +} + +GFileFlags +g_file_info_get_flags (GFileInfo *info) { - info->priv->access_rights = access_rights; + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_FLAGS); + + value = g_file_info_find_value (info, attr); + return (GFileType)get_uint32 (value); } -void -g_file_info_set_is_hidden (GFileInfo *info, - gboolean is_hidden) +const char * +g_file_info_get_name (GFileInfo *info) { - info->priv->is_hidden = is_hidden; + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_NAME); + + value = g_file_info_find_value (info, attr); + return get_byte_string (value); } -void -g_file_info_set_stat_info (GFileInfo *info, - const struct stat *statbuf) +const char * +g_file_info_get_display_name (GFileInfo *info) { - if (statbuf == NULL) - { - g_free (info->priv->stat_info); - info->priv->stat_info = NULL; - } - else - { - if (info->priv->stat_info == NULL) - info->priv->stat_info = g_new (struct stat, 1); - *info->priv->stat_info = *statbuf; - } + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_DISPLAY_NAME); + + value = g_file_info_find_value (info, attr); + return get_string (value); } -void -g_file_info_set_from_stat (GFileInfo *info, - GFileInfoRequestFlags requested, - const struct stat *statbuf) +const char * +g_file_info_get_edit_name (GFileInfo *info) { - if (requested & G_FILE_INFO_FILE_TYPE) - { - if (S_ISREG (statbuf->st_mode)) - info->priv->file_type = G_FILE_TYPE_REGULAR; - else if (S_ISDIR (statbuf->st_mode)) - info->priv->file_type = G_FILE_TYPE_DIRECTORY; - else if (S_ISCHR (statbuf->st_mode) || - S_ISBLK (statbuf->st_mode) || - S_ISFIFO (statbuf->st_mode) -#ifdef S_ISSOCK - || S_ISSOCK (statbuf->st_mode) -#endif - ) - info->priv->file_type = G_FILE_TYPE_SPECIAL; - else if (S_ISLNK (statbuf->st_mode)) - info->priv->file_type = G_FILE_TYPE_SYMBOLIC_LINK; - else - info->priv->file_type = G_FILE_TYPE_UNKNOWN; - } + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_EDIT_NAME); - if (requested & G_FILE_INFO_SIZE) - g_file_info_set_size (info, statbuf->st_size); + value = g_file_info_find_value (info, attr); + return get_string (value); +} - if (requested & G_FILE_INFO_MODIFICATION_TIME) - g_file_info_set_modification_time (info, statbuf->st_mtime); +const char * +g_file_info_get_icon (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; - if (requested & G_FILE_INFO_STAT_INFO) - g_file_info_set_stat_info (info, statbuf); + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ICON); + + value = g_file_info_find_value (info, attr); + return get_string (value); } +const char * +g_file_info_get_mime_type (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_MIME_TYPE); + + value = g_file_info_find_value (info, attr); + return get_string (value); +} -void -g_file_info_set_attribute (GFileInfo *info, - const char *attribute, - const char *value) -{ - GFileAttributeInternal new_internal; - GArray *attrs; - GQuark attr_q; - char *colon, *namespace; - int i; +goffset +g_file_info_get_size (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; - attr_q = g_quark_from_string (attribute); + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SIZE); + + value = g_file_info_find_value (info, attr); + return (goffset) get_uint64 (value); +} + +void +g_file_info_get_modification_time (GFileInfo *info, + GTimeVal *result) +{ + static guint32 attr_mtime = 0, attr_mtime_usec; + GFileAttributeValue *value; - attrs = info->priv->attributes; - for (i = 0; i < attrs->len; i++) + if (attr_mtime == 0) { - GFileAttributeInternal *internal = &g_array_index (attrs, GFileAttributeInternal, i); - - if (internal->attribute_q == attr_q) - { - g_free (internal->value); - internal->value = g_strdup (value); - return; - } + attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_STD_MTIME); + attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_STD_MTIME_USEC); } + + value = g_file_info_find_value (info, attr_mtime); + result->tv_sec = get_uint64 (value); + value = g_file_info_find_value (info, attr_mtime_usec); + result->tv_usec = get_uint32 (value); +} - new_internal.value = g_strdup (value); - new_internal.attribute_q = g_quark_from_string (attribute); +const char * +g_file_info_get_symlink_target (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET); + + value = g_file_info_find_value (info, attr); + return get_byte_string (value); +} - colon = strchr (attribute, ':'); - if (colon && colon != attribute) { - namespace = g_strndup (attribute, colon - attribute); - new_internal.namespace_q = g_quark_from_string (namespace); - g_free (namespace); - } else { - new_internal.namespace_q = 0; - } +GFileAccessRights +g_file_info_get_access_rights (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS); + + value = g_file_info_find_value (info, attr); + return (goffset) get_uint32 (value); +} - g_array_append_val(attrs,new_internal); +GFileAccessRights +g_file_info_get_access_rights_mask (GFileInfo *info) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS_MASK); + + value = g_file_info_find_value (info, attr); + return (goffset) get_uint32 (value); } +/* Helper setters: */ + void -g_file_info_set_attributes (GFileInfo *info, - GFileAttribute *attributes, - int n_attributes) +g_file_info_set_file_type (GFileInfo *info, + GFileType type) { - int i; + static guint32 attr = 0; + GFileAttributeValue *value; - for (i = 0; i < n_attributes; i++) { - g_file_info_set_attribute (info, - attributes[i].attribute, - attributes[i].value); - } + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_TYPE); + + value = g_file_info_create_value (info, attr); + set_uint32 (value, type); } -#define ON_STACK_NAMESPACES 3 -#define ON_STACK_ATTRIBUTES 3 +void +g_file_info_set_flags (GFileInfo *info, + GFileFlags flags) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_FLAGS); + + value = g_file_info_create_value (info, attr); + set_uint32 (value, flags); +} -typedef struct { - GQuark namespace; - gboolean all; - GQuark full_names[ON_STACK_ATTRIBUTES]; - GArray *more_full_names; -} NamespaceMatcher; +void +g_file_info_set_name (GFileInfo *info, + const char *name) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_NAME); + + value = g_file_info_create_value (info, attr); + set_byte_string (value, name); +} -struct _GFileAttributeMatcher { - gboolean all; - NamespaceMatcher namespaces[ON_STACK_NAMESPACES]; - GArray *more_namespaces; +void +g_file_info_set_display_name (GFileInfo *info, + const char *display_name) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_DISPLAY_NAME); + + value = g_file_info_create_value (info, attr); + set_string (value, display_name); +} - /* Interator */ - NamespaceMatcher *matched_namespace; - int attribute_pos; -}; +void +g_file_info_set_edit_name (GFileInfo *info, + const char *edit_name) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_EDIT_NAME); + + value = g_file_info_create_value (info, attr); + set_string (value, edit_name); +} -static NamespaceMatcher * -matcher_find_namespace (GFileAttributeMatcher *matcher, - GQuark namespace_q, - gboolean create) +void +g_file_info_set_icon (GFileInfo *info, + const char *icon) { - NamespaceMatcher *ns_matcher; - int i; + static guint32 attr = 0; + GFileAttributeValue *value; - for (i = 0; i < ON_STACK_NAMESPACES; i++) - { - ns_matcher = &matcher->namespaces[i]; + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ICON); + + value = g_file_info_create_value (info, attr); + set_string (value, icon); +} - /* First empty spot, not found, use this */ - if (ns_matcher->namespace == 0) - { - if (create) - { - ns_matcher->namespace = namespace_q; - return ns_matcher; - } - else - return NULL; - } +void +g_file_info_set_mime_type (GFileInfo *info, + const char *mime_type) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_MIME_TYPE); + + value = g_file_info_create_value (info, attr); + set_string (value, mime_type); +} - /* Found, use this */ - if (ns_matcher->namespace == namespace_q) - return ns_matcher; - } +void +g_file_info_set_size (GFileInfo *info, + goffset size) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SIZE); + + value = g_file_info_create_value (info, attr); + set_uint64 (value, size); +} - if (matcher->more_namespaces == NULL) +void +g_file_info_set_modification_time (GFileInfo *info, + GTimeVal *mtime) +{ + static guint32 attr_mtime = 0, attr_mtime_usec; + GFileAttributeValue *value; + + if (attr_mtime == 0) { - if (create) - matcher->more_namespaces = g_array_new (FALSE, FALSE, sizeof (NamespaceMatcher)); - else - return NULL; + attr_mtime = lookup_attribute (G_FILE_ATTRIBUTE_STD_MTIME); + attr_mtime_usec = lookup_attribute (G_FILE_ATTRIBUTE_STD_MTIME_USEC); } + + value = g_file_info_create_value (info, attr_mtime); + set_uint64 (value, mtime->tv_sec); + value = g_file_info_create_value (info, attr_mtime_usec); + set_uint32 (value, mtime->tv_usec); +} - for (i = 0; i < matcher->more_namespaces->len; i++) - { - ns_matcher = &g_array_index (matcher->more_namespaces, NamespaceMatcher, i); - if (ns_matcher->namespace == namespace_q) - return ns_matcher; - } +void +g_file_info_set_symlink_target (GFileInfo *info, + const char *symlink_target) +{ + static guint32 attr = 0; + GFileAttributeValue *value; - if (create) - { - NamespaceMatcher new_space = {namespace_q}; - g_array_append_val (matcher->more_namespaces, new_space); - ns_matcher = &g_array_index (matcher->more_namespaces, NamespaceMatcher, i); - return ns_matcher; - } + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET); - return NULL; + value = g_file_info_create_value (info, attr); + set_byte_string (value, symlink_target); +} + +void +g_file_info_set_access_rights (GFileInfo *info, + GFileAccessRights rights) +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS); + + value = g_file_info_create_value (info, attr); + set_uint32 (value, rights); +} + +void +g_file_info_set_access_rights_mask (GFileInfo *info, + GFileAccessRights mask) + +{ + static guint32 attr = 0; + GFileAttributeValue *value; + + if (attr == 0) + attr = lookup_attribute (G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS_MASK); + + value = g_file_info_create_value (info, attr); + set_uint32 (value, mask); } +#define ON_STACK_MATCHERS 5 + +typedef struct { + guint32 id; + guint32 mask; +} SubMatcher; + +struct _GFileAttributeMatcher { + gboolean all; + SubMatcher sub_matchers[ON_STACK_MATCHERS]; + GArray *more_sub_matchers; + + /* Interator */ + guint32 iterator_ns; + int iterator_pos; +}; + static void -matcher_add_namespace (GFileAttributeMatcher *matcher, - GQuark namespace_q, - GQuark full_name_q) +matcher_add (GFileAttributeMatcher *matcher, + guint id, guint mask) { + SubMatcher *sub_matchers; int i; - NamespaceMatcher *ns_matcher; - - ns_matcher = matcher_find_namespace (matcher, namespace_q, TRUE); + SubMatcher s; - if (full_name_q == 0) - ns_matcher->all = TRUE; - else + for (i = 0; i < ON_STACK_MATCHERS; i++) { - for (i = 0; i < ON_STACK_ATTRIBUTES; i++) + /* First empty spot, not found, use this */ + if (matcher->sub_matchers[i].id == 0) { - - /* First empty spot, not found, use this */ - if (ns_matcher->full_names[i] == 0) - { - ns_matcher->full_names[i] = full_name_q; - break; - } - - /* Already added */ - if (ns_matcher->full_names[i] == namespace_q) - break; + matcher->sub_matchers[i].id = id; + matcher->sub_matchers[i].mask = mask; + return; } - if (i == ON_STACK_ATTRIBUTES) - { - if (ns_matcher->more_full_names == NULL) - ns_matcher->more_full_names = g_array_new (FALSE, FALSE, sizeof (GQuark)); + /* Already added */ + if (matcher->sub_matchers[i].id == id && + matcher->sub_matchers[i].mask == mask) + return; + } - for (i = 0; i < ns_matcher->more_full_names->len; i++) - { - GQuark existing_name = g_array_index (ns_matcher->more_full_names, GQuark, i); - if (existing_name == full_name_q) - break; - } - - g_array_append_val (ns_matcher->more_full_names, full_name_q); - } + if (matcher->more_sub_matchers == NULL) + matcher->more_sub_matchers = g_array_new (FALSE, FALSE, sizeof (SubMatcher)); + + sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data; + for (i = 0; i < matcher->more_sub_matchers->len; i++) + { + /* Already added */ + if (sub_matchers[i].id == id && + sub_matchers[i].mask == mask) + return; } + + s.id = id; + s.mask = mask; + + g_array_append_val (matcher->more_sub_matchers, s); } @@ -617,9 +1124,6 @@ g_file_attribute_matcher_new (const char *attributes) char **split; char *colon; int i; - int num_ns, num_fn; - GQuark full_name_q, namespace_q; - GArray *full_name_array, *namespace_array; GFileAttributeMatcher *matcher; if (attributes == NULL) @@ -629,29 +1133,30 @@ g_file_attribute_matcher_new (const char *attributes) split = g_strsplit (attributes, ",", -1); - num_ns = 0; - num_fn = 0; - - full_name_array = NULL; - namespace_array = NULL; - for (i = 0; split[i] != NULL; i++) { if (strcmp (split[i], "*") == 0) matcher->all = TRUE; else { + guint32 id, mask; + colon = strchr (split[i], ':'); - - full_name_q = 0; if (colon != NULL && colon[1] != 0) { - full_name_q = g_quark_from_string (split[i]); - *colon = 0; + id = lookup_attribute (split[i]); + mask = 0xffffffff; + } + else + { + if (colon) + *colon = 0; + + id = lookup_namespace (split[i]) << NS_POS; + mask = NS_MASK << NS_POS; } - namespace_q = g_quark_from_string (split[i]); - matcher_add_namespace (matcher, namespace_q, full_name_q); + matcher_add (matcher, id, mask); } } @@ -663,52 +1168,21 @@ g_file_attribute_matcher_new (const char *attributes) void g_file_attribute_matcher_free (GFileAttributeMatcher *matcher) { - NamespaceMatcher *ns_matcher; - int i; - if (matcher == NULL) return; - - for (i = 0; i < ON_STACK_NAMESPACES; i++) - { - ns_matcher = &matcher->namespaces[i]; - - if (ns_matcher->more_full_names != NULL) - g_array_free (ns_matcher->more_full_names, TRUE); - } - - if (matcher->more_namespaces) - { - for (i = 0; i < matcher->more_namespaces->len; i++) - { - ns_matcher = &g_array_index (matcher->more_namespaces, NamespaceMatcher, i); - - if (ns_matcher->more_full_names != NULL) - g_array_free (ns_matcher->more_full_names, TRUE); - } - - g_array_free (matcher->more_namespaces, TRUE); - } + + if (matcher->more_sub_matchers) + g_array_free (matcher->more_sub_matchers, TRUE); g_free (matcher); } gboolean g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher, - const char *namespace, - const char *full_name) + const char *attribute) { - return g_file_attribute_matcher_matches_q (matcher, - g_quark_from_string (namespace), - g_quark_from_string (full_name)); -} - -gboolean -g_file_attribute_matcher_matches_q (GFileAttributeMatcher *matcher, - GQuark namespace, - GQuark full_name) -{ - NamespaceMatcher *ns_matcher; + SubMatcher *sub_matchers; + guint32 id; int i; if (matcher == NULL) @@ -716,111 +1190,103 @@ g_file_attribute_matcher_matches_q (GFileAttributeMatcher *matcher, if (matcher->all) return TRUE; - - ns_matcher = matcher_find_namespace (matcher, namespace, FALSE); - if (ns_matcher == NULL) - return FALSE; - - if (ns_matcher->all) - return TRUE; + id = lookup_attribute (attribute); - for (i = 0; i < ON_STACK_ATTRIBUTES; i++) + for (i = 0; i < ON_STACK_MATCHERS; i++) { - if (ns_matcher->full_names[i] == 0) + if (matcher->sub_matchers[i].id == 0) return FALSE; - if (ns_matcher->full_names[i] == full_name) + if (matcher->sub_matchers[i].id == (id & matcher->sub_matchers[i].mask)) return TRUE; } - if (ns_matcher->more_full_names) + if (matcher->more_sub_matchers) { - for (i = 0; i < ns_matcher->more_full_names->len; i++) + sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data; + for (i = 0; i < matcher->more_sub_matchers->len; i++) { - GQuark existing_name = g_array_index (ns_matcher->more_full_names, GQuark, i); - if (existing_name == full_name) + if (matcher->sub_matchers[i].id == (id & matcher->sub_matchers[i].mask)) return TRUE; } } - return FALSE; } - -gboolean -g_file_attribute_matcher_enumerate (GFileAttributeMatcher *matcher, - const char *namespace) -{ - return g_file_attribute_matcher_enumerate_q (matcher, - g_quark_from_string (namespace)); -} - /* return TRUE -> all */ gboolean -g_file_attribute_matcher_enumerate_q (GFileAttributeMatcher *matcher, - GQuark namespace) +g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher, + const char *namespace) { - NamespaceMatcher *ns_matcher; - + SubMatcher *sub_matchers; + int ns_id; + int i; + if (matcher == NULL) return FALSE; if (matcher->all) return TRUE; - ns_matcher = matcher_find_namespace (matcher, namespace, FALSE); + ns_id = lookup_namespace (namespace) << NS_POS; - matcher->matched_namespace = ns_matcher; - matcher->attribute_pos = 0; - - if (ns_matcher == NULL) - return FALSE; - - if (ns_matcher->all) - return TRUE; + for (i = 0; i < ON_STACK_MATCHERS; i++) + { + if (matcher->sub_matchers[i].id == ns_id) + return TRUE; + } + + if (matcher->more_sub_matchers) + { + sub_matchers = (SubMatcher *)matcher->more_sub_matchers->data; + for (i = 0; i < matcher->more_sub_matchers->len; i++) + { + if (matcher->sub_matchers[i].id == ns_id) + return TRUE; + } + } + matcher->iterator_ns = ns_id; + matcher->iterator_pos = 0; + return FALSE; } -const char * +const const char * g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher) { - NamespaceMatcher *ns_matcher; int i; - GQuark full_name_q; - const char *full_name; + SubMatcher *sub_matcher; if (matcher == NULL) return NULL; - ns_matcher = matcher->matched_namespace; - - if (ns_matcher == NULL) - return NULL; + while (1) + { + i = matcher->iterator_pos++; - i = matcher->attribute_pos++; + if (i < ON_STACK_MATCHERS) + { + if (matcher->sub_matchers[i].id == 0) + return NULL; - if (i < ON_STACK_ATTRIBUTES) - { - full_name_q = ns_matcher->full_names[i]; - if (full_name_q == 0) - return NULL; - } - else - { - if (ns_matcher->more_full_names == NULL) - return NULL; - - i -= ON_STACK_ATTRIBUTES; - if (i < ns_matcher->more_full_names->len) - full_name_q = g_array_index (ns_matcher->more_full_names, GQuark, i); + sub_matcher = &matcher->sub_matchers[i]; + } else - return NULL; - } - - full_name = g_quark_to_string (full_name_q); + { + if (matcher->more_sub_matchers == NULL) + return NULL; + + i -= ON_STACK_MATCHERS; + if (i < matcher->more_sub_matchers->len) + sub_matcher = &g_array_index (matcher->more_sub_matchers, SubMatcher, i); + else + return NULL; + } - /* Full names are guaranteed to have a ':' in them */ - return strchr (full_name, ':') + 1; + if (sub_matcher->mask == 0xffffffff && + (sub_matcher->id & (NS_MASK << NS_POS)) == matcher->iterator_ns) + return get_attribute_for_id (sub_matcher->id); + } } diff --git a/gio/gfileinfo.h b/gio/gfileinfo.h index 42b0831b..b37c14f1 100644 --- a/gio/gfileinfo.h +++ b/gio/gfileinfo.h @@ -1,8 +1,6 @@ #ifndef __G_FILE_INFO_H__ #define __G_FILE_INFO_H__ -#include <sys/stat.h> - #include <glib-object.h> #include <gio/gvfstypes.h> @@ -17,8 +15,6 @@ G_BEGIN_DECLS typedef struct _GFileInfo GFileInfo; typedef struct _GFileInfoClass GFileInfoClass; -typedef struct _GFileInfoPrivate GFileInfoPrivate; -typedef struct _GFileAttribute GFileAttribute; typedef struct _GFileAttributeMatcher GFileAttributeMatcher; typedef enum { @@ -39,114 +35,160 @@ typedef enum { G_FILE_ACCESS_CAN_RENAME = 1 << 5, } GFileAccessRights; -struct _GFileInfo -{ - GObject parent_instance; +typedef enum { + G_FILE_ATTRIBUTE_TYPE_INVALID = 0, + G_FILE_ATTRIBUTE_TYPE_STRING, + G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, + G_FILE_ATTRIBUTE_TYPE_UINT32, + G_FILE_ATTRIBUTE_TYPE_INT32, + G_FILE_ATTRIBUTE_TYPE_UINT64, + G_FILE_ATTRIBUTE_TYPE_INT64 +} GFileAttributeType; - GFileInfoPrivate *priv; -}; +typedef enum { + G_FILE_FLAG_HIDDEN = (1<<0), + G_FILE_FLAG_SYMLINK = (1<<1), + G_FILE_FLAG_LOCAL = (1<<2), + G_FILE_FLAG_VIRTUAL = (1<<3), +} GFileFlags; struct _GFileInfoClass { GObjectClass parent_class; }; -struct _GFileAttribute { - const char *attribute; - const char *value; -}; - -typedef enum { - G_FILE_INFO_FILE_TYPE = 1 << 0, - G_FILE_INFO_NAME = 1 << 1, - G_FILE_INFO_DISPLAY_NAME = 1 << 2, - G_FILE_INFO_EDIT_NAME = 1 << 3, - G_FILE_INFO_ICON = 1 << 4, - G_FILE_INFO_MIME_TYPE = 1 << 5, - G_FILE_INFO_SIZE = 1 << 6, - G_FILE_INFO_MODIFICATION_TIME = 1 << 7, - G_FILE_INFO_ACCESS_RIGHTS = 1 << 8, - G_FILE_INFO_STAT_INFO = 1 << 9, - G_FILE_INFO_SYMLINK_TARGET = 1 << 10, - G_FILE_INFO_IS_HIDDEN = 1 << 11, -} GFileInfoRequestFlags; - -#define G_FILE_INFO_REQUEST_FLAGS_FROM_STAT_MASK (G_FILE_INFO_FILE_TYPE | G_FILE_INFO_SIZE | G_FILE_INFO_MODIFICATION_TIME | G_FILE_INFO_STAT_INFO) +/* Common Attributes: */ + +#define G_FILE_ATTRIBUTE_STD_TYPE "std:type" +#define G_FILE_ATTRIBUTE_STD_FLAGS "std:flags" +#define G_FILE_ATTRIBUTE_STD_NAME "std:name" +#define G_FILE_ATTRIBUTE_STD_DISPLAY_NAME "std:display_name" +#define G_FILE_ATTRIBUTE_STD_EDIT_NAME "std:edit_name" +#define G_FILE_ATTRIBUTE_STD_ICON "std:icon" +#define G_FILE_ATTRIBUTE_STD_MIME_TYPE "std:mime_type" +#define G_FILE_ATTRIBUTE_STD_SIZE "std:size" +#define G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET "std:symlink_target" +#define G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS "std:access_rights" +#define G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS_MASK "std:access_rights_mask" +#define G_FILE_ATTRIBUTE_STD_MTIME "std:mtime" +#define G_FILE_ATTRIBUTE_STD_MTIME_USEC "std:mtime_usec" + +/* Unix specific attributes */ + +#define G_FILE_ATTRIBUTE_UNIX_DEVICE "unix:device" +#define G_FILE_ATTRIBUTE_UNIX_INODE "unix:inode" +#define G_FILE_ATTRIBUTE_UNIX_MODE "unix:mode" +#define G_FILE_ATTRIBUTE_UNIX_NLINK "unix:nlink" +#define G_FILE_ATTRIBUTE_UNIX_UID "unix:uid" +#define G_FILE_ATTRIBUTE_UNIX_GID "unix:gid" +#define G_FILE_ATTRIBUTE_UNIX_RDEV "unix:rdev" +#define G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE "unix:block_size" +#define G_FILE_ATTRIBUTE_UNIX_BLOCKS "unix:blocks" +#define G_FILE_ATTRIBUTE_UNIX_ATIME "unix:atime" +#define G_FILE_ATTRIBUTE_UNIX_ATIME_USEC "unix:atime_usec" +#define G_FILE_ATTRIBUTE_UNIX_CTIME "unix:ctime" +#define G_FILE_ATTRIBUTE_UNIX_CTIME_USEC "unix:ctime_usec" + +/* Owner attributes */ + +#define G_FILE_ATTRIBUTE_OWNER_USER "owner:user" +#define G_FILE_ATTRIBUTE_OWNER_GROUP "owner:group" GType g_file_info_get_type (void) G_GNUC_CONST; - -GFileInfo * g_file_info_new (void); -GFileType g_file_info_get_file_type (GFileInfo *info); -const char * g_file_info_get_name (GFileInfo *info); -const char * g_file_info_get_display_name (GFileInfo *info); -const char * g_file_info_get_edit_name (GFileInfo *info); -const char * g_file_info_get_icon (GFileInfo *info); -const char * g_file_info_get_mime_type (GFileInfo *info); -GQuark g_file_info_get_mime_type_quark (GFileInfo *info); -goffset g_file_info_get_size (GFileInfo *info); -time_t g_file_info_get_modification_time (GFileInfo *info); -const char * g_file_info_get_symlink_target (GFileInfo *info); -GFileAccessRights g_file_info_get_access_rights (GFileInfo *info); -gboolean g_file_info_can_read (GFileInfo *info); -gboolean g_file_info_can_write (GFileInfo *info); -gboolean g_file_info_can_delete (GFileInfo *info); -gboolean g_file_info_can_rename (GFileInfo *info); -gboolean g_file_info_get_is_hidden (GFileInfo *info); -const struct stat * g_file_info_get_stat_info (GFileInfo *info); -const char * g_file_info_get_attribute (GFileInfo *info, - const char *attribute); -GFileAttribute * g_file_info_get_attributes (GFileInfo *info, - const char *namespace, - int *n_attributes); -GFileAttribute * g_file_info_get_all_attributes (GFileInfo *info, - int *n_attributes); -void g_file_info_set_file_type (GFileInfo *info, - GFileType type); -void g_file_info_set_name (GFileInfo *info, - const char *name); -void g_file_info_set_display_name (GFileInfo *info, - const char *display_name); -void g_file_info_set_edit_name (GFileInfo *info, - const char *edit_name); -void g_file_info_set_icon (GFileInfo *info, - const char *icon); -void g_file_info_set_mime_type (GFileInfo *info, - const char *mime_type); -void g_file_info_set_size (GFileInfo *info, - goffset size); -void g_file_info_set_modification_time (GFileInfo *info, - time_t time); -void g_file_info_set_symlink_target (GFileInfo *info, - const char *link_target); -void g_file_info_set_access_rights (GFileInfo *info, - GFileAccessRights access_rights); -void g_file_info_set_is_hidden (GFileInfo *info, - gboolean is_hidden); -void g_file_info_set_stat_info (GFileInfo *info, - const struct stat *statbuf); -void g_file_info_set_attribute (GFileInfo *info, - const char *attribute, - const char *value); -void g_file_info_set_attributes (GFileInfo *info, - GFileAttribute *attributes, - int n_attributes); - -void g_file_info_set_from_stat (GFileInfo *info, - GFileInfoRequestFlags requested, - const struct stat *statbuf); + +GFileInfo * g_file_info_new (void); +GFileInfo * g_file_info_copy (GFileInfo *info); +gboolean g_file_info_has_attribute (GFileInfo *info, + const char *attribute); +char ** g_file_info_list_attributes (GFileInfo *info, + const char *name_space); +GFileAttributeType g_file_info_get_attribute_type (GFileInfo *info, + const char *attribute); +void g_file_info_remove_attribute (GFileInfo *info, + const char *attribute); +char * g_file_info_get_attribute_as_string (GFileInfo *info, + const char *attribute); +const char * g_file_info_get_attribute_string (GFileInfo *info, + const char *attribute); +const char * g_file_info_get_attribute_byte_string (GFileInfo *info, + const char *attribute); +guint32 g_file_info_get_attribute_uint32 (GFileInfo *info, + const char *attribute); +gint32 g_file_info_get_attribute_int32 (GFileInfo *info, + const char *attribute); +guint64 g_file_info_get_attribute_uint64 (GFileInfo *info, + const char *attribute); +gint64 g_file_info_get_attribute_int64 (GFileInfo *info, + const char *attribute); +void g_file_info_set_attribute_string (GFileInfo *info, + const char *attribute, + const char *value); +void g_file_info_set_attribute_byte_string (GFileInfo *info, + const char *attribute, + const char *value); +void g_file_info_set_attribute_uint32 (GFileInfo *info, + const char *attribute, + guint32 value); +void g_file_info_set_attribute_int32 (GFileInfo *info, + const char *attribute, + gint32 value); +void g_file_info_set_attribute_uint64 (GFileInfo *info, + const char *attribute, + guint64 value); +void g_file_info_set_attribute_int64 (GFileInfo *info, + const char *attribute, + gint64 value); + + +/* Helper getters: */ +GFileType g_file_info_get_file_type (GFileInfo *info); +GFileFlags g_file_info_get_flags (GFileInfo *info); +const char * g_file_info_get_name (GFileInfo *info); +const char * g_file_info_get_display_name (GFileInfo *info); +const char * g_file_info_get_edit_name (GFileInfo *info); +const char * g_file_info_get_icon (GFileInfo *info); +const char * g_file_info_get_mime_type (GFileInfo *info); +goffset g_file_info_get_size (GFileInfo *info); +void g_file_info_get_modification_time (GFileInfo *info, + GTimeVal *result); +const char * g_file_info_get_symlink_target (GFileInfo *info); +GFileAccessRights g_file_info_get_access_rights (GFileInfo *info); +GFileAccessRights g_file_info_get_access_rights_mask (GFileInfo *info); + + +/* Helper setters: */ +void g_file_info_set_file_type (GFileInfo *info, + GFileType type); +void g_file_info_set_flags (GFileInfo *info, + GFileFlags flags); +void g_file_info_set_name (GFileInfo *info, + const char *name); +void g_file_info_set_display_name (GFileInfo *info, + const char *display_name); +void g_file_info_set_edit_name (GFileInfo *info, + const char *edit_name); +void g_file_info_set_icon (GFileInfo *info, + const char *icon); +void g_file_info_set_mime_type (GFileInfo *info, + const char *mime_type); +void g_file_info_set_size (GFileInfo *info, + goffset size); +void g_file_info_set_modification_time (GFileInfo *info, + GTimeVal *mtime); +void g_file_info_set_symlink_target (GFileInfo *info, + const char *symlink_target); +void g_file_info_set_access_rights (GFileInfo *info, + GFileAccessRights rights); +void g_file_info_set_access_rights_mask (GFileInfo *info, + GFileAccessRights mask); + GFileAttributeMatcher *g_file_attribute_matcher_new (const char *attributes); void g_file_attribute_matcher_free (GFileAttributeMatcher *matcher); gboolean g_file_attribute_matcher_matches (GFileAttributeMatcher *matcher, - const char *namespace, const char *full_name); -gboolean g_file_attribute_matcher_matches_q (GFileAttributeMatcher *matcher, - GQuark namespace, - GQuark full_name); -gboolean g_file_attribute_matcher_enumerate (GFileAttributeMatcher *matcher, - const char *namespace); -gboolean g_file_attribute_matcher_enumerate_q (GFileAttributeMatcher *matcher, - GQuark namespace); +gboolean g_file_attribute_matcher_enumerate_namespace (GFileAttributeMatcher *matcher, + const char *namespace); const char * g_file_attribute_matcher_enumerate_next (GFileAttributeMatcher *matcher); G_END_DECLS diff --git a/gio/gfileinfolocal.c b/gio/gfileinfolocal.c index 6dbd0eba..858f9b69 100644 --- a/gio/gfileinfolocal.c +++ b/gio/gfileinfolocal.c @@ -65,8 +65,7 @@ get_selinux_context (const char *path, #ifdef HAVE_SELINUX char *context; - if (!g_file_attribute_matcher_matches (attribute_matcher, - "selinux", "selinux:context")) + if (!g_file_attribute_matcher_matches (attribute_matcher, "selinux:context")) return; if (is_selinux_enabled ()) @@ -84,7 +83,7 @@ get_selinux_context (const char *path, if (context) { - g_file_info_set_attribute (info, "selinux:context", context); + g_file_info_set_attribute_string (info, "selinux:context", context); freecon(context); } } @@ -121,7 +120,7 @@ escape_xattr (GFileInfo *info, } if (num_invalid == 0) - g_file_info_set_attribute (info, full_attr, value); + g_file_info_set_attribute_string (info, full_attr, value); else { escaped_val = g_malloc (len + num_invalid*3 + 1); @@ -141,7 +140,7 @@ escape_xattr (GFileInfo *info, } } *p++ = 0; - g_file_info_set_attribute (info, full_attr, escaped_val); + g_file_info_set_attribute_string (info, full_attr, escaped_val); g_free (escaped_val); } @@ -217,7 +216,7 @@ get_xattrs (const char *path, char *list; const char *attr; - all = g_file_attribute_matcher_enumerate (matcher, "xattr"); + all = g_file_attribute_matcher_enumerate_namespace (matcher, "xattr"); if (all) { @@ -327,7 +326,7 @@ get_xattrs_from_fd (int fd, char *list; const char *attr; - all = g_file_attribute_matcher_enumerate (matcher, "xattr"); + all = g_file_attribute_matcher_enumerate_namespace (matcher, "xattr"); if (all) { @@ -425,40 +424,90 @@ get_access_rights (const gchar *path) return rights; } +static void +set_info_from_stat (GFileInfo *info, struct stat *statbuf) +{ + GFileType file_type; + GTimeVal t; + + file_type = G_FILE_TYPE_UNKNOWN; + + if (S_ISREG (statbuf->st_mode)) + file_type = G_FILE_TYPE_REGULAR; + else if (S_ISDIR (statbuf->st_mode)) + file_type = G_FILE_TYPE_DIRECTORY; + else if (S_ISCHR (statbuf->st_mode) || + S_ISBLK (statbuf->st_mode) || + S_ISFIFO (statbuf->st_mode) +#ifdef S_ISSOCK + || S_ISSOCK (statbuf->st_mode) +#endif + ) + file_type = G_FILE_TYPE_SPECIAL; + else if (S_ISLNK (statbuf->st_mode)) + file_type = G_FILE_TYPE_SYMBOLIC_LINK; + + g_file_info_set_file_type (info, file_type); + g_file_info_set_size (info, statbuf->st_size); + + t.tv_sec = statbuf->st_mtime; +#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) + t.tv_usec = statbuf->st_mtimensec / 1000; +#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) + t.tv_usec = statbuf->st_mtim.tv_nsec / 1000; +#else + t.tv_usec = 0; +#endif + g_file_info_set_modification_time (info, &t); + + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE, statbuf->st_dev); + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE, statbuf->st_ino); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, statbuf->st_mode); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_NLINK, statbuf->st_nlink); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, statbuf->st_uid); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, statbuf->st_uid); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV, statbuf->st_rdev); + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE, statbuf->st_blksize); + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_BLOCKS, statbuf->st_blocks); + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_ATIME, statbuf->st_atime); +#if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_ATIME_USEC, statbuf->st_atimensec / 1000); +#elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_ATIME_USEC, statbuf->st_atim.tv_nsec / 1000); +#endif + g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_CTIME, statbuf->st_ctime); +#if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_CTIME_USEC, statbuf->st_ctimensec / 1000); +#elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC) + g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_CTIME_USEC, statbuf->st_ctim.tv_nsec / 1000); +#endif +} GFileInfo * g_file_info_local_get (const char *basename, const char *path, - GFileInfoRequestFlags requested, GFileAttributeMatcher *attribute_matcher, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GError **error) { GFileInfo *info; struct stat statbuf; + struct stat statbuf2; int res; + GFileFlags file_flags; + gboolean is_symlink; info = g_file_info_new (); - - if (requested & G_FILE_INFO_NAME) - g_file_info_set_name (info, basename); - - if (requested & G_FILE_INFO_IS_HIDDEN) - g_file_info_set_is_hidden (info, - basename != NULL && - basename[0] == '.'); + file_flags = 0; + + g_file_info_set_name (info, basename); /* Avoid stat in trivial case */ - if ((requested & ~(G_FILE_INFO_NAME|G_FILE_INFO_IS_HIDDEN)) == 0 && - attribute_matcher == NULL) + if (attribute_matcher == NULL) return info; - - if (follow_symlinks) - res = stat (path, &statbuf); - else - res = lstat (path, &statbuf); - + + res = g_lstat (path, &statbuf); if (res == -1) { g_object_unref (info); @@ -468,23 +517,54 @@ g_file_info_local_get (const char *basename, path, g_strerror (errno)); return NULL; } + + is_symlink = S_ISLNK (statbuf.st_mode); - g_file_info_set_from_stat (info, requested, &statbuf); + if (is_symlink) + { + file_flags |= G_FILE_FLAG_SYMLINK; + + /* Unless NOFOLLOW was set we default to following symlinks */ + if (!(flags & G_FILE_GET_INFO_NOFOLLOW_SYMLINKS)) + { + res = stat (path, &statbuf2); + + /* Report broken links as symlinks */ + if (res != -1) + statbuf = statbuf2; + } + } + + set_info_from_stat (info, &statbuf); - if (requested & G_FILE_INFO_SYMLINK_TARGET) + if (basename != NULL && basename[0] == '.') + file_flags |= G_FILE_FLAG_HIDDEN; + + g_file_info_set_flags (info, file_flags); + + if (is_symlink && + g_file_attribute_matcher_matches (attribute_matcher, + G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET)) { char *link = read_link (path); g_file_info_set_symlink_target (info, link); g_free (link); } - if (requested & G_FILE_INFO_ACCESS_RIGHTS) + if (g_file_attribute_matcher_matches (attribute_matcher, + G_FILE_ATTRIBUTE_STD_ACCESS_RIGHTS)) { GFileAccessRights rights = get_access_rights (path); g_file_info_set_access_rights (info, rights); + /* TODO: Figure out DELETE and RENAME rights */ + g_file_info_set_access_rights_mask (info, + G_FILE_ACCESS_CAN_READ | + G_FILE_ACCESS_CAN_WRITE | + G_FILE_ACCESS_CAN_EXECUTE); } - if (requested & G_FILE_INFO_DISPLAY_NAME) + if (g_file_attribute_matcher_matches (attribute_matcher, + G_FILE_ATTRIBUTE_STD_DISPLAY_NAME)) { char *display_name = g_filename_display_basename (path); @@ -498,32 +578,34 @@ g_file_info_local_get (const char *basename, g_free (display_name); } - if (requested & G_FILE_INFO_EDIT_NAME) + if (g_file_attribute_matcher_matches (attribute_matcher, + G_FILE_ATTRIBUTE_STD_EDIT_NAME)) { char *edit_name = g_filename_display_basename (path); g_file_info_set_edit_name (info, edit_name); g_free (edit_name); } - if (requested & G_FILE_INFO_MIME_TYPE) + if (g_file_attribute_matcher_matches (attribute_matcher, + G_FILE_ATTRIBUTE_STD_MIME_TYPE)) { /* TODO */ } - if (requested & G_FILE_INFO_ICON) + if (g_file_attribute_matcher_matches (attribute_matcher, + G_FILE_ATTRIBUTE_STD_ICON)) { /* TODO */ } - get_selinux_context (path, info, attribute_matcher, follow_symlinks); - get_xattrs (path, info, attribute_matcher, follow_symlinks); + get_selinux_context (path, info, attribute_matcher, (flags & G_FILE_GET_INFO_NOFOLLOW_SYMLINKS) == 0); + get_xattrs (path, info, attribute_matcher, (flags & G_FILE_GET_INFO_NOFOLLOW_SYMLINKS) == 0); return info; } GFileInfo * g_file_info_local_get_from_fd (int fd, - GFileInfoRequestFlags requested, char *attributes, GError **error) { @@ -541,19 +623,19 @@ g_file_info_local_get_from_fd (int fd, } info = g_file_info_new (); - - g_file_info_set_from_stat (info, requested, &stat_buf); + set_info_from_stat (info, &stat_buf); + matcher = g_file_attribute_matcher_new (attributes); #ifdef HAVE_SELINUX - if (g_file_attribute_matcher_matches (matcher, "selinux", "selinux:context") && + if (g_file_attribute_matcher_matches (matcher, "selinux:context") && is_selinux_enabled ()) { char *context; if (fgetfilecon_raw (fd, &context) >= 0) { - g_file_info_set_attribute (info, "selinux:context", context); + g_file_info_set_attribute_string (info, "selinux:context", context); freecon(context); } } diff --git a/gio/gfileinfolocal.h b/gio/gfileinfolocal.h index 37c54987..25163f7b 100644 --- a/gio/gfileinfolocal.h +++ b/gio/gfileinfolocal.h @@ -2,17 +2,16 @@ #define __G_FILE_INFO_LOCAL_H__ #include <gio/gfileinfo.h> +#include <gio/gfile.h> G_BEGIN_DECLS GFileInfo *g_file_info_local_get (const char *basename, const char *path, - GFileInfoRequestFlags requested, GFileAttributeMatcher *attribute_matcher, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GError **error); GFileInfo *g_file_info_local_get_from_fd (int fd, - GFileInfoRequestFlags requested, char *attributes, GError **error); diff --git a/gio/gfileinputstream.c b/gio/gfileinputstream.c index 8cef6560..3e01fcae 100644 --- a/gio/gfileinputstream.c +++ b/gio/gfileinputstream.c @@ -53,7 +53,6 @@ g_file_input_stream_init (GFileInputStream *stream) GFileInfo * g_file_input_stream_get_file_info (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error) @@ -90,7 +89,7 @@ g_file_input_stream_get_file_info (GFileInputStream *stream, class = G_FILE_INPUT_STREAM_GET_CLASS (stream); if (class->get_file_info) - info = class->get_file_info (stream, requested, attributes, cancellable, error); + info = class->get_file_info (stream, attributes, cancellable, error); else g_set_error (error, G_VFS_ERROR, G_VFS_ERROR_NOT_SUPPORTED, _("Stream doesn't support get_file_info")); diff --git a/gio/gfileinputstream.h b/gio/gfileinputstream.h index 6d7f46ee..42b7295b 100644 --- a/gio/gfileinputstream.h +++ b/gio/gfileinputstream.h @@ -37,7 +37,6 @@ struct _GFileInputStreamClass GCancellable *cancellable, GError **error); GFileInfo *(*get_file_info) (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); @@ -54,7 +53,6 @@ GType g_file_input_stream_get_type (void) G_GNUC_CONST; /* TODO: Turn this into a interface like GSeekable? */ GFileInfo *g_file_input_stream_get_file_info (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); diff --git a/gio/gfileinputstreamlocal.c b/gio/gfileinputstreamlocal.c index b60336a6..2b192a0a 100644 --- a/gio/gfileinputstreamlocal.c +++ b/gio/gfileinputstreamlocal.c @@ -33,7 +33,6 @@ static gboolean g_file_input_stream_local_close (GInputStream GCancellable *cancellable, GError **error); static GFileInfo *g_file_input_stream_local_get_file_info (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); @@ -199,7 +198,6 @@ g_file_input_stream_local_close (GInputStream *stream, static GFileInfo * g_file_input_stream_local_get_file_info (GFileInputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error) @@ -218,7 +216,6 @@ g_file_input_stream_local_get_file_info (GFileInputStream *stream, } return g_file_info_local_get_from_fd (file->priv->fd, - requested, attributes, error); } diff --git a/gio/gfilelocal.c b/gio/gfilelocal.c index 812a906b..19dc69f5 100644 --- a/gio/gfilelocal.c +++ b/gio/gfilelocal.c @@ -236,24 +236,21 @@ g_file_local_get_child (GFile *file, static GFileEnumerator * g_file_local_enumerate_children (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { GFileLocal *local = G_FILE_LOCAL (file); return g_file_enumerator_local_new (local->filename, - requested, attributes, - follow_symlinks, + attributes, flags, cancellable, error); } static GFileInfo * g_file_local_get_info (GFile *file, - GFileInfoRequestFlags requested, const char *attributes, - gboolean follow_symlinks, + GFileGetInfoFlags flags, GCancellable *cancellable, GError **error) { @@ -267,8 +264,8 @@ g_file_local_get_info (GFile *file, basename = g_path_get_basename (local->filename); info = g_file_info_local_get (basename, local->filename, - requested, matcher, follow_symlinks, - error); + matcher, flags, + error); g_free (basename); diff --git a/gio/gfileoutputstream.c b/gio/gfileoutputstream.c index fed7ebdc..d456e54f 100644 --- a/gio/gfileoutputstream.c +++ b/gio/gfileoutputstream.c @@ -8,7 +8,7 @@ G_DEFINE_TYPE (GFileOutputStream, g_file_output_stream, G_TYPE_OUTPUT_STREAM); struct _GFileOutputStreamPrivate { guint get_final_mtime : 1; - time_t final_mtime; + GTimeVal final_mtime; }; static void @@ -27,7 +27,6 @@ g_file_output_stream_init (GFileOutputStream *stream) GFileInfo * g_file_output_stream_get_file_info (GFileOutputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error) @@ -64,7 +63,7 @@ g_file_output_stream_get_file_info (GFileOutputStream *stream, class = G_FILE_OUTPUT_STREAM_GET_CLASS (stream); if (class->get_file_info) - info = class->get_file_info (stream, requested, attributes, cancellable, error); + info = class->get_file_info (stream, attributes, cancellable, error); else g_set_error (error, G_VFS_ERROR, G_VFS_ERROR_NOT_SUPPORTED, _("Stream doesn't support get_file_info")); @@ -96,21 +95,22 @@ g_file_output_stream_get_should_get_final_mtime (GFileOutputStream *stream) return stream->priv->get_final_mtime; } -time_t -g_file_output_stream_get_final_mtime (GFileOutputStream *stream) +void +g_file_output_stream_get_final_mtime (GFileOutputStream *stream, + GTimeVal *final_mtime) { - g_return_val_if_fail (G_IS_FILE_OUTPUT_STREAM (stream), FALSE); - g_return_val_if_fail (stream != NULL, FALSE); + g_return_if_fail (G_IS_FILE_OUTPUT_STREAM (stream)); + g_return_if_fail (stream != NULL); - return stream->priv->final_mtime; + *final_mtime = stream->priv->final_mtime; } void g_file_output_stream_set_final_mtime (GFileOutputStream *stream, - time_t final_mtime) + GTimeVal *final_mtime) { g_return_if_fail (G_IS_FILE_OUTPUT_STREAM (stream)); g_return_if_fail (stream != NULL); - stream->priv->final_mtime = final_mtime; + stream->priv->final_mtime = *final_mtime; } diff --git a/gio/gfileoutputstream.h b/gio/gfileoutputstream.h index 9c3b67e3..69ab2a88 100644 --- a/gio/gfileoutputstream.h +++ b/gio/gfileoutputstream.h @@ -37,7 +37,6 @@ struct _GFileOutputStreamClass GCancellable *cancellable, GError **error); GFileInfo *(*get_file_info) (GFileOutputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); @@ -54,16 +53,16 @@ GType g_file_output_stream_get_type (void) G_GNUC_CONST; GFileInfo *g_file_output_stream_get_file_info (GFileOutputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); void g_file_output_stream_set_should_get_final_mtime (GFileOutputStream *stream, gboolean get_final_mtime); -time_t g_file_output_stream_get_final_mtime (GFileOutputStream *stream); +void g_file_output_stream_get_final_mtime (GFileOutputStream *stream, + GTimeVal *mtime); gboolean g_file_output_stream_get_should_get_final_mtime (GFileOutputStream *stream); void g_file_output_stream_set_final_mtime (GFileOutputStream *stream, - time_t final_mtime); + GTimeVal *final_mtime); G_END_DECLS diff --git a/gio/gfileoutputstreamlocal.c b/gio/gfileoutputstreamlocal.c index 44fbf83c..79aa10fa 100644 --- a/gio/gfileoutputstreamlocal.c +++ b/gio/gfileoutputstreamlocal.c @@ -38,7 +38,6 @@ static gboolean g_file_output_stream_local_close (GOutputStream GCancellable *cancellable, GError **error); static GFileInfo *g_file_output_stream_local_get_file_info (GFileOutputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error); @@ -195,8 +194,19 @@ g_file_output_stream_local_close (GOutputStream *stream, } if (fstat (file->priv->fd, &final_stat) == 0) - g_file_output_stream_set_final_mtime (G_FILE_OUTPUT_STREAM (stream), - final_stat.st_mtime); + { + GTimeVal tv; + tv.tv_sec = final_stat.st_mtime; +#if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) + tv.tv_usec = final_stat.st_mtimensec / 1000; +#elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) + tv.tv_usec = final_stat.st_mtim.tv_nsec / 1000; +#else + tv.tv_usec = 0; +#endif + g_file_output_stream_set_final_mtime (G_FILE_OUTPUT_STREAM (stream), + &tv); + } } while (1) @@ -222,7 +232,6 @@ g_file_output_stream_local_close (GOutputStream *stream, static GFileInfo * g_file_output_stream_local_get_file_info (GFileOutputStream *stream, - GFileInfoRequestFlags requested, char *attributes, GCancellable *cancellable, GError **error) @@ -241,7 +250,6 @@ g_file_output_stream_local_get_file_info (GFileOutputStream *stream, } return g_file_info_local_get_from_fd (file->priv->fd, - requested, attributes, error); } diff --git a/programs/gvfs-info.c b/programs/gvfs-info.c index 3c1578c3..00cbe7ec 100644 --- a/programs/gvfs-info.c +++ b/programs/gvfs-info.c @@ -5,12 +5,12 @@ #include <gio/gfile.h> static char *attributes = NULL; -static gboolean follow_symlinks = FALSE; +static gboolean nofollow_symlinks = FALSE; static GOptionEntry entries[] = { { "attributes", 'a', 0, G_OPTION_ARG_STRING, &attributes, "The attributes to get", NULL }, - { "follow-symlinks", 'f', 0, G_OPTION_ARG_NONE, &follow_symlinks, "Follow symlinks", NULL }, + { "nofollow-symlinks", 'n', 0, G_OPTION_ARG_NONE, &nofollow_symlinks, "Don't follow symlinks", NULL }, { NULL } }; @@ -77,8 +77,8 @@ show_info (GFileInfo *info) const char *name, *type; char *escaped; goffset size; - GFileAttribute *attributes; - int n_attributes, i; + char **attributes; + int i; name = g_file_info_get_display_name (info); if (name) @@ -102,37 +102,41 @@ show_info (GFileInfo *info) size = g_file_info_get_size (info); g_print ("size: %"G_GUINT64_FORMAT"\n", (guint64)size); - if (g_file_info_get_is_hidden (info)) + if (g_file_info_get_flags (info) & G_FILE_FLAG_HIDDEN) g_print ("hidden\n"); - attributes = g_file_info_get_all_attributes (info, &n_attributes); + attributes = g_file_info_list_attributes (info, NULL); - if (attributes != NULL) + g_print ("attributes:\n"); + for (i = 0; attributes[i] != NULL; i++) { - g_print ("attributes:\n"); - for (i = 0; i < n_attributes; i++) - g_print (" %s: %s\n", attributes[i].attribute, attributes[i].value); - g_free (attributes); + char *value; + value = g_file_info_get_attribute_as_string (info, attributes[i]); + g_print (" %s: %s\n", attributes[i], value); + g_free (value); } + g_strfreev (attributes); } static void get_info (GFile *file) { - GFileInfoRequestFlags request; + GFileGetInfoFlags flags; GFileInfo *info; GError *error; if (file == NULL) return; - request = - G_FILE_INFO_FILE_TYPE | G_FILE_INFO_NAME | - G_FILE_INFO_SIZE | G_FILE_INFO_IS_HIDDEN | - G_FILE_INFO_DISPLAY_NAME | G_FILE_INFO_EDIT_NAME; + if (attributes == NULL) + attributes = "*"; + + flags = 0; + if (nofollow_symlinks) + flags |= G_FILE_GET_INFO_NOFOLLOW_SYMLINKS; error = NULL; - info = g_file_get_info (file, request, attributes, follow_symlinks, NULL, &error); + info = g_file_get_info (file, attributes, flags, NULL, &error); if (info == NULL) { diff --git a/programs/gvfs-ls.c b/programs/gvfs-ls.c index 59ed1d1b..81d965d8 100644 --- a/programs/gvfs-ls.c +++ b/programs/gvfs-ls.c @@ -51,7 +51,7 @@ show_info (GFileInfo *info) const char *name, *type; goffset size; - if (g_file_info_get_is_hidden (info) && !show_hidden) + if ((g_file_info_get_flags (info) & G_FILE_FLAG_HIDDEN) && !show_hidden) return; name = g_file_info_get_name (info); @@ -66,18 +66,18 @@ show_info (GFileInfo *info) static void list (GFile *file) { - GFileInfoRequestFlags request; GFileEnumerator *enumerator; GFileInfo *info; GError *error; - + if (file == NULL) return; - - request = G_FILE_INFO_FILE_TYPE | G_FILE_INFO_NAME | G_FILE_INFO_SIZE | G_FILE_INFO_IS_HIDDEN; + if (attributes == NULL) + attributes = "*"; + error = NULL; - enumerator = g_file_enumerate_children (file, request, attributes, TRUE, NULL, &error); + enumerator = g_file_enumerate_children (file, attributes, 0, NULL, &error); if (enumerator == NULL) { g_print ("Error: %s\n", error->message); |