diff options
author | Ondrej Holy <oholy@redhat.com> | 2018-09-13 17:33:59 +0200 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2018-10-17 12:42:04 +0200 |
commit | 0f5017fb701b221846f04fa610c8429bbaa49136 (patch) | |
tree | d299a6691313bcbce75bdf6f4eb5fdc9d9649b7d /gio/glocalfile.c | |
parent | 035975da099dc5f4e06d02af4d593c8cf22a2234 (diff) | |
download | glib-0f5017fb701b221846f04fa610c8429bbaa49136.tar.gz |
glocalfile: Fix access::can-trash if parent is symlink
G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH can be set to a wrong value if
its parent dir is a symlink. This is because the find_mountpoint_for()
function tries to find mountpoint for a filepath and expands symlinks
only in parent dirs. But in this case the path is already parent dir
and needs to be expanded first...
Closes: https://gitlab.gnome.org/GNOME/glib/issues/1522
Diffstat (limited to 'gio/glocalfile.c')
-rw-r--r-- | gio/glocalfile.c | 104 |
1 files changed, 65 insertions, 39 deletions
diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 30fa2281c..33b5ba3da 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -109,7 +109,7 @@ G_DEFINE_TYPE_WITH_CODE (GLocalFile, g_local_file, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_FILE, g_local_file_file_iface_init)) -static char *find_mountpoint_for (const char *file, dev_t dev); +static char *find_mountpoint_for (const char *file, dev_t dev, gboolean resolve_basename_symlink); static void g_local_file_finalize (GObject *object) @@ -791,7 +791,7 @@ get_mount_info (GFileInfo *fs_info, { mount_info = 0; - mountpoint = find_mountpoint_for (path, buf.st_dev); + mountpoint = find_mountpoint_for (path, buf.st_dev, FALSE); if (mountpoint == NULL) mountpoint = g_strdup ("/"); @@ -886,7 +886,7 @@ get_volume_for_path (const char *path) } static char * -find_mountpoint_for (const char *file, dev_t dev) +find_mountpoint_for (const char *file, dev_t dev, gboolean resolve_basename_symlink) { wchar_t *wpath; char *utf8_path; @@ -1132,7 +1132,7 @@ g_local_file_find_enclosing_mount (GFile *file, if (g_lstat (local->filename, &buf) != 0) goto error; - mountpoint = find_mountpoint_for (local->filename, buf.st_dev); + mountpoint = find_mountpoint_for (local->filename, buf.st_dev, FALSE); if (mountpoint == NULL) goto error; @@ -1584,12 +1584,51 @@ expand_symlink (const char *link) } static char * -get_parent (const char *path, - dev_t *parent_dev) +expand_symlinks (const char *path, + dev_t *dev) { - char *parent, *tmp; - GStatBuf parent_stat; + char *tmp, *target; + GStatBuf target_stat; int num_recursions; + + target = g_strdup (path); + + num_recursions = 0; + do + { + if (g_lstat (target, &target_stat) != 0) + { + g_free (target); + return NULL; + } + + if (S_ISLNK (target_stat.st_mode)) + { + tmp = target; + target = expand_symlink (target); + g_free (tmp); + } + + num_recursions++; + if (num_recursions > 12) + { + g_free (target); + return NULL; + } + } + while (S_ISLNK (target_stat.st_mode)); + + if (dev) + *dev = target_stat.st_dev; + + return target; +} + +static char * +get_parent (const char *path, + dev_t *parent_dev) +{ + char *parent, *res; char *path_copy; path_copy = strip_trailing_slashes (path); @@ -1604,32 +1643,10 @@ get_parent (const char *path, } g_free (path_copy); - num_recursions = 0; - do { - if (g_lstat (parent, &parent_stat) != 0) - { - g_free (parent); - return NULL; - } - - if (S_ISLNK (parent_stat.st_mode)) - { - tmp = parent; - parent = expand_symlink (parent); - g_free (tmp); - } - - num_recursions++; - if (num_recursions > 12) - { - g_free (parent); - return NULL; - } - } while (S_ISLNK (parent_stat.st_mode)); + res = expand_symlinks (parent, parent_dev); + g_free (parent); - *parent_dev = parent_stat.st_dev; - - return parent; + return res; } static char * @@ -1656,13 +1673,22 @@ expand_all_symlinks (const char *path) } static char * -find_mountpoint_for (const char *file, - dev_t dev) +find_mountpoint_for (const char *file, + dev_t dev, + gboolean resolve_basename_symlink) { char *dir, *parent; dev_t dir_dev, parent_dev; - dir = g_strdup (file); + if (resolve_basename_symlink) + { + dir = expand_symlinks (file, NULL); + if (dir == NULL) + return g_strdup (file); + } + else + dir = g_strdup (file); + dir_dev = dev; while (1) @@ -1693,7 +1719,7 @@ _g_local_file_find_topdir_for (const char *file) if (dir == NULL) return NULL; - mountpoint = find_mountpoint_for (dir, dir_dev); + mountpoint = find_mountpoint_for (dir, dir_dev, TRUE); g_free (dir); return mountpoint; @@ -1789,7 +1815,7 @@ _g_local_file_has_trash_dir (const char *dirname, dev_t dir_dev) if (dir_dev == home_dev) return TRUE; - topdir = find_mountpoint_for (dirname, dir_dev); + topdir = find_mountpoint_for (dirname, dir_dev, TRUE); if (topdir == NULL) return FALSE; @@ -1856,7 +1882,7 @@ _g_local_file_is_lost_found_dir (const char *path, dev_t path_dev) if (!g_str_has_suffix (path, "/lost+found")) goto out; - mount_dir = find_mountpoint_for (path, path_dev); + mount_dir = find_mountpoint_for (path, path_dev, FALSE); if (mount_dir == NULL) goto out; |