From a9aab0702cb513604ad425cd652745c1e68b4a6b Mon Sep 17 00:00:00 2001 From: WGH Date: Sun, 9 Jan 2022 22:35:46 +0300 Subject: [PATCH] GIOLister: ignore system mounts as defined by GIO Strawberry has some heuristics to exclude things like the root mount, /boot, tmpfs, etc. from the devices list. However, it's somewhat incomplete. GIO (GLib component) has more complete definition of "internal system mounts" that should not be presented to the user. Additionally, don't try to query filesystems free/total size if it's internal, as that triggers automounting for autofs filesystems (#410). --- CMakeLists.txt | 8 ++++++++ src/CMakeLists.txt | 9 +++++++++ src/config.h.in | 1 + src/device/giolister.cpp | 26 ++++++++++++++++++++++---- src/device/giolister.h | 3 ++- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0bb6cfcec..9d6bebd82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,9 @@ endif() pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(GOBJECT REQUIRED gobject-2.0) pkg_check_modules(GIO REQUIRED gio-2.0) +if(UNIX) + pkg_check_modules(GIO_UNIX gio-unix-2.0) +endif() pkg_check_modules(LIBCDIO libcdio) pkg_check_modules(GSTREAMER gstreamer-1.0) pkg_check_modules(GSTREAMER_BASE gstreamer-base-1.0) @@ -391,6 +394,11 @@ optional_component(GIO ON "Devices: GIO device backend" DEPENDS "Unix or Windows" "NOT APPLE" ) +optional_component(GIO_UNIX ON "Devices: GIO device backend (Unix support)" + DEPENDS "libgio-unix" GIO_UNIX_FOUND + DEPENDS "Unix" "UNIX" +) + optional_component(LIBGPOD ON "Devices: iPod classic support" DEPENDS "libgpod" LIBGPOD_FOUND DEPENDS "gdk-pixbuf" GDK_PIXBUF_FOUND diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd22e1fca..d1a85043c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -986,6 +986,10 @@ if(HAVE_GIO) link_directories(${GIO_LIBRARY_DIRS}) endif() +if(HAVE_GIO_UNIX) + link_directories(${GIO_UNIX_LIBRARY_DIRS}) +endif() + if(HAVE_AUDIOCD) link_directories(${LIBCDIO_LIBRARY_DIRS}) endif() @@ -1113,6 +1117,11 @@ if(HAVE_GIO) target_link_libraries(strawberry_lib PRIVATE ${GIO_LIBRARIES}) endif() +if(HAVE_GIO_UNIX) + target_include_directories(strawberry_lib SYSTEM PRIVATE ${GIO_UNIX_INCLUDE_DIRS}) + target_link_libraries(strawberry_lib PRIVATE ${GIO_UNIX_LIBRARIES}) +endif() + if(HAVE_AUDIOCD) target_include_directories(strawberry_lib SYSTEM PRIVATE ${LIBCDIO_INCLUDE_DIRS}) target_link_libraries(strawberry_lib PRIVATE ${LIBCDIO_LIBRARIES}) diff --git a/src/config.h.in b/src/config.h.in index 395f03b66..08f8a277b 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -7,6 +7,7 @@ #cmakedefine HAVE_BACKTRACE #cmakedefine HAVE_GIO +#cmakedefine HAVE_GIO_UNIX #cmakedefine HAVE_DBUS #cmakedefine HAVE_X11 #cmakedefine HAVE_UDISKS2 diff --git a/src/device/giolister.cpp b/src/device/giolister.cpp index 77520d176..b01e24c47 100644 --- a/src/device/giolister.cpp +++ b/src/device/giolister.cpp @@ -25,6 +25,9 @@ #include #include #include +#ifdef HAVE_GIO_UNIX +# include +#endif #include #include @@ -60,6 +63,8 @@ bool GioLister::DeviceInfo::is_suitable() const { if (!volume_ptr) return false; // This excludes smb or ssh mounts + if (is_system_internal) return false; + if (drive_ptr && !drive_removable) return false; // This excludes internal drives if (filesystem_type.isEmpty()) return true; @@ -447,7 +452,8 @@ void GioLister::DeviceInfo::ReadMountInfo(GMount *mount) { } g_object_unref(icon); - GFile *root = g_mount_get_root(mount); + ScopedGObject root; + root.reset_without_add(g_mount_get_root(mount)); // Get the mount path mount_path = ConvertAndFree(g_file_get_path(root)); @@ -466,6 +472,21 @@ void GioLister::DeviceInfo::ReadMountInfo(GMount *mount) { g_object_unref(actual_mount); } +#ifdef HAVE_GIO_UNIX + GUnixMountEntry *unix_mount = g_unix_mount_for(g_file_get_path(root), NULL); + if (unix_mount) { + // the GIO's definition of system internal mounts include filesystems like + // autofs, tmpfs, sysfs, etc, and various system directories, including the root, + // /boot, /var, /home, etc. + is_system_internal = g_unix_mount_is_system_internal(unix_mount); + g_unix_mount_free(unix_mount); + // Although checking most of the internal mounts is safe, + // we really don't want to touch autofs filesystems, as that would + // trigger automounting. + if (is_system_internal) return; + } +#endif + // Query the filesystem info for size, free space, and type error = nullptr; GFileInfo *info = g_file_query_filesystem_info(root, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE "," G_FILE_ATTRIBUTE_FILESYSTEM_FREE "," G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, nullptr, &error); @@ -494,9 +515,6 @@ void GioLister::DeviceInfo::ReadMountInfo(GMount *mount) { g_object_unref(info); } } - - g_object_unref(root); - } void GioLister::DeviceInfo::ReadVolumeInfo(GVolume *volume) { diff --git a/src/device/giolister.h b/src/device/giolister.h index d7169f35f..9c0e8ee06 100644 --- a/src/device/giolister.h +++ b/src/device/giolister.h @@ -77,7 +77,7 @@ class GioLister : public DeviceLister { private: struct DeviceInfo { - DeviceInfo() : drive_removable(false), filesystem_size(0), filesystem_free(0), invalid_enclosing_mount(false) {} + DeviceInfo() : drive_removable(false), filesystem_size(0), filesystem_free(0), invalid_enclosing_mount(false), is_system_internal(false) {} QString unique_id() const; bool is_suitable() const; @@ -111,6 +111,7 @@ class GioLister : public DeviceLister { QString filesystem_type; bool invalid_enclosing_mount; + bool is_system_internal; }; void VolumeAdded(GVolume *volume);