Annotation of src/usr.bin/cap_mkdb/cap_mkdb.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: cap_mkdb.c,v 1.5 1995/09/02 05:47:12 jtc Exp $ */
! 2:
! 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. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. 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: #ifndef lint
! 37: static char copyright[] =
! 38: "@(#) Copyright (c) 1992, 1993\n\
! 39: The Regents of the University of California. All rights reserved.\n";
! 40: #endif /* not lint */
! 41:
! 42: #ifndef lint
! 43: #if 0
! 44: static char sccsid[] = "@(#)cap_mkdb.c 8.2 (Berkeley) 4/27/95";
! 45: #endif
! 46: static char rcsid[] = "$NetBSD: cap_mkdb.c,v 1.5 1995/09/02 05:47:12 jtc Exp $";
! 47: #endif /* not lint */
! 48:
! 49: #include <sys/param.h>
! 50: #include <sys/stat.h>
! 51:
! 52: #include <db.h>
! 53: #include <err.h>
! 54: #include <errno.h>
! 55: #include <fcntl.h>
! 56: #include <limits.h>
! 57: #include <stdio.h>
! 58: #include <stdlib.h>
! 59: #include <string.h>
! 60: #include <unistd.h>
! 61:
! 62: void db_build __P((char **));
! 63: void dounlink __P((void));
! 64: void usage __P((void));
! 65:
! 66: DB *capdbp;
! 67: int verbose;
! 68: char *capdb, *capname, buf[8 * 1024];
! 69:
! 70: HASHINFO openinfo = {
! 71: 4096, /* bsize */
! 72: 16, /* ffactor */
! 73: 256, /* nelem */
! 74: 2048 * 1024, /* cachesize */
! 75: NULL, /* hash() */
! 76: 0 /* lorder */
! 77: };
! 78:
! 79: /*
! 80: * Mkcapdb creates a capability hash database for quick retrieval of capability
! 81: * records. The database contains 2 types of entries: records and references
! 82: * marked by the first byte in the data. A record entry contains the actual
! 83: * capability record whereas a reference contains the name (key) under which
! 84: * the correct record is stored.
! 85: */
! 86: int
! 87: main(argc, argv)
! 88: int argc;
! 89: char *argv[];
! 90: {
! 91: int c;
! 92:
! 93: capname = NULL;
! 94: while ((c = getopt(argc, argv, "f:v")) != EOF) {
! 95: switch(c) {
! 96: case 'f':
! 97: capname = optarg;
! 98: break;
! 99: case 'v':
! 100: verbose = 1;
! 101: break;
! 102: case '?':
! 103: default:
! 104: usage();
! 105: }
! 106: }
! 107: argc -= optind;
! 108: argv += optind;
! 109:
! 110: if (*argv == NULL)
! 111: usage();
! 112:
! 113: /*
! 114: * The database file is the first argument if no name is specified.
! 115: * Make arrangements to unlink it if exit badly.
! 116: */
! 117: (void)snprintf(buf, sizeof(buf), "%s.db", capname ? capname : *argv);
! 118: if ((capname = strdup(buf)) == NULL)
! 119: err(1, "");
! 120: if ((capdbp = dbopen(capname, O_CREAT | O_TRUNC | O_RDWR,
! 121: DEFFILEMODE, DB_HASH, &openinfo)) == NULL)
! 122: err(1, "%s", buf);
! 123:
! 124: if (atexit(dounlink))
! 125: err(1, "atexit");
! 126:
! 127: db_build(argv);
! 128:
! 129: if (capdbp->close(capdbp) < 0)
! 130: err(1, "%s", capname);
! 131: capname = NULL;
! 132: exit(0);
! 133: }
! 134:
! 135: void
! 136: dounlink()
! 137: {
! 138: if (capname != NULL)
! 139: (void)unlink(capname);
! 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 capabilty 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 = cgetnext(&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, "");
! 177: }
! 178:
! 179: /* Find the end of the name field. */
! 180: if ((p = strchr(bp, ':')) == NULL) {
! 181: warnx("no name field: %.*s", MIN(len, 20), bp);
! 182: continue;
! 183: }
! 184:
! 185: /* First byte of stored record indicates status. */
! 186: switch(st) {
! 187: case 1:
! 188: ((char *)(data.data))[0] = RECOK;
! 189: break;
! 190: case 2:
! 191: ((char *)(data.data))[0] = TCERR;
! 192: warnx("Record not tc expanded: %.*s", p - bp, bp);
! 193: break;
! 194: }
! 195:
! 196: /* Create the stored record. */
! 197: memmove(&((u_char *)(data.data))[1], bp, len + 1);
! 198: data.size = len + 2;
! 199:
! 200: /* Store the record under the name field. */
! 201: key.data = bp;
! 202: key.size = p - bp;
! 203:
! 204: switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) {
! 205: case -1:
! 206: err(1, "put");
! 207: /* NOTREACHED */
! 208: case 1:
! 209: warnx("ignored duplicate: %.*s",
! 210: key.size, (char *)key.data);
! 211: continue;
! 212: }
! 213: ++reccnt;
! 214:
! 215: /* If only one name, ignore the rest. */
! 216: if ((p = strchr(bp, '|')) == NULL)
! 217: continue;
! 218:
! 219: /* The rest of the names reference the entire name. */
! 220: ((char *)(data.data))[0] = SHADOW;
! 221: memmove(&((u_char *)(data.data))[1], key.data, key.size);
! 222: data.size = key.size + 1;
! 223:
! 224: /* Store references for other names. */
! 225: for (p = t = bp;; ++p) {
! 226: if (p > t && (*p == ':' || *p == '|')) {
! 227: key.size = p - t;
! 228: key.data = t;
! 229: switch(capdbp->put(capdbp,
! 230: &key, &data, R_NOOVERWRITE)) {
! 231: case -1:
! 232: err(1, "put");
! 233: /* NOTREACHED */
! 234: case 1:
! 235: warnx("ignored duplicate: %.*s",
! 236: key.size, (char *)key.data);
! 237: }
! 238: t = p + 1;
! 239: }
! 240: if (*p == ':')
! 241: break;
! 242: }
! 243: }
! 244:
! 245: switch(st) {
! 246: case -1:
! 247: err(1, "file argument");
! 248: /* NOTREACHED */
! 249: case -2:
! 250: errx(1, "potential reference loop detected");
! 251: /* NOTREACHED */
! 252: }
! 253:
! 254: if (verbose)
! 255: (void)printf("cap_mkdb: %d capability records\n", reccnt);
! 256: }
! 257:
! 258: void
! 259: usage()
! 260: {
! 261: (void)fprintf(stderr,
! 262: "usage: cap_mkdb [-v] [-f outfile] file1 [file2 ...]\n");
! 263: exit(1);
! 264: }