gunixmounts: Add mount point/entry getters from files

We don’t expect users to start querying the fstab or mtab by explicitly
loading data from those file paths. These functions are mainly intended
to prove a controllable entry point into the `gunixmounts.c` code for
unit testing.

It means we can provide a file with controllable contents in order to
test the mount entry/point code on.

See: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4155

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
This commit is contained in:
Philip Withnall 2024-07-20 14:53:57 +02:00
parent 107b47226c
commit 5040cf1943
No known key found for this signature in database
GPG Key ID: DCDF5885B1F3ED73
2 changed files with 430 additions and 76 deletions

View File

@ -148,7 +148,13 @@ G_DEFINE_BOXED_TYPE (GUnixMountPoint, g_unix_mount_point,
g_unix_mount_point_copy, g_unix_mount_point_free) g_unix_mount_point_copy, g_unix_mount_point_free)
static GList *_g_get_unix_mounts (void); 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 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); static gboolean proc_mounts_watch_is_running (void);
G_LOCK_DEFINE_STATIC (proc_mounts_source); 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; static struct libmnt_monitor *proc_mounts_monitor = NULL;
#endif #endif
static guint64 get_mounts_timestamp (void);
static guint64 get_mount_points_timestamp (void);
static gboolean static gboolean
is_in (const char *value, const char *set[]) is_in (const char *value, const char *set[])
{ {
@ -218,6 +227,45 @@ is_in (const char *value, const char *set[])
return FALSE; 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: * g_unix_is_mount_path_system_internal:
* @mount_path: (type filename): a mount path, e.g. `/media/disk` or `/usr` * @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" #define PROC_MOUNTINFO_PATH "/proc/self/mountinfo"
static GList * static GUnixMountEntry **
_g_get_unix_mounts (void) _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_table *table = NULL;
struct libmnt_iter* iter = NULL; struct libmnt_iter* iter = NULL;
struct libmnt_fs *fs = NULL; struct libmnt_fs *fs = NULL;
GUnixMountEntry *mount_entry = 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 (); table = mnt_new_table ();
if (mnt_table_parse_mtab (table, NULL) < 0) if (mnt_table_parse_mtab (table, table_path) < 0)
goto out; goto out;
iter = mnt_new_iter (MNT_ITER_FORWARD); iter = mnt_new_iter (MNT_ITER_FORWARD);
@ -541,14 +595,29 @@ _g_get_unix_mounts (void)
mnt_fs_get_options (fs), mnt_fs_get_options (fs),
is_read_only); 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); mnt_free_iter (iter);
out: out:
mnt_free_table (table); 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 #else
@ -571,8 +640,10 @@ get_mtab_read_file (void)
G_LOCK_DEFINE_STATIC(getmntent); G_LOCK_DEFINE_STATIC(getmntent);
#endif #endif
static GList * static GUnixMountEntry **
_g_get_unix_mounts (void) _g_unix_mounts_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_entries_out)
{ {
#ifdef HAVE_GETMNTENT_R #ifdef HAVE_GETMNTENT_R
struct mntent ent; struct mntent ent;
@ -580,19 +651,18 @@ _g_get_unix_mounts (void)
#endif #endif
struct mntent *mntent; struct mntent *mntent;
FILE *file; FILE *file;
const char *read_file;
GUnixMountEntry *mount_entry; GUnixMountEntry *mount_entry;
GHashTable *mounts_hash; GHashTable *mounts_hash;
GList *return_list; GPtrArray *return_array = NULL;
read_file = get_mtab_read_file (); if (time_read_out != NULL)
*time_read_out = get_mounts_timestamp ();
file = setmntent (read_file, "re"); file = setmntent (table_path, "re");
if (file == NULL) if (file == NULL)
return 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); mounts_hash = g_hash_table_new (g_str_hash, g_str_equal);
#ifdef HAVE_GETMNTENT_R #ifdef HAVE_GETMNTENT_R
@ -641,7 +711,7 @@ _g_get_unix_mounts (void)
mount_entry->device_path, mount_entry->device_path,
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); g_hash_table_destroy (mounts_hash);
@ -651,7 +721,21 @@ _g_get_unix_mounts (void)
G_UNLOCK (getmntent); G_UNLOCK (getmntent);
#endif #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 */ #endif /* HAVE_LIBMOUNT */
@ -718,22 +802,25 @@ get_mtab_monitor_file (void)
return get_mtab_read_file (); return get_mtab_read_file ();
} }
static GList * static GUnixMountEntry **
_g_get_unix_mounts (void) _g_unix_mounts_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_entries_out)
{ {
struct mnttab mntent; struct mnttab mntent;
FILE *file; FILE *file;
const char *read_file; const char *read_file;
GUnixMountEntry *mount_entry; GUnixMountEntry *mount_entry;
GList *return_list; GPtrArray *return_array = NULL;
read_file = get_mtab_read_file (); if (time_read_out != NULL)
*time_read_out = get_mounts_timestamp ();
file = setmntent (read_file, "re"); file = setmntent (read_file, "re");
if (file == NULL) if (file == NULL)
return NULL; return NULL;
return_list = NULL; return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_free, TRUE);
G_LOCK (getmntent); G_LOCK (getmntent);
while (! getmntent (file, &mntent)) while (! getmntent (file, &mntent))
@ -752,14 +839,28 @@ _g_get_unix_mounts (void)
mntent.mnt_opts, mntent.mnt_opts,
is_read_only); 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); endmntent (file);
G_UNLOCK (getmntent); 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 */ /* mntctl.h (AIX) {{{2 */
@ -832,6 +933,20 @@ _g_get_unix_mounts (void)
return g_list_reverse (return_list); 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 */ /* sys/mount.h {{{2 */
#elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H) #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); 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 */ /* Interix {{{2 */
#elif defined(__INTERIX) #elif defined(__INTERIX)
@ -962,6 +1091,20 @@ _g_get_unix_mounts (void)
return return_list; 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 */ /* QNX {{{2 */
#elif defined (HAVE_QNX) #elif defined (HAVE_QNX)
@ -972,6 +1115,20 @@ get_mtab_monitor_file (void)
return NULL; 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 * static GList *
_g_get_unix_mounts (void) _g_get_unix_mounts (void)
{ {
@ -1015,17 +1172,23 @@ get_fstab_file (void)
#ifdef HAVE_LIBMOUNT #ifdef HAVE_LIBMOUNT
static GList * static GUnixMountPoint **
_g_get_unix_mount_points (void) _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_table *table = NULL;
struct libmnt_iter* iter = NULL; struct libmnt_iter* iter = NULL;
struct libmnt_fs *fs = NULL; struct libmnt_fs *fs = NULL;
GUnixMountPoint *mount_point = 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 (); table = mnt_new_table ();
if (mnt_table_parse_fstab (table, NULL) < 0) if (mnt_table_parse_fstab (table, table_path) < 0)
goto out; goto out;
iter = mnt_new_iter (MNT_ITER_FORWARD); iter = mnt_new_iter (MNT_ITER_FORWARD);
@ -1089,20 +1252,37 @@ _g_get_unix_mount_points (void)
if (mount_options) if (mount_options)
g_free (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); mnt_free_iter (iter);
out: out:
mnt_free_table (table); 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 #else
static GList * static GUnixMountPoint **
_g_get_unix_mount_points (void) _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 #ifdef HAVE_GETMNTENT_R
struct mntent ent; struct mntent ent;
@ -1112,15 +1292,20 @@ _g_get_unix_mount_points (void)
FILE *file; FILE *file;
char *read_file; char *read_file;
GUnixMountPoint *mount_point; GUnixMountPoint *mount_point;
GList *return_list; GPtrArray *return_array = NULL;
read_file = get_fstab_file (); if (time_read_out != NULL)
*time_read_out = get_mount_points_timestamp ();
file = setmntent (read_file, "re"); file = setmntent (table_path, "re");
if (file == NULL) if (file == NULL)
{
if (n_points_out != NULL)
*n_points_out = 0;
return NULL; return NULL;
}
return_list = NULL; return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
#ifdef HAVE_GETMNTENT_R #ifdef HAVE_GETMNTENT_R
while ((mntent = getmntent_r (file, &ent, buf, sizeof (buf))) != NULL) while ((mntent = getmntent_r (file, &ent, buf, sizeof (buf))) != NULL)
@ -1177,7 +1362,7 @@ _g_get_unix_mount_points (void)
is_user_mountable, is_user_mountable,
is_loopback); is_loopback);
return_list = g_list_prepend (return_list, mount_point); g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
} }
endmntent (file); endmntent (file);
@ -1186,7 +1371,22 @@ _g_get_unix_mount_points (void)
G_UNLOCK (getmntent); G_UNLOCK (getmntent);
#endif #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 */ #endif /* HAVE_LIBMOUNT */
@ -1194,22 +1394,29 @@ _g_get_unix_mount_points (void)
/* mnttab.h {{{2 */ /* mnttab.h {{{2 */
#elif defined (HAVE_SYS_MNTTAB_H) #elif defined (HAVE_SYS_MNTTAB_H)
static GList * static GUnixMountPoint **
_g_get_unix_mount_points (void) _g_unix_mount_points_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_points_out)
{ {
struct mnttab mntent; struct mnttab mntent;
FILE *file; FILE *file;
char *read_file; char *read_file;
GUnixMountPoint *mount_point; GUnixMountPoint *mount_point;
GList *return_list; GPtrArray *return_array = NULL;
read_file = get_fstab_file (); if (time_read_out != NULL)
*time_read_out = get_mount_points_timestamp ();
file = setmntent (read_file, "re"); file = setmntent (table_path, "re");
if (file == NULL) if (file == NULL)
{
if (n_points_out != NULL)
*n_points_out = 0;
return NULL; return NULL;
}
return_list = NULL; return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
G_LOCK (getmntent); G_LOCK (getmntent);
while (! getmntent (file, &mntent)) while (! getmntent (file, &mntent))
@ -1249,13 +1456,28 @@ _g_get_unix_mount_points (void)
is_user_mountable, is_user_mountable,
is_loopback); is_loopback);
return_list = g_list_prepend (return_list, mount_point); g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
} }
endmntent (file); endmntent (file);
G_UNLOCK (getmntent); 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 */ /* mntctl.h (AIX) {{{2 */
@ -1368,23 +1590,30 @@ aix_fs_get (FILE *fd,
return 0; return 0;
} }
static GList * static GUnixMountPoint **
_g_get_unix_mount_points (void) _g_unix_mount_points_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_points_out)
{ {
struct mntent *mntent; struct mntent *mntent;
FILE *file; FILE *file;
char *read_file; char *read_file;
GUnixMountPoint *mount_point; GUnixMountPoint *mount_point;
AixMountTableEntry mntent; AixMountTableEntry mntent;
GList *return_list; GPtrArray *return_array = NULL;
read_file = get_fstab_file (); if (time_read_out != NULL)
*time_read_out = get_mount_points_timestamp ();
file = setmntent (read_file, "re"); file = setmntent (table_path, "re");
if (file == NULL) if (file == NULL)
{
if (n_points_out != NULL)
*n_points_out = 0;
return NULL; return NULL;
}
return_list = NULL; return_array = g_ptr_array_new_null_terminated (0, (GDestroyNotify) g_unix_mount_point_free, TRUE);
while (!aix_fs_get (file, &mntent)) while (!aix_fs_get (file, &mntent))
{ {
@ -1398,13 +1627,28 @@ _g_get_unix_mount_points (void)
TRUE, TRUE,
FALSE); FALSE);
return_list = g_list_prepend (return_list, mount_point); g_ptr_array_add (return_array, g_steal_pointer (&mount_point));
} }
} }
endmntent (file); 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) #elif (defined(HAVE_GETVFSSTAT) || defined(HAVE_GETFSSTAT)) && defined(HAVE_FSTAB_H) && defined(HAVE_SYS_MOUNT_H)
@ -1495,6 +1739,19 @@ _g_get_unix_mount_points (void)
return g_list_reverse (return_list); return g_list_reverse (return_list);
} }
static GUnixMountPoint **
_g_unix_mount_points_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_points_out)
{
/* 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;
}
/* Interix {{{2 */ /* Interix {{{2 */
#elif defined(__INTERIX) #elif defined(__INTERIX)
static GList * static GList *
@ -1503,6 +1760,19 @@ _g_get_unix_mount_points (void)
return _g_get_unix_mounts (); return _g_get_unix_mounts ();
} }
static GUnixMountPoint **
_g_unix_mount_points_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_points_out)
{
/* Not supported on Interix systems. */
if (time_read_out != NULL)
*time_read_out = 0;
if (n_points_out != NULL)
*n_points_out = 0;
return NULL;
}
/* QNX {{{2 */ /* QNX {{{2 */
#elif defined (HAVE_QNX) #elif defined (HAVE_QNX)
static GList * static GList *
@ -1511,6 +1781,19 @@ _g_get_unix_mount_points (void)
return _g_get_unix_mounts (); return _g_get_unix_mounts ();
} }
static GUnixMountPoint **
_g_unix_mount_points_get_from_file (const char *table_path,
uint64_t *time_read_out,
size_t *n_points_out)
{
/* Not supported on QNX systems. */
if (time_read_out != NULL)
*time_read_out = 0;
if (n_points_out != NULL)
*n_points_out = 0;
return NULL;
}
/* Common code {{{2 */ /* Common code {{{2 */
#else #else
#error No g_get_mount_table() implementation for system #error No g_get_mount_table() implementation for system
@ -1588,6 +1871,37 @@ g_unix_mounts_get (guint64 *time_read)
return _g_get_unix_mounts (); 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: * g_unix_mount_at:
* @mount_path: (type filename): path for a possible unix mount. * @mount_path: (type filename): path for a possible unix mount.
@ -1724,6 +2038,37 @@ g_unix_mount_points_get (guint64 *time_read)
return mnt_pts; 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: * g_unix_mount_point_at:
* @mount_path: (type filename): path for a possible unix mount point. * @mount_path: (type filename): path for a possible unix mount point.

View File

@ -24,6 +24,7 @@
#define __G_UNIX_MOUNTS_H__ #define __G_UNIX_MOUNTS_H__
#include <gio/gio.h> #include <gio/gio.h>
#include <stdint.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -134,11 +135,19 @@ GIcon * g_unix_mount_point_guess_symbolic_icon (GUnixMountPoint *mount
GIO_AVAILABLE_IN_ALL GIO_AVAILABLE_IN_ALL
GList * g_unix_mount_points_get (guint64 *time_read); 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 GIO_AVAILABLE_IN_2_66
GUnixMountPoint *g_unix_mount_point_at (const char *mount_path, GUnixMountPoint *g_unix_mount_point_at (const char *mount_path,
guint64 *time_read); guint64 *time_read);
GIO_AVAILABLE_IN_ALL GIO_AVAILABLE_IN_ALL
GList * g_unix_mounts_get (guint64 *time_read); 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 GIO_AVAILABLE_IN_ALL
GUnixMountEntry *g_unix_mount_at (const char *mount_path, GUnixMountEntry *g_unix_mount_at (const char *mount_path,
guint64 *time_read); guint64 *time_read);