source: trunk/essentials/app-arch/cpio/src/idcache.c

Last change on this file was 3332, checked in by bird, 18 years ago

cpio 2.7

File size: 5.1 KB
Line 
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
15 License along with this program; if not, write to the Free
16 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA. */
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include <stdio.h>
24#include <sys/types.h>
25#include <pwd.h>
26#include <grp.h>
27
28#if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
29#include <string.h>
30#else
31#include <strings.h>
32#endif
33
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37#ifndef _POSIX_VERSION
38struct passwd *getpwuid ();
39struct passwd *getpwnam ();
40struct group *getgrgid ();
41struct group *getgrnam ();
42#endif
43
44char *xmalloc ();
45char *xstrdup ();
46
47struct userid
48{
49 union
50 {
51 uid_t u;
52 gid_t g;
53 } id;
54 char *name;
55 struct userid *next;
56};
57
58static struct userid *user_alist;
59
60/* The members of this list have names not in the local passwd file. */
61static struct userid *nouser_alist;
62
63/* Translate UID to a login name or a stringified number,
64 with cache. */
65
66char *
67getuser (uid_t uid)
68{
69 register struct userid *tail;
70 struct passwd *pwent;
71 char usernum_string[20];
72
73 for (tail = user_alist; tail; tail = tail->next)
74 if (tail->id.u == uid)
75 return tail->name;
76
77 pwent = getpwuid (uid);
78 tail = (struct userid *) xmalloc (sizeof (struct userid));
79 tail->id.u = uid;
80 if (pwent == 0)
81 {
82 sprintf (usernum_string, "%u", (unsigned) uid);
83 tail->name = xstrdup (usernum_string);
84 }
85 else
86 tail->name = xstrdup (pwent->pw_name);
87
88 /* Add to the head of the list, so most recently used is first. */
89 tail->next = user_alist;
90 user_alist = tail;
91 return tail->name;
92}
93
94/* Translate USER to a UID, with cache.
95 Return NULL if there is no such user.
96 (We also cache which user names have no passwd entry,
97 so we don't keep looking them up.) */
98
99uid_t *
100getuidbyname (char *user)
101{
102 register struct userid *tail;
103 struct passwd *pwent;
104
105 for (tail = user_alist; tail; tail = tail->next)
106 /* Avoid a function call for the most common case. */
107 if (*tail->name == *user && !strcmp (tail->name, user))
108 return &tail->id.u;
109
110 for (tail = nouser_alist; tail; tail = tail->next)
111 /* Avoid a function call for the most common case. */
112 if (*tail->name == *user && !strcmp (tail->name, user))
113 return 0;
114
115 pwent = getpwnam (user);
116
117 tail = (struct userid *) xmalloc (sizeof (struct userid));
118 tail->name = xstrdup (user);
119
120 /* Add to the head of the list, so most recently used is first. */
121 if (pwent)
122 {
123 tail->id.u = pwent->pw_uid;
124 tail->next = user_alist;
125 user_alist = tail;
126 return &tail->id.u;
127 }
128
129 tail->next = nouser_alist;
130 nouser_alist = tail;
131 return 0;
132}
133
134/* Use the same struct as for userids. */
135static struct userid *group_alist;
136static struct userid *nogroup_alist;
137
138/* Translate GID to a group name or a stringified number,
139 with cache. */
140
141char *
142getgroup (gid_t gid)
143{
144 register struct userid *tail;
145 struct group *grent;
146 char groupnum_string[20];
147
148 for (tail = group_alist; tail; tail = tail->next)
149 if (tail->id.g == gid)
150 return tail->name;
151
152 grent = getgrgid (gid);
153 tail = (struct userid *) xmalloc (sizeof (struct userid));
154 tail->id.g = gid;
155 if (grent == 0)
156 {
157 sprintf (groupnum_string, "%u", (unsigned int) gid);
158 tail->name = xstrdup (groupnum_string);
159 }
160 else
161 tail->name = xstrdup (grent->gr_name);
162
163 /* Add to the head of the list, so most recently used is first. */
164 tail->next = group_alist;
165 group_alist = tail;
166 return tail->name;
167}
168
169/* Translate GROUP to a UID, with cache.
170 Return NULL if there is no such group.
171 (We also cache which group names have no group entry,
172 so we don't keep looking them up.) */
173
174gid_t *
175getgidbyname (char *group)
176{
177 register struct userid *tail;
178 struct group *grent;
179
180 for (tail = group_alist; tail; tail = tail->next)
181 /* Avoid a function call for the most common case. */
182 if (*tail->name == *group && !strcmp (tail->name, group))
183 return &tail->id.g;
184
185 for (tail = nogroup_alist; tail; tail = tail->next)
186 /* Avoid a function call for the most common case. */
187 if (*tail->name == *group && !strcmp (tail->name, group))
188 return 0;
189
190 grent = getgrnam (group);
191
192 tail = (struct userid *) xmalloc (sizeof (struct userid));
193 tail->name = xstrdup (group);
194
195 /* Add to the head of the list, so most recently used is first. */
196 if (grent)
197 {
198 tail->id.g = grent->gr_gid;
199 tail->next = group_alist;
200 group_alist = tail;
201 return &tail->id.g;
202 }
203
204 tail->next = nogroup_alist;
205 nogroup_alist = tail;
206 return 0;
207}
Note: See TracBrowser for help on using the repository browser.