mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-02 17:26:17 +01:00
Merge branch 'wip/pwithnall/unix-mount-tests' into 'main'
gunixmounts: Add mount point/entry getters from files and add tests based on them See merge request GNOME/glib!4163
This commit is contained in:
commit
f4aceb0e91
@ -148,7 +148,13 @@ G_DEFINE_BOXED_TYPE (GUnixMountPoint, g_unix_mount_point,
|
||||
g_unix_mount_point_copy, g_unix_mount_point_free)
|
||||
|
||||
static GList *_g_get_unix_mounts (void);
|
||||
static GUnixMountEntry **_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out);
|
||||
static GList *_g_get_unix_mount_points (void);
|
||||
static GUnixMountPoint **_g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out);
|
||||
static gboolean proc_mounts_watch_is_running (void);
|
||||
|
||||
G_LOCK_DEFINE_STATIC (proc_mounts_source);
|
||||
@ -206,6 +212,9 @@ static GSource *proc_mounts_watch_source = NULL;
|
||||
static struct libmnt_monitor *proc_mounts_monitor = NULL;
|
||||
#endif
|
||||
|
||||
static guint64 get_mounts_timestamp (void);
|
||||
static guint64 get_mount_points_timestamp (void);
|
||||
|
||||
static gboolean
|
||||
is_in (const char *value, const char *set[])
|
||||
{
|
||||
@ -218,6 +227,45 @@ is_in (const char *value, const char *set[])
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Marked as unused because these are only used on some platform variants, but
|
||||
* working out the #if sequence for that would be too much for my little brain. */
|
||||
static GList *unix_mount_entry_array_free_to_list (GUnixMountEntry **entries,
|
||||
size_t n_entries) G_GNUC_UNUSED;
|
||||
static GList *unix_mount_point_array_free_to_list (GUnixMountPoint **points,
|
||||
size_t n_points) G_GNUC_UNUSED;
|
||||
|
||||
/* Helper to convert to a list for the old API.
|
||||
* Steals ownership of the @entries array. */
|
||||
static GList *
|
||||
unix_mount_entry_array_free_to_list (GUnixMountEntry **entries,
|
||||
size_t n_entries)
|
||||
{
|
||||
GList *l = NULL;
|
||||
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
l = g_list_prepend (l, g_steal_pointer (&entries[i]));
|
||||
|
||||
g_free (entries);
|
||||
|
||||
return g_list_reverse (l);
|
||||
}
|
||||
|
||||
/* Helper to convert to a list for the old API.
|
||||
* Steals ownership of the @entries array. */
|
||||
static GList *
|
||||
unix_mount_point_array_free_to_list (GUnixMountPoint **points,
|
||||
size_t n_points)
|
||||
{
|
||||
GList *l = NULL;
|
||||
|
||||
for (size_t i = 0; i < n_points; i++)
|
||||
l = g_list_prepend (l, g_steal_pointer (&points[i]));
|
||||
|
||||
g_free (points);
|
||||
|
||||
return g_list_reverse (l);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_is_mount_path_system_internal:
|
||||
* @mount_path: (type filename): a mount path, e.g. `/media/disk` or `/usr`
|
||||
@ -501,17 +549,23 @@ create_unix_mount_point (const char *device_path,
|
||||
*/
|
||||
#define PROC_MOUNTINFO_PATH "/proc/self/mountinfo"
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
struct libmnt_table *table = NULL;
|
||||
struct libmnt_iter* iter = NULL;
|
||||
struct libmnt_fs *fs = NULL;
|
||||
GUnixMountEntry *mount_entry = NULL;
|
||||
GList *return_list = NULL;
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mounts_timestamp ();
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_free, TRUE);
|
||||
table = mnt_new_table ();
|
||||
if (mnt_table_parse_mtab (table, NULL) < 0)
|
||||
if (mnt_table_parse_mtab (table, table_path) < 0)
|
||||
goto out;
|
||||
|
||||
iter = mnt_new_iter (MNT_ITER_FORWARD);
|
||||
@ -541,14 +595,29 @@ _g_get_unix_mounts (void)
|
||||
mnt_fs_get_options (fs),
|
||||
is_read_only);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_entry));
|
||||
}
|
||||
mnt_free_iter (iter);
|
||||
|
||||
out:
|
||||
mnt_free_table (table);
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = return_array->len;
|
||||
|
||||
return (GUnixMountEntry **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
{
|
||||
GUnixMountEntry **entries = NULL;
|
||||
size_t n_entries = 0;
|
||||
|
||||
entries = _g_unix_mounts_get_from_file (NULL /* default libmount filename */,
|
||||
NULL, &n_entries);
|
||||
|
||||
return unix_mount_entry_array_free_to_list (g_steal_pointer (&entries), n_entries);
|
||||
}
|
||||
|
||||
#else
|
||||
@ -571,8 +640,10 @@ get_mtab_read_file (void)
|
||||
G_LOCK_DEFINE_STATIC(getmntent);
|
||||
#endif
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
#ifdef HAVE_GETMNTENT_R
|
||||
struct mntent ent;
|
||||
@ -580,19 +651,18 @@ _g_get_unix_mounts (void)
|
||||
#endif
|
||||
struct mntent *mntent;
|
||||
FILE *file;
|
||||
const char *read_file;
|
||||
GUnixMountEntry *mount_entry;
|
||||
GHashTable *mounts_hash;
|
||||
GList *return_list;
|
||||
|
||||
read_file = get_mtab_read_file ();
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
file = setmntent (read_file, "re");
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mounts_timestamp ();
|
||||
|
||||
file = setmntent (table_path, "re");
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
|
||||
return_list = NULL;
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_free, TRUE);
|
||||
mounts_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
|
||||
#ifdef HAVE_GETMNTENT_R
|
||||
@ -641,7 +711,7 @@ _g_get_unix_mounts (void)
|
||||
mount_entry->device_path,
|
||||
mount_entry->device_path);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_entry));
|
||||
}
|
||||
g_hash_table_destroy (mounts_hash);
|
||||
|
||||
@ -651,7 +721,21 @@ _g_get_unix_mounts (void)
|
||||
G_UNLOCK (getmntent);
|
||||
#endif
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = return_array->len;
|
||||
|
||||
return (GUnixMountEntry **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
{
|
||||
GUnixMountEntry **entries = NULL;
|
||||
size_t n_entries = 0;
|
||||
|
||||
entries = _g_unix_mounts_get_from_file (get_mtab_read_file (), NULL, &n_entries);
|
||||
|
||||
return unix_mount_entry_array_free_to_list (g_steal_pointer (&entries), n_entries);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBMOUNT */
|
||||
@ -718,23 +802,26 @@ get_mtab_monitor_file (void)
|
||||
return get_mtab_read_file ();
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
struct mnttab mntent;
|
||||
FILE *file;
|
||||
const char *read_file;
|
||||
GUnixMountEntry *mount_entry;
|
||||
GList *return_list;
|
||||
|
||||
read_file = get_mtab_read_file ();
|
||||
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mounts_timestamp ();
|
||||
|
||||
file = setmntent (read_file, "re");
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
|
||||
return_list = NULL;
|
||||
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_free, TRUE);
|
||||
|
||||
G_LOCK (getmntent);
|
||||
while (! getmntent (file, &mntent))
|
||||
{
|
||||
@ -752,14 +839,28 @@ _g_get_unix_mounts (void)
|
||||
mntent.mnt_opts,
|
||||
is_read_only);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_entry);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_entry));
|
||||
}
|
||||
|
||||
endmntent (file);
|
||||
|
||||
G_UNLOCK (getmntent);
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = return_array->len;
|
||||
|
||||
return (GUnixMountEntry **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
{
|
||||
GUnixMountEntry **entries = NULL;
|
||||
size_t n_entries = 0;
|
||||
|
||||
entries = _g_unix_mounts_get_from_file (get_mtab_read_file (), NULL, &n_entries);
|
||||
|
||||
return unix_mount_entry_array_free_to_list (g_steal_pointer (&entries), n_entries);
|
||||
}
|
||||
|
||||
/* mntctl.h (AIX) {{{2 */
|
||||
@ -832,6 +933,20 @@ _g_get_unix_mounts (void)
|
||||
return g_list_reverse (return_list);
|
||||
}
|
||||
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
/* Not supported on mntctl() systems. */
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = 0;
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* sys/mount.h {{{2 */
|
||||
#elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
|
||||
|
||||
@ -905,6 +1020,20 @@ _g_get_unix_mounts (void)
|
||||
return g_list_reverse (return_list);
|
||||
}
|
||||
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
/* Not supported on getvfsstat()/getfsstat() systems. */
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = 0;
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Interix {{{2 */
|
||||
#elif defined(__INTERIX)
|
||||
|
||||
@ -962,6 +1091,20 @@ _g_get_unix_mounts (void)
|
||||
return return_list;
|
||||
}
|
||||
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
/* Not supported on Interix systems. */
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = 0;
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* QNX {{{2 */
|
||||
#elif defined (HAVE_QNX)
|
||||
|
||||
@ -972,6 +1115,20 @@ get_mtab_monitor_file (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GUnixMountEntry **
|
||||
_g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
/* Not implemented, as per _g_get_unix_mounts() below */
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = 0;
|
||||
if (n_entries_out != NULL)
|
||||
*n_entries_out = 0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mounts (void)
|
||||
{
|
||||
@ -1015,17 +1172,23 @@ get_fstab_file (void)
|
||||
|
||||
#ifdef HAVE_LIBMOUNT
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
static GUnixMountPoint **
|
||||
_g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out)
|
||||
{
|
||||
struct libmnt_table *table = NULL;
|
||||
struct libmnt_iter* iter = NULL;
|
||||
struct libmnt_fs *fs = NULL;
|
||||
GUnixMountPoint *mount_point = NULL;
|
||||
GList *return_list = NULL;
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mount_points_timestamp ();
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
|
||||
table = mnt_new_table ();
|
||||
if (mnt_table_parse_fstab (table, NULL) < 0)
|
||||
if (mnt_table_parse_fstab (table, table_path) < 0)
|
||||
goto out;
|
||||
|
||||
iter = mnt_new_iter (MNT_ITER_FORWARD);
|
||||
@ -1089,20 +1252,37 @@ _g_get_unix_mount_points (void)
|
||||
if (mount_options)
|
||||
g_free (mount_options);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_point);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
|
||||
}
|
||||
mnt_free_iter (iter);
|
||||
|
||||
out:
|
||||
mnt_free_table (table);
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = return_array->len;
|
||||
|
||||
return (GUnixMountPoint **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
{
|
||||
GUnixMountPoint **points = NULL;
|
||||
size_t n_points = 0;
|
||||
|
||||
points = _g_unix_mount_points_get_from_file (NULL /* default libmount filename */,
|
||||
NULL, &n_points);
|
||||
|
||||
return unix_mount_point_array_free_to_list (g_steal_pointer (&points), n_points);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
static GUnixMountPoint **
|
||||
_g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out)
|
||||
{
|
||||
#ifdef HAVE_GETMNTENT_R
|
||||
struct mntent ent;
|
||||
@ -1112,16 +1292,21 @@ _g_get_unix_mount_points (void)
|
||||
FILE *file;
|
||||
char *read_file;
|
||||
GUnixMountPoint *mount_point;
|
||||
GList *return_list;
|
||||
|
||||
read_file = get_fstab_file ();
|
||||
|
||||
file = setmntent (read_file, "re");
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mount_points_timestamp ();
|
||||
|
||||
file = setmntent (table_path, "re");
|
||||
if (file == NULL)
|
||||
{
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
|
||||
|
||||
return_list = NULL;
|
||||
|
||||
#ifdef HAVE_GETMNTENT_R
|
||||
while ((mntent = getmntent_r (file, &ent, buf, sizeof (buf))) != NULL)
|
||||
#else
|
||||
@ -1177,7 +1362,7 @@ _g_get_unix_mount_points (void)
|
||||
is_user_mountable,
|
||||
is_loopback);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_point);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
|
||||
}
|
||||
|
||||
endmntent (file);
|
||||
@ -1185,8 +1370,23 @@ _g_get_unix_mount_points (void)
|
||||
#ifndef HAVE_GETMNTENT_R
|
||||
G_UNLOCK (getmntent);
|
||||
#endif
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = return_array->len;
|
||||
|
||||
return (GUnixMountPoint **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
{
|
||||
GUnixMountPoint **points = NULL;
|
||||
size_t n_points = 0;
|
||||
|
||||
points = _g_unix_mount_points_get_from_file (get_fstab_file (),
|
||||
NULL, &n_points);
|
||||
|
||||
return unix_mount_point_array_free_to_list (g_steal_pointer (&points), n_points);
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBMOUNT */
|
||||
@ -1194,22 +1394,29 @@ _g_get_unix_mount_points (void)
|
||||
/* mnttab.h {{{2 */
|
||||
#elif defined (HAVE_SYS_MNTTAB_H)
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
static GUnixMountPoint **
|
||||
_g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out)
|
||||
{
|
||||
struct mnttab mntent;
|
||||
FILE *file;
|
||||
char *read_file;
|
||||
GUnixMountPoint *mount_point;
|
||||
GList *return_list;
|
||||
|
||||
read_file = get_fstab_file ();
|
||||
|
||||
file = setmntent (read_file, "re");
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
return_list = NULL;
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mount_points_timestamp ();
|
||||
|
||||
file = setmntent (table_path, "re");
|
||||
if (file == NULL)
|
||||
{
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
|
||||
|
||||
G_LOCK (getmntent);
|
||||
while (! getmntent (file, &mntent))
|
||||
@ -1249,13 +1456,28 @@ _g_get_unix_mount_points (void)
|
||||
is_user_mountable,
|
||||
is_loopback);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_point);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
|
||||
}
|
||||
|
||||
endmntent (file);
|
||||
G_UNLOCK (getmntent);
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = return_array->len;
|
||||
|
||||
return (GUnixMountPoint **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
{
|
||||
GUnixMountPoint **points = NULL;
|
||||
size_t n_points = 0;
|
||||
|
||||
points = _g_unix_mount_points_get_from_file (get_fstab_file (),
|
||||
NULL, &n_points);
|
||||
|
||||
return unix_mount_point_array_free_to_list (g_steal_pointer (&points), n_points);
|
||||
}
|
||||
|
||||
/* mntctl.h (AIX) {{{2 */
|
||||
@ -1368,24 +1590,31 @@ aix_fs_get (FILE *fd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
static GUnixMountPoint **
|
||||
_g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out)
|
||||
{
|
||||
struct mntent *mntent;
|
||||
FILE *file;
|
||||
char *read_file;
|
||||
GUnixMountPoint *mount_point;
|
||||
AixMountTableEntry mntent;
|
||||
GList *return_list;
|
||||
|
||||
read_file = get_fstab_file ();
|
||||
|
||||
file = setmntent (read_file, "re");
|
||||
GPtrArray *return_array = NULL;
|
||||
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = get_mount_points_timestamp ();
|
||||
|
||||
file = setmntent (table_path, "re");
|
||||
if (file == NULL)
|
||||
return NULL;
|
||||
|
||||
return_list = NULL;
|
||||
|
||||
{
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
|
||||
|
||||
while (!aix_fs_get (file, &mntent))
|
||||
{
|
||||
if (strcmp ("cdrfs", mntent.mnt_fstype) == 0)
|
||||
@ -1398,13 +1627,28 @@ _g_get_unix_mount_points (void)
|
||||
TRUE,
|
||||
FALSE);
|
||||
|
||||
return_list = g_list_prepend (return_list, mount_point);
|
||||
g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
|
||||
}
|
||||
}
|
||||
|
||||
endmntent (file);
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = return_array->len;
|
||||
|
||||
return (GUnixMountPoint **) g_ptr_array_free (g_steal_pointer (&return_array), FALSE);
|
||||
}
|
||||
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
{
|
||||
GUnixMountPoint **points = NULL;
|
||||
size_t n_points = 0;
|
||||
|
||||
points = _g_unix_mount_points_get_from_file (get_fstab_file (),
|
||||
NULL, &n_points);
|
||||
|
||||
return unix_mount_point_array_free_to_list (g_steal_pointer (&points), n_points);
|
||||
}
|
||||
|
||||
#elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
|
||||
@ -1495,20 +1739,18 @@ _g_get_unix_mount_points (void)
|
||||
|
||||
return g_list_reverse (return_list);
|
||||
}
|
||||
/* Interix {{{2 */
|
||||
#elif defined(__INTERIX)
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
{
|
||||
return _g_get_unix_mounts ();
|
||||
}
|
||||
|
||||
/* QNX {{{2 */
|
||||
#elif defined (HAVE_QNX)
|
||||
static GList *
|
||||
_g_get_unix_mount_points (void)
|
||||
static GUnixMountPoint **
|
||||
_g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out)
|
||||
{
|
||||
return _g_get_unix_mounts ();
|
||||
/* Not supported on getfsent() systems. */
|
||||
if (time_read_out != NULL)
|
||||
*time_read_out = 0;
|
||||
if (n_points_out != NULL)
|
||||
*n_points_out = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Common code {{{2 */
|
||||
@ -1588,6 +1830,37 @@ g_unix_mounts_get (guint64 *time_read)
|
||||
return _g_get_unix_mounts ();
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_mounts_get_from_file:
|
||||
* @table_path: path to the mounts table file (for example `/proc/self/mountinfo`)
|
||||
* @time_read_out: (optional) (out caller-allocates): return location for the
|
||||
* modification time of @table_path
|
||||
* @n_entries_out: (optional) (out caller-allocates): return location for the
|
||||
* number of mount entries returned
|
||||
*
|
||||
* Gets an array of [struct@Gio.UnixMountEntry]s containing the Unix mounts
|
||||
* listed in @table_path.
|
||||
*
|
||||
* This is a generalized version of g_unix_mounts_get(), mainly intended for
|
||||
* internal testing use. Note that g_unix_mounts_get() may parse multiple
|
||||
* hierarchical table files, so this function is not a direct superset of its
|
||||
* functionality.
|
||||
*
|
||||
* If there is an error reading or parsing the file, `NULL` will be returned
|
||||
* and both out parameters will be set to `0`.
|
||||
*
|
||||
* Returns: (transfer full) (array length=n_entries_out) (nullable): mount
|
||||
* entries, or `NULL` if there was an error loading them
|
||||
* Since: 2.82
|
||||
*/
|
||||
GUnixMountEntry **
|
||||
g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out)
|
||||
{
|
||||
return _g_unix_mounts_get_from_file (table_path, time_read_out, n_entries_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_mount_at:
|
||||
* @mount_path: (type filename): path for a possible unix mount.
|
||||
@ -1724,6 +1997,37 @@ g_unix_mount_points_get (guint64 *time_read)
|
||||
return mnt_pts;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_mount_points_get_from_file:
|
||||
* @table_path: path to the mount points table file (for example `/etc/fstab`)
|
||||
* @time_read_out: (optional) (out caller-allocates): return location for the
|
||||
* modification time of @table_path
|
||||
* @n_points_out: (optional) (out caller-allocates): return location for the
|
||||
* number of mount points returned
|
||||
*
|
||||
* Gets an array of [struct@Gio.UnixMountPoint]s containing the Unix mount
|
||||
* points listed in @table_path.
|
||||
*
|
||||
* This is a generalized version of g_unix_mount_points_get(), mainly intended
|
||||
* for internal testing use. Note that g_unix_mount_points_get() may parse
|
||||
* multiple hierarchical table files, so this function is not a direct superset
|
||||
* of its functionality.
|
||||
*
|
||||
* If there is an error reading or parsing the file, `NULL` will be returned
|
||||
* and both out parameters will be set to `0`.
|
||||
*
|
||||
* Returns: (transfer full) (array length=n_points_out) (nullable): mount
|
||||
* points, or `NULL` if there was an error loading them
|
||||
* Since: 2.82
|
||||
*/
|
||||
GUnixMountPoint **
|
||||
g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out)
|
||||
{
|
||||
return _g_unix_mount_points_get_from_file (table_path, time_read_out, n_points_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_unix_mount_point_at:
|
||||
* @mount_path: (type filename): path for a possible unix mount point.
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define __G_UNIX_MOUNTS_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -134,11 +135,19 @@ GIcon * g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint *mount
|
||||
|
||||
GIO_AVAILABLE_IN_ALL
|
||||
GList * g_unix_mount_points_get (guint64 *time_read);
|
||||
GIO_AVAILABLE_IN_2_82
|
||||
GUnixMountPoint **g_unix_mount_points_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_points_out);
|
||||
GIO_AVAILABLE_IN_2_66
|
||||
GUnixMountPoint *g_unix_mount_point_at (const char *mount_path,
|
||||
guint64 *time_read);
|
||||
GIO_AVAILABLE_IN_ALL
|
||||
GList * g_unix_mounts_get (guint64 *time_read);
|
||||
GIO_AVAILABLE_IN_2_82
|
||||
GUnixMountEntry **g_unix_mounts_get_from_file (const char *table_path,
|
||||
uint64_t *time_read_out,
|
||||
size_t *n_entries_out);
|
||||
GIO_AVAILABLE_IN_ALL
|
||||
GUnixMountEntry *g_unix_mount_at (const char *mount_path,
|
||||
guint64 *time_read);
|
||||
|
@ -18,6 +18,8 @@
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#ifndef G_OS_UNIX
|
||||
@ -26,6 +28,12 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
/* Needed on macOS and FreeBSD for uselocale() */
|
||||
#include <xlocale.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gunixmounts.h>
|
||||
@ -50,6 +58,279 @@ test_is_system_device_path (void)
|
||||
g_assert_false (g_unix_is_system_device_path ("/"));
|
||||
}
|
||||
|
||||
static void
|
||||
assert_cmp_icon (GIcon *icon,
|
||||
gboolean expected_icon)
|
||||
{
|
||||
if (expected_icon)
|
||||
{
|
||||
char *icon_str = NULL;
|
||||
|
||||
/* While it would be nice to compare the icon value, that would make these
|
||||
* tests depend on the icon themes installed. So just compare nullness. */
|
||||
g_assert_nonnull (icon);
|
||||
icon_str = g_icon_to_string (icon);
|
||||
g_test_message ("Icon: %s", icon_str);
|
||||
g_free (icon_str);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert_null (icon);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_get_mount_points (void)
|
||||
{
|
||||
GUnixMountPoint **points = NULL;
|
||||
uint64_t time_read = 0;
|
||||
size_t n_points = 0;
|
||||
int fd = -1;
|
||||
char *tmp_file = NULL;
|
||||
gboolean res;
|
||||
#ifdef HAVE_USELOCALE
|
||||
locale_t original_locale;
|
||||
locale_t new_locale;
|
||||
locale_t result;
|
||||
#endif
|
||||
const char *fake_fstab = "# Some comment\n"
|
||||
"/dev/mapper/fedora-root / ext4 defaults,x-systemd.device-timeout=0 1 1\n"
|
||||
"UUID=1234-ABCD /boot ext4 defaults 1 2\n"
|
||||
"UUID=ABCD-1234 /boot/efi vfat umask=0077,shortname=winnt,ro 0 2\n"
|
||||
"/dev/mapper/fedora-home /home ext4 defaults,x-systemd.device-timeout=0 1 2\n"
|
||||
"/dev/mapper/fedora-swap none swap defaults,x-systemd.device-timeout=0 0 0\n"
|
||||
"/dev/mapper/unused none ext4 defaults\n";
|
||||
const struct
|
||||
{
|
||||
const char *device_path;
|
||||
const char *fs_type;
|
||||
const char *options;
|
||||
gboolean is_readonly;
|
||||
gboolean is_user_mountable;
|
||||
gboolean is_loopback;
|
||||
gboolean guessed_icon;
|
||||
gboolean guessed_symbolic_icon;
|
||||
const char *guessed_name;
|
||||
gboolean guessed_can_eject;
|
||||
}
|
||||
expected_points[] =
|
||||
{
|
||||
{
|
||||
.device_path = "/dev/mapper/fedora-root",
|
||||
.fs_type = "ext4",
|
||||
.options = "defaults,x-systemd.device-timeout=0",
|
||||
.is_readonly = FALSE,
|
||||
.is_user_mountable = FALSE,
|
||||
.is_loopback = FALSE,
|
||||
.guessed_icon = TRUE,
|
||||
.guessed_symbolic_icon = TRUE,
|
||||
.guessed_name = "Filesystem root",
|
||||
.guessed_can_eject = FALSE,
|
||||
},
|
||||
{
|
||||
.device_path = "UUID=1234-ABCD",
|
||||
.fs_type = "ext4",
|
||||
.options = "defaults",
|
||||
.is_readonly = FALSE,
|
||||
.is_user_mountable = FALSE,
|
||||
.is_loopback = FALSE,
|
||||
.guessed_icon = TRUE,
|
||||
.guessed_symbolic_icon = TRUE,
|
||||
.guessed_name = "boot",
|
||||
.guessed_can_eject = FALSE,
|
||||
},
|
||||
{
|
||||
.device_path = "UUID=ABCD-1234",
|
||||
.fs_type = "vfat",
|
||||
.options = "umask=0077,shortname=winnt,ro",
|
||||
.is_readonly = TRUE,
|
||||
.is_user_mountable = FALSE,
|
||||
.is_loopback = FALSE,
|
||||
.guessed_icon = TRUE,
|
||||
.guessed_symbolic_icon = TRUE,
|
||||
.guessed_name = "efi",
|
||||
.guessed_can_eject = FALSE,
|
||||
},
|
||||
{
|
||||
.device_path = "/dev/mapper/fedora-home",
|
||||
.fs_type = "ext4",
|
||||
.options = "defaults,x-systemd.device-timeout=0",
|
||||
.is_readonly = FALSE,
|
||||
.is_user_mountable = FALSE,
|
||||
.is_loopback = FALSE,
|
||||
.guessed_icon = TRUE,
|
||||
.guessed_symbolic_icon = TRUE,
|
||||
.guessed_name = "home",
|
||||
.guessed_can_eject = FALSE,
|
||||
},
|
||||
/* the swap partition is ignored */
|
||||
/* as is the ignored unused partition */
|
||||
};
|
||||
|
||||
g_test_summary ("Basic test of g_unix_mount_points_get_from_file()");
|
||||
|
||||
fd = g_file_open_tmp ("unix-mounts-XXXXXX", &tmp_file, NULL);
|
||||
g_assert (fd != -1);
|
||||
close (fd);
|
||||
|
||||
res = g_file_set_contents (tmp_file, fake_fstab, -1, NULL);
|
||||
g_assert (res);
|
||||
|
||||
points = g_unix_mount_points_get_from_file (tmp_file, &time_read, &n_points);
|
||||
|
||||
if (points == NULL)
|
||||
{
|
||||
/* Some platforms may not support parsing a specific mount point file */
|
||||
g_assert_cmpuint (time_read, ==, 0);
|
||||
g_assert_cmpuint (n_points, ==, 0);
|
||||
g_test_skip ("Parsing mount points from a file not supported on this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert_nonnull (points);
|
||||
|
||||
/* Check the properties of the mount points. This needs to be done in a known
|
||||
* locale, because the guessed mount point name is translatable. */
|
||||
g_assert_cmpuint (n_points, ==, G_N_ELEMENTS (expected_points));
|
||||
|
||||
#ifdef HAVE_USELOCALE
|
||||
original_locale = uselocale ((locale_t) 0);
|
||||
g_assert_true (original_locale != (locale_t) 0);
|
||||
new_locale = newlocale (LC_ALL_MASK, "C", (locale_t) 0);
|
||||
g_assert_true (new_locale != (locale_t) 0);
|
||||
result = uselocale (new_locale);
|
||||
g_assert_true (result == original_locale);
|
||||
#endif /* HAVE_USELOCALE */
|
||||
|
||||
for (size_t i = 0; i < n_points; i++)
|
||||
{
|
||||
GIcon *icon = NULL;
|
||||
char *name = NULL;
|
||||
|
||||
g_assert_cmpstr (g_unix_mount_point_get_device_path (points[i]), ==, expected_points[i].device_path);
|
||||
g_assert_cmpstr (g_unix_mount_point_get_fs_type (points[i]), ==, expected_points[i].fs_type);
|
||||
g_assert_cmpstr (g_unix_mount_point_get_options (points[i]), ==, expected_points[i].options);
|
||||
g_assert_true (g_unix_mount_point_is_readonly (points[i]) == expected_points[i].is_readonly);
|
||||
g_assert_true (g_unix_mount_point_is_user_mountable (points[i]) == expected_points[i].is_user_mountable);
|
||||
g_assert_true (g_unix_mount_point_is_loopback (points[i]) == expected_points[i].is_loopback);
|
||||
|
||||
icon = g_unix_mount_point_guess_icon (points[i]);
|
||||
assert_cmp_icon (icon, expected_points[i].guessed_icon);
|
||||
g_clear_object (&icon);
|
||||
|
||||
icon = g_unix_mount_point_guess_symbolic_icon (points[i]);
|
||||
assert_cmp_icon (icon, expected_points[i].guessed_symbolic_icon);
|
||||
g_clear_object (&icon);
|
||||
|
||||
name = g_unix_mount_point_guess_name (points[i]);
|
||||
#ifdef HAVE_USELOCALE
|
||||
g_assert_cmpstr (name, ==, expected_points[i].guessed_name);
|
||||
#else
|
||||
g_assert_nonnull (name);
|
||||
#endif
|
||||
g_free (name);
|
||||
|
||||
g_assert_true (g_unix_mount_point_guess_can_eject (points[i]) == expected_points[i].guessed_can_eject);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n_points; i++)
|
||||
g_unix_mount_point_free (points[i]);
|
||||
g_free (points);
|
||||
g_free (tmp_file);
|
||||
|
||||
#ifdef HAVE_USELOCALE
|
||||
result = uselocale (original_locale);
|
||||
g_assert_true (result == new_locale);
|
||||
freelocale (new_locale);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
test_get_mount_entries (void)
|
||||
{
|
||||
GUnixMountEntry **entries = NULL;
|
||||
uint64_t time_read = 0;
|
||||
size_t n_entries = 0;
|
||||
int fd = -1;
|
||||
char *tmp_file = NULL;
|
||||
gboolean res;
|
||||
const char *fake_mtab = "# Some comment\n"
|
||||
"67 1 253:1 / / rw,relatime shared:1 - ext4 /dev/mapper/fedora-root rw,seclabel\n"
|
||||
"35 67 0:6 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=4096k,nr_inodes=1995515,mode=755,inode64\n"
|
||||
"1537 1080 253:1 /usr/share/fonts /run/host/fonts ro,nosuid,nodev,relatime master:1 - ext4 /dev/mapper/fedora-root rw,seclabel\n";
|
||||
const struct
|
||||
{
|
||||
const char *device_path;
|
||||
const char *fs_type;
|
||||
const char *mount_path;
|
||||
const char *options;
|
||||
const char *root_path;
|
||||
}
|
||||
expected_entries[] =
|
||||
{
|
||||
{
|
||||
.device_path = "/dev/mapper/fedora-root",
|
||||
.fs_type = "ext4",
|
||||
.mount_path = "/",
|
||||
.options = "rw,relatime,seclabel",
|
||||
.root_path = "/",
|
||||
},
|
||||
{
|
||||
.device_path = "devtmpfs",
|
||||
.fs_type = "devtmpfs",
|
||||
.mount_path = "/dev",
|
||||
.options = "rw,nosuid,seclabel,size=4096k,nr_inodes=1995515,mode=755,inode64",
|
||||
.root_path = "/",
|
||||
},
|
||||
{
|
||||
.device_path = "/dev/mapper/fedora-root",
|
||||
.fs_type = "ext4",
|
||||
.mount_path = "/run/host/fonts",
|
||||
.options = "ro,nosuid,nodev,relatime,seclabel",
|
||||
.root_path = "/usr/share/fonts",
|
||||
},
|
||||
};
|
||||
|
||||
g_test_summary ("Basic test of g_unix_mounts_get_from_file()");
|
||||
|
||||
fd = g_file_open_tmp ("unix-mounts-XXXXXX", &tmp_file, NULL);
|
||||
g_assert (fd != -1);
|
||||
close (fd);
|
||||
|
||||
res = g_file_set_contents (tmp_file, fake_mtab, -1, NULL);
|
||||
g_assert (res);
|
||||
|
||||
entries = g_unix_mounts_get_from_file (tmp_file, &time_read, &n_entries);
|
||||
|
||||
if (entries == NULL)
|
||||
{
|
||||
/* Some platforms may not support parsing a specific mount entry file */
|
||||
g_assert_cmpuint (time_read, ==, 0);
|
||||
g_assert_cmpuint (n_entries, ==, 0);
|
||||
g_test_skip ("Parsing mount entries from a file not supported on this platform");
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert_nonnull (entries);
|
||||
|
||||
/* Check the properties of the mount entries. */
|
||||
g_assert_cmpuint (n_entries, ==, G_N_ELEMENTS (expected_entries));
|
||||
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
{
|
||||
g_assert_cmpstr (g_unix_mount_get_device_path (entries[i]), ==, expected_entries[i].device_path);
|
||||
g_assert_cmpstr (g_unix_mount_get_fs_type (entries[i]), ==, expected_entries[i].fs_type);
|
||||
g_assert_cmpstr (g_unix_mount_get_mount_path (entries[i]), ==, expected_entries[i].mount_path);
|
||||
g_assert_cmpstr (g_unix_mount_get_options (entries[i]), ==, expected_entries[i].options);
|
||||
g_assert_cmpstr (g_unix_mount_get_root_path (entries[i]), ==, expected_entries[i].root_path);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n_entries; i++)
|
||||
g_unix_mount_free (entries[i]);
|
||||
g_free (entries);
|
||||
g_free (tmp_file);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -60,6 +341,8 @@ main (int argc,
|
||||
|
||||
g_test_add_func ("/unix-mounts/is-system-fs-type", test_is_system_fs_type);
|
||||
g_test_add_func ("/unix-mounts/is-system-device-path", test_is_system_device_path);
|
||||
g_test_add_func ("/unix-mounts/get-mount-points", test_get_mount_points);
|
||||
g_test_add_func ("/unix-mounts/get-mount-entries", test_get_mount_entries);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user