2 * Copyright (c) 1992 Keith Muller.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 static char sccsid
[] = "@(#)cache.c 8.1 (Berkeley) 5/31/93";
40 #include <sys/types.h>
53 * routines that control user, group, uid and gid caches (for the archive
54 * member print routine).
56 * these routines cache BOTH hits and misses, a major performance improvement
59 static int pwopn
= 0; /* is password file open */
60 static int gropn
= 0; /* is group file open */
61 static UIDC
**uidtb
= NULL
; /* uid to name cache */
62 static GIDC
**gidtb
= NULL
; /* gid to name cache */
63 static UIDC
**usrtb
= NULL
; /* user name to uid cache */
64 static GIDC
**grptb
= NULL
; /* group name to gid cache */
68 * creates an an empty uidtb
70 * 0 if ok, -1 otherwise
82 if ((uidtb
= (UIDC
**)calloc(UID_SZ
, sizeof(UIDC
*))) == NULL
) {
84 paxwarn(1, "Unable to allocate memory for user id cache table");
92 * creates an an empty gidtb
94 * 0 if ok, -1 otherwise
106 if ((gidtb
= (GIDC
**)calloc(GID_SZ
, sizeof(GIDC
*))) == NULL
) {
108 paxwarn(1, "Unable to allocate memory for group id cache table");
116 * creates an an empty usrtb
118 * 0 if ok, -1 otherwise
130 if ((usrtb
= (UIDC
**)calloc(UNM_SZ
, sizeof(UIDC
*))) == NULL
) {
132 paxwarn(1, "Unable to allocate memory for user name cache table");
140 * creates an an empty grptb
142 * 0 if ok, -1 otherwise
154 if ((grptb
= (GIDC
**)calloc(GNM_SZ
, sizeof(GIDC
*))) == NULL
) {
156 paxwarn(1,"Unable to allocate memory for group name cache table");
164 * caches the name (if any) for the uid. If frc set, we always return the
165 * the stored name (if valid or invalid match). We use a simple hash table.
167 * Pointer to stored name (or an empty string).
171 name_uid(uid_t uid
, int frc
)
176 if ((uidtb
== NULL
) && (uidtb_start() < 0))
180 * see if we have this uid cached
182 ptr
= uidtb
[uid
% UID_SZ
];
183 if ((ptr
!= NULL
) && (ptr
->valid
> 0) && (ptr
->uid
== uid
)) {
185 * have an entry for this uid
187 if (frc
|| (ptr
->valid
== VALID
))
193 * No entry for this uid, we will add it
200 ptr
= uidtb
[uid
% UID_SZ
] = (UIDC
*)malloc(sizeof(UIDC
));
202 if ((pw
= getpwuid(uid
)) == NULL
) {
204 * no match for this uid in the local password file
205 * a string that is the uid in numeric format
210 ptr
->valid
= INVALID
;
212 (void)snprintf(ptr
->name
, sizeof(ptr
->name
), "%u", uid
);
214 (void)snprintf(ptr
->name
, sizeof(ptr
->name
), "%lu",
221 * there is an entry for this uid in the password file
226 (void)strncpy(ptr
->name
, pw
->pw_name
, UNMLEN
- 1);
227 ptr
->name
[UNMLEN
-1] = '\0';
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.
238 * Pointer to stored name (or an empty string).
242 name_gid(gid_t gid
, int frc
)
247 if ((gidtb
== NULL
) && (gidtb_start() < 0))
251 * see if we have this gid cached
253 ptr
= gidtb
[gid
% GID_SZ
];
254 if ((ptr
!= NULL
) && (ptr
->valid
> 0) && (ptr
->gid
== gid
)) {
256 * have an entry for this gid
258 if (frc
|| (ptr
->valid
== VALID
))
264 * No entry for this gid, we will add it
271 ptr
= gidtb
[gid
% GID_SZ
] = (GIDC
*)malloc(sizeof(GIDC
));
273 if ((gr
= getgrgid(gid
)) == NULL
) {
275 * no match for this gid in the local group file, put in
276 * a string that is the gid in numeric format
281 ptr
->valid
= INVALID
;
283 (void)snprintf(ptr
->name
, sizeof(ptr
->name
), "%u", gid
);
285 (void)snprintf(ptr
->name
, sizeof(ptr
->name
), "%lu",
292 * there is an entry for this group in the group file
297 (void)strncpy(ptr
->name
, gr
->gr_name
, GNMLEN
- 1);
298 ptr
->name
[GNMLEN
-1] = '\0';
306 * caches the uid for a given user name. We use a simple hash table.
308 * the uid (if any) for a user name, or a -1 if no match can be found
312 uid_name(char *name
, uid_t
*uid
)
319 * return -1 for mangled names
321 if (((namelen
= strlen(name
)) == 0) || (name
[0] == '\0'))
323 if ((usrtb
== NULL
) && (usrtb_start() < 0))
327 * look up in hash table, if found and valid return the uid,
328 * if found and invalid, return a -1
330 ptr
= usrtb
[st_hash(name
, namelen
, UNM_SZ
)];
331 if ((ptr
!= NULL
) && (ptr
->valid
> 0) && !strcmp(name
, ptr
->name
)) {
332 if (ptr
->valid
== INVALID
)
344 ptr
= usrtb
[st_hash(name
, namelen
, UNM_SZ
)] =
345 (UIDC
*)malloc(sizeof(UIDC
));
348 * no match, look it up, if no match store it as an invalid entry,
349 * or store the matching uid
352 if ((pw
= getpwnam(name
)) == NULL
)
357 (void)strncpy(ptr
->name
, name
, UNMLEN
- 1);
358 ptr
->name
[UNMLEN
-1] = '\0';
359 if ((pw
= getpwnam(name
)) == NULL
) {
360 ptr
->valid
= INVALID
;
364 *uid
= ptr
->uid
= pw
->pw_uid
;
370 * caches the gid for a given group name. We use a simple hash table.
372 * the gid (if any) for a group name, or a -1 if no match can be found
376 gid_name(char *name
, gid_t
*gid
)
383 * return -1 for mangled names
385 if (((namelen
= strlen(name
)) == 0) || (name
[0] == '\0'))
387 if ((grptb
== NULL
) && (grptb_start() < 0))
391 * look up in hash table, if found and valid return the uid,
392 * if found and invalid, return a -1
394 ptr
= grptb
[st_hash(name
, namelen
, GID_SZ
)];
395 if ((ptr
!= NULL
) && (ptr
->valid
> 0) && !strcmp(name
, ptr
->name
)) {
396 if (ptr
->valid
== INVALID
)
407 ptr
= grptb
[st_hash(name
, namelen
, GID_SZ
)] =
408 (GIDC
*)malloc(sizeof(GIDC
));
411 * no match, look it up, if no match store it as an invalid entry,
412 * or store the matching gid
415 if ((gr
= getgrnam(name
)) == NULL
)
421 (void)strncpy(ptr
->name
, name
, GNMLEN
- 1);
422 ptr
->name
[GNMLEN
-1] = '\0';
423 if ((gr
= getgrnam(name
)) == NULL
) {
424 ptr
->valid
= INVALID
;
428 *gid
= ptr
->gid
= gr
->gr_gid
;