glib r6679 - trunk/gio



Author: alexl
Date: Tue Mar 11 14:48:28 2008
New Revision: 6679
URL: http://svn.gnome.org/viewvc/glib?rev=6679&view=rev

Log:
2008-03-11  Alexander Larsson  <alexl redhat com>

        * glocalfile.c:
        * glocalfileinfo.[ch]:
	Correctly implement can_trash by actually
	looking for a trash dir, not just assuming
	one exists.



Modified:
   trunk/gio/ChangeLog
   trunk/gio/glocalfile.c
   trunk/gio/glocalfileinfo.c
   trunk/gio/glocalfileinfo.h

Modified: trunk/gio/glocalfile.c
==============================================================================
--- trunk/gio/glocalfile.c	(original)
+++ trunk/gio/glocalfile.c	Tue Mar 11 14:48:28 2008
@@ -1576,6 +1576,79 @@
   return g_string_free (str, FALSE);
 }
 
+gboolean
+_g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev)
+{
+  static gsize home_dev = 0;
+  char *topdir, *globaldir, *trashdir, *tmpname;
+  uid_t uid;
+  char uid_str[32];
+  struct stat global_stat, trash_stat;
+  gboolean res;
+  int statres;
+      
+  if (g_once_init_enter (&home_dev))
+    {
+      gsize setup_value = 0;
+      struct stat home_stat;
+      
+      g_stat (g_get_home_dir (), &home_stat);
+      setup_value = home_stat.st_dev;
+      g_once_init_leave (&home_dev, setup_value);
+    }
+
+  /* Assume we can trash to the home */
+  if (dir_dev == (dev_t)home_dev)
+    return TRUE;
+
+  topdir = find_mountpoint_for (dirname, dir_dev);
+  if (topdir == NULL)
+    return FALSE;
+
+  globaldir = g_build_filename (topdir, ".Trash", NULL); 
+  statres = g_lstat (globaldir, &global_stat);
+ if (g_lstat (globaldir, &global_stat) == 0 &&
+      S_ISDIR (global_stat.st_mode) &&
+      (global_stat.st_mode & S_ISVTX) != 0)
+    {
+      /* got a toplevel sysadmin created dir, assume we
+       * can trash to it (we should be able to create a dir)
+       * This fails for the FAT case where the ownership of
+       * that dir would be wrong though..
+       */
+      g_free (globaldir);
+      g_free (topdir);
+      return TRUE;
+    }
+  g_free (globaldir);
+
+  /* No global trash dir, or it failed the tests, fall back to $topdir/.Trash-$uid */
+  uid = geteuid ();
+  g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long) uid);
+  
+  tmpname = g_strdup_printf (".Trash-%s", uid_str);
+  trashdir = g_build_filename (topdir, tmpname, NULL);
+  g_free (tmpname);
+
+  if (g_lstat (trashdir, &trash_stat) == 0)
+    {
+      g_free (topdir);
+      g_free (trashdir);
+      return
+	S_ISDIR (trash_stat.st_mode) &&
+	trash_stat.st_uid == uid;
+    }
+  g_free (trashdir);
+
+  /* User specific trash didn't exist, can we create it? */
+  res = g_access (topdir, W_OK) == 0;
+  
+  g_free (topdir);
+  
+  return res;
+}
+
+
 static gboolean
 g_local_file_trash (GFile         *file,
 		    GCancellable  *cancellable,

Modified: trunk/gio/glocalfileinfo.c
==============================================================================
--- trunk/gio/glocalfileinfo.c	(original)
+++ trunk/gio/glocalfileinfo.c	Tue Mar 11 14:48:28 2008
@@ -781,6 +781,7 @@
   
   parent_info->writable = FALSE;
   parent_info->is_sticky = FALSE;
+  parent_info->has_trash_dir = FALSE;
   parent_info->device = 0;
 
   if (g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME) ||
@@ -806,6 +807,10 @@
 #endif
 	  parent_info->owner = statbuf.st_uid;
 	  parent_info->device = statbuf.st_dev;
+          /* No need to find trash dir if its not writable anyway */
+          if (parent_info->writable &&
+              g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH))
+            parent_info->has_trash_dir = _g_local_file_has_trash_dir (dir, statbuf.st_dev);
 	}
     }
 }
@@ -863,10 +868,9 @@
 	g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE,
 					   writable);
 
-      /* TODO: This means we can move it, but we should also look for a trash dir */
       if (g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH))
-	g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
-					   writable);
+        g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH,
+                                           writable && parent_info->has_trash_dir);
     }
 }
 

Modified: trunk/gio/glocalfileinfo.h
==============================================================================
--- trunk/gio/glocalfileinfo.h	(original)
+++ trunk/gio/glocalfileinfo.h	Tue Mar 11 14:48:28 2008
@@ -35,10 +35,13 @@
 typedef struct {
   gboolean writable;
   gboolean is_sticky;
+  gboolean has_trash_dir;
   int owner;
   dev_t device;
 } GLocalParentFileInfo;
 
+gboolean   _g_local_file_has_trash_dir        (const char *dirname,
+					       dev_t dir_dev);
 void       _g_local_file_info_get_parent_info (const char                 *dir,
 					       GFileAttributeMatcher      *attribute_matcher,
 					       GLocalParentFileInfo       *parent_info);



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