diff options
author | Daan De Meyer <daan.j.demeyer@gmail.com> | 2023-09-29 11:33:12 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-29 11:33:12 +0200 |
commit | 4444564a9545a1bfd82367a64dd454d8fac84474 (patch) | |
tree | 7e7c367a10e5a5e0656e8977abaab4f8882c1169 /src | |
parent | Merge pull request #29241 from poettering/pidref-watch (diff) | |
parent | Rework unit_name_mangle_with_suffix() to (very slightly) simplify the path (diff) | |
download | systemd-4444564a9545a1bfd82367a64dd454d8fac84474.tar.xz systemd-4444564a9545a1bfd82367a64dd454d8fac84474.zip |
Merge pull request #29193 from keszybz/path-util-adjustment
Make unit mangling follow paths
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/cgroup-util.c | 21 | ||||
-rw-r--r-- | src/basic/fileio.c | 22 | ||||
-rw-r--r-- | src/basic/path-util.c | 62 | ||||
-rw-r--r-- | src/basic/path-util.h | 24 | ||||
-rw-r--r-- | src/basic/unit-name.c | 45 | ||||
-rw-r--r-- | src/basic/user-util.c | 16 | ||||
-rw-r--r-- | src/core/dbus-path.c | 21 | ||||
-rw-r--r-- | src/core/dbus-socket.c | 8 | ||||
-rw-r--r-- | src/delta/delta.c | 4 | ||||
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 8 | ||||
-rw-r--r-- | src/mount/mount-tool.c | 41 | ||||
-rw-r--r-- | src/portable/portable.c | 19 | ||||
-rw-r--r-- | src/shared/install.c | 21 | ||||
-rw-r--r-- | src/test/test-path-util.c | 140 | ||||
-rw-r--r-- | src/test/test-unit-name.c | 48 | ||||
-rw-r--r-- | src/udev/udev-node.c | 9 |
16 files changed, 339 insertions, 170 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 947fb900d6..ca697ed97a 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -978,6 +978,7 @@ int cg_is_empty_recursive(const char *controller, const char *path) { int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) { _cleanup_free_ char *controller = NULL, *path = NULL; + int r; assert(spec); @@ -986,11 +987,9 @@ int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) { return -EINVAL; if (ret_path) { - path = strdup(spec); - if (!path) - return -ENOMEM; - - path_simplify(path); + r = path_simplify_alloc(spec, &path); + if (r < 0) + return r; } } else { @@ -1037,22 +1036,14 @@ int cg_split_spec(const char *spec, char **ret_controller, char **ret_path) { int cg_mangle_path(const char *path, char **result) { _cleanup_free_ char *c = NULL, *p = NULL; - char *t; int r; assert(path); assert(result); /* First, check if it already is a filesystem path */ - if (path_startswith(path, "/sys/fs/cgroup")) { - - t = strdup(path); - if (!t) - return -ENOMEM; - - *result = path_simplify(t); - return 0; - } + if (path_startswith(path, "/sys/fs/cgroup")) + return path_simplify_alloc(path, result); /* Otherwise, treat it as cg spec */ r = cg_split_spec(path, &c, &p); diff --git a/src/basic/fileio.c b/src/basic/fileio.c index 48ffb4e5e6..ee1621822c 100644 --- a/src/basic/fileio.c +++ b/src/basic/fileio.c @@ -1110,6 +1110,7 @@ int search_and_fopen( char **ret_path) { _cleanup_strv_free_ char **copy = NULL; + int r; assert(filename); assert(mode); @@ -1123,13 +1124,9 @@ int search_and_fopen( return -errno; if (ret_path) { - char *p; - - p = strdup(filename); - if (!p) - return -ENOMEM; - - *ret_path = path_simplify(p); + r = path_simplify_alloc(filename, ret_path); + if (r < 0) + return r; } *ret = TAKE_PTR(f); @@ -1152,6 +1149,7 @@ int search_and_fopen_nulstr( char **ret_path) { _cleanup_strv_free_ char **s = NULL; + int r; if (path_is_absolute(filename)) { _cleanup_fclose_ FILE *f = NULL; @@ -1161,13 +1159,9 @@ int search_and_fopen_nulstr( return -errno; if (ret_path) { - char *p; - - p = strdup(filename); - if (!p) - return -ENOMEM; - - *ret_path = path_simplify(p); + r = path_simplify_alloc(filename, ret_path); + if (r < 0) + return r; } *ret = TAKE_PTR(f); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 7204c80e79..6810bf66aa 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -40,7 +40,7 @@ int path_split_and_make_absolute(const char *p, char ***ret) { return r; } -char *path_make_absolute(const char *p, const char *prefix) { +char* path_make_absolute(const char *p, const char *prefix) { assert(p); /* Makes every item in the list an absolute path by prepending @@ -132,11 +132,9 @@ int path_make_relative(const char *from, const char *to, char **ret) { return -ENOMEM; } else { /* 'to' is inside of 'from'. */ - result = strdup(t); - if (!result) - return -ENOMEM; - - path_simplify(result); + r = path_simplify_alloc(t, &result); + if (r < 0) + return r; if (!path_is_valid(result)) return -EINVAL; @@ -252,7 +250,7 @@ int path_strv_make_absolute_cwd(char **l) { return 0; } -char **path_strv_resolve(char **l, const char *root) { +char** path_strv_resolve(char **l, const char *root) { unsigned k = 0; bool enomem = false; int r; @@ -333,7 +331,7 @@ char **path_strv_resolve(char **l, const char *root) { return l; } -char **path_strv_resolve_uniq(char **l, const char *root) { +char** path_strv_resolve_uniq(char **l, const char *root) { if (strv_isempty(l)) return l; @@ -344,9 +342,9 @@ char **path_strv_resolve_uniq(char **l, const char *root) { return strv_uniq(l); } -char *path_simplify_full(char *path, PathSimplifyFlags flags) { - bool add_slash = false, keep_trailing_slash; - char *f = ASSERT_PTR(path); +char* path_simplify_full(char *path, PathSimplifyFlags flags) { + bool add_slash = false, keep_trailing_slash, absolute, beginning = true; + char *f = path; int r; /* Removes redundant inner and trailing slashes. Also removes unnecessary dots. @@ -354,6 +352,8 @@ char *path_simplify_full(char *path, PathSimplifyFlags flags) { * * ///foo//./bar/. becomes /foo/bar * .//./foo//./bar/. becomes foo/bar + * /../foo/bar becomes /foo/bar + * /../foo/bar/.. becomes /foo/bar/.. */ if (isempty(path)) @@ -361,8 +361,8 @@ char *path_simplify_full(char *path, PathSimplifyFlags flags) { keep_trailing_slash = FLAGS_SET(flags, PATH_SIMPLIFY_KEEP_TRAILING_SLASH) && endswith(path, "/"); - if (path_is_absolute(path)) - f++; + absolute = path_is_absolute(path); + f += absolute; /* Keep leading /, if present. */ for (const char *p = f;;) { const char *e; @@ -371,11 +371,17 @@ char *path_simplify_full(char *path, PathSimplifyFlags flags) { if (r == 0) break; + if (r > 0 && absolute && beginning && path_startswith(e, "..")) + /* If we're at the beginning of an absolute path, we can safely skip ".." */ + continue; + + beginning = false; + if (add_slash) *f++ = '/'; if (r < 0) { - /* if path is invalid, then refuse to simplify remaining part. */ + /* if path is invalid, then refuse to simplify the remaining part. */ memmove(f, p, strlen(p) + 1); return path; } @@ -397,7 +403,7 @@ char *path_simplify_full(char *path, PathSimplifyFlags flags) { return path; } -char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) { +char* path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) { assert(path); assert(prefix); @@ -657,7 +663,14 @@ static int find_executable_impl(const char *name, const char *root, char **ret_f return 0; } -int find_executable_full(const char *name, const char *root, char **exec_search_path, bool use_path_envvar, char **ret_filename, int *ret_fd) { +int find_executable_full( + const char *name, + const char *root, + char **exec_search_path, + bool use_path_envvar, + char **ret_filename, + int *ret_fd) { + int last_error = -ENOENT, r = 0; const char *p = NULL; @@ -807,7 +820,7 @@ int fsck_exists_for_fstype(const char *fstype) { return executable_is_good(checker); } -static const char *skip_slash_or_dot(const char *p) { +static const char* skip_slash_or_dot(const char *p) { for (; !isempty(p); p++) { if (*p == '/') continue; @@ -891,7 +904,7 @@ int path_find_first_component(const char **p, bool accept_dot_dot, const char ** return len; } -static const char *skip_slash_or_dot_backward(const char *path, const char *q) { +static const char* skip_slash_or_dot_backward(const char *path, const char *q) { assert(path); assert(!q || q >= path); @@ -1000,7 +1013,7 @@ int path_find_last_component(const char *path, bool accept_dot_dot, const char * return len; } -const char *last_path_component(const char *path) { +const char* last_path_component(const char *path) { /* Finds the last component of the path, preserving the optional trailing slash that signifies a directory. * @@ -1272,9 +1285,16 @@ bool hidden_or_backup_file(const char *filename) { bool is_device_path(const char *path) { /* Returns true for paths that likely refer to a device, either by path in sysfs or to something in - * /dev. */ + * /dev. This accepts any path that starts with /dev/ or /sys/ and has something after that prefix. + * It does not actually resolve the path. + * + * Examples: + * /dev/sda, /dev/sda/foo, /sys/class, /dev/.., /sys/.., /./dev/foo → yes. + * /../dev/sda, /dev, /sys, /usr/path, /usr/../dev/sda → no. + */ - return PATH_STARTSWITH_SET(path, "/dev/", "/sys/"); + const char *p = PATH_STARTSWITH_SET(ASSERT_PTR(path), "/dev/", "/sys/"); + return !isempty(p); } bool valid_device_node_path(const char *path) { diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 507aec27c5..6d943e967f 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -53,7 +53,7 @@ int safe_getcwd(char **ret); int path_make_absolute_cwd(const char *p, char **ret); int path_make_relative(const char *from, const char *to, char **ret); int path_make_relative_parent(const char *from_child, const char *to, char **ret); -char *path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) _pure_; +char* path_startswith_full(const char *path, const char *prefix, bool accept_dot_dot) _pure_; static inline char* path_startswith(const char *path, const char *prefix) { return path_startswith_full(path, prefix, true); } @@ -80,11 +80,27 @@ typedef enum PathSimplifyFlags { PATH_SIMPLIFY_KEEP_TRAILING_SLASH = 1 << 0, } PathSimplifyFlags; -char *path_simplify_full(char *path, PathSimplifyFlags flags); +char* path_simplify_full(char *path, PathSimplifyFlags flags); static inline char* path_simplify(char *path) { return path_simplify_full(path, 0); } +static inline int path_simplify_alloc(const char *path, char **ret) { + assert(ret); + + if (!path) { + *ret = NULL; + return 0; + } + + char *t = strdup(path); + if (!t) + return -ENOMEM; + + *ret = path_simplify(t); + return 0; +} + static inline bool path_equal_ptr(const char *a, const char *b) { return !!a == !!b && (!a || path_equal(a, b)); } @@ -159,7 +175,7 @@ int fsck_exists_for_fstype(const char *fstype); int path_find_first_component(const char **p, bool accept_dot_dot, const char **ret); int path_find_last_component(const char *path, bool accept_dot_dot, const char **next, const char **ret); -const char *last_path_component(const char *path); +const char* last_path_component(const char *path); int path_extract_filename(const char *path, char **ret); int path_extract_directory(const char *path, char **ret); @@ -196,7 +212,7 @@ static inline const char *skip_dev_prefix(const char *p) { } bool empty_or_root(const char *path); -static inline const char *empty_to_root(const char *path) { +static inline const char* empty_to_root(const char *path) { return isempty(path) ? "/" : path; } diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index 3b739c758a..8bf28ba749 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -389,15 +389,14 @@ int unit_name_unescape(const char *f, char **ret) { int unit_name_path_escape(const char *f, char **ret) { _cleanup_free_ char *p = NULL; char *s; + int r; assert(f); assert(ret); - p = strdup(f); - if (!p) - return -ENOMEM; - - path_simplify(p); + r = path_simplify_alloc(f, &p); + if (r < 0) + return r; if (empty_or_root(p)) s = strdup("-"); @@ -701,9 +700,15 @@ static bool do_escape_mangle(const char *f, bool allow_globs, char *t) { * * If @allow_globs, globs characters are preserved. Otherwise, they are escaped. */ -int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNameMangle flags, const char *suffix, char **ret) { +int unit_name_mangle_with_suffix( + const char *name, + const char *operation, + UnitNameMangle flags, + const char *suffix, + char **ret) { + _cleanup_free_ char *s = NULL; - bool mangled, suggest_escape = true; + bool mangled, suggest_escape = true, warn = flags & UNIT_NAME_MANGLE_WARN; int r; assert(name); @@ -724,22 +729,28 @@ int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNa if (string_is_glob(name) && in_charset(name, VALID_CHARS_GLOB)) { if (flags & UNIT_NAME_MANGLE_GLOB) goto good; - log_full(flags & UNIT_NAME_MANGLE_WARN ? LOG_NOTICE : LOG_DEBUG, + log_full(warn ? LOG_NOTICE : LOG_DEBUG, "Glob pattern passed%s%s, but globs are not supported for this.", operation ? " " : "", strempty(operation)); suggest_escape = false; } - if (is_device_path(name)) { - r = unit_name_from_path(name, ".device", ret); - if (r >= 0) - return 1; - if (r != -EINVAL) + if (path_is_absolute(name)) { + _cleanup_free_ char *n = NULL; + + r = path_simplify_alloc(name, &n); + if (r < 0) return r; - } - if (path_is_absolute(name)) { - r = unit_name_from_path(name, ".mount", ret); + if (is_device_path(n)) { + r = unit_name_from_path(n, ".device", ret); + if (r >= 0) + return 1; + if (r != -EINVAL) + return r; + } + + r = unit_name_from_path(n, ".mount", ret); if (r >= 0) return 1; if (r != -EINVAL) @@ -752,7 +763,7 @@ int unit_name_mangle_with_suffix(const char *name, const char *operation, UnitNa mangled = do_escape_mangle(name, flags & UNIT_NAME_MANGLE_GLOB, s); if (mangled) - log_full(flags & UNIT_NAME_MANGLE_WARN ? LOG_NOTICE : LOG_DEBUG, + log_full(warn ? LOG_NOTICE : LOG_DEBUG, "Invalid unit name \"%s\" escaped as \"%s\"%s.", name, s, suggest_escape ? " (maybe you should use systemd-escape?)" : ""); diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 5c39847733..9ae8577238 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -589,7 +589,6 @@ int getgroups_alloc(gid_t** gids) { int get_home_dir(char **ret) { struct passwd *p; const char *e; - char *h; uid_t u; assert(ret); @@ -622,18 +621,12 @@ int get_home_dir(char **ret) { return -EINVAL; found: - h = strdup(e); - if (!h) - return -ENOMEM; - - *ret = path_simplify(h); - return 0; + return path_simplify_alloc(e, ret); } int get_shell(char **ret) { struct passwd *p; const char *e; - char *s; uid_t u; assert(ret); @@ -665,12 +658,7 @@ int get_shell(char **ret) { return -EINVAL; found: - s = strdup(e); - if (!s) - return -ENOMEM; - - *ret = path_simplify(s); - return 0; + return path_simplify_alloc(e, ret); } int reset_uid_gid(void) { diff --git a/src/core/dbus-path.c b/src/core/dbus-path.c index 22de551c54..8cb6a265fa 100644 --- a/src/core/dbus-path.c +++ b/src/core/dbus-path.c @@ -97,22 +97,21 @@ static int bus_path_set_transient_property( if (!UNIT_WRITE_FLAGS_NOOP(flags)) { _cleanup_free_ char *k = NULL; - PathSpec *s; - k = strdup(path); - if (!k) - return -ENOMEM; - - path_simplify(k); + r = path_simplify_alloc(path, &k); + if (r < 0) + return r; - s = new0(PathSpec, 1); + PathSpec *s = new(PathSpec, 1); if (!s) return -ENOMEM; - s->unit = u; - s->path = TAKE_PTR(k); - s->type = t; - s->inotify_fd = -EBADF; + *s = (PathSpec) { + .unit = u, + .path = TAKE_PTR(k), + .type = t, + .inotify_fd = -EBADF, + }; LIST_PREPEND(spec, p->specs, s); diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 04552b7c60..5e5b715e90 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -391,11 +391,9 @@ static int bus_socket_set_transient_property( if (!path_is_absolute(a) || !path_is_valid(a)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid socket path: %s", a); - p->path = strdup(a); - if (!p->path) - return log_oom(); - - path_simplify(p->path); + r = path_simplify_alloc(a, &p->path); + if (r < 0) + return r; } else if (streq(t, "Netlink")) { r = socket_address_parse_netlink(&p->address, a); diff --git a/src/delta/delta.c b/src/delta/delta.c index beca7ea975..d830c5e162 100644 --- a/src/delta/delta.c +++ b/src/delta/delta.c @@ -611,9 +611,7 @@ static int run(int argc, char *argv[]) { pager_open(arg_pager_flags); if (optind < argc) { - int i; - - for (i = optind; i < argc; i++) { + for (int i = optind; i < argc; i++) { path_simplify(argv[i]); k = process_suffix_chop(argv[i]); diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index 2dff9e1a91..75725a75b3 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -232,11 +232,9 @@ int device_set_syspath(sd_device *device, const char *_syspath, bool verify) { "sd-device: Syspath '%s' is not a subdirectory of /sys", _syspath); - syspath = strdup(_syspath); - if (!syspath) - return log_oom_debug(); - - path_simplify(syspath); + r = path_simplify_alloc(_syspath, &syspath); + if (r < 0) + return r; } assert_se(devpath = startswith(syspath, "/sys")); diff --git a/src/mount/mount-tool.c b/src/mount/mount-tool.c index a0dcdf53b6..90feb2f197 100644 --- a/src/mount/mount-tool.c +++ b/src/mount/mount-tool.c @@ -83,30 +83,26 @@ STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_automount_property, strv_freep); static int parse_where(const char *input, char **ret_where) { - _cleanup_free_ char *where = NULL; int r; assert(input); assert(ret_where); if (arg_transport == BUS_TRANSPORT_LOCAL) { - r = chase(input, NULL, CHASE_NONEXISTENT, &where, NULL); + r = chase(input, NULL, CHASE_NONEXISTENT, ret_where, NULL); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", input); } else { - where = strdup(input); - if (!where) - return log_oom(); - - path_simplify(where); - - if (!path_is_absolute(where)) + if (!path_is_absolute(input)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path must be absolute when operating remotely: %s", - where); + input); + + r = path_simplify_alloc(input, ret_where); + if (r < 0) + return log_error_errno(r, "Failed to simplify path %s: %m", input); } - *ret_where = TAKE_PTR(where); return 0; } @@ -441,17 +437,16 @@ static int parse_argv(int argc, char *argv[]) { r = chase(u, NULL, 0, &arg_mount_what, NULL); if (r < 0) return log_error_errno(r, "Failed to make path %s absolute: %m", u); - } else { - arg_mount_what = strdup(argv[optind]); - if (!arg_mount_what) - return log_oom(); - path_simplify(arg_mount_what); - - if (!path_is_absolute(arg_mount_what)) + } else { + if (!path_is_absolute(argv[optind])) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Path must be absolute when operating remotely: %s", - arg_mount_what); + argv[optind]); + + r = path_simplify_alloc(argv[optind], &arg_mount_what); + if (r < 0) + return log_error_errno(r, "Failed to simplify path: %m"); } } @@ -1054,11 +1049,9 @@ static int action_umount( for (int i = optind; i < argc; i++) { _cleanup_free_ char *p = NULL; - p = strdup(argv[i]); - if (!p) - return log_oom(); - - path_simplify(p); + r = path_simplify_alloc(argv[i], &p); + if (r < 0) + return r; r = stop_mounts(bus, p); if (r < 0) diff --git a/src/portable/portable.c b/src/portable/portable.c index 545a3ed5d2..52f38dc83e 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -838,6 +838,7 @@ static int portable_changes_add( _cleanup_free_ char *p = NULL, *s = NULL; PortableChange *c; + int r; assert(path); assert(!changes == !n_changes); @@ -855,19 +856,13 @@ static int portable_changes_add( return -ENOMEM; *changes = c; - p = strdup(path); - if (!p) - return -ENOMEM; - - path_simplify(p); - - if (source) { - s = strdup(source); - if (!s) - return -ENOMEM; + r = path_simplify_alloc(path, &p); + if (r < 0) + return r; - path_simplify(s); - } + r = path_simplify_alloc(source, &s); + if (r < 0) + return r; c[(*n_changes)++] = (PortableChange) { .type_or_errno = type_or_errno, diff --git a/src/shared/install.c b/src/shared/install.c index e25e78629e..ba3be0e99d 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -285,6 +285,7 @@ InstallChangeType install_changes_add( _cleanup_free_ char *p = NULL, *s = NULL; InstallChange *c; + int r; assert(!changes == !n_changes); assert(INSTALL_CHANGE_TYPE_VALID(type)); @@ -303,21 +304,13 @@ InstallChangeType install_changes_add( return -ENOMEM; *changes = c; - if (path) { - p = strdup(path); - if (!p) - return -ENOMEM; - - path_simplify(p); - } - - if (source) { - s = strdup(source); - if (!s) - return -ENOMEM; + r = path_simplify_alloc(path, &p); + if (r < 0) + return r; - path_simplify(s); - } + r = path_simplify_alloc(source, &s); + if (r < 0) + return r; c[(*n_changes)++] = (InstallChange) { .type = type, diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 8c3a27f228..96a4fce630 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -26,10 +26,6 @@ TEST(path) { assert_se(path_is_absolute("/")); assert_se(!path_is_absolute("./")); - assert_se(is_path("/dir")); - assert_se(is_path("a/b")); - assert_se(!is_path(".")); - assert_se(streq(basename("./aa/bb/../file.da."), "file.da.")); assert_se(streq(basename("/aa///.file"), ".file")); assert_se(streq(basename("/aa///file..."), "file...")); @@ -48,6 +44,100 @@ TEST(path) { assert_se(!path_equal_ptr(NULL, "/a")); } +TEST(is_path) { + assert_se(!is_path("foo")); + assert_se(!is_path("dos.ext")); + assert_se( is_path("/dir")); + assert_se( is_path("a/b")); + assert_se( is_path("a/b.ext")); + + assert_se(!is_path(".")); + assert_se(!is_path("")); + assert_se(!is_path("..")); + + assert_se( is_path("/dev")); + assert_se( is_path("/./dev")); + assert_se( is_path("/./dev/.")); + assert_se( is_path("/./dev.")); + assert_se( is_path("//dev")); + assert_se( is_path("///dev")); + assert_se( is_path("/dev/")); + assert_se( is_path("///dev/")); + assert_se( is_path("/./dev/")); + assert_se( is_path("/../dev/")); + assert_se( is_path("/dev/sda")); + assert_se( is_path("/dev/sda5")); + assert_se( is_path("/dev/sda5b3")); + assert_se( is_path("/dev/sda5b3/idontexit")); + assert_se( is_path("/../dev/sda")); + assert_se( is_path("/../../dev/sda5")); + assert_se( is_path("/../../../dev/sda5b3")); + assert_se( is_path("/.././.././dev/sda5b3/idontexit")); + assert_se( is_path("/sys")); + assert_se( is_path("/sys/")); + assert_se( is_path("/./sys")); + assert_se( is_path("/./sys/.")); + assert_se( is_path("/./sys.")); + assert_se( is_path("/sys/what")); + assert_se( is_path("/sys/something/..")); + assert_se( is_path("/sys/something/../")); + assert_se( is_path("/sys////")); + assert_se( is_path("/sys////.")); + assert_se( is_path("/sys/..")); + assert_se( is_path("/sys/../")); + assert_se( is_path("/usr/../dev/sda")); +} + +TEST(is_device_path) { + assert_se(!is_device_path("foo")); + assert_se(!is_device_path("dos.ext")); + assert_se(!is_device_path("/dir")); + assert_se(!is_device_path("a/b")); + assert_se(!is_device_path("a/b.ext")); + + assert_se(!is_device_path(".")); + assert_se(!is_device_path("")); + assert_se(!is_device_path("..")); + + assert_se(!is_device_path("/dev")); + assert_se(!is_device_path("/./dev")); + assert_se(!is_device_path("/./dev/.")); + assert_se(!is_device_path("/./dev.")); + assert_se( is_device_path("/./dev/foo")); + assert_se( is_device_path("/./dev/./foo")); + assert_se(!is_device_path("/./dev./foo")); + assert_se(!is_device_path("//dev")); + assert_se(!is_device_path("///dev")); + assert_se(!is_device_path("/dev/")); + assert_se(!is_device_path("///dev/")); + assert_se(!is_device_path("/./dev/")); + assert_se(!is_device_path("/../dev/")); + assert_se( is_device_path("/dev/sda")); + assert_se( is_device_path("/dev/sda5")); + assert_se( is_device_path("/dev/sda5b3")); + assert_se( is_device_path("/dev/sda5b3/idontexit")); + assert_se(!is_device_path("/../dev/sda")); + assert_se(!is_device_path("/../../dev/sda5")); + assert_se(!is_device_path("/../../../dev/sda5b3")); + assert_se(!is_device_path("/.././.././dev/sda5b3/idontexit")); + assert_se(!is_device_path("/sys")); + assert_se(!is_device_path("/sys/")); + assert_se(!is_device_path("/./sys")); + assert_se(!is_device_path("/./sys/.")); + assert_se(!is_device_path("/./sys.")); + assert_se( is_device_path("/./sys/foo")); + assert_se( is_device_path("/./sys/./foo")); + assert_se(!is_device_path("/./sys./foo")); + assert_se( is_device_path("/sys/what")); + assert_se( is_device_path("/sys/something/..")); + assert_se( is_device_path("/sys/something/../")); + assert_se(!is_device_path("/sys////")); + assert_se(!is_device_path("/sys////.")); + assert_se( is_device_path("/sys/..")); + assert_se( is_device_path("/sys/../")); + assert_se(!is_device_path("/usr/../dev/sda")); +} + static void test_path_simplify_one(const char *in, const char *out, PathSimplifyFlags flags) { char *p; @@ -68,7 +158,7 @@ TEST(path_simplify) { test_path_simplify_one("///", "/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); test_path_simplify_one("///.//", "/", 0); test_path_simplify_one("///.//.///", "/", 0); - test_path_simplify_one("////.././///../.", "/../..", 0); + test_path_simplify_one("////.././///../.", "/", 0); test_path_simplify_one(".", ".", 0); test_path_simplify_one("./", ".", 0); test_path_simplify_one("./", "./", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); @@ -84,6 +174,46 @@ TEST(path_simplify) { "../aaa/.bbb/../c./d.dd/..eeee/..", 0); test_path_simplify_one("abc///", "abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../abc///", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../abc///", "/abc", 0); + test_path_simplify_one("/../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../abc///..", "/abc/..", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../abc///../", "/abc/../", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../abc///../", "/abc/..", 0); + + test_path_simplify_one("/../../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../../abc///", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../../abc///", "/abc", 0); + test_path_simplify_one("/../../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../../abc///../..", "/abc/../..", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../../abc///../../", "/abc/../../", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/../../abc///../../", "/abc/../..", 0); + + test_path_simplify_one("/.././../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.././../abc///", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.././../abc///", "/abc", 0); + test_path_simplify_one("/.././../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.././../abc///../..", "/abc/../..", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.././../abc///../../", "/abc/../../", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.././../abc///../../", "/abc/../..", 0); + + test_path_simplify_one("/./.././../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/./.././../abc///", "/abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/./.././../abc///", "/abc", 0); + test_path_simplify_one("/./.././../abc", "/abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/./.././../abc///../..", "/abc/../..", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/./.././../abc///../../", "/abc/../../", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/./.././../abc///../../", "/abc/../..", 0); + + test_path_simplify_one("/.../abc", "/.../abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.../abc///", "/.../abc/", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.../abc///", "/.../abc", 0); + test_path_simplify_one("/.../abc", "/.../abc", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.../abc///...", "/.../abc/...", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.../abc///.../", "/.../abc/.../", PATH_SIMPLIFY_KEEP_TRAILING_SLASH); + test_path_simplify_one("/.../abc///.../", "/.../abc/...", 0); + memset(foo, 'a', sizeof(foo) -1); char_array_0(foo); diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index ada8330408..8e9332c33e 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -201,8 +201,12 @@ TEST(unit_name_to_path) { static void test_unit_name_mangle_one(bool allow_globs, const char *pattern, const char *expect, int ret) { _cleanup_free_ char *t = NULL; + int r; + + r = unit_name_mangle(pattern, (allow_globs * UNIT_NAME_MANGLE_GLOB) | UNIT_NAME_MANGLE_WARN, &t); + log_debug("%s: %s -> %d, %s", __func__, pattern, r, strnull(t)); - assert_se(unit_name_mangle(pattern, (allow_globs * UNIT_NAME_MANGLE_GLOB) | UNIT_NAME_MANGLE_WARN, &t) == ret); + assert_se(r == ret); puts(strna(t)); assert_se(streq_ptr(t, expect)); @@ -234,6 +238,48 @@ TEST(unit_name_mangle) { test_unit_name_mangle_one(true, "ü*", "\\xc3\\xbc*", 1); } +static void test_unit_name_mangle_with_suffix_one(const char *arg, int expected, const char *expected_name) { + _cleanup_free_ char *s = NULL; + int r; + + r = unit_name_mangle_with_suffix(arg, NULL, 0, ".service", &s); + log_debug("%s: %s -> %d, %s", __func__, arg, r, strnull(s)); + + assert_se(r == expected); + assert_se(streq_ptr(s, expected_name)); +} + +TEST(unit_name_mangle_with_suffix) { + test_unit_name_mangle_with_suffix_one("", -EINVAL, NULL); + + test_unit_name_mangle_with_suffix_one("/dev", 1, "dev.mount"); + test_unit_name_mangle_with_suffix_one("/../dev", 1, "dev.mount"); + test_unit_name_mangle_with_suffix_one("/../dev/.", 1, "dev.mount"); + /* We don't skip the last '..', and it makes this an invalid device or mount name */ + test_unit_name_mangle_with_suffix_one("/.././dev/..", 1, "-..-.-dev-...service"); + test_unit_name_mangle_with_suffix_one("/.././dev", 1, "dev.mount"); + test_unit_name_mangle_with_suffix_one("/./.././../dev/", 1, "dev.mount"); + + test_unit_name_mangle_with_suffix_one("/dev/sda", 1, "dev-sda.device"); + test_unit_name_mangle_with_suffix_one("/dev/sda5", 1, "dev-sda5.device"); + + test_unit_name_mangle_with_suffix_one("/sys", 1, "sys.mount"); + test_unit_name_mangle_with_suffix_one("/../sys", 1, "sys.mount"); + test_unit_name_mangle_with_suffix_one("/../sys/.", 1, "sys.mount"); + /* We don't skip the last '..', and it makes this an invalid device or mount name */ + test_unit_name_mangle_with_suffix_one("/.././sys/..", 1, "-..-.-sys-...service"); + test_unit_name_mangle_with_suffix_one("/.././sys", 1, "sys.mount"); + test_unit_name_mangle_with_suffix_one("/./.././../sys/", 1, "sys.mount"); + + test_unit_name_mangle_with_suffix_one("/proc", 1, "proc.mount"); + test_unit_name_mangle_with_suffix_one("/../proc", 1, "proc.mount"); + test_unit_name_mangle_with_suffix_one("/../proc/.", 1, "proc.mount"); + /* We don't skip the last '..', and it makes this an invalid device or mount name */ + test_unit_name_mangle_with_suffix_one("/.././proc/..", 1, "-..-.-proc-...service"); + test_unit_name_mangle_with_suffix_one("/.././proc", 1, "proc.mount"); + test_unit_name_mangle_with_suffix_one("/./.././../proc/", 1, "proc.mount"); +} + TEST_RET(unit_printf, .sd_booted = true) { _cleanup_free_ char *architecture, *os_image_version, *boot_id = NULL, *os_build_id, diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 75845413cf..6ba38087dc 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -331,15 +331,14 @@ static int stack_directory_get_name(const char *slink, char **ret) { _cleanup_free_ char *s = NULL, *dirname = NULL; char name_enc[NAME_MAX+1]; const char *name; + int r; assert(slink); assert(ret); - s = strdup(slink); - if (!s) - return -ENOMEM; - - path_simplify(s); + r = path_simplify_alloc(slink, &s); + if (r < 0) + return r; if (!path_is_normalized(s)) return -EINVAL; |