diff options
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | src/basic/glob-util.c | 19 | ||||
-rw-r--r-- | src/basic/glob-util.h | 2 | ||||
-rw-r--r-- | src/test/test-glob-util.c | 28 | ||||
-rw-r--r-- | src/tmpfiles/tmpfiles.c | 18 |
5 files changed, 67 insertions, 5 deletions
@@ -711,9 +711,6 @@ Features: * add proper dbus APIs for the various sd_notify() commands, such as MAINPID=1 and so on, which would mean we could report errors and such. -* teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4 - project quota - * introduce DefaultSlice= or so in system.conf that allows changing where we place our units by default, i.e. change system.slice to something else. Similar, ManagerSlice= should exist so that PID1's own scope unit could @@ -1335,6 +1332,8 @@ Features: should not follow symlinks. None of the other adjustment or creation calls follow symlinks. - add --test mode + - teach tmpfiles.d q/Q logic something sensible in the context of XFS/ext4 + project quota * make sure systemd-ask-password-wall does not shutdown systemd-ask-password-console too early diff --git a/src/basic/glob-util.c b/src/basic/glob-util.c index bc0278e57f..e026b29478 100644 --- a/src/basic/glob-util.c +++ b/src/basic/glob-util.c @@ -71,3 +71,22 @@ int glob_extend(char ***strv, const char *path, int flags) { return strv_extend_strv(strv, g.gl_pathv, false); } + +int glob_non_glob_prefix(const char *path, char **ret) { + /* Return the path of the path that has no glob characters. */ + + size_t n = strcspn(path, GLOB_CHARS); + + if (path[n] != '\0') + while (n > 0 && path[n-1] != '/') + n--; + + if (n == 0) + return -ENOENT; + + char *ans = strndup(path, n); + if (!ans) + return -ENOMEM; + *ret = ans; + return 0; +} diff --git a/src/basic/glob-util.h b/src/basic/glob-util.h index d2f8718d5a..fc86e990dd 100644 --- a/src/basic/glob-util.h +++ b/src/basic/glob-util.h @@ -13,6 +13,8 @@ int safe_glob(const char *path, int flags, glob_t *pglob); int glob_exists(const char *path); int glob_extend(char ***strv, const char *path, int flags); +int glob_non_glob_prefix(const char *path, char **ret); + #define _cleanup_globfree_ _cleanup_(globfree) _pure_ static inline bool string_is_glob(const char *p) { diff --git a/src/test/test-glob-util.c b/src/test/test-glob-util.c index df6444c433..50b4924679 100644 --- a/src/test/test-glob-util.c +++ b/src/test/test-glob-util.c @@ -13,6 +13,8 @@ #include "tmpfile-util.h" static void test_glob_exists(void) { + log_info("/* %s */", __func__); + char name[] = "/tmp/test-glob_exists.XXXXXX"; int fd = -1; int r; @@ -48,6 +50,8 @@ static void test_glob_no_dot(void) { int r; + log_info("/* %s */", __func__); + assert_se(mkdtemp(template)); fn = strjoina(template, "/*"); @@ -68,6 +72,8 @@ static void test_safe_glob(void) { _cleanup_globfree_ glob_t g = {}; int r; + log_info("/* %s */", __func__); + assert_se(mkdtemp(template)); fn = strjoina(template, "/*"); @@ -93,10 +99,32 @@ static void test_safe_glob(void) { (void) rm_rf(template, REMOVE_ROOT|REMOVE_PHYSICAL); } +static void test_glob_non_glob_prefix_one(const char *path, const char *expected) { + _cleanup_free_ char *t; + + assert_se(glob_non_glob_prefix(path, &t) == 0); + assert_se(streq(t, expected)); +} + +static void test_glob_non_glob(void) { + log_info("/* %s */", __func__); + + test_glob_non_glob_prefix_one("/tmp/.X11-*", "/tmp/"); + test_glob_non_glob_prefix_one("/tmp/*", "/tmp/"); + test_glob_non_glob_prefix_one("/tmp*", "/"); + test_glob_non_glob_prefix_one("/tmp/*/whatever", "/tmp/"); + test_glob_non_glob_prefix_one("/tmp/*/whatever?", "/tmp/"); + test_glob_non_glob_prefix_one("/?", "/"); + + char *x; + assert_se(glob_non_glob_prefix("?", &x) == -ENOENT); +} + int main(void) { test_glob_exists(); test_glob_no_dot(); test_safe_glob(); + test_glob_non_glob(); return 0; } diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 071070e9f6..45cd549029 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2344,6 +2344,8 @@ static int clean_item(Item *i) { static int process_item(Item *i, OperationMask operation) { OperationMask todo; + _cleanup_free_ char *_path = NULL; + const char *path; int r, q, p; assert(i); @@ -2354,9 +2356,21 @@ static int process_item(Item *i, OperationMask operation) { i->done |= operation; - r = chase_symlinks(i->path, arg_root, CHASE_NO_AUTOFS|CHASE_WARN, NULL, NULL); + path = i->path; + if (string_is_glob(path)) { + /* We can't easily check whether a glob matches any autofs path, so let's do the check only + * for the non-glob part. */ + + r = glob_non_glob_prefix(path, &_path); + if (r < 0 && r != -ENOENT) + return log_debug_errno(r, "Failed to deglob path: %m"); + if (r >= 0) + path = _path; + } + + r = chase_symlinks(path, arg_root, CHASE_NO_AUTOFS|CHASE_NONEXISTENT|CHASE_WARN, NULL, NULL); if (r == -EREMOTE) { - log_notice_errno(r, "Skipping %s", i->path); + log_notice_errno(r, "Skipping %s", i->path); /* We log the configured path, to not confuse the user. */ return 0; } if (r < 0) |