cache.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1992 Keith Muller.
00003  * Copyright (c) 1992, 1993
00004  *      The Regents of the University of California.  All rights reserved.
00005  *
00006  * This code is derived from software contributed to Berkeley by
00007  * Keith Muller of the University of California, San Diego.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 #ifndef lint
00035 #if 0
00036 static char sccsid[] = "@(#)cache.c     8.1 (Berkeley) 5/31/93";
00037 #endif
00038 #endif /* not lint */
00039 
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #include <string.h>
00043 #include <stdio.h>
00044 #include <pwd.h>
00045 #include <grp.h>
00046 #include <unistd.h>
00047 #include <stdlib.h>
00048 #include "pax.h"
00049 #include "cache.h"
00050 #include "extern.h"
00051 
00052 /*
00053  * routines that control user, group, uid and gid caches (for the archive
00054  * member print routine).
00055  * IMPORTANT:
00056  * these routines cache BOTH hits and misses, a major performance improvement
00057  */
00058 
00059 static  int pwopn = 0;          /* is password file open */
00060 static  int gropn = 0;          /* is group file open */
00061 static UIDC **uidtb = NULL;     /* uid to name cache */
00062 static GIDC **gidtb = NULL;     /* gid to name cache */
00063 static UIDC **usrtb = NULL;     /* user name to uid cache */
00064 static GIDC **grptb = NULL;     /* group name to gid cache */
00065 
00066 /*
00067  * uidtb_start
00068  *      creates an an empty uidtb
00069  * Return:
00070  *      0 if ok, -1 otherwise
00071  */
00072 
00073 int
00074 uidtb_start(void)
00075 {
00076         static int fail = 0;
00077 
00078         if (uidtb != NULL)
00079                 return(0);
00080         if (fail)
00081                 return(-1);
00082         if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
00083                 ++fail;
00084                 paxwarn(1, "Unable to allocate memory for user id cache table");
00085                 return(-1);
00086         }
00087         return(0);
00088 }
00089 
00090 /*
00091  * gidtb_start
00092  *      creates an an empty gidtb
00093  * Return:
00094  *      0 if ok, -1 otherwise
00095  */
00096 
00097 int
00098 gidtb_start(void)
00099 {
00100         static int fail = 0;
00101 
00102         if (gidtb != NULL)
00103                 return(0);
00104         if (fail)
00105                 return(-1);
00106         if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
00107                 ++fail;
00108                 paxwarn(1, "Unable to allocate memory for group id cache table");
00109                 return(-1);
00110         }
00111         return(0);
00112 }
00113 
00114 /*
00115  * usrtb_start
00116  *      creates an an empty usrtb
00117  * Return:
00118  *      0 if ok, -1 otherwise
00119  */
00120 
00121 int
00122 usrtb_start(void)
00123 {
00124         static int fail = 0;
00125 
00126         if (usrtb != NULL)
00127                 return(0);
00128         if (fail)
00129                 return(-1);
00130         if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
00131                 ++fail;
00132                 paxwarn(1, "Unable to allocate memory for user name cache table");
00133                 return(-1);
00134         }
00135         return(0);
00136 }
00137 
00138 /*
00139  * grptb_start
00140  *      creates an an empty grptb
00141  * Return:
00142  *      0 if ok, -1 otherwise
00143  */
00144 
00145 int
00146 grptb_start(void)
00147 {
00148         static int fail = 0;
00149 
00150         if (grptb != NULL)
00151                 return(0);
00152         if (fail)
00153                 return(-1);
00154         if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
00155                 ++fail;
00156                 paxwarn(1,"Unable to allocate memory for group name cache table");
00157                 return(-1);
00158         }
00159         return(0);
00160 }
00161 
00162 /*
00163  * name_uid()
00164  *      caches the name (if any) for the uid. If frc set, we always return the
00165  *      the stored name (if valid or invalid match). We use a simple hash table.
00166  * Return
00167  *      Pointer to stored name (or an empty string).
00168  */
00169 
00170 const char *
00171 name_uid(uid_t uid, int frc)
00172 {
00173         struct passwd *pw;
00174         UIDC *ptr;
00175 
00176         if ((uidtb == NULL) && (uidtb_start() < 0))
00177                 return("");
00178 
00179         /*
00180          * see if we have this uid cached
00181          */
00182         ptr = uidtb[uid % UID_SZ];
00183         if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
00184                 /*
00185                  * have an entry for this uid
00186                  */
00187                 if (frc || (ptr->valid == VALID))
00188                         return(ptr->name);
00189                 return("");
00190         }
00191 
00192         /*
00193          * No entry for this uid, we will add it
00194          */
00195         if (!pwopn) {
00196                 setpassent(1);
00197                 ++pwopn;
00198         }
00199         if (ptr == NULL)
00200                 ptr = uidtb[uid % UID_SZ] = (UIDC *)malloc(sizeof(UIDC));
00201 
00202         if ((pw = getpwuid(uid)) == NULL) {
00203                 /*
00204                  * no match for this uid in the local password file
00205                  * a string that is the uid in numeric format
00206                  */
00207                 if (ptr == NULL)
00208                         return("");
00209                 ptr->uid = uid;
00210                 ptr->valid = INVALID;
00211 #               ifdef NET2_STAT
00212                 (void)snprintf(ptr->name, sizeof(ptr->name), "%u", uid);
00213 #               else
00214                 (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
00215                                (unsigned long)uid);
00216 #               endif
00217                 if (frc == 0)
00218                         return("");
00219         } else {
00220                 /*
00221                  * there is an entry for this uid in the password file
00222                  */
00223                 if (ptr == NULL)
00224                         return(pw->pw_name);
00225                 ptr->uid = uid;
00226                 (void)strncpy(ptr->name, pw->pw_name, UNMLEN - 1);
00227                 ptr->name[UNMLEN-1] = '\0';
00228                 ptr->valid = VALID;
00229         }
00230         return(ptr->name);
00231 }
00232 
00233 /*
00234  * name_gid()
00235  *      caches the name (if any) for the gid. If frc set, we always return the
00236  *      the stored name (if valid or invalid match). We use a simple hash table.
00237  * Return
00238  *      Pointer to stored name (or an empty string).
00239  */
00240 
00241 const char *
00242 name_gid(gid_t gid, int frc)
00243 {
00244         struct group *gr;
00245         GIDC *ptr;
00246 
00247         if ((gidtb == NULL) && (gidtb_start() < 0))
00248                 return("");
00249 
00250         /*
00251          * see if we have this gid cached
00252          */
00253         ptr = gidtb[gid % GID_SZ];
00254         if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
00255                 /*
00256                  * have an entry for this gid
00257                  */
00258                 if (frc || (ptr->valid == VALID))
00259                         return(ptr->name);
00260                 return("");
00261         }
00262 
00263         /*
00264          * No entry for this gid, we will add it
00265          */
00266         if (!gropn) {
00267                 setgroupent(1);
00268                 ++gropn;
00269         }
00270         if (ptr == NULL)
00271                 ptr = gidtb[gid % GID_SZ] = (GIDC *)malloc(sizeof(GIDC));
00272 
00273         if ((gr = getgrgid(gid)) == NULL) {
00274                 /*
00275                  * no match for this gid in the local group file, put in
00276                  * a string that is the gid in numeric format
00277                  */
00278                 if (ptr == NULL)
00279                         return("");
00280                 ptr->gid = gid;
00281                 ptr->valid = INVALID;
00282 #               ifdef NET2_STAT
00283                 (void)snprintf(ptr->name, sizeof(ptr->name), "%u", gid);
00284 #               else
00285                 (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
00286                                (unsigned long)gid);
00287 #               endif
00288                 if (frc == 0)
00289                         return("");
00290         } else {
00291                 /*
00292                  * there is an entry for this group in the group file
00293                  */
00294                 if (ptr == NULL)
00295                         return(gr->gr_name);
00296                 ptr->gid = gid;
00297                 (void)strncpy(ptr->name, gr->gr_name, GNMLEN - 1);
00298                 ptr->name[GNMLEN-1] = '\0';
00299                 ptr->valid = VALID;
00300         }
00301         return(ptr->name);
00302 }
00303 
00304 /*
00305  * uid_name()
00306  *      caches the uid for a given user name. We use a simple hash table.
00307  * Return
00308  *      the uid (if any) for a user name, or a -1 if no match can be found
00309  */
00310 
00311 int
00312 uid_name(char *name, uid_t *uid)
00313 {
00314         struct passwd *pw;
00315         UIDC *ptr;
00316         int namelen;
00317 
00318         /*
00319          * return -1 for mangled names
00320          */
00321         if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
00322                 return(-1);
00323         if ((usrtb == NULL) && (usrtb_start() < 0))
00324                 return(-1);
00325 
00326         /*
00327          * look up in hash table, if found and valid return the uid,
00328          * if found and invalid, return a -1
00329          */
00330         ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
00331         if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
00332                 if (ptr->valid == INVALID)
00333                         return(-1);
00334                 *uid = ptr->uid;
00335                 return(0);
00336         }
00337 
00338         if (!pwopn) {
00339                 setpassent(1);
00340                 ++pwopn;
00341         }
00342 
00343         if (ptr == NULL)
00344                 ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
00345                   (UIDC *)malloc(sizeof(UIDC));
00346 
00347         /*
00348          * no match, look it up, if no match store it as an invalid entry,
00349          * or store the matching uid
00350          */
00351         if (ptr == NULL) {
00352                 if ((pw = getpwnam(name)) == NULL)
00353                         return(-1);
00354                 *uid = pw->pw_uid;
00355                 return(0);
00356         }
00357         (void)strncpy(ptr->name, name, UNMLEN - 1);
00358         ptr->name[UNMLEN-1] = '\0';
00359         if ((pw = getpwnam(name)) == NULL) {
00360                 ptr->valid = INVALID;
00361                 return(-1);
00362         }
00363         ptr->valid = VALID;
00364         *uid = ptr->uid = pw->pw_uid;
00365         return(0);
00366 }
00367 
00368 /*
00369  * gid_name()
00370  *      caches the gid for a given group name. We use a simple hash table.
00371  * Return
00372  *      the gid (if any) for a group name, or a -1 if no match can be found
00373  */
00374 
00375 int
00376 gid_name(char *name, gid_t *gid)
00377 {
00378         struct group *gr;
00379         GIDC *ptr;
00380         int namelen;
00381 
00382         /*
00383          * return -1 for mangled names
00384          */
00385         if (((namelen = strlen(name)) == 0) || (name[0] == '\0'))
00386                 return(-1);
00387         if ((grptb == NULL) && (grptb_start() < 0))
00388                 return(-1);
00389 
00390         /*
00391          * look up in hash table, if found and valid return the uid,
00392          * if found and invalid, return a -1
00393          */
00394         ptr = grptb[st_hash(name, namelen, GID_SZ)];
00395         if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
00396                 if (ptr->valid == INVALID)
00397                         return(-1);
00398                 *gid = ptr->gid;
00399                 return(0);
00400         }
00401 
00402         if (!gropn) {
00403                 setgroupent(1);
00404                 ++gropn;
00405         }
00406         if (ptr == NULL)
00407                 ptr = grptb[st_hash(name, namelen, GID_SZ)] =
00408                   (GIDC *)malloc(sizeof(GIDC));
00409 
00410         /*
00411          * no match, look it up, if no match store it as an invalid entry,
00412          * or store the matching gid
00413          */
00414         if (ptr == NULL) {
00415                 if ((gr = getgrnam(name)) == NULL)
00416                         return(-1);
00417                 *gid = gr->gr_gid;
00418                 return(0);
00419         }
00420 
00421         (void)strncpy(ptr->name, name, GNMLEN - 1);
00422         ptr->name[GNMLEN-1] = '\0';
00423         if ((gr = getgrnam(name)) == NULL) {
00424                 ptr->valid = INVALID;
00425                 return(-1);
00426         }
00427         ptr->valid = VALID;
00428         *gid = ptr->gid = gr->gr_gid;
00429         return(0);
00430 }

Generated on Fri Apr 14 22:57:01 2006 for minix by  doxygen 1.4.6