]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/offline-passwd.c
8ac5431c66da8545ec480c5c3c85d86e17803bb2
[thirdparty/systemd.git] / src / shared / offline-passwd.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "fd-util.h"
4 #include "offline-passwd.h"
5 #include "path-util.h"
6 #include "user-util.h"
7
8 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(uid_gid_hash_ops, char, string_hash_func, string_compare_func, free);
9
10 int name_to_uid_offline(
11 const char *root,
12 const char *user,
13 uid_t *ret_uid,
14 Hashmap **cache) {
15
16 void *found;
17 int r;
18
19 assert(user);
20 assert(ret_uid);
21 assert(cache);
22
23 if (!*cache) {
24 _cleanup_(hashmap_freep) Hashmap *uid_by_name = NULL;
25 _cleanup_fclose_ FILE *f = NULL;
26 struct passwd *pw;
27 const char *passwd_path;
28
29 passwd_path = prefix_roota(root, "/etc/passwd");
30 f = fopen(passwd_path, "re");
31 if (!f)
32 return errno == ENOENT ? -ESRCH : -errno;
33
34 uid_by_name = hashmap_new(&uid_gid_hash_ops);
35 if (!uid_by_name)
36 return -ENOMEM;
37
38 while ((r = fgetpwent_sane(f, &pw)) > 0) {
39 _cleanup_free_ char *n = NULL;
40
41 n = strdup(pw->pw_name);
42 if (!n)
43 return -ENOMEM;
44
45 r = hashmap_put(uid_by_name, n, UID_TO_PTR(pw->pw_uid));
46 if (r == -EEXIST) {
47 log_warning_errno(r, "Duplicate entry in %s for %s: %m", passwd_path, pw->pw_name);
48 continue;
49 }
50 if (r < 0)
51 return r;
52
53 TAKE_PTR(n);
54 }
55
56 *cache = TAKE_PTR(uid_by_name);
57 }
58
59 found = hashmap_get(*cache, user);
60 if (!found)
61 return -ESRCH;
62
63 *ret_uid = PTR_TO_UID(found);
64 return 0;
65 }
66
67 int name_to_gid_offline(
68 const char *root,
69 const char *group,
70 gid_t *ret_gid,
71 Hashmap **cache) {
72
73 void *found;
74 int r;
75
76 assert(group);
77 assert(ret_gid);
78 assert(cache);
79
80 if (!*cache) {
81 _cleanup_(hashmap_freep) Hashmap *gid_by_name = NULL;
82 _cleanup_fclose_ FILE *f = NULL;
83 struct group *gr;
84 const char *group_path;
85
86 group_path = prefix_roota(root, "/etc/group");
87 f = fopen(group_path, "re");
88 if (!f)
89 return errno == ENOENT ? -ESRCH : -errno;
90
91 gid_by_name = hashmap_new(&uid_gid_hash_ops);
92 if (!gid_by_name)
93 return -ENOMEM;
94
95 while ((r = fgetgrent_sane(f, &gr)) > 0) {
96 _cleanup_free_ char *n = NULL;
97
98 n = strdup(gr->gr_name);
99 if (!n)
100 return -ENOMEM;
101
102 r = hashmap_put(gid_by_name, n, GID_TO_PTR(gr->gr_gid));
103 if (r == -EEXIST) {
104 log_warning_errno(r, "Duplicate entry in %s for %s: %m", group_path, gr->gr_name);
105 continue;
106 }
107 if (r < 0)
108 return r;
109
110 TAKE_PTR(n);
111 }
112
113 *cache = TAKE_PTR(gid_by_name);
114 }
115
116 found = hashmap_get(*cache, group);
117 if (!found)
118 return -ESRCH;
119
120 *ret_gid = PTR_TO_GID(found);
121 return 0;
122 }