Annotation of src/usr.bin/info_mkdb/info_mkdb.c, Revision 1.1
1.1 ! tholo 1: /* $OpenBSD$ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
! 5: * 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. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by SigmaSoft, Th. Lockert.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! 22: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
! 23: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
! 24: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 25: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 26: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 27: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 28: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 29: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 30: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: #ifndef lint
! 34: static char rcsid[] = "$OpenBSD$";
! 35: #endif /* not lint */
! 36:
! 37: #include <sys/param.h>
! 38: #include <sys/stat.h>
! 39:
! 40: #include <db.h>
! 41: #include <err.h>
! 42: #include <errno.h>
! 43: #include <fcntl.h>
! 44: #include <limits.h>
! 45: #include <stdio.h>
! 46: #include <stdlib.h>
! 47: #include <string.h>
! 48: #include <ctype.h>
! 49: #include <unistd.h>
! 50:
! 51: void db_build __P((char **));
! 52: void dounlink __P((void));
! 53: void usage __P((void));
! 54: int igetnext __P((char **, char **));
! 55: int main __P((int, char *[]));
! 56:
! 57: DB *infodbp;
! 58: int verbose;
! 59: char *infoname, buf[8 * 1024];
! 60:
! 61: HASHINFO openinfo = {
! 62: 4096, /* bsize */
! 63: 16, /* ffactor */
! 64: 256, /* nelem */
! 65: 2048 * 1024, /* cachesize */
! 66: NULL, /* hash() */
! 67: 0 /* lorder */
! 68: };
! 69:
! 70: /*
! 71: * info_mkdb creates a capability hash database for quick retrieval of capability
! 72: * records. The database contains 2 types of entries: records and references
! 73: * marked by the first byte in the data. A record entry contains the actual
! 74: * capability record whereas a reference contains the name (key) under which
! 75: * the correct record is stored.
! 76: */
! 77: int
! 78: main(argc, argv)
! 79: int argc;
! 80: char *argv[];
! 81: {
! 82: int c;
! 83:
! 84: infoname = NULL;
! 85: while ((c = getopt(argc, argv, "f:v")) != EOF) {
! 86: switch(c) {
! 87: case 'f':
! 88: infoname = optarg;
! 89: break;
! 90: case 'v':
! 91: verbose = 1;
! 92: break;
! 93: case '?':
! 94: default:
! 95: usage();
! 96: }
! 97: }
! 98: argc -= optind;
! 99: argv += optind;
! 100:
! 101: if (*argv == NULL)
! 102: usage();
! 103:
! 104: /*
! 105: * The database file is the first argument if no name is specified.
! 106: * Make arrangements to unlink it if exit badly.
! 107: */
! 108: (void)snprintf(buf, sizeof(buf), "%s.db", infoname ? infoname : *argv);
! 109: if ((infoname = strdup(buf)) == NULL) {
! 110: err(1, "strdup");
! 111: /* NOTREACHED */
! 112: }
! 113: if ((infodbp = dbopen(infoname, O_CREAT | O_TRUNC | O_RDWR,
! 114: DEFFILEMODE, DB_HASH, &openinfo)) == NULL) {
! 115: err(1, "%s", buf);
! 116: /* NOTREACHED */
! 117: }
! 118:
! 119: if (atexit(dounlink)) {
! 120: err(1, "atexit");
! 121: /* NOTREACHED */
! 122: }
! 123:
! 124: db_build(argv);
! 125:
! 126: if (infodbp->close(infodbp) < 0) {
! 127: err(1, "%s", infoname);
! 128: /* NOTREACHED */
! 129: }
! 130: infoname = NULL;
! 131: exit(0);
! 132: /* NOTREACHED */
! 133: }
! 134:
! 135: void
! 136: dounlink()
! 137: {
! 138: if (infoname != NULL)
! 139: (void)unlink(infoname);
! 140: }
! 141:
! 142: /*
! 143: * Any changes to these definitions should be made also in the getcap(3)
! 144: * library routines.
! 145: */
! 146: #define RECOK (char)0
! 147: #define TCERR (char)1
! 148: #define SHADOW (char)2
! 149:
! 150: /*
! 151: * db_build() builds the name and capability databases according to the
! 152: * details above.
! 153: */
! 154: void
! 155: db_build(ifiles)
! 156: char **ifiles;
! 157: {
! 158: DBT key, data;
! 159: recno_t reccnt;
! 160: size_t len, bplen;
! 161: int st;
! 162: char *bp, *p, *t;
! 163:
! 164: data.data = NULL;
! 165: key.data = NULL;
! 166: for (reccnt = 0, bplen = 0; (st = igetnext(&bp, ifiles)) > 0;) {
! 167:
! 168: /*
! 169: * Allocate enough memory to store record, terminating
! 170: * NULL and one extra byte.
! 171: */
! 172: len = strlen(bp);
! 173: if (bplen <= len + 2) {
! 174: bplen += MAX(256, len + 2);
! 175: if ((data.data = realloc(data.data, bplen)) == NULL) {
! 176: err(1, "realloc");
! 177: /* NOTREACHED */
! 178: }
! 179: }
! 180:
! 181: /* Find the end of the name field. */
! 182: if ((p = strchr(bp, ',')) == NULL) {
! 183: warnx("no name field: %.*s", (int)MIN(len, 20), bp);
! 184: continue;
! 185: }
! 186:
! 187: if (isspace(*bp)) {
! 188: warnx("bad name field: %.*s", (int)MIN(len, 20), bp);
! 189: continue;
! 190: }
! 191:
! 192: /* First byte of stored record indicates status. */
! 193: switch(st) {
! 194: case 1:
! 195: ((char *)(data.data))[0] = RECOK;
! 196: break;
! 197: case 2:
! 198: ((char *)(data.data))[0] = TCERR;
! 199: warnx("Record not use expanded: %.*s", (int)(p - bp), bp);
! 200: break;
! 201: }
! 202:
! 203: /* Create the stored record. */
! 204: (void) memmove(&((u_char *)(data.data))[1], bp, len + 1);
! 205: data.size = len + 2;
! 206: for (t = memchr((char *)data.data + 1, ',', data.size - 1) ; t ; t = memchr(t, ',', data.size - (t - (char *)data.data)))
! 207: *t++ = ':';
! 208:
! 209: if (memchr((char *)data.data + 1, '\0', data.size - 2)) {
! 210: warnx("NUL in entry: %.*s", (int)MIN(len, 20), bp);
! 211: continue;
! 212: }
! 213:
! 214: /* Store the record under the name field. */
! 215: key.data = bp;
! 216: key.size = p - bp;
! 217:
! 218: switch(infodbp->put(infodbp, &key, &data, R_NOOVERWRITE)) {
! 219: case -1:
! 220: err(1, "put");
! 221: /* NOTREACHED */
! 222: case 1:
! 223: warnx("ignored duplicate: %.*s",
! 224: (int)key.size, (char *)key.data);
! 225: continue;
! 226: }
! 227: ++reccnt;
! 228:
! 229: /* If only one name, ignore the rest. */
! 230: if ((p = strchr(bp, '|')) == NULL)
! 231: continue;
! 232:
! 233: /* The rest of the names reference the entire name. */
! 234: ((char *)(data.data))[0] = SHADOW;
! 235: (void) memmove(&((u_char *)(data.data))[1], key.data, key.size);
! 236: data.size = key.size + 1;
! 237:
! 238: /* Store references for other names. */
! 239: for (p = t = bp;; ++p) {
! 240: if (p > t && (*p == ',' || *p == '|')) {
! 241: key.size = p - t;
! 242: key.data = t;
! 243:
! 244: switch(infodbp->put(infodbp,
! 245: &key, &data, R_NOOVERWRITE)) {
! 246: case -1:
! 247: err(1, "put");
! 248: /* NOTREACHED */
! 249: case 1:
! 250: warnx("ignored duplicate: %.*s",
! 251: (int)key.size, (char *)key.data);
! 252: }
! 253: t = p + 1;
! 254: }
! 255: if (*p == ',')
! 256: break;
! 257: }
! 258: }
! 259:
! 260: switch(st) {
! 261: case -1:
! 262: err(1, "file argument");
! 263: /* NOTREACHED */
! 264: case -2:
! 265: errx(1, "potential reference loop detected");
! 266: /* NOTREACHED */
! 267: }
! 268:
! 269: if (verbose)
! 270: (void)printf("info_mkdb: %d capability records\n", reccnt);
! 271: }
! 272:
! 273: void
! 274: usage()
! 275: {
! 276: (void)fprintf(stderr,
! 277: "usage: info_mkdb [-v] [-f outfile] file1 [file2 ...]\n");
! 278: exit(1);
! 279: }