[glib] Add extension point for adding metadata for local files



commit 7662c86611bf44175f18ec6eb66f159040ac73c5
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Jun 18 09:05:27 2009 +0200

    Add extension point for adding metadata for local files
    
    This adds a local_file_add_info vfunc to GVfs that vfs implementations
    can override to add metadata for local files.

 gio/glocalfile.c           |   75 +++++++++++++++++++++---------
 gio/glocalfileenumerator.c |    2 +
 gio/glocalfileinfo.c       |  108 +++++++++++++++++++++++++++++++++++++++-----
 gio/glocalfileinfo.h       |    3 +
 gio/gvfs.h                 |   26 +++++++++--
 5 files changed, 175 insertions(+), 39 deletions(-)
---
diff --git a/gio/glocalfile.c b/gio/glocalfile.c
index 8ac6014..1f956a5 100644
--- a/gio/glocalfile.c
+++ b/gio/glocalfile.c
@@ -110,7 +110,7 @@
 static void g_local_file_file_iface_init (GFileIface *iface);
 
 static GFileAttributeInfoList *local_writable_attributes = NULL;
-static GFileAttributeInfoList *local_writable_namespaces = NULL;
+static /* GFileAttributeInfoList * */ gsize local_writable_namespaces = 0;
 
 struct _GLocalFile
 {
@@ -201,24 +201,6 @@ g_local_file_class_init (GLocalFileClass *klass)
 #endif
 
   local_writable_attributes = list;
-
-  /* Writable namespaces: */
-  
-  list = g_file_attribute_info_list_new ();
-
-#ifdef HAVE_XATTR
-  g_file_attribute_info_list_add (list,
-				  "xattr",
-				  G_FILE_ATTRIBUTE_TYPE_STRING,
-				  G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
-				  G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
-  g_file_attribute_info_list_add (list,
-				  "xattr-sys",
-				  G_FILE_ATTRIBUTE_TYPE_STRING,
-				  G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
-#endif
-
-  local_writable_namespaces = list;
 }
 
 static void
@@ -1204,6 +1186,8 @@ g_local_file_query_info (GFile                *file,
 				 matcher, flags, &parent_info,
 				 error);
   
+
+  _g_local_file_info_free_parent_info (&parent_info);
   g_free (basename);
 
   g_file_attribute_matcher_unref (matcher);
@@ -1224,7 +1208,38 @@ g_local_file_query_writable_namespaces (GFile         *file,
 					GCancellable  *cancellable,
 					GError       **error)
 {
-  return g_file_attribute_info_list_ref (local_writable_namespaces);
+  GFileAttributeInfoList *list;
+  GVfsClass *class;
+  GVfs *vfs;
+
+  if (g_once_init_enter (&local_writable_namespaces))
+    {
+      /* Writable namespaces: */
+
+      list = g_file_attribute_info_list_new ();
+
+#ifdef HAVE_XATTR
+      g_file_attribute_info_list_add (list,
+				      "xattr",
+				      G_FILE_ATTRIBUTE_TYPE_STRING,
+				      G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
+				      G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
+      g_file_attribute_info_list_add (list,
+				      "xattr-sys",
+				      G_FILE_ATTRIBUTE_TYPE_STRING,
+				      G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
+#endif
+
+      vfs = g_vfs_get_default ();
+      class = G_VFS_GET_CLASS (vfs);
+      if (class->add_writable_namespaces)
+	class->add_writable_namespaces (vfs, list);
+
+      g_once_init_leave (&local_writable_namespaces, (gsize)list);
+    }
+  list = (GFileAttributeInfoList *)local_writable_namespaces;
+
+  return g_file_attribute_info_list_ref (list);
 }
 
 static gboolean
@@ -1409,7 +1424,9 @@ g_local_file_delete (GFile         *file,
 		     GError       **error)
 {
   GLocalFile *local = G_LOCAL_FILE (file);
-  
+  GVfsClass *class;
+  GVfs *vfs;
+
   if (g_remove (local->filename) == -1)
     {
       int errsv = errno;
@@ -1426,7 +1443,12 @@ g_local_file_delete (GFile         *file,
 		   g_strerror (errsv));
       return FALSE;
     }
-  
+
+  vfs = g_vfs_get_default ();
+  class = G_VFS_GET_CLASS (vfs);
+  if (class->local_file_removed)
+    class->local_file_removed (vfs, local->filename);
+
   return TRUE;
 }
 
@@ -2176,7 +2198,9 @@ g_local_file_move (GFile                  *source,
   char *backup_name;
   int res;
   off_t source_size;
-  
+  GVfsClass *class;
+  GVfs *vfs;
+
   if (!G_IS_LOCAL_FILE (source) ||
       !G_IS_LOCAL_FILE (destination))
     {
@@ -2294,6 +2318,11 @@ g_local_file_move (GFile                  *source,
       return FALSE;
     }
 
+  vfs = g_vfs_get_default ();
+  class = G_VFS_GET_CLASS (vfs);
+  if (class->local_file_moved)
+    class->local_file_moved (vfs, local_source->filename, local_destination->filename);
+
   /* Make sure we send full copied size */
   if (progress_callback)
     progress_callback (source_size, source_size, progress_callback_data);
diff --git a/gio/glocalfileenumerator.c b/gio/glocalfileenumerator.c
index eda7b03..e39c050 100644
--- a/gio/glocalfileenumerator.c
+++ b/gio/glocalfileenumerator.c
@@ -116,6 +116,8 @@ g_local_file_enumerator_finalize (GObject *object)
 
   local = G_LOCAL_FILE_ENUMERATOR (object);
 
+  if (local->got_parent_info)
+    _g_local_file_info_free_parent_info (&local->parent_info);
   g_free (local->filename);
   g_file_attribute_matcher_unref (local->matcher);
   if (local->dir)
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index 95ccf2e..c6d4be0 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -60,6 +60,7 @@
 
 #include <glib/gstdio.h>
 #include <gfileattribute-priv.h>
+#include <gvfs.h>
 
 #include "glibintl.h"
 
@@ -791,7 +792,9 @@ _g_local_file_info_get_parent_info (const char            *dir,
    */
   struct stat statbuf;
   int res;
-  
+
+  parent_info->extra_data = NULL;
+  parent_info->free_extra_data = NULL;
   parent_info->writable = FALSE;
   parent_info->is_sticky = FALSE;
   parent_info->has_trash_dir = FALSE;
@@ -833,6 +836,14 @@ _g_local_file_info_get_parent_info (const char            *dir,
     }
 }
 
+void
+_g_local_file_info_free_parent_info (GLocalParentFileInfo *parent_info)
+{
+  if (parent_info->extra_data &&
+      parent_info->free_extra_data)
+    parent_info->free_extra_data (parent_info->extra_data);
+}
+
 static void
 get_access_rights (GFileAttributeMatcher *attribute_matcher,
 		   GFileInfo             *info,
@@ -1417,6 +1428,9 @@ _g_local_file_info_get (const char             *basename,
 #ifdef G_OS_WIN32
   DWORD dos_attributes;
 #endif
+  char *symlink_target;
+  GVfs *vfs;
+  GVfsClass *class;
 
   info = g_file_info_new ();
 
@@ -1514,16 +1528,15 @@ _g_local_file_info_get (const char             *basename,
     g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_DOS_IS_SYSTEM, TRUE);
 #endif
 
-#ifdef S_ISLNK
-  if (is_symlink &&
-      g_file_attribute_matcher_matches (attribute_matcher,
-					G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
+  symlink_target = NULL;
+  if (is_symlink)
     {
-      char *link = read_link (path);
-      g_file_info_set_symlink_target (info, link);
-      g_free (link);
+      symlink_target = read_link (path);
+      if (symlink_target &&
+          g_file_attribute_matcher_matches (attribute_matcher,
+                                            G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET))
+        g_file_info_set_symlink_target (info, symlink_target);
     }
-#endif
 
   if (g_file_attribute_matcher_matches (attribute_matcher,
 					G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
@@ -1689,9 +1702,34 @@ _g_local_file_info_get (const char             *basename,
   if (g_file_attribute_matcher_matches (attribute_matcher,
 					G_FILE_ATTRIBUTE_THUMBNAIL_PATH))
     get_thumbnail_attributes (path, info);
-  
+
+  vfs = g_vfs_get_default ();
+  class = G_VFS_GET_CLASS (vfs);
+  if (class->local_file_add_info)
+    {
+      const char *extra_target;
+
+      extra_target = path;
+      if (!(flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) &&
+          is_symlink &&
+          !symlink_broken &&
+          symlink_target != NULL)
+        extra_target = symlink_target;
+
+      class->local_file_add_info (vfs,
+                                  extra_target,
+                                  statbuf.st_dev,
+                                  attribute_matcher,
+                                  info,
+                                  NULL,
+                                  &parent_info->extra_data,
+                                  &parent_info->free_extra_data);
+    }
+
   g_file_info_unset_attribute_mask (info);
 
+  g_free (symlink_target);
+
   return info;
 }
 
@@ -2126,6 +2164,8 @@ _g_local_file_info_set_attribute (char                 *filename,
 				  GError              **error)
 {
   GFileAttributeValue value = { 0 };
+  GVfsClass *class;
+  GVfs *vfs;
 
   _g_file_attribute_value_set_from_pointer (&value, type, value_p, FALSE);
   
@@ -2166,7 +2206,36 @@ _g_local_file_info_set_attribute (char                 *filename,
   else if (strcmp (attribute, G_FILE_ATTRIBUTE_SELINUX_CONTEXT) == 0)
     return set_selinux_context (filename, &value, error);
 #endif
-  
+
+  vfs = g_vfs_get_default ();
+  class = G_VFS_GET_CLASS (vfs);
+  if (class->local_file_set_attributes)
+    {
+      GFileInfo *info;
+
+      info = g_file_info_new ();
+      g_file_info_set_attribute (info,
+                                 attribute,
+                                 type,
+                                 value_p);
+      if (!class->local_file_set_attributes (vfs, filename,
+                                             info,
+                                             flags, cancellable,
+                                             error))
+        {
+          g_object_unref (info);
+	  return FALSE;
+        }
+
+      if (g_file_info_get_attribute_status (info, attribute) == G_FILE_ATTRIBUTE_STATUS_SET)
+        {
+          g_object_unref (info);
+          return TRUE;
+        }
+
+      g_object_unref (info);
+    }
+
   g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
 	       _("Setting attribute %s not supported"), attribute);
   return FALSE;
@@ -2190,6 +2259,8 @@ _g_local_file_info_set_attributes  (char                 *filename,
   GFileAttributeStatus status;
 #endif
   gboolean res;
+  GVfsClass *class;
+  GVfs *vfs;
   
   /* Handles setting multiple specified data in a single set, and takes care
      of ordering restrictions when setting attributes */
@@ -2310,5 +2381,20 @@ _g_local_file_info_set_attributes  (char                 *filename,
   }
 #endif
 
+  vfs = g_vfs_get_default ();
+  class = G_VFS_GET_CLASS (vfs);
+  if (class->local_file_set_attributes)
+    {
+      if (!class->local_file_set_attributes (vfs, filename,
+                                             info,
+                                             flags, cancellable,
+                                             error))
+        {
+	  res = FALSE;
+	  /* Don't set error multiple times */
+	  error = NULL;
+        }
+    }
+
   return res;
 }
diff --git a/gio/glocalfileinfo.h b/gio/glocalfileinfo.h
index 29ccfc0..82ad746 100644
--- a/gio/glocalfileinfo.h
+++ b/gio/glocalfileinfo.h
@@ -39,6 +39,8 @@ typedef struct
   gboolean has_trash_dir;
   int      owner;
   dev_t    device;
+  gpointer extra_data;
+  GDestroyNotify free_extra_data;
 } GLocalParentFileInfo;
 
 #ifdef G_OS_WIN32
@@ -53,6 +55,7 @@ gboolean   _g_local_file_has_trash_dir        (const char             *dirname,
 void       _g_local_file_info_get_parent_info (const char             *dir,
                                                GFileAttributeMatcher  *attribute_matcher,
                                                GLocalParentFileInfo   *parent_info);
+void       _g_local_file_info_free_parent_info (GLocalParentFileInfo   *parent_info);
 GFileInfo *_g_local_file_info_get             (const char             *basename,
                                                const char             *path,
                                                GFileAttributeMatcher  *attribute_matcher,
diff --git a/gio/gvfs.h b/gio/gvfs.h
index bb8fd80..be0156f 100644
--- a/gio/gvfs.h
+++ b/gio/gvfs.h
@@ -75,6 +75,27 @@ struct _GVfsClass
 
   /*< private >*/
   /* Padding for future expansion */
+  void                  (* local_file_add_info)       (GVfs       *vfs,
+						       const char *filename,
+						       guint64     device,
+						       GFileAttributeMatcher *attribute_matcher,
+						       GFileInfo  *info,
+						       GCancellable *cancellable,
+						       gpointer   *extra_data,
+						       GDestroyNotify *free_extra_data);
+  void                  (* add_writable_namespaces)   (GVfs       *vfs,
+						       GFileAttributeInfoList *list);
+  gboolean              (* local_file_set_attributes) (GVfs       *vfs,
+						       const char *filename,
+						       GFileInfo  *info,
+                                                       GFileQueryInfoFlags flags,
+                                                       GCancellable *cancellable,
+						       GError    **error);
+  void                  (* local_file_removed)        (GVfs       *vfs,
+						       const char *filename);
+  void                  (* local_file_moved)          (GVfs       *vfs,
+						       const char *source,
+						       const char *dest);
   void (*_g_reserved1) (void);
   void (*_g_reserved2) (void);
   void (*_g_reserved3) (void);
@@ -82,11 +103,6 @@ struct _GVfsClass
   void (*_g_reserved5) (void);
   void (*_g_reserved6) (void);
   void (*_g_reserved7) (void);
-  void (*_g_reserved8) (void);
-  void (*_g_reserved9) (void);
-  void (*_g_reserved10) (void);
-  void (*_g_reserved11) (void);
-  void (*_g_reserved12) (void);
 };
 
 GType                 g_vfs_get_type                  (void) G_GNUC_CONST;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]