157194Smuller /*-
257194Smuller * Copyright (c) 1992 Keith Muller.
3*60676Sbostic * Copyright (c) 1992, 1993
4*60676Sbostic * The Regents of the University of California. All rights reserved.
557194Smuller *
657194Smuller * This code is derived from software contributed to Berkeley by
757194Smuller * Keith Muller of the University of California, San Diego.
857194Smuller *
957194Smuller * %sccs.include.redist.c%
1057194Smuller */
1157194Smuller
1257194Smuller #ifndef lint
13*60676Sbostic static char sccsid[] = "@(#)cache.c 8.1 (Berkeley) 05/31/93";
1457194Smuller #endif /* not lint */
1557194Smuller
1657194Smuller #include <sys/types.h>
1757194Smuller #include <sys/time.h>
1857194Smuller #include <sys/stat.h>
1957194Smuller #include <sys/param.h>
2057194Smuller #include <string.h>
2157194Smuller #include <stdio.h>
2257194Smuller #include <ctype.h>
2357194Smuller #include <pwd.h>
2457194Smuller #include <grp.h>
2557194Smuller #include <unistd.h>
2657194Smuller #include <stdlib.h>
2757194Smuller #include "pax.h"
2857194Smuller #include "cache.h"
2957194Smuller #include "extern.h"
3057194Smuller
3157194Smuller /*
3257194Smuller * routines that control user, group, uid and gid caches (for the archive
3357194Smuller * member print routine).
3457194Smuller * IMPORTANT:
3557194Smuller * these routines cache BOTH hits and misses, a major performance improvement
3657194Smuller */
3757194Smuller
3857194Smuller static int pwopn = 0; /* is password file open */
3957194Smuller static int gropn = 0; /* is group file open */
4057194Smuller static UIDC **uidtb = NULL; /* uid to name cache */
4157194Smuller static GIDC **gidtb = NULL; /* gid to name cache */
4257194Smuller static UIDC **usrtb = NULL; /* user name to uid cache */
4357194Smuller static GIDC **grptb = NULL; /* group name to gid cache */
4457194Smuller
4557194Smuller /*
4657194Smuller * uidtb_start
4757194Smuller * creates an an empty uidtb
4857194Smuller * Return:
4957194Smuller * 0 if ok, -1 otherwise
5057194Smuller */
5157194Smuller
5257194Smuller #if __STDC__
5357194Smuller int
uidtb_start(void)5457194Smuller uidtb_start(void)
5557194Smuller #else
5657194Smuller int
5757194Smuller uidtb_start()
5857194Smuller #endif
5957194Smuller {
6057194Smuller static int fail = 0;
6157194Smuller
6257194Smuller if (uidtb != NULL)
6357194Smuller return(0);
6457194Smuller if (fail)
6557194Smuller return(-1);
6657194Smuller if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
6757194Smuller ++fail;
6857194Smuller warn(1, "Unable to allocate memory for user id cache table");
6957194Smuller return(-1);
7057194Smuller }
7157194Smuller return(0);
7257194Smuller }
7357194Smuller
7457194Smuller /*
7557194Smuller * gidtb_start
7657194Smuller * creates an an empty gidtb
7757194Smuller * Return:
7857194Smuller * 0 if ok, -1 otherwise
7957194Smuller */
8057194Smuller
8157194Smuller #if __STDC__
8257194Smuller int
gidtb_start(void)8357194Smuller gidtb_start(void)
8457194Smuller #else
8557194Smuller int
8657194Smuller gidtb_start()
8757194Smuller #endif
8857194Smuller {
8957194Smuller static int fail = 0;
9057194Smuller
9157194Smuller if (gidtb != NULL)
9257194Smuller return(0);
9357194Smuller if (fail)
9457194Smuller return(-1);
9557194Smuller if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
9657194Smuller ++fail;
9757194Smuller warn(1, "Unable to allocate memory for group id cache table");
9857194Smuller return(-1);
9957194Smuller }
10057194Smuller return(0);
10157194Smuller }
10257194Smuller
10357194Smuller /*
10457194Smuller * usrtb_start
10557194Smuller * creates an an empty usrtb
10657194Smuller * Return:
10757194Smuller * 0 if ok, -1 otherwise
10857194Smuller */
10957194Smuller
11057194Smuller #if __STDC__
11157194Smuller int
usrtb_start(void)11257194Smuller usrtb_start(void)
11357194Smuller #else
11457194Smuller int
11557194Smuller usrtb_start()
11657194Smuller #endif
11757194Smuller {
11857194Smuller static int fail = 0;
11957194Smuller
12057194Smuller if (usrtb != NULL)
12157194Smuller return(0);
12257194Smuller if (fail)
12357194Smuller return(-1);
12457194Smuller if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
12557194Smuller ++fail;
12657194Smuller warn(1, "Unable to allocate memory for user name cache table");
12757194Smuller return(-1);
12857194Smuller }
12957194Smuller return(0);
13057194Smuller }
13157194Smuller
13257194Smuller /*
13357194Smuller * grptb_start
13457194Smuller * creates an an empty grptb
13557194Smuller * Return:
13657194Smuller * 0 if ok, -1 otherwise
13757194Smuller */
13857194Smuller
13957194Smuller #if __STDC__
14057194Smuller int
grptb_start(void)14157194Smuller grptb_start(void)
14257194Smuller #else
14357194Smuller int
14457194Smuller grptb_start()
14557194Smuller #endif
14657194Smuller {
14757194Smuller static int fail = 0;
14857194Smuller
14957194Smuller if (grptb != NULL)
15057194Smuller return(0);
15157194Smuller if (fail)
15257194Smuller return(-1);
15357194Smuller if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
15457194Smuller ++fail;
15557194Smuller warn(1,"Unable to allocate memory for group name cache table");
15657194Smuller return(-1);
15757194Smuller }
15857194Smuller return(0);
15957194Smuller }
16057194Smuller
16157194Smuller /*
16257194Smuller * name_uid()
16357194Smuller * caches the name (if any) for the uid. If frc set, we always return the
16457194Smuller * the stored name (if valid or invalid match). We use a simple hash table.
16557194Smuller * Return
16657194Smuller * Pointer to stored name (or a empty string)
16757194Smuller */
16857194Smuller
16957194Smuller #if __STDC__
17057194Smuller char *
name_uid(uid_t uid,int frc)17157194Smuller name_uid(uid_t uid, int frc)
17257194Smuller #else
17357194Smuller char *
17457194Smuller name_uid(uid, frc)
17557194Smuller uid_t uid;
17657194Smuller int frc;
17757194Smuller #endif
17857194Smuller {
17957194Smuller register struct passwd *pw;
18057194Smuller register UIDC *ptr;
18157194Smuller
18257194Smuller if ((uidtb == NULL) && (uidtb_start() < 0))
18357194Smuller return("");
18457194Smuller
18557194Smuller /*
18657194Smuller * see if we have this uid cached
18757194Smuller */
18857194Smuller ptr = uidtb[uid % UID_SZ];
18957194Smuller if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
19057194Smuller /*
19157194Smuller * have an entry for this uid
19257194Smuller */
19357194Smuller if (frc || (ptr->valid == VALID))
19457194Smuller return(ptr->name);
19557194Smuller return("");
19657194Smuller }
19757194Smuller
19857194Smuller /*
19957194Smuller * No entry for this uid, we will add it
20057194Smuller */
20157194Smuller if (!pwopn) {
20257194Smuller setpassent(1);
20357194Smuller ++pwopn;
20457194Smuller }
20557194Smuller if (ptr == NULL)
20657194Smuller ptr = (UIDC *)malloc(sizeof(UIDC));
20757194Smuller
20857194Smuller if ((pw = getpwuid(uid)) == NULL) {
20957194Smuller /*
21057194Smuller * no match for this uid in the local password file
21157194Smuller * a string that is the uid in numberic format
21257194Smuller */
21357194Smuller if (ptr == NULL)
21457194Smuller return("");
21557194Smuller ptr->uid = uid;
21657194Smuller ptr->valid = INVALID;
21757194Smuller # ifdef NET2_STAT
21857194Smuller (void)sprintf(ptr->name, "%u", uid);
21957194Smuller # else
22057194Smuller (void)sprintf(ptr->name, "%lu", uid);
22157194Smuller # endif
22257194Smuller if (frc == 0)
22357194Smuller return("");
22457194Smuller } else {
22557194Smuller /*
22657194Smuller * there is an entry for this uid in the password file
22757194Smuller */
22857194Smuller if (ptr == NULL)
22957194Smuller return(pw->pw_name);
23057194Smuller ptr->uid = uid;
23157194Smuller (void)strncpy(ptr->name, pw->pw_name, UNMLEN);
23257194Smuller ptr->name[UNMLEN-1] = '\0';
23357194Smuller ptr->valid = VALID;
23457194Smuller }
23557194Smuller return(ptr->name);
23657194Smuller }
23757194Smuller
23857194Smuller /*
23957194Smuller * name_gid()
24057194Smuller * caches the name (if any) for the gid. If frc set, we always return the
24157194Smuller * the stored name (if valid or invalid match). We use a simple hash table.
24257194Smuller * Return
24357194Smuller * Pointer to stored name (or a empty string)
24457194Smuller */
24557194Smuller
24657194Smuller #if __STDC__
24757194Smuller char *
name_gid(gid_t gid,int frc)24857194Smuller name_gid(gid_t gid, int frc)
24957194Smuller #else
25057194Smuller char *
25157194Smuller name_gid(gid, frc)
25257194Smuller gid_t gid;
25357194Smuller int frc;
25457194Smuller #endif
25557194Smuller {
25657194Smuller register struct group *gr;
25757194Smuller register GIDC *ptr;
25857194Smuller
25957194Smuller if ((gidtb == NULL) && (gidtb_start() < 0))
26057194Smuller return("");
26157194Smuller
26257194Smuller /*
26357194Smuller * see if we have this gid cached
26457194Smuller */
26557194Smuller ptr = gidtb[gid % GID_SZ];
26657194Smuller if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
26757194Smuller /*
26857194Smuller * have an entry for this gid
26957194Smuller */
27057194Smuller if (frc || (ptr->valid == VALID))
27157194Smuller return(ptr->name);
27257194Smuller return("");
27357194Smuller }
27457194Smuller
27557194Smuller /*
27657194Smuller * No entry for this gid, we will add it
27757194Smuller */
27857194Smuller if (!gropn) {
27957194Smuller setgroupent(1);
28057194Smuller ++gropn;
28157194Smuller }
28257194Smuller if (ptr == NULL)
28357194Smuller ptr = (GIDC *)malloc(sizeof(GIDC));
28457194Smuller
28557194Smuller if ((gr = getgrgid(gid)) == NULL) {
28657194Smuller /*
28757194Smuller * no match for this gid in the local group file, put in
28857194Smuller * a string that is the gid in numberic format
28957194Smuller */
29057194Smuller if (ptr == NULL)
29157194Smuller return("");
29257194Smuller ptr->gid = gid;
29357194Smuller ptr->valid = INVALID;
29457194Smuller # ifdef NET2_STAT
29557194Smuller (void)sprintf(ptr->name, "%u", gid);
29657194Smuller # else
29757194Smuller (void)sprintf(ptr->name, "%lu", gid);
29857194Smuller # endif
29957194Smuller if (frc == 0)
30057194Smuller return("");
30157194Smuller } else {
30257194Smuller /*
30357194Smuller * there is an entry for this group in the group file
30457194Smuller */
30557194Smuller if (ptr == NULL)
30657194Smuller return(gr->gr_name);
30757194Smuller ptr->gid = gid;
30857194Smuller (void)strncpy(ptr->name, gr->gr_name, GNMLEN);
30957194Smuller ptr->name[GNMLEN-1] = '\0';
31057194Smuller ptr->valid = VALID;
31157194Smuller }
31257194Smuller return(ptr->name);
31357194Smuller }
31457194Smuller
31557194Smuller /*
31657194Smuller * uid_name()
31757194Smuller * caches the uid for a given user name. We use a simple hash table.
31857194Smuller * Return
31957194Smuller * the uid (if any) for a user name, or a -1 if no match can be found
32057194Smuller */
32157194Smuller
32257194Smuller #if __STDC__
32357194Smuller int
uid_name(char * name,uid_t * uid)32457194Smuller uid_name(char *name, uid_t *uid)
32557194Smuller #else
32657194Smuller int
32757194Smuller uid_name(name, uid)
32857194Smuller char *name;
32957194Smuller uid_t *uid;
33057194Smuller #endif
33157194Smuller {
33257194Smuller register struct passwd *pw;
33357194Smuller register UIDC *ptr;
33457194Smuller register int namelen;
33557194Smuller
33657194Smuller /*
33757194Smuller * return -1 for mangled names
33857194Smuller */
33957194Smuller if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
34057194Smuller return(-1);
34157194Smuller if ((usrtb == NULL) && (usrtb_start() < 0))
34257194Smuller return(-1);
34357194Smuller
34457194Smuller /*
34557194Smuller * look up in hash table, if found and valid return the uid,
34657194Smuller * if found and invalid, return a -1
34757194Smuller */
34857194Smuller ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
34957194Smuller if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
35057194Smuller if (ptr->valid == INVALID)
35157194Smuller return(-1);
35257194Smuller *uid = ptr->uid;
35357194Smuller return(0);
35457194Smuller }
35557194Smuller
35657194Smuller if (!pwopn) {
35757194Smuller setpassent(1);
35857194Smuller ++pwopn;
35957194Smuller }
36057194Smuller
36157194Smuller if (ptr == NULL)
36257194Smuller ptr = (UIDC *)malloc(sizeof(UIDC));
36357194Smuller
36457194Smuller /*
36557194Smuller * no match, look it up, if no match store it as an invalid entry,
36657194Smuller * or store the matching uid
36757194Smuller */
36857194Smuller if (ptr == NULL) {
36957194Smuller if ((pw = getpwnam(name)) == NULL)
37057194Smuller return(-1);
37157194Smuller *uid = pw->pw_uid;
37257194Smuller return(0);
37357194Smuller }
37457194Smuller (void)strncpy(ptr->name, name, UNMLEN);
37557194Smuller ptr->name[UNMLEN-1] = '\0';
37657194Smuller if ((pw = getpwnam(name)) == NULL) {
37757194Smuller ptr->valid = INVALID;
37857194Smuller return(-1);
37957194Smuller }
38057194Smuller ptr->valid = VALID;
38157194Smuller *uid = ptr->uid = pw->pw_uid;
38257194Smuller return(0);
38357194Smuller }
38457194Smuller
38557194Smuller /*
38657194Smuller * gid_name()
38757194Smuller * caches the gid for a given group name. We use a simple hash table.
38857194Smuller * Return
38957194Smuller * the gid (if any) for a group name, or a -1 if no match can be found
39057194Smuller */
39157194Smuller
39257194Smuller #if __STDC__
39357194Smuller int
gid_name(char * name,gid_t * gid)39457194Smuller gid_name(char *name, gid_t *gid)
39557194Smuller #else
39657194Smuller int
39757194Smuller gid_name(name, gid)
39857194Smuller char *name;
39957194Smuller gid_t *gid;
40057194Smuller #endif
40157194Smuller {
40257194Smuller register struct group *gr;
40357194Smuller register GIDC *ptr;
40457194Smuller register int namelen;
40557194Smuller
40657194Smuller /*
40757194Smuller * return -1 for mangled names
40857194Smuller */
40957194Smuller if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
41057194Smuller return(-1);
41157194Smuller if ((grptb == NULL) && (grptb_start() < 0))
41257194Smuller return(-1);
41357194Smuller
41457194Smuller /*
41557194Smuller * look up in hash table, if found and valid return the uid,
41657194Smuller * if found and invalid, return a -1
41757194Smuller */
41857194Smuller ptr = grptb[st_hash(name, namelen, GID_SZ)];
41957194Smuller if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
42057194Smuller if (ptr->valid == INVALID)
42157194Smuller return(-1);
42257194Smuller *gid = ptr->gid;
42357194Smuller return(0);
42457194Smuller }
42557194Smuller
42657194Smuller if (!gropn) {
42757194Smuller setgroupent(1);
42857573Smuller ++gropn;
42957194Smuller }
43057194Smuller if (ptr == NULL)
43157194Smuller ptr = (GIDC *)malloc(sizeof(GIDC));
43257194Smuller
43357194Smuller /*
43457194Smuller * no match, look it up, if no match store it as an invalid entry,
43557194Smuller * or store the matching gid
43657194Smuller */
43757194Smuller if (ptr == NULL) {
43857194Smuller if ((gr = getgrnam(name)) == NULL)
43957194Smuller return(-1);
44057194Smuller *gid = gr->gr_gid;
44157194Smuller return(0);
44257194Smuller }
44357194Smuller
44457194Smuller (void)strncpy(ptr->name, name, GNMLEN);
44557194Smuller ptr->name[GNMLEN-1] = '\0';
44657194Smuller if ((gr = getgrnam(name)) == NULL) {
44757194Smuller ptr->valid = INVALID;
44857194Smuller return(-1);
44957194Smuller }
45057194Smuller ptr->valid = VALID;
45157194Smuller *gid = ptr->gid = gr->gr_gid;
45257194Smuller return(0);
45357194Smuller }
454