[gnome-settings-daemon/benzea/gsd-housekeeping: 8/8] housekeeping: Never cross into a different filesystem



commit c25c003152271fd42eb852da79a4b10be82c1c97
Author: Benjamin Berg <bberg redhat com>
Date:   Thu Feb 20 15:58:35 2020 +0100

    housekeeping: Never cross into a different filesystem
    
    This stops us from crossing into another file system. The test simply
    uses the file system tag, which means that e.g. bind mounts to the same
    file system are not found.
    
    The exception to this is trash:, in that case, set filesystem to NULL
    and allow crossing over. This must be done as trash: is virtual and
    files might be coming from various locations.
    
    Fixes: #252

 plugins/housekeeping/gsd-disk-space.c      | 56 +++++++++++++++++++++++++-----
 plugins/housekeeping/gsd-disk-space.h      |  6 +++-
 plugins/housekeeping/gsd-purge-temp-test.c |  4 ++-
 3 files changed, 56 insertions(+), 10 deletions(-)
---
diff --git a/plugins/housekeeping/gsd-disk-space.c b/plugins/housekeeping/gsd-disk-space.c
index 87c130af..9d57531f 100644
--- a/plugins/housekeeping/gsd-disk-space.c
+++ b/plugins/housekeeping/gsd-disk-space.c
@@ -251,13 +251,15 @@ delete_data_new (GFile        *file,
                  GDateTime    *old,
                  gboolean      dry_run,
                  gboolean      trash,
-                 gint          depth)
+                 gint          depth,
+                 const char   *filesystem)
 {
         DeleteData *data;
 
         data = g_new (DeleteData, 1);
         data->ref_count = 1;
         data->file = g_object_ref (file);
+        data->filesystem = g_strdup (filesystem);
         data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
         data->old = g_date_time_ref (old);
         data->dry_run = dry_run;
@@ -268,6 +270,21 @@ delete_data_new (GFile        *file,
         return data;
 }
 
+char*
+get_filesystem (GFile *file)
+{
+        g_autoptr(GFileInfo) info = NULL;
+
+        info = g_file_query_info (file,
+                                  G_FILE_ATTRIBUTE_ID_FILESYSTEM,
+                                  G_FILE_QUERY_INFO_NONE,
+                                  NULL,
+                                  NULL);
+
+        return g_file_info_get_attribute_as_string (info,
+                                                    G_FILE_ATTRIBUTE_ID_FILESYSTEM);
+}
+
 static DeleteData *
 delete_data_ref (DeleteData *data)
 {
@@ -287,6 +304,7 @@ delete_data_unref (DeleteData *data)
                 g_object_unref (data->cancellable);
         g_date_time_unref (data->old);
         g_free (data->name);
+        g_free (data->filesystem);
         g_free (data);
 }
 
@@ -297,6 +315,7 @@ delete_batch (GObject      *source,
 {
         GFileEnumerator *enumerator = G_FILE_ENUMERATOR (source);
         DeleteData *data = user_data;
+        const char *fs;
         GList *files, *f;
         GFile *child_file;
         DeleteData *child;
@@ -313,13 +332,26 @@ delete_batch (GObject      *source,
                                 break;
                         info = f->data;
 
+                        fs = g_file_info_get_attribute_string (info,
+                                                               G_FILE_ATTRIBUTE_ID_FILESYSTEM);
+
+                        /* Do not consider the file if it is on a different file system.
+                         * Ignore data->filesystem if it is NULL (this only happens if
+                         * it is the toplevel trash directory). */
+                        if (data->filesystem && g_strcmp0 (fs, data->filesystem) != 0) {
+                                g_debug ("GsdHousekeeping: skipping file \"%s\" as it is on a different file 
system",
+                                         g_file_info_get_name (info));
+                                continue;
+                        }
+
                         child_file = g_file_get_child (data->file, g_file_info_get_name (info));
                         child = delete_data_new (child_file,
                                                  data->cancellable,
                                                  data->old,
                                                  data->dry_run,
                                                  data->trash,
-                                                 data->depth + 1);
+                                                 data->depth + 1,
+                                                 fs);
                         delete_recursively_by_age (child);
                         delete_data_unref (child);
                         g_object_unref (child_file);
@@ -418,7 +450,8 @@ delete_subdir_check_symlink (GObject      *source,
         } else {
                 g_file_enumerate_children_async (data->file,
                                                  G_FILE_ATTRIBUTE_STANDARD_NAME ","
-                                                 G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                                                 G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+                                                 G_FILE_ATTRIBUTE_ID_FILESYSTEM,
                                                  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                                  0,
                                                  data->cancellable,
@@ -455,7 +488,7 @@ gsd_ldsm_purge_trash (GDateTime *old)
         DeleteData *data;
 
         file = g_file_new_for_uri ("trash:");
-        data = delete_data_new (file, NULL, old, FALSE, TRUE, 0);
+        data = delete_data_new (file, NULL, old, FALSE, TRUE, 0, NULL);
         delete_recursively_by_age (data);
         delete_data_unref (data);
         g_object_unref (file);
@@ -466,6 +499,7 @@ gsd_ldsm_purge_temp_files (GDateTime *old)
 {
         DeleteData *data;
         GFile *file;
+        char *filesystem;
 
         /* Never clean temporary files on a sane (i.e. systemd managed)
          * system. In that case systemd already ships
@@ -482,14 +516,18 @@ gsd_ldsm_purge_temp_files (GDateTime *old)
                 return;
 
         file = g_file_new_for_path (g_get_tmp_dir ());
-        data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
+        filesystem = get_filesystem (file);
+        data = delete_data_new (file, NULL, old, FALSE, FALSE, 0, filesystem);
+        g_free (filesystem);
         delete_recursively_by_age (data);
         delete_data_unref (data);
         g_object_unref (file);
 
         if (g_strcmp0 (g_get_tmp_dir (), "/var/tmp") != 0) {
                 file = g_file_new_for_path ("/var/tmp");
-                data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
+                filesystem = get_filesystem (file);
+                data = delete_data_new (file, NULL, old, FALSE, FALSE, 0, filesystem);
+                g_free (filesystem);
                 delete_recursively_by_age (data);
                 delete_data_unref (data);
                 g_object_unref (file);
@@ -497,7 +535,9 @@ gsd_ldsm_purge_temp_files (GDateTime *old)
 
         if (g_strcmp0 (g_get_tmp_dir (), "/tmp") != 0) {
                 file = g_file_new_for_path ("/tmp");
-                data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
+                filesystem = get_filesystem (file);
+                data = delete_data_new (file, NULL, old, FALSE, FALSE, 0, filesystem);
+                g_free (filesystem);
                 delete_recursively_by_age (data);
                 delete_data_unref (data);
                 g_object_unref (file);
@@ -513,7 +553,7 @@ gsd_ldsm_show_empty_trash (void)
 
         old = g_date_time_new_now_local ();
         file = g_file_new_for_uri ("trash:");
-        data = delete_data_new (file, NULL, old, TRUE, TRUE, 0);
+        data = delete_data_new (file, NULL, old, TRUE, TRUE, 0, NULL);
         g_object_unref (file);
         g_date_time_unref (old);
 
diff --git a/plugins/housekeeping/gsd-disk-space.h b/plugins/housekeeping/gsd-disk-space.h
index 67e4a4a9..38c29639 100644
--- a/plugins/housekeeping/gsd-disk-space.h
+++ b/plugins/housekeeping/gsd-disk-space.h
@@ -35,6 +35,7 @@ typedef struct {
         gboolean         dry_run;
         gboolean         trash;
         gchar           *name;
+        gchar           *filesystem;
         gint             depth;
 } DeleteData;
 
@@ -44,7 +45,10 @@ DeleteData *delete_data_new (GFile        *file,
                              GDateTime    *old,
                              gboolean      dry_run,
                              gboolean      trash,
-                             gint          depth);
+                             gint          depth,
+                             const char   *filesystem);
+char* get_filesystem (GFile *file);
+
 void delete_recursively_by_age (DeleteData *data);
 
 void gsd_ldsm_setup (gboolean check_now);
diff --git a/plugins/housekeeping/gsd-purge-temp-test.c b/plugins/housekeeping/gsd-purge-temp-test.c
index 2e789327..6ff2d5eb 100644
--- a/plugins/housekeeping/gsd-purge-temp-test.c
+++ b/plugins/housekeeping/gsd-purge-temp-test.c
@@ -33,6 +33,7 @@ main (int    argc,
         DeleteData *data;
         GDateTime *old;
         GMainLoop *loop;
+        g_autofree char *filesystem = NULL;
 
         g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
 
@@ -48,7 +49,8 @@ main (int    argc,
         }
 
         old = g_date_time_new_now_local ();
-        data = delete_data_new (file, NULL, old, FALSE, FALSE, 0);
+        filesystem = get_filesystem (file);
+        data = delete_data_new (file, NULL, old, FALSE, FALSE, 0, filesystem);
         delete_recursively_by_age (data);
         delete_data_unref (data);
         g_object_unref (file);


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