Skip to content
Snippets Groups Projects
Commit cbd9e214 authored by Ludovico de Nittis's avatar Ludovico de Nittis :palm_tree:
Browse files

utils: Add pv_file_test_in_sysroot


With this new function it will be possible to test the existence or
properties of a given filename under a specific sysroot.

Signed-off-by: default avatarLudovico de Nittis <ludovico.denittis@collabora.com>
parent bb55eddd
No related branches found
No related tags found
No related merge requests found
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include "flatpak-utils-base-private.h" #include "flatpak-utils-base-private.h"
#include "flatpak-utils-private.h" #include "flatpak-utils-private.h"
#include "resolve-in-sysroot.h"
static void static void
child_setup_cb (gpointer user_data) child_setup_cb (gpointer user_data)
{ {
...@@ -926,3 +928,74 @@ pv_terminate_all_child_processes (GTimeSpan wait_period, ...@@ -926,3 +928,74 @@ pv_terminate_all_child_processes (GTimeSpan wait_period,
return TRUE; return TRUE;
} }
/**
* pv_file_test_in_sysroot:
* @sysroot: (type filename): A path used as the root
* @filename: (type filename): A path below the root directory, either
* absolute or relative (to the root)
* @test: The test to perform on the resolved file in @sysroot.
* G_FILE_TEST_IS_SYMLINK is not a valid GFileTest value because the
* path is resolved following symlinks too.
*
* Returns: %TRUE if the @filename resolved in @sysroot passes the @test.
*/
gboolean
pv_file_test_in_sysroot (const char *sysroot,
const char *filename,
GFileTest test)
{
glnx_autofd int file_fd = -1;
glnx_autofd int sysroot_fd = -1;
struct stat stat_buf;
g_autofree gchar *file_realpath_in_sysroot = NULL;
g_autoptr(GError) error = NULL;
g_return_val_if_fail (sysroot != NULL, FALSE);
g_return_val_if_fail (filename != NULL, FALSE);
/* We reject G_FILE_TEST_IS_SYMLINK because the provided filename is resolved
* in sysroot, following the eventual symlinks too. So it is not possible for
* the resolved filename to be a symlink */
g_return_val_if_fail ((test & (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE
| G_FILE_TEST_IS_REGULAR
| G_FILE_TEST_IS_DIR)) == test, FALSE);
if (!glnx_opendirat (-1, sysroot, FALSE, &sysroot_fd, &error))
{
g_debug ("An error occurred trying to open %s: %s", sysroot,
error->message);
return FALSE;
}
file_fd = pv_resolve_in_sysroot (sysroot_fd,
filename, PV_RESOLVE_FLAGS_NONE,
&file_realpath_in_sysroot, &error);
if (file_fd < 0)
{
g_debug ("An error occurred trying to resolve %s in sysroot: %s",
filename, error->message);
return FALSE;
}
if (fstat (file_fd, &stat_buf) != 0)
{
g_debug ("fstat %s/%s: %s",
sysroot, file_realpath_in_sysroot, g_strerror (errno));
return FALSE;
}
if (test & G_FILE_TEST_EXISTS)
return TRUE;
if ((test & G_FILE_TEST_IS_EXECUTABLE) && (stat_buf.st_mode & 0111))
return TRUE;
if ((test & G_FILE_TEST_IS_REGULAR) && S_ISREG (stat_buf.st_mode))
return TRUE;
if ((test & G_FILE_TEST_IS_DIR) && S_ISDIR (stat_buf.st_mode))
return TRUE;
return FALSE;
}
...@@ -73,3 +73,7 @@ gboolean pv_wait_for_child_processes (pid_t main_process, ...@@ -73,3 +73,7 @@ gboolean pv_wait_for_child_processes (pid_t main_process,
gboolean pv_terminate_all_child_processes (GTimeSpan wait_period, gboolean pv_terminate_all_child_processes (GTimeSpan wait_period,
GTimeSpan grace_period, GTimeSpan grace_period,
GError **error); GError **error);
gboolean pv_file_test_in_sysroot (const char *sysroot,
const char *filename,
GFileTest test);
...@@ -278,6 +278,107 @@ test_search_path_append (Fixture *f, ...@@ -278,6 +278,107 @@ test_search_path_append (Fixture *f,
g_assert_cmpstr (str->str, ==, "/bin:/usr/bin:/usr/bin"); g_assert_cmpstr (str->str, ==, "/bin:/usr/bin:/usr/bin");
} }
typedef struct
{
const char *name;
mode_t mode;
} File;
typedef struct
{
const char *name;
const char *target;
} Symlink;
typedef struct
{
const char *path;
GFileTest test;
gboolean expected_result;
} InSysrootTest;
static void
test_file_in_sysroot (Fixture *f,
gconstpointer context)
{
static const char * const prepare_dirs[] =
{
"dir1/dir2/dir3",
};
static const File prepare_files[] =
{
{ "dir1/file1", 0600 },
{ "dir1/dir2/file2", 0600 },
{ "dir1/exec1", 0700 },
};
static const Symlink prepare_symlinks[] =
{
{ "dir1/dir2/symlink_to_dir3", "dir3" },
{ "dir1/dir2/symlink_to_file2", "file2" },
{ "dir1/dir2/sym_to_sym_to_file2", "symlink_to_file2" },
{ "dir1/abs_symlink_to_run", "/run" },
};
static const InSysrootTest tests[] =
{
{ "dir1", G_FILE_TEST_IS_DIR, TRUE },
{ "dir1", G_FILE_TEST_EXISTS, TRUE },
{ "/dir1", G_FILE_TEST_EXISTS, TRUE },
{ "dir1/dir2", G_FILE_TEST_IS_DIR, TRUE },
/* These gets solved in sysroot, following symlinks too */
{ "dir1/dir2/symlink_to_dir3", G_FILE_TEST_IS_DIR, TRUE },
{ "dir1/dir2/sym_to_sym_to_file2", G_FILE_TEST_IS_REGULAR, TRUE },
{ "dir1/abs_symlink_to_run", G_FILE_TEST_IS_DIR, FALSE },
{ "dir1/missing", G_FILE_TEST_EXISTS, FALSE },
{ "dir1/file1", G_FILE_TEST_IS_REGULAR, TRUE },
{ "dir1/file1", (G_FILE_TEST_IS_DIR | G_FILE_TEST_IS_EXECUTABLE), FALSE },
{ "dir1/exec1", G_FILE_TEST_IS_REGULAR, TRUE },
{ "dir1/exec1", G_FILE_TEST_IS_EXECUTABLE, TRUE },
};
g_autoptr(GError) error = NULL;
g_auto(GLnxTmpDir) tmpdir = { FALSE };
gsize i;
glnx_mkdtemp ("test-XXXXXX", 0700, &tmpdir, &error);
g_assert_no_error (error);
for (i = 0; i < G_N_ELEMENTS (prepare_dirs); i++)
{
const char *it = prepare_dirs[i];
glnx_shutil_mkdir_p_at (tmpdir.fd, it, 0700, NULL, &error);
g_assert_no_error (error);
}
for (i = 0; i < G_N_ELEMENTS (prepare_files); i++)
{
const File *it = &prepare_files[i];
glnx_autofd int fd = openat (tmpdir.fd, it->name, O_WRONLY|O_CREAT, it->mode);
if (fd == -1)
g_error ("openat %s: %s", it->name, g_strerror (errno));
}
for (i = 0; i < G_N_ELEMENTS (prepare_symlinks); i++)
{
const Symlink *it = &prepare_symlinks[i];
if (symlinkat (it->target, tmpdir.fd, it->name) != 0)
g_error ("symlinkat %s: %s", it->name, g_strerror (errno));
}
for (i = 0; i < G_N_ELEMENTS (tests); i++)
{
const InSysrootTest *it = &tests[i];
g_assert_cmpint (pv_file_test_in_sysroot (tmpdir.path, it->path, it->test),
==, it->expected_result);
}
}
int int
main (int argc, main (int argc,
char **argv) char **argv)
...@@ -294,6 +395,8 @@ main (int argc, ...@@ -294,6 +395,8 @@ main (int argc,
g_test_add ("/same-file", Fixture, NULL, setup, test_same_file, teardown); g_test_add ("/same-file", Fixture, NULL, setup, test_same_file, teardown);
g_test_add ("/search-path-append", Fixture, NULL, g_test_add ("/search-path-append", Fixture, NULL,
setup, test_search_path_append, teardown); setup, test_search_path_append, teardown);
g_test_add ("/test-file-in-sysroot", Fixture, NULL,
setup, test_file_in_sysroot, teardown);
return g_test_run (); return g_test_run ();
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment