gio: Add g_unix_mount_get_root_path

Currently, there isn't API to determine root path for mounts created
over bind operation (or btrfs subvolumes). This causes issues to our
volume monitors if there is multiple mounts for one device, which can
happen with libmount-based implementation currently. Let's propagate
root path from libmount over g_unix_mount_get_root_path, so we can
handle this somehow in our volume monitors.

https://gitlab.gnome.org/GNOME/glib/issues/1271
This commit is contained in:
Ondrej Holy 2018-04-26 10:37:33 +02:00
parent 035975da09
commit e1fa5ffb91
3 changed files with 41 additions and 1 deletions

View File

@ -1552,6 +1552,7 @@ g_unix_mount_compare
g_unix_mount_copy g_unix_mount_copy
g_unix_mount_get_mount_path g_unix_mount_get_mount_path
g_unix_mount_get_device_path g_unix_mount_get_device_path
g_unix_mount_get_root_path
g_unix_mount_get_fs_type g_unix_mount_get_fs_type
g_unix_mount_get_options g_unix_mount_get_options
g_unix_mount_is_readonly g_unix_mount_is_readonly

View File

@ -125,6 +125,7 @@ typedef enum {
struct _GUnixMountEntry { struct _GUnixMountEntry {
char *mount_path; char *mount_path;
char *device_path; char *device_path;
char *root_path;
char *filesystem_type; char *filesystem_type;
char *options; char *options;
gboolean is_read_only; gboolean is_read_only;
@ -408,6 +409,7 @@ guess_system_internal (const char *mountpoint,
static GUnixMountEntry * static GUnixMountEntry *
create_unix_mount_entry (const char *device_path, create_unix_mount_entry (const char *device_path,
const char *mount_path, const char *mount_path,
const char *root_path,
const char *filesystem_type, const char *filesystem_type,
const char *options, const char *options,
gboolean is_read_only) gboolean is_read_only)
@ -417,6 +419,7 @@ create_unix_mount_entry (const char *device_path,
mount_entry = g_new0 (GUnixMountEntry, 1); mount_entry = g_new0 (GUnixMountEntry, 1);
mount_entry->device_path = g_strdup (device_path); mount_entry->device_path = g_strdup (device_path);
mount_entry->mount_path = g_strdup (mount_path); mount_entry->mount_path = g_strdup (mount_path);
mount_entry->root_path = g_strdup (root_path);
mount_entry->filesystem_type = g_strdup (filesystem_type); mount_entry->filesystem_type = g_strdup (filesystem_type);
mount_entry->options = g_strdup (options); mount_entry->options = g_strdup (options);
mount_entry->is_read_only = is_read_only; mount_entry->is_read_only = is_read_only;
@ -496,6 +499,7 @@ _g_get_unix_mounts (void)
mount_entry = create_unix_mount_entry (device_path, mount_entry = create_unix_mount_entry (device_path,
mnt_fs_get_target (fs), mnt_fs_get_target (fs),
mnt_fs_get_root (fs),
mnt_fs_get_fstype (fs), mnt_fs_get_fstype (fs),
mnt_fs_get_options (fs), mnt_fs_get_options (fs),
is_read_only); is_read_only);
@ -591,6 +595,7 @@ _g_get_unix_mounts (void)
mount_entry = create_unix_mount_entry (device_path, mount_entry = create_unix_mount_entry (device_path,
mntent->mnt_dir, mntent->mnt_dir,
NULL,
mntent->mnt_type, mntent->mnt_type,
mntent->mnt_opts, mntent->mnt_opts,
is_read_only); is_read_only);
@ -705,6 +710,7 @@ _g_get_unix_mounts (void)
mount_entry = create_unix_mount_entry (mntent.mnt_special, mount_entry = create_unix_mount_entry (mntent.mnt_special,
mntent.mnt_mountp, mntent.mnt_mountp,
NULL,
mntent.mnt_fstype, mntent.mnt_fstype,
mntent.mnt_opts, mntent.mnt_opts,
is_read_only); is_read_only);
@ -772,6 +778,7 @@ _g_get_unix_mounts (void)
mount_entry = create_unix_mount_entry (vmt2dataptr (vmount_info, VMT_OBJECT), mount_entry = create_unix_mount_entry (vmt2dataptr (vmount_info, VMT_OBJECT),
vmt2dataptr (vmount_info, VMT_STUB), vmt2dataptr (vmount_info, VMT_STUB),
NULL,
fs_info == NULL ? "unknown" : fs_info->vfsent_name, fs_info == NULL ? "unknown" : fs_info->vfsent_name,
NULL, NULL,
is_read_only); is_read_only);
@ -848,6 +855,7 @@ _g_get_unix_mounts (void)
mount_entry = create_unix_mount_entry (mntent[i].f_mntfromname, mount_entry = create_unix_mount_entry (mntent[i].f_mntfromname,
mntent[i].f_mntonname, mntent[i].f_mntonname,
NULL,
mntent[i].f_fstypename, mntent[i].f_fstypename,
NULL, NULL,
is_read_only); is_read_only);
@ -1992,6 +2000,7 @@ g_unix_mount_free (GUnixMountEntry *mount_entry)
g_free (mount_entry->mount_path); g_free (mount_entry->mount_path);
g_free (mount_entry->device_path); g_free (mount_entry->device_path);
g_free (mount_entry->root_path);
g_free (mount_entry->filesystem_type); g_free (mount_entry->filesystem_type);
g_free (mount_entry->options); g_free (mount_entry->options);
g_free (mount_entry); g_free (mount_entry);
@ -2017,6 +2026,7 @@ g_unix_mount_copy (GUnixMountEntry *mount_entry)
copy = g_new0 (GUnixMountEntry, 1); copy = g_new0 (GUnixMountEntry, 1);
copy->mount_path = g_strdup (mount_entry->mount_path); copy->mount_path = g_strdup (mount_entry->mount_path);
copy->device_path = g_strdup (mount_entry->device_path); copy->device_path = g_strdup (mount_entry->device_path);
copy->root_path = g_strdup (mount_entry->root_path);
copy->filesystem_type = g_strdup (mount_entry->filesystem_type); copy->filesystem_type = g_strdup (mount_entry->filesystem_type);
copy->options = g_strdup (mount_entry->options); copy->options = g_strdup (mount_entry->options);
copy->is_read_only = mount_entry->is_read_only; copy->is_read_only = mount_entry->is_read_only;
@ -2098,6 +2108,10 @@ g_unix_mount_compare (GUnixMountEntry *mount1,
if (res != 0) if (res != 0)
return res; return res;
res = g_strcmp0 (mount1->root_path, mount2->root_path);
if (res != 0)
return res;
res = g_strcmp0 (mount1->filesystem_type, mount2->filesystem_type); res = g_strcmp0 (mount1->filesystem_type, mount2->filesystem_type);
if (res != 0) if (res != 0)
return res; return res;
@ -2145,6 +2159,29 @@ g_unix_mount_get_device_path (GUnixMountEntry *mount_entry)
return mount_entry->device_path; return mount_entry->device_path;
} }
/**
* g_unix_mount_get_root_path:
* @mount_entry: a #GUnixMountEntry.
*
* Gets the root of the mount within the filesystem. This is useful e.g. for
* mounts created by bind operation, or btrfs subvolumes.
*
* For example, the root path is equal to "/" for mount created by
* "mount /dev/sda1 /mnt/foo" and "/bar" for
* "mount --bind /mnt/foo/bar /mnt/bar".
*
* Returns: (nullable): a string containing the root, or %NULL if not supported.
*
* Since: 2.60
*/
const gchar *
g_unix_mount_get_root_path (GUnixMountEntry *mount_entry)
{
g_return_val_if_fail (mount_entry != NULL, NULL);
return mount_entry->root_path;
}
/** /**
* g_unix_mount_get_fs_type: * g_unix_mount_get_fs_type:
* @mount_entry: a #GUnixMount. * @mount_entry: a #GUnixMount.

View File

@ -79,6 +79,8 @@ GLIB_AVAILABLE_IN_ALL
const char * g_unix_mount_get_mount_path (GUnixMountEntry *mount_entry); const char * g_unix_mount_get_mount_path (GUnixMountEntry *mount_entry);
GLIB_AVAILABLE_IN_ALL GLIB_AVAILABLE_IN_ALL
const char * g_unix_mount_get_device_path (GUnixMountEntry *mount_entry); const char * g_unix_mount_get_device_path (GUnixMountEntry *mount_entry);
GLIB_AVAILABLE_IN_2_60
const char * g_unix_mount_get_root_path (GUnixMountEntry *mount_entry);
GLIB_AVAILABLE_IN_ALL GLIB_AVAILABLE_IN_ALL
const char * g_unix_mount_get_fs_type (GUnixMountEntry *mount_entry); const char * g_unix_mount_get_fs_type (GUnixMountEntry *mount_entry);
GLIB_AVAILABLE_IN_2_58 GLIB_AVAILABLE_IN_2_58