2017-10-25 16:03:17 +02:00
|
|
|
|
/* GLib testing framework examples and tests
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2017 Endless Mobile, Inc.
|
|
|
|
|
*
|
2022-05-18 10:20:07 +02:00
|
|
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
|
*
|
2017-10-25 16:03:17 +02:00
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General
|
|
|
|
|
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2024-07-20 16:59:19 +02:00
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2017-10-25 16:03:17 +02:00
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
|
|
#ifndef G_OS_UNIX
|
|
|
|
|
#error This is a Unix-specific test
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <locale.h>
|
2024-07-20 16:59:19 +02:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_XLOCALE_H
|
|
|
|
|
/* Needed on macOS and FreeBSD for uselocale() */
|
|
|
|
|
#include <xlocale.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2017-10-25 16:03:17 +02:00
|
|
|
|
#include <glib/gstdio.h>
|
|
|
|
|
#include <gio/gio.h>
|
|
|
|
|
#include <gio/gunixmounts.h>
|
|
|
|
|
|
2024-10-22 17:15:18 +02:00
|
|
|
|
/* We test all of the old g_unix_mount_*() API before it was renamed to
|
|
|
|
|
* g_unix_mount_entry_*(). The old API calls the new API, so both methods get
|
|
|
|
|
* tested at once. */
|
|
|
|
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
|
|
|
|
|
2017-10-25 16:03:17 +02:00
|
|
|
|
static void
|
|
|
|
|
test_is_system_fs_type (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert_true (g_unix_is_system_fs_type ("tmpfs"));
|
|
|
|
|
g_assert_false (g_unix_is_system_fs_type ("ext4"));
|
2018-06-20 13:16:34 +02:00
|
|
|
|
|
|
|
|
|
/* Check that some common network file systems aren’t considered ‘system’. */
|
|
|
|
|
g_assert_false (g_unix_is_system_fs_type ("cifs"));
|
|
|
|
|
g_assert_false (g_unix_is_system_fs_type ("nfs"));
|
|
|
|
|
g_assert_false (g_unix_is_system_fs_type ("nfs4"));
|
|
|
|
|
g_assert_false (g_unix_is_system_fs_type ("smbfs"));
|
2017-10-25 16:03:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_is_system_device_path (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert_true (g_unix_is_system_device_path ("devpts"));
|
|
|
|
|
g_assert_false (g_unix_is_system_device_path ("/"));
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-20 16:59:19 +02:00
|
|
|
|
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;
|
2024-08-27 13:13:35 +02:00
|
|
|
|
#ifdef HAVE_LIBMOUNT
|
|
|
|
|
/* This is an edited /proc/self/mountinfo file, used because that’s what
|
|
|
|
|
* libmount parses by default, and it allows for the representation of root_path. */
|
2024-07-20 16:59:19 +02:00
|
|
|
|
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";
|
2024-08-27 13:13:35 +02:00
|
|
|
|
#else
|
|
|
|
|
/* This is an edited /proc/mounts, used because that’s what getmntent() parses
|
|
|
|
|
* (and it can’t parse mountinfo files). Unfortunately this means that
|
|
|
|
|
* non-NULL root_path values are not representable. */
|
|
|
|
|
const char *fake_mtab = "# Some comment\n"
|
|
|
|
|
"/dev/mapper/fedora-root / ext4 rw,relatime,seclabel 0 0\n"
|
|
|
|
|
"devtmpfs /dev devtmpfs rw,nosuid,seclabel,size=4096k,nr_inodes=1995515,mode=755,inode64 0 0\n";
|
|
|
|
|
#endif
|
2024-07-20 16:59:19 +02:00
|
|
|
|
const struct
|
|
|
|
|
{
|
|
|
|
|
const char *device_path;
|
|
|
|
|
const char *fs_type;
|
|
|
|
|
const char *mount_path;
|
|
|
|
|
const char *options;
|
2024-08-27 13:13:35 +02:00
|
|
|
|
const char *root_path; /* if supported */
|
2024-07-20 16:59:19 +02:00
|
|
|
|
}
|
|
|
|
|
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 = "/",
|
|
|
|
|
},
|
2024-08-27 13:13:35 +02:00
|
|
|
|
#ifdef HAVE_LIBMOUNT
|
2024-07-20 16:59:19 +02:00
|
|
|
|
{
|
|
|
|
|
.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",
|
|
|
|
|
},
|
2024-08-27 13:13:35 +02:00
|
|
|
|
#endif
|
2024-07-20 16:59:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2024-10-22 17:15:18 +02:00
|
|
|
|
entries = g_unix_mounts_get_from_file (tmp_file, &time_read, &n_entries);
|
2024-07-20 16:59:19 +02:00
|
|
|
|
|
|
|
|
|
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++)
|
|
|
|
|
{
|
2024-10-22 17:15:18 +02:00
|
|
|
|
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);
|
2024-08-27 13:13:35 +02:00
|
|
|
|
|
|
|
|
|
/* root_path is only supported by libmount */
|
|
|
|
|
#ifdef HAVE_LIBMOUNT
|
2024-10-22 17:15:18 +02:00
|
|
|
|
g_assert_cmpstr (g_unix_mount_get_root_path (entries[i]), ==, expected_entries[i].root_path);
|
2024-08-27 13:13:35 +02:00
|
|
|
|
#else
|
|
|
|
|
g_assert_null (g_unix_mount_get_root_path (entries[i]));
|
|
|
|
|
#endif
|
2024-07-20 16:59:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < n_entries; i++)
|
2024-10-22 17:15:18 +02:00
|
|
|
|
g_unix_mount_free (entries[i]);
|
2024-07-20 16:59:19 +02:00
|
|
|
|
g_free (entries);
|
|
|
|
|
g_free (tmp_file);
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-22 17:15:18 +02:00
|
|
|
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
|
|
|
|
|
2017-10-25 16:03:17 +02:00
|
|
|
|
int
|
|
|
|
|
main (int argc,
|
|
|
|
|
char *argv[])
|
|
|
|
|
{
|
|
|
|
|
setlocale (LC_ALL, "");
|
|
|
|
|
|
|
|
|
|
g_test_init (&argc, &argv, NULL);
|
|
|
|
|
|
|
|
|
|
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);
|
2024-07-20 16:59:19 +02:00
|
|
|
|
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);
|
2017-10-25 16:03:17 +02:00
|
|
|
|
|
|
|
|
|
return g_test_run ();
|
|
|
|
|
}
|