mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
Correctly implement can_trash by actually looking for a trash dir, not
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. svn path=/trunk/; revision=6679
This commit is contained in:
parent
15f3867833
commit
c5a10d2650
@ -1,3 +1,11 @@
|
||||
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.
|
||||
|
||||
2008-03-10 Matthias Clasen <mclasen@redhat.com>
|
||||
|
||||
* === Released 2.16.1 ===
|
||||
|
@ -1576,6 +1576,79 @@ escape_trash_name (char *name)
|
||||
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,
|
||||
|
@ -781,6 +781,7 @@ _g_local_file_info_get_parent_info (const char *dir,
|
||||
|
||||
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 @@ _g_local_file_info_get_parent_info (const char *dir,
|
||||
#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 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,13 @@ G_BEGIN_DECLS
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user