diff options
author | Thomas Haller <thaller@redhat.com> | 2018-10-19 10:21:53 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-10-23 10:32:53 +0200 |
commit | f90b3adc153c78a828ad265aa8c65c0f7f54e023 (patch) | |
tree | 82ea76c72ebea201267c15249bb19cc634254014 | |
parent | 9dce4a426ba82307cd27de23f3f3d8aed569d79b (diff) | |
download | NetworkManager-f90b3adc153c78a828ad265aa8c65c0f7f54e023.tar.gz |
core: add nm_utils_file_is_in_path() for checking paths
Add a helper function for the common check whether a file is
inside a path. Also, this function handles special cases like
repeated file separators. However, as it is still entirely text
based, it also cannot recognize if two (literally) different
paths reference the same inode/file.
-rw-r--r-- | src/NetworkManagerUtils.c | 60 | ||||
-rw-r--r-- | src/NetworkManagerUtils.h | 6 | ||||
-rw-r--r-- | src/nm-core-utils.c | 4 | ||||
-rw-r--r-- | src/tests/test-general.c | 21 |
4 files changed, 91 insertions, 0 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 1404854d71..ae17ee5179 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -34,6 +34,7 @@ #include "platform/nm-platform.h" #include "nm-auth-utils.h" +#include "systemd/nm-sd-utils.h" /*****************************************************************************/ @@ -998,3 +999,62 @@ nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle) g_object_weak_unref (handle->watched_obj, _shutdown_waitobj_cb, handle); _shutdown_waitobj_unregister (handle); } + +/*****************************************************************************/ + +/** + * nm_utils_file_is_in_path: + * @abs_filename: the absolute filename to test + * @abs_path: the absolute path, to check whether filename is in. + * + * This tests, whether @abs_filename is a file which lies inside @abs_path. + * Basically, this checks whether @abs_filename is the same as @abs_path + + * basename(@abs_filename). It allows simple normalizations, like coalescing + * multiple "//". + * + * However, beware that this function is purely filename based. That means, + * it will reject files that reference the same file (i.e. inode) via + * symlinks or bind mounts. Maybe one would like to check for file (inode) + * identity, but that is not really possible based on the file name alone. + * + * This means, that nm_utils_file_is_in_path("/var/run/some-file", "/var/run") + * will succeed, but nm_utils_file_is_in_path("/run/some-file", "/var/run") + * will not (although, it's well known that they reference the same path). + * + * Also, note that @abs_filename must not have trailing slashes itself. + * So, this will reject nm_utils_file_is_in_path("/usr/lib/", "/usr") as + * invalid, because the function searches for file names (and "lib/" is + * clearly a directory). + * + * Returns: if @abs_filename is a file inside @abs_path, returns the + * trailing part of @abs_filename which is the filename. Otherwise + * %NULL. + */ +const char * +nm_utils_file_is_in_path (const char *abs_filename, + const char *abs_path) +{ + const char *path; + + g_return_val_if_fail (abs_filename && abs_filename[0] == '/', NULL); + g_return_val_if_fail (abs_path && abs_path[0] == '/', NULL); + + path = nm_sd_utils_path_startswith (abs_filename, abs_path); + if (!path) + return NULL; + + nm_assert (path[0] != '/'); + nm_assert (path > abs_filename); + nm_assert (path <= &abs_filename[strlen (abs_filename)]); + + /* we require a non-empty remainder with no slashes. That is, only a filename. + * + * Note this will reject "/var/run/" as not being in "/var", + * while "/var/run" would pass. The function searches for files + * only, so a trailing slash (indicating a directory) is not allowed). + * This is despite that the function cannot determine whether "/var/run" + * is itself a file or a directory. "*/ + return path[0] && !strchr (path, '/') + ? path + : NULL; +} diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 26907243f6..93edb912dd 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -86,4 +86,10 @@ void nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle); /*****************************************************************************/ +const char * +nm_utils_file_is_in_path (const char *abs_filename, + const char *abs_path); + +/*****************************************************************************/ + #endif /* __NETWORKMANAGER_UTILS_H__ */ diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 50f127c090..75dd2e2c22 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -47,6 +47,10 @@ #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" +#ifdef __NM_SD_UTILS_H__ +#error "nm-core-utils.c should stay independent of systemd utils. Are you looking for NetworkMangerUtils.c? " +#endif + G_STATIC_ASSERT (sizeof (NMUtilsTestFlags) <= sizeof (int)); static int _nm_utils_testing = 0; diff --git a/src/tests/test-general.c b/src/tests/test-general.c index d8586cc7f5..e436b36d3a 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -1845,6 +1845,25 @@ test_nm_utils_exp10 (void) /*****************************************************************************/ +static void +test_utils_file_is_in_path (void) +{ + g_assert (!nm_utils_file_is_in_path ("/", "/")); + g_assert (!nm_utils_file_is_in_path ("//", "/")); + g_assert (!nm_utils_file_is_in_path ("/a/", "/")); + g_assert ( nm_utils_file_is_in_path ("/a", "/")); + g_assert ( nm_utils_file_is_in_path ("///a", "/")); + g_assert ( nm_utils_file_is_in_path ("//b/a", "/b//")); + g_assert ( nm_utils_file_is_in_path ("//b///a", "/b//")); + g_assert (!nm_utils_file_is_in_path ("//b///a/", "/b//")); + g_assert (!nm_utils_file_is_in_path ("//b///a/", "/b/a/")); + g_assert (!nm_utils_file_is_in_path ("//b///a", "/b/a/")); + g_assert ( nm_utils_file_is_in_path ("//b///a/.", "/b/a/")); + g_assert ( nm_utils_file_is_in_path ("//b///a/..", "/b/a/")); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -1891,6 +1910,8 @@ main (int argc, char **argv) g_test_add_func ("/general/stable-id/parse", test_stable_id_parse); g_test_add_func ("/general/stable-id/generated-complete", test_stable_id_generated_complete); + g_test_add_func ("/general/test_utils_file_is_in_path", test_utils_file_is_in_path); + return g_test_run (); } |