]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/cpio/src/idcache.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / cpio / src / idcache.c
1 /* idcache.c -- map user and group IDs, cached for speed
2    Copyright (C) 1985, 1988, 1989, 1990, 2004 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation, Inc.,
16    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <pwd.h>
25 #include <grp.h>
26
27 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
28 #include <string.h>
29 #else
30 #include <strings.h>
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #ifndef _POSIX_VERSION
37 struct passwd *getpwuid ();
38 struct passwd *getpwnam ();
39 struct group *getgrgid ();
40 struct group *getgrnam ();
41 #endif
42
43 char *xmalloc ();
44 char *xstrdup ();
45
46 struct userid
47 {
48   union
49     {
50       uid_t u;
51       gid_t g;
52     } id;
53   char *name;
54   struct userid *next;
55 };
56
57 static struct userid *user_alist;
58
59 /* The members of this list have names not in the local passwd file.  */
60 static struct userid *nouser_alist;
61
62 /* Translate UID to a login name or a stringified number,
63    with cache.  */
64
65 char *
66 getuser (uid_t uid)
67 {
68   register struct userid *tail;
69   struct passwd *pwent;
70   char usernum_string[20];
71
72   for (tail = user_alist; tail; tail = tail->next)
73     if (tail->id.u == uid)
74       return tail->name;
75
76   pwent = getpwuid (uid);
77   tail = (struct userid *) xmalloc (sizeof (struct userid));
78   tail->id.u = uid;
79   if (pwent == 0)
80     {
81       sprintf (usernum_string, "%u", (unsigned) uid);
82       tail->name = xstrdup (usernum_string);
83     }
84   else
85     tail->name = xstrdup (pwent->pw_name);
86
87   /* Add to the head of the list, so most recently used is first.  */
88   tail->next = user_alist;
89   user_alist = tail;
90   return tail->name;
91 }
92
93 /* Translate USER to a UID, with cache.
94    Return NULL if there is no such user.
95    (We also cache which user names have no passwd entry,
96    so we don't keep looking them up.)  */
97
98 uid_t *
99 getuidbyname (char *user)
100 {
101   register struct userid *tail;
102   struct passwd *pwent;
103
104   for (tail = user_alist; tail; tail = tail->next)
105     /* Avoid a function call for the most common case.  */
106     if (*tail->name == *user && !strcmp (tail->name, user))
107       return &tail->id.u;
108
109   for (tail = nouser_alist; tail; tail = tail->next)
110     /* Avoid a function call for the most common case.  */
111     if (*tail->name == *user && !strcmp (tail->name, user))
112       return 0;
113
114   pwent = getpwnam (user);
115
116   tail = (struct userid *) xmalloc (sizeof (struct userid));
117   tail->name = xstrdup (user);
118
119   /* Add to the head of the list, so most recently used is first.  */
120   if (pwent)
121     {
122       tail->id.u = pwent->pw_uid;
123       tail->next = user_alist;
124       user_alist = tail;
125       return &tail->id.u;
126     }
127
128   tail->next = nouser_alist;
129   nouser_alist = tail;
130   return 0;
131 }
132
133 /* Use the same struct as for userids.  */
134 static struct userid *group_alist;
135 static struct userid *nogroup_alist;
136
137 /* Translate GID to a group name or a stringified number,
138    with cache.  */
139
140 char *
141 getgroup (gid_t gid)
142 {
143   register struct userid *tail;
144   struct group *grent;
145   char groupnum_string[20];
146
147   for (tail = group_alist; tail; tail = tail->next)
148     if (tail->id.g == gid)
149       return tail->name;
150
151   grent = getgrgid (gid);
152   tail = (struct userid *) xmalloc (sizeof (struct userid));
153   tail->id.g = gid;
154   if (grent == 0)
155     {
156       sprintf (groupnum_string, "%u", (unsigned int) gid);
157       tail->name = xstrdup (groupnum_string);
158     }
159   else
160     tail->name = xstrdup (grent->gr_name);
161
162   /* Add to the head of the list, so most recently used is first.  */
163   tail->next = group_alist;
164   group_alist = tail;
165   return tail->name;
166 }
167
168 /* Translate GROUP to a UID, with cache.
169    Return NULL if there is no such group.
170    (We also cache which group names have no group entry,
171    so we don't keep looking them up.)  */
172
173 gid_t *
174 getgidbyname (char *group)
175 {
176   register struct userid *tail;
177   struct group *grent;
178
179   for (tail = group_alist; tail; tail = tail->next)
180     /* Avoid a function call for the most common case.  */
181     if (*tail->name == *group && !strcmp (tail->name, group))
182       return &tail->id.g;
183
184   for (tail = nogroup_alist; tail; tail = tail->next)
185     /* Avoid a function call for the most common case.  */
186     if (*tail->name == *group && !strcmp (tail->name, group))
187       return 0;
188
189   grent = getgrnam (group);
190
191   tail = (struct userid *) xmalloc (sizeof (struct userid));
192   tail->name = xstrdup (group);
193
194   /* Add to the head of the list, so most recently used is first.  */
195   if (grent)
196     {
197       tail->id.g = grent->gr_gid;
198       tail->next = group_alist;
199       group_alist = tail;
200       return &tail->id.g;
201     }
202
203   tail->next = nogroup_alist;
204   nogroup_alist = tail;
205   return 0;
206 }