summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-03-28 17:28:48 +0100
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-07-19 16:49:41 +0200
commitcde7910993b08f7fe605457d69c2d28b2510c756 (patch)
treef519fd7360f614ede8d1a72b3cfedce7d6582ec7
parentb124d3f2ce87cc71065fde589caafd5ceb4764b6 (diff)
downloadsystemd-cde7910993b08f7fe605457d69c2d28b2510c756.tar.gz
sysusers,strv: export the hash ops to map char* → strv
Also make string_strv_hashmap_put return 0 only if the entry already existed.
-rw-r--r--src/basic/strv.c60
-rw-r--r--src/basic/strv.h5
-rw-r--r--src/sysusers/sysusers.c37
3 files changed, 67 insertions, 35 deletions
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/sysusers/sysusers.c b/src/sysusers/sysusers.c
index 990a2f927b..5f12ef18da 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;
}