]> git.ipfire.org Git - thirdparty/util-linux.git/blob - lib/idcache.c
libmount: accept '\' as escape for options separator
[thirdparty/util-linux.git] / lib / idcache.c
1 /*
2 * No copyright is claimed. This code is in the public domain; do with
3 * it what you wish.
4 *
5 * Written by Karel Zak <kzak@redhat.com>
6 */
7 #include <wchar.h>
8 #include <pwd.h>
9 #include <grp.h>
10 #include <sys/types.h>
11
12 #include "c.h"
13 #include "idcache.h"
14
15 struct identry *get_id(struct idcache *ic, unsigned long int id)
16 {
17 struct identry *ent;
18
19 if (!ic)
20 return NULL;
21
22 for (ent = ic->ent; ent; ent = ent->next) {
23 if (ent->id == id)
24 return ent;
25 }
26
27 return NULL;
28 }
29
30 struct idcache *new_idcache(void)
31 {
32 return calloc(1, sizeof(struct idcache));
33 }
34
35 void free_idcache(struct idcache *ic)
36 {
37 struct identry *ent;
38
39 if (!ic)
40 return;
41
42 ent = ic->ent;
43
44 while (ent) {
45 struct identry *next = ent->next;
46 free(ent->name);
47 free(ent);
48 ent = next;
49 }
50
51 free(ic);
52 }
53
54 static void add_id(struct idcache *ic, char *name, unsigned long int id)
55 {
56 struct identry *ent, *x;
57 int w = 0;
58
59 if (!ic)
60 return;
61
62 ent = calloc(1, sizeof(struct identry));
63 if (!ent)
64 return;
65 ent->id = id;
66
67 if (name) {
68 #ifdef HAVE_WIDECHAR
69 wchar_t wc[LOGIN_NAME_MAX + 1];
70
71 if (mbstowcs(wc, name, LOGIN_NAME_MAX) > 0) {
72 wc[LOGIN_NAME_MAX] = '\0';
73 w = wcswidth(wc, LOGIN_NAME_MAX);
74 }
75 else
76 #endif
77 w = strlen(name);
78 }
79
80 /* note, we ignore names with non-printable widechars */
81 if (w > 0) {
82 ent->name = strdup(name);
83 if (!ent->name) {
84 free(ent);
85 return;
86 }
87 } else {
88 if (asprintf(&ent->name, "%lu", id) < 0) {
89 free(ent);
90 return;
91 }
92 }
93
94 for (x = ic->ent; x && x->next; x = x->next);
95
96 if (x)
97 x->next = ent;
98 else
99 ic->ent = ent;
100
101 if (w <= 0)
102 w = ent->name ? strlen(ent->name) : 0;
103 ic->width = ic->width < w ? w : ic->width;
104 }
105
106 void add_uid(struct idcache *cache, unsigned long int id)
107 {
108 struct identry *ent = get_id(cache, id);
109
110 if (!ent) {
111 struct passwd *pw = getpwuid((uid_t) id);
112 add_id(cache, pw ? pw->pw_name : NULL, id);
113 }
114 }
115
116 void add_gid(struct idcache *cache, unsigned long int id)
117 {
118 struct identry *ent = get_id(cache, id);
119
120 if (!ent) {
121 struct group *gr = getgrgid((gid_t) id);
122 add_id(cache, gr ? gr->gr_name : NULL, id);
123 }
124 }
125