diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-07-19 21:47:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-19 21:47:10 +0200 |
commit | a505166845f9806ac87389821474b6aa16cd0d9d (patch) | |
tree | ca796515ffb546e53431dacacc5760518ed7da59 /src | |
parent | 9b4abc69b201e5d7295e1b0762883659f053e747 (diff) | |
parent | f20319402af8136da61b2fa211f4c8e9834c3c00 (diff) | |
download | systemd-a505166845f9806ac87389821474b6aa16cd0d9d.tar.gz systemd-a505166845f9806ac87389821474b6aa16cd0d9d.tar.bz2 systemd-a505166845f9806ac87389821474b6aa16cd0d9d.zip |
Merge pull request #13096 from keszybz/unit-loading
Preparatory work for the unit loading rework
Diffstat (limited to 'src')
43 files changed, 725 insertions, 474 deletions
diff --git a/src/basic/hash-funcs.c b/src/basic/hash-funcs.c index 1be43d41a9..11cd371fad 100644 --- a/src/basic/hash-funcs.c +++ b/src/basic/hash-funcs.c @@ -10,6 +10,9 @@ void string_hash_func(const char *p, struct siphash *state) { } DEFINE_HASH_OPS(string_hash_ops, char, string_hash_func, string_compare_func); +DEFINE_HASH_OPS_FULL(string_hash_ops_free_free, + char, string_hash_func, string_compare_func, free, + char, free); void path_hash_func(const char *q, struct siphash *state) { size_t n; diff --git a/src/basic/hash-funcs.h b/src/basic/hash-funcs.h index 3d2ae4b55e..0d2d428389 100644 --- a/src/basic/hash-funcs.h +++ b/src/basic/hash-funcs.h @@ -76,6 +76,7 @@ struct hash_ops { void string_hash_func(const char *p, struct siphash *state); #define string_compare_func strcmp extern const struct hash_ops string_hash_ops; +extern const struct hash_ops string_hash_ops_free_free; void path_hash_func(const char *p, struct siphash *state); int path_compare_func(const char *a, const char *b) _pure_; diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index f244d767da..3bd94a1320 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -733,8 +733,8 @@ bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const v return true; } -bool set_iterate(Set *s, Iterator *i, void **value) { - return internal_hashmap_iterate(HASHMAP_BASE(s), i, value, NULL); +bool set_iterate(const Set *s, Iterator *i, void **value) { + return internal_hashmap_iterate(HASHMAP_BASE((Set*) s), i, value, NULL); } #define HASHMAP_FOREACH_IDX(idx, h, i) \ @@ -1768,6 +1768,32 @@ int set_consume(Set *s, void *value) { return r; } +int hashmap_put_strdup(Hashmap **h, const char *k, const char *v) { + int r; + + r = hashmap_ensure_allocated(h, &string_hash_ops_free_free); + if (r < 0) + return r; + + _cleanup_free_ char *kdup = NULL, *vdup = NULL; + kdup = strdup(k); + vdup = strdup(v); + if (!kdup || !vdup) + return -ENOMEM; + + r = hashmap_put(*h, kdup, vdup); + if (r < 0) { + if (r == -EEXIST && streq(v, hashmap_get(*h, kdup))) + return 0; + return r; + } + + assert(r > 0); /* 0 would mean vdup is already in the hashmap, which cannot be */ + kdup = vdup = NULL; + + return 0; +} + int set_put_strdup(Set *s, const char *p) { char *c; diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 1b071c230e..65adc92513 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -147,6 +147,8 @@ static inline int ordered_hashmap_put(OrderedHashmap *h, const void *key, void * return hashmap_put(PLAIN_HASHMAP(h), key, value); } +int hashmap_put_strdup(Hashmap **h, const char *k, const char *v); + int hashmap_update(Hashmap *h, const void *key, void *value); static inline int ordered_hashmap_update(OrderedHashmap *h, const void *key, void *value) { return hashmap_update(PLAIN_HASHMAP(h), key, value); diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 570f88627d..18c7dabbae 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -207,6 +207,18 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) { return 0; } +char* path_startswith_strv(const char *p, char **set) { + char **s, *t; + + STRV_FOREACH(s, set) { + t = path_startswith(p, *s); + if (t) + return t; + } + + return NULL; +} + int path_strv_make_absolute_cwd(char **l) { char **s; int r; @@ -382,6 +394,52 @@ char *path_simplify(char *path, bool kill_dots) { return path; } +int path_simplify_and_warn( + char *path, + unsigned flag, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue) { + + bool fatal = flag & PATH_CHECK_FATAL; + + assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)); + + if (!utf8_is_valid(path)) + return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path); + + if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) { + bool absolute; + + absolute = path_is_absolute(path); + + if (!absolute && (flag & PATH_CHECK_ABSOLUTE)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path is not absolute%s: %s", + lvalue, fatal ? "" : ", ignoring", path); + + if (absolute && (flag & PATH_CHECK_RELATIVE)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path is absolute%s: %s", + lvalue, fatal ? "" : ", ignoring", path); + } + + path_simplify(path, true); + + if (!path_is_valid(path)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path has invalid length (%zu bytes)%s.", + lvalue, strlen(path), fatal ? "" : ", ignoring"); + + if (!path_is_normalized(path)) + return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), + "%s= path is not normalized%s: %s", + lvalue, fatal ? "" : ", ignoring", path); + + return 0; +} + char* path_startswith(const char *path, const char *prefix) { assert(path); assert(prefix); @@ -1058,49 +1116,3 @@ bool empty_or_root(const char *root) { return root[strspn(root, "/")] == 0; } - -int path_simplify_and_warn( - char *path, - unsigned flag, - const char *unit, - const char *filename, - unsigned line, - const char *lvalue) { - - bool fatal = flag & PATH_CHECK_FATAL; - - assert(!FLAGS_SET(flag, PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)); - - if (!utf8_is_valid(path)) - return log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, path); - - if (flag & (PATH_CHECK_ABSOLUTE | PATH_CHECK_RELATIVE)) { - bool absolute; - - absolute = path_is_absolute(path); - - if (!absolute && (flag & PATH_CHECK_ABSOLUTE)) - return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), - "%s= path is not absolute%s: %s", - lvalue, fatal ? "" : ", ignoring", path); - - if (absolute && (flag & PATH_CHECK_RELATIVE)) - return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), - "%s= path is absolute%s: %s", - lvalue, fatal ? "" : ", ignoring", path); - } - - path_simplify(path, true); - - if (!path_is_valid(path)) - return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), - "%s= path has invalid length (%zu bytes)%s.", - lvalue, strlen(path), fatal ? "" : ", ignoring"); - - if (!path_is_normalized(path)) - return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), - "%s= path is not normalized%s: %s", - lvalue, fatal ? "" : ", ignoring", path); - - return 0; -} diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 4a1ed0a1a8..1f46cd65c9 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -54,6 +54,14 @@ char* path_join_internal(const char *first, ...); char* path_simplify(char *path, bool kill_dots); +enum { + PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */ + PATH_CHECK_ABSOLUTE = 1 << 1, + PATH_CHECK_RELATIVE = 1 << 2, +}; + +int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue); + static inline bool path_equal_ptr(const char *a, const char *b) { return !!a == !!b && (!a || path_equal(a, b)); } @@ -71,17 +79,8 @@ static inline bool path_equal_ptr(const char *a, const char *b) { _found; \ }) -#define PATH_STARTSWITH_SET(p, ...) \ - ({ \ - const char *_p = (p); \ - char *_found = NULL, **_i; \ - STRV_FOREACH(_i, STRV_MAKE(__VA_ARGS__)) { \ - _found = path_startswith(_p, *_i); \ - if (_found) \ - break; \ - } \ - _found; \ - }) +char* path_startswith_strv(const char *p, char **set); +#define PATH_STARTSWITH_SET(p, ...) path_startswith_strv(p, STRV_MAKE(__VA_ARGS__)) int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *root); @@ -178,11 +177,3 @@ bool empty_or_root(const char *root); static inline const char *empty_to_root(const char *path) { return isempty(path) ? "/" : path; } - -enum { - PATH_CHECK_FATAL = 1 << 0, /* If not set, then error message is appended with 'ignoring'. */ - PATH_CHECK_ABSOLUTE = 1 << 1, - PATH_CHECK_RELATIVE = 1 << 2, -}; - -int path_simplify_and_warn(char *path, unsigned flag, const char *unit, const char *filename, unsigned line, const char *lvalue); diff --git a/src/basic/set.h b/src/basic/set.h index 2a80632b79..2bb26c68b8 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -28,13 +28,13 @@ int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHM int set_put(Set *s, const void *key); /* no set_update */ /* no set_replace */ -static inline void *set_get(Set *s, void *key) { - return internal_hashmap_get(HASHMAP_BASE(s), key); +static inline void *set_get(const Set *s, void *key) { + return internal_hashmap_get(HASHMAP_BASE((Set *) s), key); } /* no set_get2 */ -static inline bool set_contains(Set *s, const void *key) { - return internal_hashmap_contains(HASHMAP_BASE(s), key); +static inline bool set_contains(const Set *s, const void *key) { + return internal_hashmap_contains(HASHMAP_BASE((Set *) s), key); } static inline void *set_remove(Set *s, const void *key) { @@ -59,19 +59,19 @@ static inline int set_move_one(Set *s, Set *other, const void *key) { return internal_hashmap_move_one(HASHMAP_BASE(s), HASHMAP_BASE(other), key); } -static inline unsigned set_size(Set *s) { - return internal_hashmap_size(HASHMAP_BASE(s)); +static inline unsigned set_size(const Set *s) { + return internal_hashmap_size(HASHMAP_BASE((Set *) s)); } -static inline bool set_isempty(Set *s) { +static inline bool set_isempty(const Set *s) { return set_size(s) == 0; } -static inline unsigned set_buckets(Set *s) { - return internal_hashmap_buckets(HASHMAP_BASE(s)); +static inline unsigned set_buckets(const Set *s) { + return internal_hashmap_buckets(HASHMAP_BASE((Set *) s)); } -bool set_iterate(Set *s, Iterator *i, void **value); +bool set_iterate(const Set *s, Iterator *i, void **value); static inline void set_clear(Set *s) { internal_hashmap_clear(HASHMAP_BASE(s), NULL, NULL); diff --git a/src/basic/strv.c b/src/basic/strv.c index 2ae685f35a..88b85867bb 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -889,3 +889,63 @@ int fputstrv(FILE *f, char **l, const char *separator, bool *space) { return 0; } + +static int string_strv_hashmap_put_internal(Hashmap *h, const char *key, const char *value) { + char **l; + int r; + + l = hashmap_get(h, key); + if (l) { + /* A list for this key already exists, let's append to it if it is not listed yet */ + if (strv_contains(l, value)) + return 0; + + r = strv_extend(&l, value); + if (r < 0) + return r; + + assert_se(hashmap_update(h, key, l) >= 0); + } else { + /* No list for this key exists yet, create one */ + _cleanup_strv_free_ char **l2 = NULL; + _cleanup_free_ char *t = NULL; + + t = strdup(key); + if (!t) + return -ENOMEM; + + r = strv_extend(&l2, value); + if (r < 0) + return r; + + r = hashmap_put(h, t, l2); + if (r < 0) + return r; + TAKE_PTR(t); + TAKE_PTR(l2); + } + + return 1; +} + +int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value) { + int r; + + r = hashmap_ensure_allocated(h, &string_strv_hash_ops); + if (r < 0) + return r; + + return string_strv_hashmap_put_internal(*h, key, value); +} + +int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value) { + int r; + + r = ordered_hashmap_ensure_allocated(h, &string_strv_hash_ops); + if (r < 0) + return r; + + return string_strv_hashmap_put_internal(PLAIN_HASHMAP(*h), key, value); +} + +DEFINE_HASH_OPS_FULL(string_strv_hash_ops, char, string_hash_func, string_compare_func, free, char*, strv_free); diff --git a/src/basic/strv.h b/src/basic/strv.h index aa5f95ab72..e80964acd1 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -9,6 +9,7 @@ #include "alloc-util.h" #include "extract-word.h" +#include "hashmap.h" #include "macro.h" #include "string-util.h" @@ -188,3 +189,7 @@ int fputstrv(FILE *f, char **l, const char *separator, bool *space); (b) = NULL; \ 0; \ }) + +extern const struct hash_ops string_strv_hash_ops; +int string_strv_hashmap_put(Hashmap **h, const char *key, const char *value); +int string_strv_ordered_hashmap_put(OrderedHashmap **h, const char *key, const char *value); diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c index af873d0ffd..4226f3014d 100644 --- a/src/basic/unit-name.c +++ b/src/basic/unit-name.c @@ -140,12 +140,10 @@ int unit_name_to_prefix(const char *n, char **ret) { return 0; } -int unit_name_to_instance(const char *n, char **instance) { +int unit_name_to_instance(const char *n, char **ret) { const char *p, *d; - char *i; assert(n); - assert(instance); if (!unit_name_is_valid(n, UNIT_NAME_ANY)) return -EINVAL; @@ -153,8 +151,9 @@ int unit_name_to_instance(const char *n, char **instance) { /* Everything past the first @ and before the last . is the instance */ p = strchr(n, '@'); if (!p) { - *instance = NULL; - return 0; + if (ret) + *ret = NULL; + return UNIT_NAME_PLAIN; } p++; @@ -163,12 +162,14 @@ int unit_name_to_instance(const char *n, char **instance) { if (!d) return -EINVAL; - i = strndup(p, d-p); - if (!i) - return -ENOMEM; + if (ret) { + char *i = strndup(p, d-p); + if (!i) + return -ENOMEM; - *instance = i; - return 1; + *ret = i; + } + return d > p ? UNIT_NAME_INSTANCE : UNIT_NAME_TEMPLATE; } int unit_name_to_prefix_and_instance(const char *n, char **ret) { diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h index 0629db3f67..2e060ff3e8 100644 --- a/src/basic/unit-name.h +++ b/src/basic/unit-name.h @@ -10,9 +10,9 @@ typedef enum UnitNameFlags { UNIT_NAME_PLAIN = 1 << 0, /* Allow foo.service */ - UNIT_NAME_INSTANCE = 1 << 1, /* Allow foo@bar.service */ - UNIT_NAME_TEMPLATE = 1 << 2, /* Allow foo@.service */ - UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE, + UNIT_NAME_TEMPLATE = 1 << 1, /* Allow foo@.service */ + UNIT_NAME_INSTANCE = 1 << 2, /* Allow foo@bar.service */ + UNIT_NAME_ANY = UNIT_NAME_PLAIN|UNIT_NAME_TEMPLATE|UNIT_NAME_INSTANCE, } UnitNameFlags; bool unit_name_is_valid(const char *n, UnitNameFlags flags) _pure_; @@ -20,13 +20,11 @@ bool unit_prefix_is_valid(const char *p) _pure_; bool unit_instance_is_valid(const char *i) _pure_; bool unit_suffix_is_valid(const char *s) _pure_; -static inline int unit_prefix_and_instance_is_valid(const char *p) { - /* For prefix+instance and instance the same rules apply */ - return unit_instance_is_valid(p); +int unit_name_to_prefix(const char *n, char **ret); +int unit_name_to_instance(const char *n, char **ret); +static inline int unit_name_classify(const char *n) { + return unit_name_to_instance(n, NULL); } - -int unit_name_to_prefix(const char *n, char **prefix); -int unit_name_to_instance(const char *n, char **instance); int unit_name_to_prefix_and_instance(const char *n, char **ret); UnitType unit_name_to_type(const char *n) _pure_; diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index 7a8b848fb3..a637437a5a 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -23,6 +23,7 @@ #include "memory-util.h" #include "missing_syscall.h" #include "unit.h" +#include "strv.h" #include "virt.h" enum { diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 1366d11c06..6e0afa4bca 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -279,7 +279,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) { prefix, c->memory_limit, prefix, c->tasks_max, prefix, cgroup_device_policy_to_string(c->device_policy), - prefix, strnull(disable_controllers_str), + prefix, strempty(disable_controllers_str), prefix, yes_no(c->delegate)); if (c->delegate) { diff --git a/src/core/dbus-job.c b/src/core/dbus-job.c index d11e58b51d..a7d342257b 100644 --- a/src/core/dbus-job.c +++ b/src/core/dbus-job.c @@ -10,6 +10,7 @@ #include "log.h" #include "selinux-access.h" #include "string-util.h" +#include "strv.h" static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, job_type, JobType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_state, job_state, JobState); diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 220b4c2372..ef434fb9f1 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -12,6 +12,7 @@ #include "dbus-util.h" #include "dbus.h" #include "fd-util.h" +#include "install.h" #include "locale-util.h" #include "log.h" #include "path-util.h" diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c index fb0a794348..e7a2f64525 100644 --- a/src/core/dynamic-user.c +++ b/src/core/dynamic-user.c @@ -20,6 +20,7 @@ #include "socket-util.h" #include "stdio-util.h" #include "string-util.h" +#include "strv.h" #include "user-util.h" /* Takes a value generated randomly or by hashing and turns it into a UID in the right range */ diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h index bb10a76338..ea15554d88 100644 --- a/src/core/load-dropin.h +++ b/src/core/load-dropin.h @@ -9,11 +9,12 @@ static inline int unit_find_dropin_paths(Unit *u, char ***paths) { assert(u); - return unit_file_find_dropin_conf_paths(NULL, - u->manager->lookup_paths.search_path, - u->manager->unit_path_cache, - u->names, - paths); + return unit_file_find_dropin_paths(NULL, + u->manager->lookup_paths.search_path, + u->manager->unit_path_cache, + ".d", ".conf", + u->names, + paths); } int unit_load_dropin(Unit *u); diff --git a/src/core/manager.c b/src/core/manager.c index 9f482bf6e9..0e613d745d 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -46,6 +46,7 @@ #include "fs-util.h" #include "hashmap.h" #include "io-util.h" +#include "install.h" #include "label.h" #include "locale-setup.h" #include "log.h" diff --git a/src/core/transaction.c b/src/core/transaction.c index d1bf2e64c9..a0825c595c 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -6,9 +6,10 @@ #include "alloc-util.h" #include "bus-common-errors.h" #include "bus-error.h" +#include "dbus-unit.h" +#include "strv.h" #include "terminal-util.h" #include "transaction.h" -#include "dbus-unit.h" static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies); diff --git a/src/core/unit.c b/src/core/unit.c index 5d497f12b7..fa89bd4a4d 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -28,6 +28,7 @@ #include "fs-util.h" #include "id128-util.h" #include "io-util.h" +#include "install.h" #include "load-dropin.h" #include "load-fragment.h" #include "log.h" @@ -1123,13 +1124,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { UnitDependency d; Iterator i; const char *prefix2; - char - timestamp0[FORMAT_TIMESTAMP_MAX], - timestamp1[FORMAT_TIMESTAMP_MAX], - timestamp2[FORMAT_TIMESTAMP_MAX], - timestamp3[FORMAT_TIMESTAMP_MAX], - timestamp4[FORMAT_TIMESTAMP_MAX], - timespan[FORMAT_TIMESPAN_MAX]; + char timestamp[5][FORMAT_TIMESTAMP_MAX], timespan[FORMAT_TIMESPAN_MAX]; Unit *following; _cleanup_set_free_ Set *following_set = NULL; const char *n; @@ -1172,11 +1167,11 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { prefix, strna(u->instance), prefix, unit_load_state_to_string(u->load_state), prefix, unit_active_state_to_string(unit_active_state(u)), - prefix, strna(format_timestamp(timestamp0, sizeof(timestamp0), u->state_change_timestamp.realtime)), - prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->inactive_exit_timestamp.realtime)), - prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)), - prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)), - prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->state_change_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[1], sizeof(timestamp[1]), u->inactive_exit_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[2], sizeof(timestamp[2]), u->active_enter_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[3], sizeof(timestamp[3]), u->active_exit_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[4], sizeof(timestamp[4]), u->inactive_enter_timestamp.realtime)), prefix, yes_no(unit_may_gc(u)), prefix, yes_no(unit_need_daemon_reload(u)), prefix, yes_no(u->transient), @@ -1272,14 +1267,14 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { fprintf(f, "%s\tCondition Timestamp: %s\n" "%s\tCondition Result: %s\n", - prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->condition_timestamp.realtime)), prefix, yes_no(u->condition_result)); if (dual_timestamp_is_set(&u->assert_timestamp)) fprintf(f, "%s\tAssert Timestamp: %s\n" "%s\tAssert Result: %s\n", - prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->assert_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp[0], sizeof(timestamp[0]), u->assert_timestamp.realtime)), prefix, yes_no(u->assert_result)); for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { @@ -1797,7 +1792,7 @@ int unit_start(Unit *u) { * condition checks, so that we rather return condition check errors (which are usually not * considered a true failure) than "not supported" errors (which are considered a failure). */ - if (!unit_supported(u)) + if (!unit_type_supported(u->type)) return -EOPNOTSUPP; /* Let's make sure that the deps really are in order before we start this. Normally the job engine @@ -1832,7 +1827,7 @@ bool unit_can_start(Unit *u) { if (u->load_state != UNIT_LOADED) return false; - if (!unit_supported(u)) + if (!unit_type_supported(u->type)) return false; /* Scope units may be started only once */ @@ -1881,7 +1876,7 @@ int unit_stop(Unit *u) { bool unit_can_stop(Unit *u) { assert(u); - if (!unit_supported(u)) + if (!unit_type_supported(u->type)) return false; if (u->perpetual) diff --git a/src/core/unit.h b/src/core/unit.h index 7456f99efe..47ec9877a6 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -8,10 +8,9 @@ #include "bpf-program.h" #include "condition.h" #include "emergency-action.h" -#include "install.h" #include "list.h" #include "set.h" -#include "unit-name.h" +#include "unit-file.h" #include "cgroup.h" typedef struct UnitRef UnitRef; @@ -800,10 +799,6 @@ bool unit_is_unneeded(Unit *u); pid_t unit_control_pid(Unit *u); pid_t unit_main_pid(Unit *u); -static inline bool unit_supported(Unit *u) { - return unit_type_supported(u->type); -} - void unit_warn_if_dir_nonempty(Unit *u, const char* where); int unit_fail_if_noncanonical(Unit *u, const char* where); diff --git a/src/environment-d-generator/environment-d-generator.c b/src/environment-d-generator/environment-d-generator.c index b2558f0c84..d1293eff16 100644 --- a/src/environment-d-generator/environment-d-generator.c +++ b/src/environment-d-generator/environment-d-generator.c @@ -8,6 +8,7 @@ #include "escape.h" #include "log.h" #include "path-lookup.h" +#include "strv.h" static int environment_dirs(char ***ret) { _cleanup_strv_free_ char **dirs = NULL; diff --git a/src/portable/portable.c b/src/portable/portable.c index 4956ae7310..d37880cfd1 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -10,6 +10,7 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "install.h" #include "io-util.h" #include "locale-util.h" #include "loop-util.h" diff --git a/src/shared/dropin.c b/src/shared/dropin.c index 409eef21ff..4a29bd09c5 100644 --- a/src/shared/dropin.c +++ b/src/shared/dropin.c @@ -24,16 +24,15 @@ #include "unit-name.h" int drop_in_file(const char *dir, const char *unit, unsigned level, - const char *name, char **_p, char **_q) { + const char *name, char **ret_p, char **ret_q) { char prefix[DECIMAL_STR_MAX(unsigned)]; - _cleanup_free_ char *b = NULL; - char *p, *q; + _cleanup_free_ char *b = NULL, *p = NULL, *q = NULL; assert(unit); assert(name); - assert(_p); - assert(_q); + assert(ret_p); + assert(ret_q); sprintf(prefix, "%u", level); @@ -45,17 +44,12 @@ int drop_in_file(const char *dir, const char *unit, unsigned level, return -EINVAL; p = strjoin(dir, "/", unit, ".d"); - if (!p) - return -ENOMEM; - q = strjoin(p, "/", prefix, "-", b, ".conf"); - if (!q) { - free(p); + if (!p || !q) return -ENOMEM; - } - *_p = p; - *_q = q; + *ret_p = TAKE_PTR(p); + *ret_q = TAKE_PTR(q); return 0; } @@ -99,7 +93,7 @@ int write_drop_in_format(const char *dir, const char *unit, unsigned level, return write_drop_in(dir, unit, level, name, p); } -static int unit_file_find_dir( +static int unit_file_add_dir( const char *original_root, const char *path, char ***dirs) { @@ -109,6 +103,8 @@ static int unit_file_find_dir( assert(path); + /* This adds [original_root]/path to dirs, if it exists. */ + r = chase_symlinks(path, original_root, 0, &chased); if (r == -ENOENT) /* Ignore -ENOENT, after all most units won't have a drop-in dir. */ return 0; @@ -121,11 +117,9 @@ static int unit_file_find_dir( if (r < 0) return log_warning_errno(r, "Failed to canonicalize path '%s': %m", path); - r = strv_push(dirs, chased); - if (r < 0) + if (strv_consume(dirs, TAKE_PTR(chased)) < 0) return log_oom(); - chased = NULL; return 0; } @@ -151,7 +145,7 @@ static int unit_file_find_dirs( path = strjoina(unit_path, "/", name, suffix); if (!unit_path_cache || set_get(unit_path_cache, path)) { - r = unit_file_find_dir(original_root, path, dirs); + r = unit_file_add_dir(original_root, path, dirs); if (r < 0) return r; } @@ -228,19 +222,19 @@ int unit_file_find_dropin_paths( Set *unit_path_cache, const char *dir_suffix, const char *file_suffix, - Set *names, + const Set *names, char ***ret) { _cleanup_strv_free_ char **dirs = NULL; - char *t, **p; + char *name, **p; Iterator i; int r; assert(ret); - SET_FOREACH(t, names, i) + SET_FOREACH(name, names, i) STRV_FOREACH(p, lookup_path) - (void) unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs); + (void) unit_file_find_dirs(original_root, unit_path_cache, *p, name, dir_suffix, &dirs); if (strv_isempty(dirs)) { *ret = NULL; diff --git a/src/shared/dropin.h b/src/shared/dropin.h index ae7379beee..89a2ab1098 100644 --- a/src/shared/dropin.h +++ b/src/shared/dropin.h @@ -21,19 +21,5 @@ int unit_file_find_dropin_paths( Set *unit_path_cache, const char *dir_suffix, const char *file_suffix, - Set *names, + const Set *names, char ***paths); - -static inline int unit_file_find_dropin_conf_paths( - const char *original_root, - char **lookup_path, - Set *unit_path_cache, - Set *names, - char ***paths) { - - return unit_file_find_dropin_paths(original_root, - lookup_path, - unit_path_cache, - ".d", ".conf", - names, paths); -} diff --git a/src/shared/install.c b/src/shared/install.c index 68ffd12f03..dfb6036191 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -37,7 +37,7 @@ #include "string-table.h" #include "string-util.h" #include "strv.h" -#include "unit-name.h" +#include "unit-file.h" #define UNIT_FILE_FOLLOW_SYMLINK_MAX 64 @@ -98,25 +98,6 @@ static void presets_freep(Presets *p) { p->n_rules = 0; } -bool unit_type_may_alias(UnitType type) { - return IN_SET(type, - UNIT_SERVICE, - UNIT_SOCKET, - UNIT_TARGET, - UNIT_DEVICE, - UNIT_TIMER, - UNIT_PATH); -} - -bool unit_type_may_template(UnitType type) { - return IN_SET(type, - UNIT_SERVICE, - UNIT_SOCKET, - UNIT_TARGET, - UNIT_TIMER, - UNIT_PATH); -} - static const char *const unit_file_type_table[_UNIT_FILE_TYPE_MAX] = { [UNIT_FILE_TYPE_REGULAR] = "regular", [UNIT_FILE_TYPE_SYMLINK] = "symlink", diff --git a/src/shared/install.h b/src/shared/install.h index e452940991..b2ad9c4a71 100644 --- a/src/shared/install.h +++ b/src/shared/install.h @@ -1,8 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once -typedef enum UnitFileScope UnitFileScope; -typedef enum UnitFileState UnitFileState; typedef enum UnitFilePresetMode UnitFilePresetMode; typedef enum UnitFileChangeType UnitFileChangeType; typedef enum UnitFileFlags UnitFileFlags; @@ -19,31 +17,6 @@ typedef struct UnitFileInstallInfo UnitFileInstallInfo; #include "strv.h" #include "unit-name.h" -enum UnitFileScope { - UNIT_FILE_SYSTEM, - UNIT_FILE_GLOBAL, - UNIT_FILE_USER, - _UNIT_FILE_SCOPE_MAX, - _UNIT_FILE_SCOPE_INVALID = -1 -}; - -enum UnitFileState { - UNIT_FILE_ENABLED, - UNIT_FILE_ENABLED_RUNTIME, - UNIT_FILE_LINKED, - UNIT_FILE_LINKED_RUNTIME, - UNIT_FILE_MASKED, - UNIT_FILE_MASKED_RUNTIME, - UNIT_FILE_STATIC, - UNIT_FILE_DISABLED, - UNIT_FILE_INDIRECT, - UNIT_FILE_GENERATED, - UNIT_FILE_TRANSIENT, - UNIT_FILE_BAD, - _UNIT_FILE_STATE_MAX, - _UNIT_FILE_STATE_INVALID = -1 -}; - enum UnitFilePresetMode { UNIT_FILE_PRESET_FULL, UNIT_FILE_PRESET_ENABLE_ONLY, @@ -114,9 +87,6 @@ struct UnitFileInstallInfo { bool auxiliary; }; -bool unit_type_may_alias(UnitType type) _const_; -bool unit_type_may_template(UnitType type) _const_; - int unit_file_enable( UnitFileScope scope, UnitFileFlags flags, diff --git a/src/shared/meson.build b/src/shared/meson.build index bdd823bbd1..ca24d15eab 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -170,6 +170,8 @@ shared_sources = files(''' udev-util.h uid-range.c uid-range.h + unit-file.h + unit-file.c utmp-wtmp.h varlink.c varlink.h diff --git a/src/shared/path-lookup.h b/src/shared/path-lookup.h index cb7d4d537f..7070b94249 100644 --- a/src/shared/path-lookup.h +++ b/src/shared/path-lookup.h @@ -5,7 +5,7 @@ typedef struct LookupPaths LookupPaths; -#include "install.h" +#include "unit-file.h" #include "macro.h" typedef enum LookupPathsFlags { diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c new file mode 100644 index 0000000000..deed7dcf09 --- /dev/null +++ b/src/shared/unit-file.c @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "macro.h" +#include "unit-file.h" + +bool unit_type_may_alias(UnitType type) { + return IN_SET(type, + UNIT_SERVICE, + UNIT_SOCKET, + UNIT_TARGET, + UNIT_DEVICE, + UNIT_TIMER, + UNIT_PATH); +} + +bool unit_type_may_template(UnitType type) { + return IN_SET(type, + UNIT_SERVICE, + UNIT_SOCKET, + UNIT_TARGET, + UNIT_TIMER, + UNIT_PATH); +} diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h new file mode 100644 index 0000000000..2b9df655ee --- /dev/null +++ b/src/shared/unit-file.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include <stdbool.h> + +#include "unit-name.h" + +typedef enum UnitFileState UnitFileState; +typedef enum UnitFileScope UnitFileScope; + +enum UnitFileState { + UNIT_FILE_ENABLED, + UNIT_FILE_ENABLED_RUNTIME, + UNIT_FILE_LINKED, + UNIT_FILE_LINKED_RUNTIME, + UNIT_FILE_MASKED, + UNIT_FILE_MASKED_RUNTIME, + UNIT_FILE_STATIC, + UNIT_FILE_DISABLED, + UNIT_FILE_INDIRECT, + UNIT_FILE_GENERATED, + UNIT_FILE_TRANSIENT, + UNIT_FILE_BAD, + _UNIT_FILE_STATE_MAX, + _UNIT_FILE_STATE_INVALID = -1 +}; + +enum UnitFileScope { + UNIT_FILE_SYSTEM, + UNIT_FILE_GLOBAL, + UNIT_FILE_USER, + _UNIT_FILE_SCOPE_MAX, + _UNIT_FILE_SCOPE_INVALID = -1 +}; + +bool unit_type_may_alias(UnitType type) _const_; +bool unit_type_may_template(UnitType type) _const_; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 3ce3e07bd7..97f3176cc5 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1639,20 +1639,20 @@ static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, cha _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_strv_free_ char **ret = NULL; - _cleanup_free_ char *path = NULL; + _cleanup_free_ char *dbus_path = NULL; int i, r; assert(bus); assert(name); assert(deps); - path = unit_dbus_path_from_name(name); - if (!path) + dbus_path = unit_dbus_path_from_name(name); + if (!dbus_path) return log_oom(); r = bus_map_all_properties(bus, "org.freedesktop.systemd1", - path, + dbus_path, map[arg_dependency], BUS_MAP_STRDUP, &error, @@ -2532,16 +2532,16 @@ static int unit_find_paths( !install_client_side() && !unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *load_state = NULL, *unit = NULL; + _cleanup_free_ char *load_state = NULL, *dbus_path = NULL; - unit = unit_dbus_path_from_name(unit_name); - if (!unit) + dbus_path = unit_dbus_path_from_name(unit_name); + if (!dbus_path) return log_oom(); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", - unit, + dbus_path, "org.freedesktop.systemd1.Unit", "LoadState", &error, @@ -2561,7 +2561,7 @@ static int unit_find_paths( r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", - unit, + dbus_path, "org.freedesktop.systemd1.Unit", "FragmentPath", &error, @@ -2573,7 +2573,7 @@ static int unit_find_paths( r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", - unit, + dbus_path, "org.freedesktop.systemd1.Unit", "DropInPaths", &error, @@ -2616,19 +2616,21 @@ static int unit_find_paths( return log_error_errno(r, "Failed to add unit name: %m"); if (ret_dropin_paths) { - r = unit_file_find_dropin_conf_paths(arg_root, lp->search_path, NULL, names, &dropins); + r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL, + ".d", ".conf", + names, &dropins); if (r < 0) return r; } } + if (isempty(path)) { + *ret_fragment_path = NULL; r = 0; - - if (!isempty(path)) { + } else { *ret_fragment_path = TAKE_PTR(path); r = 1; - } else - *ret_fragment_path = NULL; + } if (ret_dropin_paths) { if (!strv_isempty(dropins)) { @@ -2647,21 +2649,21 @@ static int unit_find_paths( static int get_state_one_unit(sd_bus *bus, const char *name, UnitActiveState *active_state) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *buf = NULL, *path = NULL; + _cleanup_free_ char *buf = NULL, *dbus_path = NULL; UnitActiveState state; int r; assert(name); assert(active_state); - path = unit_dbus_path_from_name(name); - if (!path) + dbus_path = unit_dbus_path_from_name(name); + if (!dbus_path) return log_oom(); r = sd_bus_get_property_string( bus, "org.freedesktop.systemd1", - path, + dbus_path, "org.freedesktop.systemd1.Unit", "ActiveState", &error, @@ -2704,7 +2706,7 @@ static int unit_is_masked(sd_bus *bus, LookupPaths *lp, const char *name) { static int check_triggering_units(sd_bus *bus, const char *name) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_free_ char *n = NULL, *path = NULL, *load_state = NULL; + _cleanup_free_ char *n = NULL, *dbus_path = NULL, *load_state = NULL; _cleanup_strv_free_ char **triggered_by = NULL; bool print_warning_label = true; UnitActiveState active_state; @@ -2722,14 +2724,14 @@ static int check_triggering_units(sd_bus *bus, const char *name) { if (streq(load_state, "masked")) return 0; - path = unit_dbus_path_from_name(n); - if (!path) + dbus_path = unit_dbus_path_from_name(n); + if (!dbus_path) return log_oom(); r = sd_bus_get_property_strv( bus, "org.freedesktop.systemd1", - path, + dbus_path, "org.freedesktop.systemd1.Unit", "TriggeredBy", &error, diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index f9cb338d8a..d4d3f3b4a5 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1358,8 +1358,6 @@ static bool item_equal(Item *a, Item *b) { return true; } -DEFINE_PRIVATE_HASH_OPS_FULL(members_hash_ops, char, string_hash_func, string_compare_func, free, char*, strv_free); - static int parse_line(const char *fname, unsigned line, const char *buffer) { static const Specifier specifier_table[] = { @@ -1511,8 +1509,6 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { return 0; case ADD_MEMBER: { - char **l; - /* Try to extend an existing member or group item */ if (!name) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -1535,38 +1531,9 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { fname, line, action[0], description ? "GECOS" : home ? "home directory" : "login shell"); - r = ordered_hashmap_ensure_allocated(&members, &members_hash_ops); + r = string_strv_ordered_hashmap_put(&members, resolved_id, resolved_name); if (r < 0) - return log_oom(); - - l = ordered_hashmap_get(members, resolved_id); - if (l) { - /* A list for this group name already exists, let's append to it */ - r = strv_push(&l, resolved_name); - if (r < 0) - return log_oom(); - - resolved_name = NULL; - - assert_se(ordered_hashmap_update(members, resolved_id, l) >= 0); - } else { - /* No list for this group name exists yet, create one */ - - l = new0(char *, 2); - if (!l) - return -ENOMEM; - - l[0] = resolved_name; - l[1] = NULL; - - r = ordered_hashmap_put(members, resolved_id, l); - if (r < 0) { - free(l); - return log_oom(); - } - - resolved_id = resolved_name = NULL; - } + return log_error_errno(r, "Failed to store mapping for %s: %m", resolved_id); return 0; } diff --git a/src/test/meson.build b/src/test/meson.build index 34dd5cbc45..ddc04dda65 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -148,7 +148,7 @@ tests += [ libmount, libblkid]], - [['src/test/test-unit-file.c', + [['src/test/test-load-fragment.c', 'src/test/test-helper.c'], [libcore, libshared], @@ -607,6 +607,10 @@ tests += [ [], []], + [['src/test/test-env-file.c'], + [], + []], + [['src/test/test-env-util.c'], [], []], diff --git a/src/test/test-engine.c b/src/test/test-engine.c index 9809d408f6..633cc42534 100644 --- a/src/test/test-engine.c +++ b/src/test/test-engine.c @@ -7,6 +7,7 @@ #include "bus-util.h" #include "manager.h" #include "rm-rf.h" +#include "strv.h" #include "test-helper.h" #include "tests.h" #include "service.h" diff --git a/src/test/test-env-file.c b/src/test/test-env-file.c new file mode 100644 index 0000000000..47f86a5676 --- /dev/null +++ b/src/test/test-env-file.c @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include "env-file.h" +#include "fd-util.h" +#include "fs-util.h" +#include "macro.h" +#include "strv.h" +#include "tests.h" +#include "tmpfile-util.h" + +#define env_file_1 \ + "a=a\n" \ + "b=b\\\n" \ + "c\n" \ + "d=d\\\n" \ + "e\\\n" \ + "f\n" \ + "g=g\\ \n" \ + "h=h\n" \ + "i=i\\" + +#define env_file_2 \ + "a=a\\\n" + +#define env_file_3 \ + "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \ + "#--nouser-config \\\n" \ + "normal=line" + +#define env_file_4 \ + "# Generated\n" \ + "\n" \ + "HWMON_MODULES=\"coretemp f71882fg\"\n" \ + "\n" \ + "# For compatibility reasons\n" \ + "\n" \ + "MODULE_0=coretemp\n" \ + "MODULE_1=f71882fg" + +#define env_file_5 \ + "a=\n" \ + "b=" + +static void test_load_env_file_1(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "a=a")); + assert_se(streq(data[1], "b=bc")); + assert_se(streq(data[2], "d=def")); + assert_se(streq(data[3], "g=g ")); + assert_se(streq(data[4], "h=h")); + assert_se(streq(data[5], "i=i")); + assert_se(data[6] == NULL); +} + +static void test_load_env_file_2(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "a=a")); + assert_se(data[1] == NULL); +} + +static void test_load_env_file_3(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(data == NULL); +} + +static void test_load_env_file_4(void) { + _cleanup_strv_free_ char **data = NULL; + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + int r; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg")); + assert_se(streq(data[1], "MODULE_0=coretemp")); + assert_se(streq(data[2], "MODULE_1=f71882fg")); + assert_se(data[3] == NULL); +} + +static void test_load_env_file_5(void) { + _cleanup_strv_free_ char **data = NULL; + int r; + + _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; + _cleanup_close_ int fd; + + fd = mkostemp_safe(name); + assert_se(fd >= 0); + assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5)); + + r = load_env_file(NULL, name, &data); + assert_se(r == 0); + assert_se(streq(data[0], "a=")); + assert_se(streq(data[1], "b=")); + assert_se(data[2] == NULL); +} + +int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + + test_load_env_file_1(); + test_load_env_file_2(); + test_load_env_file_3(); + test_load_env_file_4(); + test_load_env_file_5(); +} diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index 85d679826f..7cf4f4976b 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -795,11 +795,11 @@ int main(int argc, char *argv[]) { arg_test_dir = argv[1]; + test_chase_symlinks(); test_unlink_noerrno(); - test_get_files_in_directory(); test_readlink_and_make_absolute(); + test_get_files_in_directory(); test_var_tmp(); - test_chase_symlinks(); test_dot_or_dot_dot(); test_access_fd(); test_touch_file(); diff --git a/src/test/test-hashmap-plain.c b/src/test/test-hashmap-plain.c index fdb0c7e87f..57cf89ff53 100644 --- a/src/test/test-hashmap-plain.c +++ b/src/test/test-hashmap-plain.c @@ -831,6 +831,31 @@ static void test_hashmap_free(void) { } } +typedef struct Item { + int seen; +} Item; +static void item_seen(Item *item) { + item->seen++; +} + +static void test_hashmap_free_with_destructor(void) { + Hashmap *m; + struct Item items[4] = {}; + unsigned i; + + log_info("/* %s */", __func__); + + assert_se(m = hashmap_new(NULL)); + for (i = 0; i < ELEMENTSOF(items) - 1; i++) + assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1); + + m = hashmap_free_with_destructor(m, item_seen); + assert_se(items[0].seen == 1); + assert_se(items[1].seen == 1); + assert_se(items[2].seen == 1); + assert_se(items[3].seen == 0); +} + static void test_hashmap_first(void) { _cleanup_hashmap_free_ Hashmap *m = NULL; @@ -978,9 +1003,65 @@ static void test_hashmap_reserve(void) { assert_se(hashmap_reserve(m, UINT_MAX - 1) == -ENOMEM); } +static void test_path_hashmap(void) { + _cleanup_hashmap_free_ Hashmap *h = NULL; + + log_info("/* %s */", __func__); + + assert_se(h = hashmap_new(&path_hash_ops)); + + assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0); + assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0); + assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST); + assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0); + assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST); + assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0); + assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST); + + assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1)); + assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1)); + assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1)); + assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2)); + assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2)); + assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2)); + assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4)); + assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4)); + assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4)); + assert_se(!hashmap_get(h, "foox")); + assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6)); + assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6)); + assert_se(!hashmap_get(h, "/foo////bar////quux/////")); +} + +static void test_string_strv_hashmap(void) { + _cleanup_hashmap_free_ Hashmap *m = NULL; + char **s; + + log_info("/* %s */", __func__); + + assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 1); + assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0); + assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 1); + assert_se(string_strv_hashmap_put(&m, "foo", "BAR") == 0); + assert_se(string_strv_hashmap_put(&m, "foo", "bar") == 0); + assert_se(hashmap_contains(m, "foo")); + + s = hashmap_get(m, "foo"); + assert_se(strv_equal(s, STRV_MAKE("bar", "BAR"))); + + assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 1); + assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0); + assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 1); + assert_se(string_strv_hashmap_put(&m, "xxx", "BAR") == 0); + assert_se(string_strv_hashmap_put(&m, "xxx", "bar") == 0); + assert_se(hashmap_contains(m, "xxx")); + + s = hashmap_get(m, "xxx"); + assert_se(strv_equal(s, STRV_MAKE("bar", "BAR"))); +} + void test_hashmap_funcs(void) { - log_parse_environment(); - log_open(); + log_info("/************ %s ************/", __func__); test_hashmap_copy(); test_hashmap_get_strv(); @@ -1005,6 +1086,7 @@ void test_hashmap_funcs(void) { test_hashmap_size(); test_hashmap_many(); test_hashmap_free(); + test_hashmap_free_with_destructor(); test_hashmap_first(); test_hashmap_first_key(); test_hashmap_steal_first_key(); @@ -1012,4 +1094,6 @@ void test_hashmap_funcs(void) { test_hashmap_clear_free_free(); test_hashmap_clear_free_with_destructor(); test_hashmap_reserve(); + test_path_hashmap(); + test_string_strv_hashmap(); } diff --git a/src/test/test-hashmap.c b/src/test/test-hashmap.c index ee4c0e66db..1a6e8ffa58 100644 --- a/src/test/test-hashmap.c +++ b/src/test/test-hashmap.c @@ -31,31 +31,6 @@ static void test_ordered_hashmap_next(void) { assert_se(!ordered_hashmap_next(m, INT_TO_PTR(3))); } -typedef struct Item { - int seen; -} Item; -static void item_seen(Item *item) { - item->seen++; -} - -static void test_hashmap_free_with_destructor(void) { - Hashmap *m; - struct Item items[4] = {}; - unsigned i; - - log_info("/* %s */", __func__); - - assert_se(m = hashmap_new(NULL)); - for (i = 0; i < ELEMENTSOF(items) - 1; i++) - assert_se(hashmap_put(m, INT_TO_PTR(i), items + i) == 1); - - m = hashmap_free_with_destructor(m, item_seen); - assert_se(items[0].seen == 1); - assert_se(items[1].seen == 1); - assert_se(items[2].seen == 1); - assert_se(items[3].seen == 0); -} - static void test_uint64_compare_func(void) { const uint64_t a = 0x100, b = 0x101; @@ -134,47 +109,24 @@ static void test_iterated_cache(void) { assert_se(iterated_cache_free(c) == NULL); } -static void test_path_hashmap(void) { - _cleanup_hashmap_free_ Hashmap *h = NULL; +int main(int argc, const char *argv[]) { + /* This file tests in test-hashmap-plain.c, and tests in test-hashmap-ordered.c, which is generated + * from test-hashmap-plain.c. Hashmap tests should be added to test-hashmap-plain.c, and here only if + * they don't apply to ordered hashmaps. */ - log_info("/* %s */", __func__); + log_parse_environment(); + log_open(); - assert_se(h = hashmap_new(&path_hash_ops)); - - assert_se(hashmap_put(h, "foo", INT_TO_PTR(1)) >= 0); - assert_se(hashmap_put(h, "/foo", INT_TO_PTR(2)) >= 0); - assert_se(hashmap_put(h, "//foo", INT_TO_PTR(3)) == -EEXIST); - assert_se(hashmap_put(h, "//foox/", INT_TO_PTR(4)) >= 0); - assert_se(hashmap_put(h, "/foox////", INT_TO_PTR(5)) == -EEXIST); - assert_se(hashmap_put(h, "foo//////bar/quux//", INT_TO_PTR(6)) >= 0); - assert_se(hashmap_put(h, "foo/bar//quux/", INT_TO_PTR(8)) == -EEXIST); - - assert_se(hashmap_get(h, "foo") == INT_TO_PTR(1)); - assert_se(hashmap_get(h, "foo/") == INT_TO_PTR(1)); - assert_se(hashmap_get(h, "foo////") == INT_TO_PTR(1)); - assert_se(hashmap_get(h, "/foo") == INT_TO_PTR(2)); - assert_se(hashmap_get(h, "//foo") == INT_TO_PTR(2)); - assert_se(hashmap_get(h, "/////foo////") == INT_TO_PTR(2)); - assert_se(hashmap_get(h, "/////foox////") == INT_TO_PTR(4)); - assert_se(hashmap_get(h, "/foox/") == INT_TO_PTR(4)); - assert_se(hashmap_get(h, "/foox") == INT_TO_PTR(4)); - assert_se(!hashmap_get(h, "foox")); - assert_se(hashmap_get(h, "foo/bar/quux") == INT_TO_PTR(6)); - assert_se(hashmap_get(h, "foo////bar////quux/////") == INT_TO_PTR(6)); - assert_se(!hashmap_get(h, "/foo////bar////quux/////")); -} - -int main(int argc, const char *argv[]) { test_hashmap_funcs(); test_ordered_hashmap_funcs(); + log_info("/************ non-shared tests ************/"); + test_ordered_hashmap_next(); - test_hashmap_free_with_destructor(); test_uint64_compare_func(); test_trivial_compare_func(); test_string_compare_func(); test_iterated_cache(); - test_path_hashmap(); return 0; } diff --git a/src/test/test-unit-file.c b/src/test/test-load-fragment.c index 8a0251e13a..8deaf4eb0f 100644 --- a/src/test/test-unit-file.c +++ b/src/test/test-load-fragment.c @@ -11,7 +11,6 @@ #include "alloc-util.h" #include "capability-util.h" #include "conf-parser.h" -#include "env-file.h" #include "fd-util.h" #include "format-util.h" #include "fs-util.h" @@ -489,130 +488,6 @@ static void test_config_parse_log_extra_fields(void) { log_info("/* %s – bye */", __func__); } -#define env_file_1 \ - "a=a\n" \ - "b=b\\\n" \ - "c\n" \ - "d=d\\\n" \ - "e\\\n" \ - "f\n" \ - "g=g\\ \n" \ - "h=h\n" \ - "i=i\\" - -#define env_file_2 \ - "a=a\\\n" - -#define env_file_3 \ - "#SPAMD_ARGS=\"-d --socketpath=/var/lib/bulwark/spamd \\\n" \ - "#--nouser-config \\\n" \ - "normal=line" - -#define env_file_4 \ - "# Generated\n" \ - "\n" \ - "HWMON_MODULES=\"coretemp f71882fg\"\n" \ - "\n" \ - "# For compatibility reasons\n" \ - "\n" \ - "MODULE_0=coretemp\n" \ - "MODULE_1=f71882fg" - -#define env_file_5 \ - "a=\n" \ - "b=" - -static void test_load_env_file_1(void) { - _cleanup_strv_free_ char **data = NULL; - int r; - - _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; - _cleanup_close_ int fd; - - fd = mkostemp_safe(name); - assert_se(fd >= 0); - assert_se(write(fd, env_file_1, strlen(env_file_1)) == strlen(env_file_1)); - - r = load_env_file(NULL, name, &data); - assert_se(r == 0); - assert_se(streq(data[0], "a=a")); - assert_se(streq(data[1], "b=bc")); - assert_se(streq(data[2], "d=def")); - assert_se(streq(data[3], "g=g ")); - assert_se(streq(data[4], "h=h")); - assert_se(streq(data[5], "i=i")); - assert_se(data[6] == NULL); -} - -static void test_load_env_file_2(void) { - _cleanup_strv_free_ char **data = NULL; - int r; - - _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; - _cleanup_close_ int fd; - - fd = mkostemp_safe(name); - assert_se(fd >= 0); - assert_se(write(fd, env_file_2, strlen(env_file_2)) == strlen(env_file_2)); - - r = load_env_file(NULL, name, &data); - assert_se(r == 0); - assert_se(streq(data[0], "a=a")); - assert_se(data[1] == NULL); -} - -static void test_load_env_file_3(void) { - _cleanup_strv_free_ char **data = NULL; - int r; - - _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; - _cleanup_close_ int fd; - - fd = mkostemp_safe(name); - assert_se(fd >= 0); - assert_se(write(fd, env_file_3, strlen(env_file_3)) == strlen(env_file_3)); - - r = load_env_file(NULL, name, &data); - assert_se(r == 0); - assert_se(data == NULL); -} - -static void test_load_env_file_4(void) { - _cleanup_strv_free_ char **data = NULL; - _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; - _cleanup_close_ int fd; - int r; - - fd = mkostemp_safe(name); - assert_se(fd >= 0); - assert_se(write(fd, env_file_4, strlen(env_file_4)) == strlen(env_file_4)); - - r = load_env_file(NULL, name, &data); - assert_se(r == 0); - assert_se(streq(data[0], "HWMON_MODULES=coretemp f71882fg")); - assert_se(streq(data[1], "MODULE_0=coretemp")); - assert_se(streq(data[2], "MODULE_1=f71882fg")); - assert_se(data[3] == NULL); -} - -static void test_load_env_file_5(void) { - _cleanup_strv_free_ char **data = NULL; - int r; - - _cleanup_(unlink_tempfilep) char name[] = "/tmp/test-load-env-file.XXXXXX"; - _cleanup_close_ int fd; - - fd = mkostemp_safe(name); - assert_se(fd >= 0); - assert_se(write(fd, env_file_5, strlen(env_file_5)) == strlen(env_file_5)); - - r = load_env_file(NULL, name, &data); - assert_se(r == 0); - assert_se(streq(data[0], "a=")); - assert_se(streq(data[1], "b=")); - assert_se(data[2] == NULL); -} - static void test_install_printf(void) { char name[] = "name.service", path[] = "/run/systemd/system/name.service"; @@ -919,11 +794,6 @@ int main(int argc, char *argv[]) { test_config_parse_capability_set(); test_config_parse_rlimit(); test_config_parse_pass_environ(); - test_load_env_file_1(); - test_load_env_file_2(); - test_load_env_file_3(); - test_load_env_file_4(); - test_load_env_file_5(); TEST_REQ_RUNNING_SYSTEMD(test_install_printf()); test_unit_dump_config_items(); diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c index 413816ceb8..ece3eb427c 100644 --- a/src/test/test-path-util.c +++ b/src/test/test-path-util.c @@ -25,6 +25,8 @@ static void test_path_simplify(const char *in, const char *out, const char *out_dot) { char *p; + log_info("/* %s */", __func__); + p = strdupa(in); assert_se(streq(path_simplify(p, false), out)); @@ -35,6 +37,8 @@ static void test_path_simplify(const char *in, const char *out, const char *out_ static void test_path(void) { _cleanup_close_ int fd = -1; + log_info("/* %s */", __func__); + test_path_compare("/goo", "/goo", 0); test_path_compare("/goo", "/goo", 0); test_path_compare("//goo", "/goo", 0); @@ -114,6 +118,8 @@ static void test_path(void) { static void test_path_equal_root(void) { /* Nail down the details of how path_equal("/", ...) works. */ + log_info("/* %s */", __func__); + assert_se(path_equal("/", "/")); assert_se(path_equal("/", "//")); @@ -156,6 +162,8 @@ static void test_path_equal_root(void) { static void test_find_binary(const char *self) { char *p; + log_info("/* %s */", __func__); + assert_se(find_binary("/bin/sh", &p) == 0); puts(p); assert_se(path_equal(p, "/bin/sh")); @@ -191,6 +199,8 @@ static void test_prefixes(void) { char s[PATH_MAX]; bool b; + log_info("/* %s */", __func__); + i = 0; PATH_FOREACH_PREFIX_MORE(s, "/a/b/c/d") { log_error("---%s---", s); @@ -238,6 +248,7 @@ static void test_prefixes(void) { } static void test_path_join(void) { + log_info("/* %s */", __func__); #define test_join(expected, ...) { \ _cleanup_free_ char *z = NULL; \ @@ -283,6 +294,8 @@ static void test_path_join(void) { } static void test_fsck_exists(void) { + log_info("/* %s */", __func__); + /* Ensure we use a sane default for PATH. */ unsetenv("PATH"); @@ -296,6 +309,8 @@ static void test_fsck_exists(void) { static void test_make_relative(void) { char *result; + log_info("/* %s */", __func__); + assert_se(path_make_relative("some/relative/path", "/some/path", &result) < 0); assert_se(path_make_relative("/some/path", "some/relative/path", &result) < 0); assert_se(path_make_relative("/some/dotdot/../path", "/some/path", &result) < 0); @@ -347,6 +362,8 @@ static void test_strv_resolve(void) { static void test_path_startswith(void) { const char *p; + log_info("/* %s */", __func__); + p = path_startswith("/foo/bar/barfoo/", "/foo"); assert_se(streq_ptr(p, "bar/barfoo/")); @@ -397,6 +414,8 @@ static void test_prefix_root_one(const char *r, const char *p, const char *expec } static void test_prefix_root(void) { + log_info("/* %s */", __func__); + test_prefix_root_one("/", "/foo", "/foo"); test_prefix_root_one(NULL, "/foo", "/foo"); test_prefix_root_one("", "/foo", "/foo"); @@ -418,6 +437,8 @@ static void test_prefix_root(void) { static void test_file_in_same_dir(void) { char *t; + log_info("/* %s */", __func__); + t = file_in_same_dir("/", "a"); assert_se(streq(t, "/a")); free(t); @@ -470,6 +491,8 @@ static void test_path_extract_filename_one(const char *input, const char *output } static void test_path_extract_filename(void) { + log_info("/* %s */", __func__); + test_path_extract_filename_one(NULL, NULL, -EINVAL); test_path_extract_filename_one("a/b/c", "c", 0); test_path_extract_filename_one("a/b/c/", "c", 0); @@ -502,6 +525,8 @@ static void test_filename_is_valid(void) { char foo[FILENAME_MAX+2]; int i; + log_info("/* %s */", __func__); + assert_se(!filename_is_valid("")); assert_se(!filename_is_valid("/bar/foo")); assert_se(!filename_is_valid("/")); @@ -519,6 +544,8 @@ static void test_filename_is_valid(void) { } static void test_hidden_or_backup_file(void) { + log_info("/* %s */", __func__); + assert_se(hidden_or_backup_file(".hidden")); assert_se(hidden_or_backup_file("..hidden")); assert_se(!hidden_or_backup_file("hidden.")); @@ -544,6 +571,8 @@ static void test_systemd_installation_has_version(const char *path) { const unsigned versions[] = {0, 231, PROJECT_VERSION, 999}; unsigned i; + log_info("/* %s */", __func__); + for (i = 0; i < ELEMENTSOF(versions); i++) { r = systemd_installation_has_version(path, versions[i]); assert_se(r >= 0); @@ -553,6 +582,7 @@ static void test_systemd_installation_has_version(const char *path) { } static void test_skip_dev_prefix(void) { + log_info("/* %s */", __func__); assert_se(streq(skip_dev_prefix("/"), "/")); assert_se(streq(skip_dev_prefix("/dev"), "")); @@ -568,6 +598,8 @@ static void test_skip_dev_prefix(void) { } static void test_empty_or_root(void) { + log_info("/* %s */", __func__); + assert_se(empty_or_root(NULL)); assert_se(empty_or_root("")); assert_se(empty_or_root("/")); @@ -581,6 +613,7 @@ static void test_empty_or_root(void) { } static void test_path_startswith_set(void) { + log_info("/* %s */", __func__); assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/bar", "/zzz"), "")); assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo/bar", "/foo/quux", "/foo/", "/zzz"), "bar")); @@ -601,6 +634,28 @@ static void test_path_startswith_set(void) { assert_se(streq_ptr(PATH_STARTSWITH_SET("/foo2/bar", "/foo/quux", "", "/zzz"), NULL)); } +static void test_path_startswith_strv(void) { + log_info("/* %s */", __func__); + + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), "")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL)); + + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), "bar2")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/foo", "/zzz")), "bar2")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo/bar2")); + assert_se(streq_ptr(path_startswith_strv("/foo/bar2", STRV_MAKE("/foo/quux", "", "/zzz")), NULL)); + + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/bar", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo/", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/foo", "/zzz")), NULL)); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "/", "/zzz")), "foo2/bar")); + assert_se(streq_ptr(path_startswith_strv("/foo2/bar", STRV_MAKE("/foo/quux", "", "/zzz")), NULL)); +} + int main(int argc, char **argv) { test_setup_logging(LOG_DEBUG); @@ -622,6 +677,7 @@ int main(int argc, char **argv) { test_skip_dev_prefix(); test_empty_or_root(); test_path_startswith_set(); + test_path_startswith_strv(); test_systemd_installation_has_version(argv[1]); /* NULL is OK */ diff --git a/src/test/test-strv.c b/src/test/test-strv.c index 903de18083..5e96f3a8a7 100644 --- a/src/test/test-strv.c +++ b/src/test/test-strv.c @@ -23,6 +23,8 @@ static void test_specifier_printf(void) { _cleanup_free_ char *w = NULL; int r; + log_info("/* %s */", __func__); + r = specifier_printf("xxx a=%a b=%b yyy", table, NULL, &w); assert_se(r >= 0); assert_se(w); @@ -38,6 +40,8 @@ static void test_specifier_printf(void) { } static void test_str_in_set(void) { + log_info("/* %s */", __func__); + assert_se(STR_IN_SET("x", "x", "y", "z")); assert_se(!STR_IN_SET("X", "x", "y", "z")); assert_se(!STR_IN_SET("", "x", "y", "z")); @@ -45,6 +49,8 @@ static void test_str_in_set(void) { } static void test_strptr_in_set(void) { + log_info("/* %s */", __func__); + assert_se(STRPTR_IN_SET("x", "x", "y", "z")); assert_se(!STRPTR_IN_SET("X", "x", "y", "z")); assert_se(!STRPTR_IN_SET("", "x", "y", "z")); @@ -57,6 +63,8 @@ static void test_strptr_in_set(void) { } static void test_startswith_set(void) { + log_info("/* %s */", __func__); + assert_se(!STARTSWITH_SET("foo", "bar", "baz", "waldo")); assert_se(!STARTSWITH_SET("foo", "bar")); @@ -105,11 +113,15 @@ static const char* const input_table_one_empty[] = { }; static void test_strv_find(void) { + log_info("/* %s */", __func__); + assert_se(strv_find((char **)input_table_multiple, "three")); assert_se(!strv_find((char **)input_table_multiple, "four")); } static void test_strv_find_prefix(void) { + log_info("/* %s */", __func__); + assert_se(strv_find_prefix((char **)input_table_multiple, "o")); assert_se(strv_find_prefix((char **)input_table_multiple, "one")); assert_se(strv_find_prefix((char **)input_table_multiple, "")); @@ -120,6 +132,8 @@ static void test_strv_find_prefix(void) { static void test_strv_find_startswith(void) { char *r; + log_info("/* %s */", __func__); + r = strv_find_startswith((char **)input_table_multiple, "o"); assert_se(r && streq(r, "ne")); @@ -136,6 +150,8 @@ static void test_strv_find_startswith(void) { static void test_strv_join(void) { _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; + log_info("/* %s */", __func__); + p = strv_join((char **)input_table_multiple, ", "); assert_se(p); assert_se(streq(p, "one, two, three")); @@ -168,6 +184,8 @@ static void test_strv_join(void) { static void test_strv_join_prefix(void) { _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; + log_info("/* %s */", __func__); + p = strv_join_prefix((char **)input_table_multiple, ", ", "foo"); assert_se(p); assert_se(streq(p, "fooone, footwo, foothree")); @@ -204,6 +222,8 @@ static void test_strv_unquote(const char *quoted, char **list) { char **t; int r; + log_info("/* %s */", __func__); + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); assert_se(r == (int) strv_length(list)); assert_se(s); @@ -221,6 +241,8 @@ static void test_invalid_unquote(const char *quoted) { char **s = NULL; int r; + log_info("/* %s */", __func__); + r = strv_split_extract(&s, quoted, WHITESPACE, EXTRACT_UNQUOTE); assert_se(s == NULL); assert_se(r == -EINVAL); @@ -230,6 +252,8 @@ static void test_strv_split(void) { _cleanup_(strv_free_erasep) char **l = NULL; const char str[] = "one,two,three"; + log_info("/* %s */", __func__); + l = strv_split(str, ","); assert_se(l); assert_se(strv_equal(l, (char**) input_table_multiple)); @@ -290,6 +314,8 @@ static void test_strv_split(void) { static void test_strv_split_empty(void) { _cleanup_strv_free_ char **l = NULL; + log_info("/* %s */", __func__); + l = strv_split("", WHITESPACE); assert_se(l); assert_se(strv_isempty(l)); @@ -355,6 +381,8 @@ static void test_strv_split_extract(void) { const char *str = ":foo\\:bar::waldo:"; int r; + log_info("/* %s */", __func__); + r = strv_split_extract(&l, str, ":", EXTRACT_DONT_COALESCE_SEPARATORS); assert_se(r == (int) strv_length(l)); assert_se(streq_ptr(l[0], "")); @@ -371,8 +399,9 @@ static void test_strv_split_newlines(void) { _cleanup_strv_free_ char **l = NULL; const char str[] = "one\ntwo\nthree"; - l = strv_split_newlines(str); + log_info("/* %s */", __func__); + l = strv_split_newlines(str); assert_se(l); STRV_FOREACH(s, l) { @@ -384,6 +413,8 @@ static void test_strv_split_nulstr(void) { _cleanup_strv_free_ char **l = NULL; const char nulstr[] = "str0\0str1\0str2\0str3\0"; + log_info("/* %s */", __func__); + l = strv_split_nulstr (nulstr); assert_se(l); @@ -397,6 +428,8 @@ static void test_strv_parse_nulstr(void) { _cleanup_strv_free_ char **l = NULL; const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx"; + log_info("/* %s */", __func__); + l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1); assert_se(l); puts("Parse nulstr:"); @@ -429,6 +462,8 @@ static void test_strv_overlap(void) { NULL }; + log_info("/* %s */", __func__); + assert_se(strv_overlap((char **)input_table, (char**)input_table_overlap)); assert_se(!strv_overlap((char **)input_table, (char**)input_table_unique)); } @@ -443,6 +478,8 @@ static void test_strv_sort(void) { NULL }; + log_info("/* %s */", __func__); + strv_sort((char **)input_table); assert_se(streq(input_table[0], "CAPITAL LETTERS FIRST")); @@ -455,6 +492,8 @@ static void test_strv_sort(void) { static void test_strv_extend_strv_concat(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; + log_info("/* %s */", __func__); + a = strv_new("without", "suffix"); b = strv_new("with", "suffix"); assert_se(a); @@ -471,6 +510,8 @@ static void test_strv_extend_strv_concat(void) { static void test_strv_extend_strv(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **n = NULL; + log_info("/* %s */", __func__); + a = strv_new("abc", "def", "ghi"); b = strv_new("jkl", "mno", "abc", "pqr"); assert_se(a); @@ -497,6 +538,8 @@ static void test_strv_extend_strv(void) { static void test_strv_extend(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; + log_info("/* %s */", __func__); + a = strv_new("test", "test1"); assert_se(a); assert_se(strv_extend(&a, "test2") >= 0); @@ -511,6 +554,8 @@ static void test_strv_extend(void) { static void test_strv_extendf(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL; + log_info("/* %s */", __func__); + a = strv_new("test", "test1"); assert_se(a); assert_se(strv_extendf(&a, "test2 %s %d %s", "foo", 128, "bar") >= 0); @@ -527,13 +572,13 @@ static void test_strv_foreach(void) { unsigned i = 0; char **check; - a = strv_new("one", "two", "three"); + log_info("/* %s */", __func__); + a = strv_new("one", "two", "three"); assert_se(a); - STRV_FOREACH(check, a) { + STRV_FOREACH(check, a) assert_se(streq(*check, input_table_multiple[i++])); - } } static void test_strv_foreach_backwards(void) { @@ -541,6 +586,8 @@ static void test_strv_foreach_backwards(void) { unsigned i = 2; char **check; + log_info("/* %s */", __func__); + a = strv_new("one", "two", "three"); assert_se(a); @@ -559,19 +606,21 @@ static void test_strv_foreach_pair(void) { _cleanup_strv_free_ char **a = NULL; char **x, **y; + log_info("/* %s */", __func__); + a = strv_new("pair_one", "pair_one", "pair_two", "pair_two", "pair_three", "pair_three"); - - STRV_FOREACH_PAIR(x, y, a) { + STRV_FOREACH_PAIR(x, y, a) assert_se(streq(*x, *y)); - } } static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) { char **j; unsigned i; + log_info("/* %s */", __func__); + j = strv_from_stdarg_alloca(first); for (i = 0;; i++) { @@ -583,6 +632,8 @@ static void test_strv_from_stdarg_alloca_one(char **l, const char *first, ...) { } static void test_strv_from_stdarg_alloca(void) { + log_info("/* %s */", __func__); + test_strv_from_stdarg_alloca_one(STRV_MAKE("foo", "bar"), "foo", "bar", NULL); test_strv_from_stdarg_alloca_one(STRV_MAKE("foo"), "foo", NULL); test_strv_from_stdarg_alloca_one(STRV_MAKE_EMPTY, NULL); @@ -591,6 +642,8 @@ static void test_strv_from_stdarg_alloca(void) { static void test_strv_insert(void) { _cleanup_strv_free_ char **a = NULL; + log_info("/* %s */", __func__); + assert_se(strv_insert(&a, 0, strdup("first")) == 0); assert_se(streq(a[0], "first")); assert_se(!a[1]); @@ -621,6 +674,8 @@ static void test_strv_insert(void) { static void test_strv_push_prepend(void) { _cleanup_strv_free_ char **a = NULL; + log_info("/* %s */", __func__); + a = strv_new("foo", "bar", "three"); assert_se(strv_push_prepend(&a, strdup("first")) >= 0); @@ -643,6 +698,8 @@ static void test_strv_push(void) { _cleanup_strv_free_ char **a = NULL; char *i, *j; + log_info("/* %s */", __func__); + assert_se(i = strdup("foo")); assert_se(strv_push(&a, i) >= 0); @@ -661,6 +718,8 @@ static void test_strv_equal(void) { _cleanup_strv_free_ char **b = NULL; _cleanup_strv_free_ char **c = NULL; + log_info("/* %s */", __func__); + a = strv_new("one", "two", "three"); assert_se(a); b = strv_new("one", "two", "three"); @@ -680,6 +739,8 @@ static void test_strv_equal(void) { static void test_strv_is_uniq(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; + log_info("/* %s */", __func__); + a = strv_new(NULL); assert_se(a); assert_se(strv_is_uniq(a)); @@ -700,6 +761,8 @@ static void test_strv_is_uniq(void) { static void test_strv_reverse(void) { _cleanup_strv_free_ char **a = NULL, **b = NULL, **c = NULL, **d = NULL; + log_info("/* %s */", __func__); + a = strv_new(NULL); assert_se(a); @@ -731,6 +794,8 @@ static void test_strv_reverse(void) { static void test_strv_shell_escape(void) { _cleanup_strv_free_ char **v = NULL; + log_info("/* %s */", __func__); + v = strv_new("foo:bar", "bar,baz", "wal\\do"); assert_se(v); assert_se(strv_shell_escape(v, ",:")); @@ -746,6 +811,8 @@ static void test_strv_skip_one(char **a, size_t n, char **b) { } static void test_strv_skip(void) { + log_info("/* %s */", __func__); + test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 0, STRV_MAKE("foo", "bar", "baz")); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 1, STRV_MAKE("bar", "baz")); test_strv_skip_one(STRV_MAKE("foo", "bar", "baz"), 2, STRV_MAKE("baz")); @@ -765,6 +832,8 @@ static void test_strv_skip(void) { static void test_strv_extend_n(void) { _cleanup_strv_free_ char **v = NULL; + log_info("/* %s */", __func__); + v = strv_new("foo", "bar"); assert_se(v); @@ -796,6 +865,8 @@ static void test_strv_make_nulstr_one(char **l) { size_t n, m; unsigned i = 0; + log_info("/* %s */", __func__); + assert_se(strv_make_nulstr(l, &b, &n) >= 0); assert_se(q = strv_parse_nulstr(b, n)); assert_se(strv_equal(l, q)); @@ -810,6 +881,8 @@ static void test_strv_make_nulstr_one(char **l) { } static void test_strv_make_nulstr(void) { + log_info("/* %s */", __func__); + test_strv_make_nulstr_one(NULL); test_strv_make_nulstr_one(STRV_MAKE(NULL)); test_strv_make_nulstr_one(STRV_MAKE("foo")); @@ -820,6 +893,8 @@ static void test_strv_make_nulstr(void) { static void test_strv_free_free(void) { char ***t; + log_info("/* %s */", __func__); + assert_se(t = new(char**, 3)); assert_se(t[0] = strv_new("a", "b")); assert_se(t[1] = strv_new("c", "d", "e")); @@ -838,6 +913,8 @@ static void test_foreach_string(void) { const char *x; unsigned i = 0; + log_info("/* %s */", __func__); + FOREACH_STRING(x, "foo", "bar", "waldo") assert_se(streq_ptr(t[i++], x)); @@ -850,6 +927,8 @@ static void test_foreach_string(void) { static void test_strv_fnmatch(void) { _cleanup_strv_free_ char **v = NULL; + log_info("/* %s */", __func__); + assert_se(!strv_fnmatch(STRV_MAKE_EMPTY, "a", 0)); v = strv_new("*\\*"); diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index fd2443e3cb..7fe732cf2f 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -430,29 +430,31 @@ static void test_unit_name_to_instance(void) { int r; r = unit_name_to_instance("foo@bar.service", &instance); - assert_se(r >= 0); + assert_se(r == UNIT_NAME_INSTANCE); assert_se(streq(instance, "bar")); free(instance); r = unit_name_to_instance("foo@.service", &instance); - assert_se(r >= 0); + assert_se(r == UNIT_NAME_TEMPLATE); assert_se(streq(instance, "")); free(instance); r = unit_name_to_instance("fo0-stUff_b@b.service", &instance); - assert_se(r >= 0); + assert_se(r == UNIT_NAME_INSTANCE); assert_se(streq(instance, "b")); free(instance); r = unit_name_to_instance("foo.service", &instance); - assert_se(r == 0); + assert_se(r == UNIT_NAME_PLAIN); assert_se(!instance); r = unit_name_to_instance("fooj@unk", &instance); assert_se(r < 0); + assert_se(!instance); r = unit_name_to_instance("foo@", &instance); assert_se(r < 0); + assert_se(!instance); } static void test_unit_name_escape(void) { |