]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysusers,strv: export the hash ops to map char* → strv
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 28 Mar 2019 16:28:48 +0000 (17:28 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 19 Jul 2019 14:49:41 +0000 (16:49 +0200)
Also make string_strv_hashmap_put return 0 only if the entry already existed.

src/basic/strv.c
src/basic/strv.h
src/sysusers/sysusers.c

index 2ae685f35a24751e9d21545c7aac126b8dee8b20..88b85867bb3bb60dc8d4181b03357021753f9215 100644 (file)
@@ -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);
index aa5f95ab72e7edaf35c3fef2a16581806f67351e..e80964acd17bcee0f70fc226c2408b9be88aa514 100644 (file)
@@ -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);
index 990a2f927b76cab6a02f3486f90d1025ba68d479..5f12ef18daf2d5bbe96575efffe0b7915b25e2aa 100644 (file)
@@ -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;
         }