206 lines
5.3 KiB
Diff
206 lines
5.3 KiB
Diff
|
|
From 0f5017fb701b221846f04fa610c8429bbaa49136 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Ondrej Holy <oholy@redhat.com>
|
||
|
|
Date: Thu, 13 Sep 2018 17:33:59 +0200
|
||
|
|
Subject: [PATCH 152/682] 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
|
||
|
|
---
|
||
|
|
gio/glocalfile.c | 104 +++++++++++++++++++++++++++++------------------
|
||
|
|
1 file 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;
|
||
|
|
|
||
|
|
--
|
||
|
|
2.19.1
|
||
|
|
|