xref: /csrg-svn/bin/pax/cache.c (revision 57194)
1*57194Smuller /*-
2*57194Smuller  * Copyright (c) 1992 Keith Muller.
3*57194Smuller  * Copyright (c) 1992 The Regents of the University of California.
4*57194Smuller  * All rights reserved.
5*57194Smuller  *
6*57194Smuller  * This code is derived from software contributed to Berkeley by
7*57194Smuller  * Keith Muller of the University of California, San Diego.
8*57194Smuller  *
9*57194Smuller  * %sccs.include.redist.c%
10*57194Smuller  */
11*57194Smuller 
12*57194Smuller #ifndef lint
13*57194Smuller static char sccsid[] = "@(#)cache.c	1.1 (Berkeley) 12/17/92";
14*57194Smuller #endif /* not lint */
15*57194Smuller 
16*57194Smuller #include <sys/types.h>
17*57194Smuller #include <sys/time.h>
18*57194Smuller #include <sys/stat.h>
19*57194Smuller #include <sys/param.h>
20*57194Smuller #include <string.h>
21*57194Smuller #include <stdio.h>
22*57194Smuller #include <ctype.h>
23*57194Smuller #include <pwd.h>
24*57194Smuller #include <grp.h>
25*57194Smuller #include <unistd.h>
26*57194Smuller #include <stdlib.h>
27*57194Smuller #include "pax.h"
28*57194Smuller #include "cache.h"
29*57194Smuller #include "extern.h"
30*57194Smuller 
31*57194Smuller /*
32*57194Smuller  * routines that control user, group, uid and gid caches (for the archive
33*57194Smuller  * member print routine).
34*57194Smuller  * IMPORTANT:
35*57194Smuller  * these routines cache BOTH hits and misses, a major performance improvement
36*57194Smuller  */
37*57194Smuller 
38*57194Smuller static	int pwopn = 0;		/* is password file open */
39*57194Smuller static	int gropn = 0;		/* is group file open */
40*57194Smuller static UIDC **uidtb = NULL;	/* uid to name cache */
41*57194Smuller static GIDC **gidtb = NULL;	/* gid to name cache */
42*57194Smuller static UIDC **usrtb = NULL;	/* user name to uid cache */
43*57194Smuller static GIDC **grptb = NULL;	/* group name to gid cache */
44*57194Smuller 
45*57194Smuller /*
46*57194Smuller  * uidtb_start
47*57194Smuller  *	creates an an empty uidtb
48*57194Smuller  * Return:
49*57194Smuller  *	0 if ok, -1 otherwise
50*57194Smuller  */
51*57194Smuller 
52*57194Smuller #if __STDC__
53*57194Smuller int
54*57194Smuller uidtb_start(void)
55*57194Smuller #else
56*57194Smuller int
57*57194Smuller uidtb_start()
58*57194Smuller #endif
59*57194Smuller {
60*57194Smuller 	static int fail = 0;
61*57194Smuller 
62*57194Smuller 	if (uidtb != NULL)
63*57194Smuller 		return(0);
64*57194Smuller 	if (fail)
65*57194Smuller 		return(-1);
66*57194Smuller 	if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
67*57194Smuller 		++fail;
68*57194Smuller 		warn(1, "Unable to allocate memory for user id cache table");
69*57194Smuller 		return(-1);
70*57194Smuller 	}
71*57194Smuller 	return(0);
72*57194Smuller }
73*57194Smuller 
74*57194Smuller /*
75*57194Smuller  * gidtb_start
76*57194Smuller  *	creates an an empty gidtb
77*57194Smuller  * Return:
78*57194Smuller  *	0 if ok, -1 otherwise
79*57194Smuller  */
80*57194Smuller 
81*57194Smuller #if __STDC__
82*57194Smuller int
83*57194Smuller gidtb_start(void)
84*57194Smuller #else
85*57194Smuller int
86*57194Smuller gidtb_start()
87*57194Smuller #endif
88*57194Smuller {
89*57194Smuller 	static int fail = 0;
90*57194Smuller 
91*57194Smuller 	if (gidtb != NULL)
92*57194Smuller 		return(0);
93*57194Smuller 	if (fail)
94*57194Smuller 		return(-1);
95*57194Smuller 	if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
96*57194Smuller 		++fail;
97*57194Smuller 		warn(1, "Unable to allocate memory for group id cache table");
98*57194Smuller 		return(-1);
99*57194Smuller 	}
100*57194Smuller 	return(0);
101*57194Smuller }
102*57194Smuller 
103*57194Smuller /*
104*57194Smuller  * usrtb_start
105*57194Smuller  *	creates an an empty usrtb
106*57194Smuller  * Return:
107*57194Smuller  *	0 if ok, -1 otherwise
108*57194Smuller  */
109*57194Smuller 
110*57194Smuller #if __STDC__
111*57194Smuller int
112*57194Smuller usrtb_start(void)
113*57194Smuller #else
114*57194Smuller int
115*57194Smuller usrtb_start()
116*57194Smuller #endif
117*57194Smuller {
118*57194Smuller 	static int fail = 0;
119*57194Smuller 
120*57194Smuller 	if (usrtb != NULL)
121*57194Smuller 		return(0);
122*57194Smuller 	if (fail)
123*57194Smuller 		return(-1);
124*57194Smuller 	if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
125*57194Smuller 		++fail;
126*57194Smuller 		warn(1, "Unable to allocate memory for user name cache table");
127*57194Smuller 		return(-1);
128*57194Smuller 	}
129*57194Smuller 	return(0);
130*57194Smuller }
131*57194Smuller 
132*57194Smuller /*
133*57194Smuller  * grptb_start
134*57194Smuller  *	creates an an empty grptb
135*57194Smuller  * Return:
136*57194Smuller  *	0 if ok, -1 otherwise
137*57194Smuller  */
138*57194Smuller 
139*57194Smuller #if __STDC__
140*57194Smuller int
141*57194Smuller grptb_start(void)
142*57194Smuller #else
143*57194Smuller int
144*57194Smuller grptb_start()
145*57194Smuller #endif
146*57194Smuller {
147*57194Smuller 	static int fail = 0;
148*57194Smuller 
149*57194Smuller 	if (grptb != NULL)
150*57194Smuller 		return(0);
151*57194Smuller 	if (fail)
152*57194Smuller 		return(-1);
153*57194Smuller 	if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
154*57194Smuller 		++fail;
155*57194Smuller 		warn(1,"Unable to allocate memory for group name cache table");
156*57194Smuller 		return(-1);
157*57194Smuller 	}
158*57194Smuller 	return(0);
159*57194Smuller }
160*57194Smuller 
161*57194Smuller /*
162*57194Smuller  * name_uid()
163*57194Smuller  *	caches the name (if any) for the uid. If frc set, we always return the
164*57194Smuller  *	the stored name (if valid or invalid match). We use a simple hash table.
165*57194Smuller  * Return
166*57194Smuller  *	Pointer to stored name (or a empty string)
167*57194Smuller  */
168*57194Smuller 
169*57194Smuller #if __STDC__
170*57194Smuller char *
171*57194Smuller name_uid(uid_t uid, int frc)
172*57194Smuller #else
173*57194Smuller char *
174*57194Smuller name_uid(uid, frc)
175*57194Smuller 	uid_t uid;
176*57194Smuller 	int frc;
177*57194Smuller #endif
178*57194Smuller {
179*57194Smuller 	register struct passwd *pw;
180*57194Smuller 	register UIDC *ptr;
181*57194Smuller 
182*57194Smuller 	if ((uidtb == NULL) && (uidtb_start() < 0))
183*57194Smuller 		return("");
184*57194Smuller 
185*57194Smuller 	/*
186*57194Smuller 	 * see if we have this uid cached
187*57194Smuller 	 */
188*57194Smuller 	ptr = uidtb[uid % UID_SZ];
189*57194Smuller 	if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
190*57194Smuller 		/*
191*57194Smuller 		 * have an entry for this uid
192*57194Smuller 		 */
193*57194Smuller 		if (frc || (ptr->valid == VALID))
194*57194Smuller 			return(ptr->name);
195*57194Smuller 		return("");
196*57194Smuller 	}
197*57194Smuller 
198*57194Smuller 	/*
199*57194Smuller 	 * No entry for this uid, we will add it
200*57194Smuller 	 */
201*57194Smuller 	if (!pwopn) {
202*57194Smuller 		setpassent(1);
203*57194Smuller 		++pwopn;
204*57194Smuller 	}
205*57194Smuller 	if (ptr == NULL)
206*57194Smuller 		ptr = (UIDC *)malloc(sizeof(UIDC));
207*57194Smuller 
208*57194Smuller 	if ((pw = getpwuid(uid)) == NULL) {
209*57194Smuller 		/*
210*57194Smuller 		 * no match for this uid in the local password file
211*57194Smuller 		 * a string that is the uid in numberic format
212*57194Smuller 		 */
213*57194Smuller 		if (ptr == NULL)
214*57194Smuller 			return("");
215*57194Smuller 		ptr->uid = uid;
216*57194Smuller 		ptr->valid = INVALID;
217*57194Smuller #		ifdef NET2_STAT
218*57194Smuller 		(void)sprintf(ptr->name, "%u", uid);
219*57194Smuller #		else
220*57194Smuller 		(void)sprintf(ptr->name, "%lu", uid);
221*57194Smuller #		endif
222*57194Smuller 		if (frc == 0)
223*57194Smuller 			return("");
224*57194Smuller 	} else {
225*57194Smuller 		/*
226*57194Smuller 		 * there is an entry for this uid in the password file
227*57194Smuller 		 */
228*57194Smuller 		if (ptr == NULL)
229*57194Smuller 			return(pw->pw_name);
230*57194Smuller 		ptr->uid = uid;
231*57194Smuller 		(void)strncpy(ptr->name, pw->pw_name, UNMLEN);
232*57194Smuller 		ptr->name[UNMLEN-1] = '\0';
233*57194Smuller 		ptr->valid = VALID;
234*57194Smuller 	}
235*57194Smuller 	return(ptr->name);
236*57194Smuller }
237*57194Smuller 
238*57194Smuller /*
239*57194Smuller  * name_gid()
240*57194Smuller  *	caches the name (if any) for the gid. If frc set, we always return the
241*57194Smuller  *	the stored name (if valid or invalid match). We use a simple hash table.
242*57194Smuller  * Return
243*57194Smuller  *	Pointer to stored name (or a empty string)
244*57194Smuller  */
245*57194Smuller 
246*57194Smuller #if __STDC__
247*57194Smuller char *
248*57194Smuller name_gid(gid_t gid, int frc)
249*57194Smuller #else
250*57194Smuller char *
251*57194Smuller name_gid(gid, frc)
252*57194Smuller 	gid_t gid;
253*57194Smuller 	int frc;
254*57194Smuller #endif
255*57194Smuller {
256*57194Smuller 	register struct group *gr;
257*57194Smuller 	register GIDC *ptr;
258*57194Smuller 
259*57194Smuller 	if ((gidtb == NULL) && (gidtb_start() < 0))
260*57194Smuller 		return("");
261*57194Smuller 
262*57194Smuller 	/*
263*57194Smuller 	 * see if we have this gid cached
264*57194Smuller 	 */
265*57194Smuller 	ptr = gidtb[gid % GID_SZ];
266*57194Smuller 	if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
267*57194Smuller 		/*
268*57194Smuller 		 * have an entry for this gid
269*57194Smuller 		 */
270*57194Smuller 		if (frc || (ptr->valid == VALID))
271*57194Smuller 			return(ptr->name);
272*57194Smuller 		return("");
273*57194Smuller 	}
274*57194Smuller 
275*57194Smuller 	/*
276*57194Smuller 	 * No entry for this gid, we will add it
277*57194Smuller 	 */
278*57194Smuller 	if (!gropn) {
279*57194Smuller 		setgroupent(1);
280*57194Smuller 		++gropn;
281*57194Smuller 	}
282*57194Smuller 	if (ptr == NULL)
283*57194Smuller 		ptr = (GIDC *)malloc(sizeof(GIDC));
284*57194Smuller 
285*57194Smuller 	if ((gr = getgrgid(gid)) == NULL) {
286*57194Smuller 		/*
287*57194Smuller 		 * no match for this gid in the local group file, put in
288*57194Smuller 		 * a string that is the gid in numberic format
289*57194Smuller 		 */
290*57194Smuller 		if (ptr == NULL)
291*57194Smuller 			return("");
292*57194Smuller 		ptr->gid = gid;
293*57194Smuller 		ptr->valid = INVALID;
294*57194Smuller #		ifdef NET2_STAT
295*57194Smuller 		(void)sprintf(ptr->name, "%u", gid);
296*57194Smuller #		else
297*57194Smuller 		(void)sprintf(ptr->name, "%lu", gid);
298*57194Smuller #		endif
299*57194Smuller 		if (frc == 0)
300*57194Smuller 			return("");
301*57194Smuller 	} else {
302*57194Smuller 		/*
303*57194Smuller 		 * there is an entry for this group in the group file
304*57194Smuller 		 */
305*57194Smuller 		if (ptr == NULL)
306*57194Smuller 			return(gr->gr_name);
307*57194Smuller 		ptr->gid = gid;
308*57194Smuller 		(void)strncpy(ptr->name, gr->gr_name, GNMLEN);
309*57194Smuller 		ptr->name[GNMLEN-1] = '\0';
310*57194Smuller 		ptr->valid = VALID;
311*57194Smuller 	}
312*57194Smuller 	return(ptr->name);
313*57194Smuller }
314*57194Smuller 
315*57194Smuller /*
316*57194Smuller  * uid_name()
317*57194Smuller  *	caches the uid for a given user name. We use a simple hash table.
318*57194Smuller  * Return
319*57194Smuller  *	the uid (if any) for a user name, or a -1 if no match can be found
320*57194Smuller  */
321*57194Smuller 
322*57194Smuller #if __STDC__
323*57194Smuller int
324*57194Smuller uid_name(char *name, uid_t *uid)
325*57194Smuller #else
326*57194Smuller int
327*57194Smuller uid_name(name, uid)
328*57194Smuller 	char *name;
329*57194Smuller 	uid_t *uid;
330*57194Smuller #endif
331*57194Smuller {
332*57194Smuller 	register struct passwd *pw;
333*57194Smuller 	register UIDC *ptr;
334*57194Smuller 	register int namelen;
335*57194Smuller 
336*57194Smuller 	/*
337*57194Smuller 	 * return -1 for mangled names
338*57194Smuller 	 */
339*57194Smuller 	if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
340*57194Smuller 		return(-1);
341*57194Smuller 	if ((usrtb == NULL) && (usrtb_start() < 0))
342*57194Smuller 		return(-1);
343*57194Smuller 
344*57194Smuller 	/*
345*57194Smuller 	 * look up in hash table, if found and valid return the uid,
346*57194Smuller 	 * if found and invalid, return a -1
347*57194Smuller 	 */
348*57194Smuller 	ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
349*57194Smuller 	if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
350*57194Smuller 		if (ptr->valid == INVALID)
351*57194Smuller 			return(-1);
352*57194Smuller 		*uid = ptr->uid;
353*57194Smuller 		return(0);
354*57194Smuller 	}
355*57194Smuller 
356*57194Smuller 	if (!pwopn) {
357*57194Smuller 		setpassent(1);
358*57194Smuller 		++pwopn;
359*57194Smuller 	}
360*57194Smuller 
361*57194Smuller 	if (ptr == NULL)
362*57194Smuller 		ptr = (UIDC *)malloc(sizeof(UIDC));
363*57194Smuller 
364*57194Smuller 	/*
365*57194Smuller 	 * no match, look it up, if no match store it as an invalid entry,
366*57194Smuller 	 * or store the matching uid
367*57194Smuller 	 */
368*57194Smuller 	if (ptr == NULL) {
369*57194Smuller 		if ((pw = getpwnam(name)) == NULL)
370*57194Smuller 			return(-1);
371*57194Smuller 		*uid = pw->pw_uid;
372*57194Smuller 		return(0);
373*57194Smuller 	}
374*57194Smuller 	(void)strncpy(ptr->name, name, UNMLEN);
375*57194Smuller 	ptr->name[UNMLEN-1] = '\0';
376*57194Smuller 	if ((pw = getpwnam(name)) == NULL) {
377*57194Smuller 		ptr->valid = INVALID;
378*57194Smuller 		return(-1);
379*57194Smuller 	}
380*57194Smuller 	ptr->valid = VALID;
381*57194Smuller 	*uid = ptr->uid = pw->pw_uid;
382*57194Smuller 	return(0);
383*57194Smuller }
384*57194Smuller 
385*57194Smuller /*
386*57194Smuller  * gid_name()
387*57194Smuller  *	caches the gid for a given group name. We use a simple hash table.
388*57194Smuller  * Return
389*57194Smuller  *	the gid (if any) for a group name, or a -1 if no match can be found
390*57194Smuller  */
391*57194Smuller 
392*57194Smuller #if __STDC__
393*57194Smuller int
394*57194Smuller gid_name(char *name, gid_t *gid)
395*57194Smuller #else
396*57194Smuller int
397*57194Smuller gid_name(name, gid)
398*57194Smuller 	char *name;
399*57194Smuller 	gid_t *gid;
400*57194Smuller #endif
401*57194Smuller {
402*57194Smuller 	register struct group *gr;
403*57194Smuller 	register GIDC *ptr;
404*57194Smuller 	register int namelen;
405*57194Smuller 
406*57194Smuller 	/*
407*57194Smuller 	 * return -1 for mangled names
408*57194Smuller 	 */
409*57194Smuller 	if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
410*57194Smuller 		return(-1);
411*57194Smuller 	if ((grptb == NULL) && (grptb_start() < 0))
412*57194Smuller 		return(-1);
413*57194Smuller 
414*57194Smuller 	/*
415*57194Smuller 	 * look up in hash table, if found and valid return the uid,
416*57194Smuller 	 * if found and invalid, return a -1
417*57194Smuller 	 */
418*57194Smuller 	ptr = grptb[st_hash(name, namelen, GID_SZ)];
419*57194Smuller 	if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
420*57194Smuller 		if (ptr->valid == INVALID)
421*57194Smuller 			return(-1);
422*57194Smuller 		*gid = ptr->gid;
423*57194Smuller 		return(0);
424*57194Smuller 	}
425*57194Smuller 
426*57194Smuller 	if (!gropn) {
427*57194Smuller 		setgroupent(1);
428*57194Smuller 		++pwopn;
429*57194Smuller 	}
430*57194Smuller 	if (ptr == NULL)
431*57194Smuller 		ptr = (GIDC *)malloc(sizeof(GIDC));
432*57194Smuller 
433*57194Smuller 	/*
434*57194Smuller 	 * no match, look it up, if no match store it as an invalid entry,
435*57194Smuller 	 * or store the matching gid
436*57194Smuller 	 */
437*57194Smuller 	if (ptr == NULL) {
438*57194Smuller 		if ((gr = getgrnam(name)) == NULL)
439*57194Smuller 			return(-1);
440*57194Smuller 		*gid = gr->gr_gid;
441*57194Smuller 		return(0);
442*57194Smuller 	}
443*57194Smuller 
444*57194Smuller 	(void)strncpy(ptr->name, name, GNMLEN);
445*57194Smuller 	ptr->name[GNMLEN-1] = '\0';
446*57194Smuller 	if ((gr = getgrnam(name)) == NULL) {
447*57194Smuller 		ptr->valid = INVALID;
448*57194Smuller 		return(-1);
449*57194Smuller 	}
450*57194Smuller 	ptr->valid = VALID;
451*57194Smuller 	*gid = ptr->gid = gr->gr_gid;
452*57194Smuller 	return(0);
453*57194Smuller }
454