source: freewrt/tools/paxmirabilis/src/cache.c@ bceb42b

freewrt_1_0 freewrt_2_0
Last change on this file since bceb42b was bceb42b, checked in by Thorsten Glaser <tg@…>, 19 years ago

wbx@ asked me a few seconds too late to use an src/ subdirectory

git-svn-id: svn://www.freewrt.org/trunk/freewrt@204 afb5a338-a214-0410-bd46-81f09a774fd1

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/** $MirOS: src/bin/pax/cache.c,v 1.2 2005/04/13 20:03:35 tg Exp $ */
2/* $OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $ */
3/* $NetBSD: cache.c,v 1.4 1995/03/21 09:07:10 cgd Exp $ */
4
5/*-
6 * Copyright (c) 1992 Keith Muller.
7 * Copyright (c) 1992, 1993
8 * The Regents of the University of California. All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * Keith Muller of the University of California, San Diego.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#include <sys/types.h>
39#include <sys/time.h>
40#include <sys/stat.h>
41#include <sys/param.h>
42#include <string.h>
43#include <stdio.h>
44#include <pwd.h>
45#include <grp.h>
46#include <unistd.h>
47#include <stdlib.h>
48#include "pax.h"
49#include "cache.h"
50#include "extern.h"
51
52__SCCSID("@(#)cache.c 8.1 (Berkeley) 5/31/93");
53__RCSID("$MirOS: src/bin/pax/cache.c,v 1.2 2005/04/13 20:03:35 tg Exp $");
54
55/*
56 * routines that control user, group, uid and gid caches (for the archive
57 * member print routine).
58 * IMPORTANT:
59 * these routines cache BOTH hits and misses, a major performance improvement
60 */
61
62static int pwopn = 0; /* is password file open */
63static int gropn = 0; /* is group file open */
64static UIDC **uidtb = NULL; /* uid to name cache */
65static GIDC **gidtb = NULL; /* gid to name cache */
66static UIDC **usrtb = NULL; /* user name to uid cache */
67static GIDC **grptb = NULL; /* group name to gid cache */
68
69/*
70 * uidtb_start
71 * creates an empty uidtb
72 * Return:
73 * 0 if ok, -1 otherwise
74 */
75
76int
77uidtb_start(void)
78{
79 static int fail = 0;
80
81 if (uidtb != NULL)
82 return(0);
83 if (fail)
84 return(-1);
85 if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
86 ++fail;
87 paxwarn(1, "Unable to allocate memory for user id cache table");
88 return(-1);
89 }
90 return(0);
91}
92
93/*
94 * gidtb_start
95 * creates an empty gidtb
96 * Return:
97 * 0 if ok, -1 otherwise
98 */
99
100int
101gidtb_start(void)
102{
103 static int fail = 0;
104
105 if (gidtb != NULL)
106 return(0);
107 if (fail)
108 return(-1);
109 if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
110 ++fail;
111 paxwarn(1, "Unable to allocate memory for group id cache table");
112 return(-1);
113 }
114 return(0);
115}
116
117/*
118 * usrtb_start
119 * creates an empty usrtb
120 * Return:
121 * 0 if ok, -1 otherwise
122 */
123
124int
125usrtb_start(void)
126{
127 static int fail = 0;
128
129 if (usrtb != NULL)
130 return(0);
131 if (fail)
132 return(-1);
133 if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
134 ++fail;
135 paxwarn(1, "Unable to allocate memory for user name cache table");
136 return(-1);
137 }
138 return(0);
139}
140
141/*
142 * grptb_start
143 * creates an empty grptb
144 * Return:
145 * 0 if ok, -1 otherwise
146 */
147
148int
149grptb_start(void)
150{
151 static int fail = 0;
152
153 if (grptb != NULL)
154 return(0);
155 if (fail)
156 return(-1);
157 if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
158 ++fail;
159 paxwarn(1,"Unable to allocate memory for group name cache table");
160 return(-1);
161 }
162 return(0);
163}
164
165/*
166 * name_uid()
167 * caches the name (if any) for the uid. If frc set, we always return the
168 * the stored name (if valid or invalid match). We use a simple hash table.
169 * Return
170 * Pointer to stored name (or a empty string)
171 */
172
173char *
174name_uid(uid_t uid, int frc)
175{
176 struct passwd *pw;
177 UIDC *ptr;
178
179 if ((uidtb == NULL) && (uidtb_start() < 0))
180 return("");
181
182 /*
183 * see if we have this uid cached
184 */
185 ptr = uidtb[uid % UID_SZ];
186 if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
187 /*
188 * have an entry for this uid
189 */
190 if (frc || (ptr->valid == VALID))
191 return(ptr->name);
192 return("");
193 }
194
195 /*
196 * No entry for this uid, we will add it
197 */
198 if (!pwopn) {
199#ifndef __INTERIX
200 setpassent(1);
201#endif
202 ++pwopn;
203 }
204 if (ptr == NULL)
205 ptr = uidtb[uid % UID_SZ] = malloc(sizeof(UIDC));
206
207 if ((pw = getpwuid(uid)) == NULL) {
208 /*
209 * no match for this uid in the local password file
210 * a string that is the uid in numeric format
211 */
212 if (ptr == NULL)
213 return("");
214 ptr->uid = uid;
215 ptr->valid = INVALID;
216 (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
217 (unsigned long)uid);
218 if (frc == 0)
219 return("");
220 } else {
221 /*
222 * there is an entry for this uid in the password file
223 */
224 if (ptr == NULL)
225 return(pw->pw_name);
226 ptr->uid = uid;
227 (void)strlcpy(ptr->name, pw->pw_name, sizeof(ptr->name));
228 ptr->valid = VALID;
229 }
230 return(ptr->name);
231}
232
233/*
234 * name_gid()
235 * caches the name (if any) for the gid. If frc set, we always return the
236 * the stored name (if valid or invalid match). We use a simple hash table.
237 * Return
238 * Pointer to stored name (or a empty string)
239 */
240
241char *
242name_gid(gid_t gid, int frc)
243{
244 struct group *gr;
245 GIDC *ptr;
246
247 if ((gidtb == NULL) && (gidtb_start() < 0))
248 return("");
249
250 /*
251 * see if we have this gid cached
252 */
253 ptr = gidtb[gid % GID_SZ];
254 if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
255 /*
256 * have an entry for this gid
257 */
258 if (frc || (ptr->valid == VALID))
259 return(ptr->name);
260 return("");
261 }
262
263 /*
264 * No entry for this gid, we will add it
265 */
266 if (!gropn) {
267#ifndef __INTERIX
268 setgroupent(1);
269#endif
270 ++gropn;
271 }
272 if (ptr == NULL)
273 ptr = gidtb[gid % GID_SZ] = malloc(sizeof(GIDC));
274
275 if ((gr = getgrgid(gid)) == NULL) {
276 /*
277 * no match for this gid in the local group file, put in
278 * a string that is the gid in numberic format
279 */
280 if (ptr == NULL)
281 return("");
282 ptr->gid = gid;
283 ptr->valid = INVALID;
284 (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
285 (unsigned long)gid);
286 if (frc == 0)
287 return("");
288 } else {
289 /*
290 * there is an entry for this group in the group file
291 */
292 if (ptr == NULL)
293 return(gr->gr_name);
294 ptr->gid = gid;
295 (void)strlcpy(ptr->name, gr->gr_name, sizeof(ptr->name));
296 ptr->valid = VALID;
297 }
298 return(ptr->name);
299}
300
301/*
302 * uid_name()
303 * caches the uid for a given user name. We use a simple hash table.
304 * Return
305 * the uid (if any) for a user name, or a -1 if no match can be found
306 */
307
308int
309uid_name(char *name, uid_t *uid)
310{
311 struct passwd *pw;
312 UIDC *ptr;
313 int namelen;
314
315 /*
316 * return -1 for mangled names
317 */
318 if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
319 return(-1);
320 if ((usrtb == NULL) && (usrtb_start() < 0))
321 return(-1);
322
323 /*
324 * look up in hash table, if found and valid return the uid,
325 * if found and invalid, return a -1
326 */
327 ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
328 if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
329 if (ptr->valid == INVALID)
330 return(-1);
331 *uid = ptr->uid;
332 return(0);
333 }
334
335 if (!pwopn) {
336#ifndef __INTERIX
337 setpassent(1);
338#endif
339 ++pwopn;
340 }
341
342 if (ptr == NULL)
343 ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
344 (UIDC *)malloc(sizeof(UIDC));
345
346 /*
347 * no match, look it up, if no match store it as an invalid entry,
348 * or store the matching uid
349 */
350 if (ptr == NULL) {
351 if ((pw = getpwnam(name)) == NULL)
352 return(-1);
353 *uid = pw->pw_uid;
354 return(0);
355 }
356 (void)strlcpy(ptr->name, name, sizeof(ptr->name));
357 if ((pw = getpwnam(name)) == NULL) {
358 ptr->valid = INVALID;
359 return(-1);
360 }
361 ptr->valid = VALID;
362 *uid = ptr->uid = pw->pw_uid;
363 return(0);
364}
365
366/*
367 * gid_name()
368 * caches the gid for a given group name. We use a simple hash table.
369 * Return
370 * the gid (if any) for a group name, or a -1 if no match can be found
371 */
372
373int
374gid_name(char *name, gid_t *gid)
375{
376 struct group *gr;
377 GIDC *ptr;
378 int namelen;
379
380 /*
381 * return -1 for mangled names
382 */
383 if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
384 return(-1);
385 if ((grptb == NULL) && (grptb_start() < 0))
386 return(-1);
387
388 /*
389 * look up in hash table, if found and valid return the uid,
390 * if found and invalid, return a -1
391 */
392 ptr = grptb[st_hash(name, namelen, GID_SZ)];
393 if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
394 if (ptr->valid == INVALID)
395 return(-1);
396 *gid = ptr->gid;
397 return(0);
398 }
399
400 if (!gropn) {
401#ifndef __INTERIX
402 setgroupent(1);
403#endif
404 ++gropn;
405 }
406 if (ptr == NULL)
407 ptr = grptb[st_hash(name, namelen, GID_SZ)] =
408 (GIDC *)malloc(sizeof(GIDC));
409
410 /*
411 * no match, look it up, if no match store it as an invalid entry,
412 * or store the matching gid
413 */
414 if (ptr == NULL) {
415 if ((gr = getgrnam(name)) == NULL)
416 return(-1);
417 *gid = gr->gr_gid;
418 return(0);
419 }
420
421 (void)strlcpy(ptr->name, name, sizeof(ptr->name));
422 if ((gr = getgrnam(name)) == NULL) {
423 ptr->valid = INVALID;
424 return(-1);
425 }
426 ptr->valid = VALID;
427 *gid = ptr->gid = gr->gr_gid;
428 return(0);
429}
Note: See TracBrowser for help on using the repository browser.