summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO5
-rw-r--r--src/basic/glob-util.c19
-rw-r--r--src/basic/glob-util.h2
-rw-r--r--src/test/test-glob-util.c28
-rw-r--r--src/tmpfiles/tmpfiles.c18
5 files changed, 67 insertions, 5 deletions
diff --git a/TODO b/TODO
index 13c3321bfb..772128faa9 100644
--- a/TODO
+++ b/TODO
@@ -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)