Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.bin/cap_mkdb/cap_mkdb.c
34677 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1992, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. Neither the name of the University nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*/
31
32
#include <sys/param.h>
33
#include <sys/stat.h>
34
35
#include <db.h>
36
#include <err.h>
37
#include <fcntl.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
43
static void db_build(char **);
44
static void dounlink(void);
45
static void usage(void);
46
47
static DB *capdbp;
48
static int verbose;
49
static char *capname, buf[8 * 1024];
50
51
static HASHINFO openinfo = {
52
4096, /* bsize */
53
0, /* ffactor */
54
0, /* nelem */
55
0, /* cachesize */
56
NULL, /* hash() */
57
0 /* lorder */
58
};
59
60
/*
61
* Mkcapdb creates a capability hash database for quick retrieval of capability
62
* records. The database contains 2 types of entries: records and references
63
* marked by the first byte in the data. A record entry contains the actual
64
* capability record whereas a reference contains the name (key) under which
65
* the correct record is stored.
66
*/
67
int
68
main(int argc, char *argv[])
69
{
70
int byteorder, c;
71
72
capname = NULL;
73
byteorder = 0;
74
while ((c = getopt(argc, argv, "bf:lv")) != -1) {
75
switch(c) {
76
case 'b':
77
case 'l':
78
if (byteorder != 0)
79
usage();
80
byteorder = c == 'b' ? 4321 : 1234;
81
break;
82
case 'f':
83
capname = optarg;
84
break;
85
case 'v':
86
verbose = 1;
87
break;
88
case '?':
89
default:
90
usage();
91
}
92
}
93
argc -= optind;
94
argv += optind;
95
96
if (*argv == NULL)
97
usage();
98
99
/* Set byte order. */
100
openinfo.lorder = byteorder;
101
102
/*
103
* The database file is the first argument if no name is specified.
104
* Make arrangements to unlink it if exit badly.
105
*/
106
(void)snprintf(buf, sizeof(buf), "%s.db", capname ? capname : *argv);
107
if ((capname = strdup(buf)) == NULL)
108
errx(1, "strdup failed");
109
if ((capdbp = dbopen(capname, O_CREAT | O_TRUNC | O_RDWR,
110
DEFFILEMODE, DB_HASH, &openinfo)) == NULL)
111
err(1, "%s", buf);
112
113
if (atexit(dounlink))
114
err(1, "atexit");
115
116
db_build(argv);
117
118
if (capdbp->close(capdbp) < 0)
119
err(1, "%s", capname);
120
capname = NULL;
121
exit(0);
122
}
123
124
static void
125
dounlink(void)
126
{
127
if (capname != NULL)
128
(void)unlink(capname);
129
}
130
131
/*
132
* Any changes to these definitions should be made also in the getcap(3)
133
* library routines.
134
*/
135
#define RECOK (char)0
136
#define TCERR (char)1
137
#define SHADOW (char)2
138
139
/*
140
* Db_build() builds the name and capability databases according to the
141
* details above.
142
*/
143
static void
144
db_build(char **ifiles)
145
{
146
DBT key, data;
147
recno_t reccnt;
148
size_t len, bplen;
149
int st;
150
char *bp, *p, *t;
151
152
data.data = NULL;
153
key.data = NULL;
154
for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) {
155
156
/*
157
* Allocate enough memory to store record, terminating
158
* NULL and one extra byte.
159
*/
160
len = strlen(bp);
161
if (bplen <= len + 2) {
162
bplen += MAX(256, len + 2);
163
if ((data.data = realloc(data.data, bplen)) == NULL)
164
errx(1, "malloc failed");
165
}
166
167
/* Find the end of the name field. */
168
if ((p = strchr(bp, ':')) == NULL) {
169
warnx("no name field: %.*s", (int)MIN(len, 20), bp);
170
continue;
171
}
172
173
/* First byte of stored record indicates status. */
174
switch(st) {
175
case 1:
176
((char *)(data.data))[0] = RECOK;
177
break;
178
case 2:
179
((char *)(data.data))[0] = TCERR;
180
warnx("record not tc expanded: %.*s", (int)(p - bp),
181
bp);
182
break;
183
}
184
185
/* Create the stored record. */
186
memmove(&((u_char *)(data.data))[1], bp, len + 1);
187
data.size = len + 2;
188
189
/* Store the record under the name field. */
190
key.data = bp;
191
key.size = p - bp;
192
193
switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) {
194
case -1:
195
err(1, "put");
196
/* NOTREACHED */
197
case 1:
198
warnx("ignored duplicate: %.*s",
199
(int)key.size, (char *)key.data);
200
continue;
201
}
202
++reccnt;
203
204
/* If only one name, ignore the rest. */
205
*p = '\0';
206
if (strchr(bp, '|') == NULL)
207
continue;
208
*p = ':';
209
210
/* The rest of the names reference the entire name. */
211
((char *)(data.data))[0] = SHADOW;
212
memmove(&((u_char *)(data.data))[1], key.data, key.size);
213
data.size = key.size + 1;
214
215
/* Store references for other names. */
216
for (p = t = bp;; ++p) {
217
if (p > t && (*p == ':' || *p == '|')) {
218
key.size = p - t;
219
key.data = t;
220
switch(capdbp->put(capdbp,
221
&key, &data, R_NOOVERWRITE)) {
222
case -1:
223
err(1, "put");
224
/* NOTREACHED */
225
case 1:
226
warnx("ignored duplicate: %.*s",
227
(int)key.size, (char *)key.data);
228
}
229
t = p + 1;
230
}
231
if (*p == ':')
232
break;
233
}
234
}
235
236
switch(st) {
237
case -1:
238
err(1, "file argument");
239
/* NOTREACHED */
240
case -2:
241
errx(1, "potential reference loop detected");
242
/* NOTREACHED */
243
}
244
245
if (verbose)
246
(void)printf("cap_mkdb: %d capability records\n", reccnt);
247
}
248
249
static void
250
usage(void)
251
{
252
(void)fprintf(stderr,
253
"usage: cap_mkdb [-b | -l] [-v] [-f outfile] file ...\n");
254
exit(1);
255
}
256
257