comparison lib/idcache.c @ 7673:a37b8b182d49

* lib/idcache.c: Restore most of the 2006-11-06 patch, so as to continue using the flexible array member (thus, this module performs half as many malloc calls), with the addition that... (getgroup, getuser): Consistently record a non-match via an empty "name" string, and map an empty string match to a NULL return value. * modules/idcache (Depends-on): Re-add flexmember.
author Jim Meyering <jim@meyering.net>
date Mon, 20 Nov 2006 10:54:06 +0000
parents d2c7e0fe0b94
children 476857ef4611
comparison
equal deleted inserted replaced
7672:d2c7e0fe0b94 7673:a37b8b182d49
17 along with this program; if not, write to the Free Software Foundation, 17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 19
20 #include <config.h> 20 #include <config.h>
21 21
22 #include <stddef.h>
22 #include <stdio.h> 23 #include <stdio.h>
23 #include <string.h> 24 #include <string.h>
24 #include <sys/types.h> 25 #include <sys/types.h>
25 #include <pwd.h> 26 #include <pwd.h>
26 #include <grp.h> 27 #include <grp.h>
38 union 39 union
39 { 40 {
40 uid_t u; 41 uid_t u;
41 gid_t g; 42 gid_t g;
42 } id; 43 } id;
43 char *name;
44 struct userid *next; 44 struct userid *next;
45 char name[FLEXIBLE_ARRAY_MEMBER];
45 }; 46 };
46 47
47 static struct userid *user_alist; 48 static struct userid *user_alist;
48 49
49 /* The members of this list have names not in the local passwd file. */ 50 /* The members of this list have names not in the local passwd file. */
53 54
54 char * 55 char *
55 getuser (uid_t uid) 56 getuser (uid_t uid)
56 { 57 {
57 struct userid *tail; 58 struct userid *tail;
58 struct passwd *pwent; 59 struct userid *match = NULL;
59 60
60 for (tail = user_alist; tail; tail = tail->next) 61 for (tail = user_alist; tail; tail = tail->next)
61 if (tail->id.u == uid) 62 {
62 return tail->name; 63 if (tail->id.u == uid)
63 64 {
64 pwent = getpwuid (uid); 65 match = tail;
65 tail = xmalloc (sizeof *tail); 66 break;
66 tail->id.u = uid; 67 }
67 tail->name = pwent ? xstrdup (pwent->pw_name) : NULL; 68 }
68 69
69 /* Add to the head of the list, so most recently used is first. */ 70 if (match == NULL)
70 tail->next = user_alist; 71 {
71 user_alist = tail; 72 struct passwd *pwent = getpwuid (uid);
72 return tail->name; 73 char const *name = pwent ? pwent->pw_name : "";
74 match = xmalloc (offsetof (struct userid, name) + strlen (name) + 1);
75 match->id.u = uid;
76 strcpy (match->name, name);
77
78 /* Add to the head of the list, so most recently used is first. */
79 match->next = user_alist;
80 user_alist = match;
81 }
82
83 return match->name[0] ? match->name : NULL;
73 } 84 }
74 85
75 /* Translate USER to a UID, with cache. 86 /* Translate USER to a UID, with cache.
76 Return NULL if there is no such user. 87 Return NULL if there is no such user.
77 (We also cache which user names have no passwd entry, 88 (We also cache which user names have no passwd entry,
102 setenv ("USER", user, 1); 113 setenv ("USER", user, 1);
103 pwent = getpwnam (user); /* now it will succeed */ 114 pwent = getpwnam (user); /* now it will succeed */
104 } 115 }
105 #endif 116 #endif
106 117
107 tail = xmalloc (sizeof *tail); 118 tail = xmalloc (offsetof (struct userid, name) + strlen (user) + 1);
108 tail->name = xstrdup (user); 119 strcpy (tail->name, user);
109 120
110 /* Add to the head of the list, so most recently used is first. */ 121 /* Add to the head of the list, so most recently used is first. */
111 if (pwent) 122 if (pwent)
112 { 123 {
113 tail->id.u = pwent->pw_uid; 124 tail->id.u = pwent->pw_uid;
129 140
130 char * 141 char *
131 getgroup (gid_t gid) 142 getgroup (gid_t gid)
132 { 143 {
133 struct userid *tail; 144 struct userid *tail;
134 struct group *grent; 145 struct userid *match = NULL;
135 146
136 for (tail = group_alist; tail; tail = tail->next) 147 for (tail = group_alist; tail; tail = tail->next)
137 if (tail->id.g == gid) 148 {
138 return tail->name; 149 if (tail->id.g == gid)
139 150 {
140 grent = getgrgid (gid); 151 match = tail;
141 tail = xmalloc (sizeof *tail); 152 break;
142 tail->id.g = gid; 153 }
143 tail->name = grent ? xstrdup (grent->gr_name) : NULL; 154 }
144 155
145 /* Add to the head of the list, so most recently used is first. */ 156 if (match == NULL)
146 tail->next = group_alist; 157 {
147 group_alist = tail; 158 struct group *grent = getgrgid (gid);
148 return tail->name; 159 char const *name = grent ? grent->gr_name : "";
160 match = xmalloc (offsetof (struct userid, name) + strlen (name) + 1);
161 match->id.g = gid;
162 strcpy (match->name, name);
163
164 /* Add to the head of the list, so most recently used is first. */
165 match->next = group_alist;
166 group_alist = match;
167 }
168
169 return match->name[0] ? match->name : NULL;
149 } 170 }
150 171
151 /* Translate GROUP to a GID, with cache. 172 /* Translate GROUP to a GID, with cache.
152 Return NULL if there is no such group. 173 Return NULL if there is no such group.
153 (We also cache which group names have no group entry, 174 (We also cache which group names have no group entry,
170 return NULL; 191 return NULL;
171 192
172 grent = getgrnam (group); 193 grent = getgrnam (group);
173 #ifdef __DJGPP__ 194 #ifdef __DJGPP__
174 /* We need to pretend to belong to group GROUP, to make 195 /* We need to pretend to belong to group GROUP, to make
175 grp functions know about any arbitrary group name. */ 196 grp functions know about an arbitrary group name. */
176 if (!grent && strspn (group, digits) < strlen (group)) 197 if (!grent && strspn (group, digits) < strlen (group))
177 { 198 {
178 setenv ("GROUP", group, 1); 199 setenv ("GROUP", group, 1);
179 grent = getgrnam (group); /* now it will succeed */ 200 grent = getgrnam (group); /* now it will succeed */
180 } 201 }
181 #endif 202 #endif
182 203
183 tail = xmalloc (sizeof *tail); 204 tail = xmalloc (offsetof (struct userid, name) + strlen (group) + 1);
184 tail->name = xstrdup (group); 205 strcpy (tail->name, group);
185 206
186 /* Add to the head of the list, so most recently used is first. */ 207 /* Add to the head of the list, so most recently used is first. */
187 if (grent) 208 if (grent)
188 { 209 {
189 tail->id.g = grent->gr_gid; 210 tail->id.g = grent->gr_gid;