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