11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3141568Sarchiestatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1992, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 3487236Smarkm#endif 351590Srgrimes 3687628Sdwmalone#if 0 371590Srgrimes#ifndef lint 38142109Srustatic char sccsid[] = "@(#)cap_mkdb.c 8.2 (Berkeley) 4/27/95"; 3953508Scharnier#endif 4087628Sdwmalone#endif 411590Srgrimes 4287628Sdwmalone#include <sys/cdefs.h> 4387628Sdwmalone__FBSDID("$FreeBSD$"); 4487628Sdwmalone 451590Srgrimes#include <sys/param.h> 461590Srgrimes#include <sys/stat.h> 471590Srgrimes 481590Srgrimes#include <db.h> 491590Srgrimes#include <err.h> 501590Srgrimes#include <fcntl.h> 511590Srgrimes#include <stdio.h> 521590Srgrimes#include <stdlib.h> 531590Srgrimes#include <string.h> 541590Srgrimes#include <unistd.h> 551590Srgrimes 56227154Sedstatic void db_build(char **); 57227154Sedstatic void dounlink(void); 58227154Sedstatic void usage(void); 591590Srgrimes 60227154Sedstatic DB *capdbp; 61227154Sedstatic int verbose; 62227154Sedstatic char *capname, buf[8 * 1024]; 631590Srgrimes 64227154Sedstatic HASHINFO openinfo = { 65142109Sru 4096, /* bsize */ 66142109Sru 0, /* ffactor */ 67142109Sru 0, /* nelem */ 68142109Sru 0, /* cachesize */ 69142109Sru NULL, /* hash() */ 70142109Sru 0 /* lorder */ 71142109Sru}; 72142109Sru 731590Srgrimes/* 741590Srgrimes * Mkcapdb creates a capability hash database for quick retrieval of capability 751590Srgrimes * records. The database contains 2 types of entries: records and references 761590Srgrimes * marked by the first byte in the data. A record entry contains the actual 771590Srgrimes * capability record whereas a reference contains the name (key) under which 781590Srgrimes * the correct record is stored. 791590Srgrimes */ 801590Srgrimesint 81100812Sdwmalonemain(int argc, char *argv[]) 821590Srgrimes{ 83142262Sru int byteorder, c; 841590Srgrimes 851590Srgrimes capname = NULL; 86142262Sru byteorder = 0; 87142262Sru while ((c = getopt(argc, argv, "bf:lv")) != -1) { 881590Srgrimes switch(c) { 89142262Sru case 'b': 90142262Sru case 'l': 91142262Sru if (byteorder != 0) 92142262Sru usage(); 93142262Sru byteorder = c == 'b' ? 4321 : 1234; 94142262Sru break; 951590Srgrimes case 'f': 961590Srgrimes capname = optarg; 971590Srgrimes break; 981590Srgrimes case 'v': 991590Srgrimes verbose = 1; 1001590Srgrimes break; 1011590Srgrimes case '?': 1021590Srgrimes default: 1031590Srgrimes usage(); 1041590Srgrimes } 1051590Srgrimes } 1061590Srgrimes argc -= optind; 1071590Srgrimes argv += optind; 1081590Srgrimes 1091590Srgrimes if (*argv == NULL) 1101590Srgrimes usage(); 1111590Srgrimes 112142262Sru /* Set byte order. */ 113142262Sru openinfo.lorder = byteorder; 114142262Sru 1151590Srgrimes /* 1161590Srgrimes * The database file is the first argument if no name is specified. 1171590Srgrimes * Make arrangements to unlink it if exit badly. 1181590Srgrimes */ 1191590Srgrimes (void)snprintf(buf, sizeof(buf), "%s.db", capname ? capname : *argv); 1201590Srgrimes if ((capname = strdup(buf)) == NULL) 12153508Scharnier errx(1, "strdup failed"); 122296424Sdwmalone if ((capdbp = dbopen(capname, O_CREAT | O_TRUNC | O_RDWR, 123142109Sru DEFFILEMODE, DB_HASH, &openinfo)) == NULL) 1241590Srgrimes err(1, "%s", buf); 1251590Srgrimes 1261590Srgrimes if (atexit(dounlink)) 1271590Srgrimes err(1, "atexit"); 1281590Srgrimes 1291590Srgrimes db_build(argv); 1301590Srgrimes 1311590Srgrimes if (capdbp->close(capdbp) < 0) 1321590Srgrimes err(1, "%s", capname); 1331590Srgrimes capname = NULL; 1341590Srgrimes exit(0); 1351590Srgrimes} 1361590Srgrimes 137227154Sedstatic void 138100812Sdwmalonedounlink(void) 1391590Srgrimes{ 1401590Srgrimes if (capname != NULL) 1411590Srgrimes (void)unlink(capname); 1421590Srgrimes} 1431590Srgrimes 1441590Srgrimes/* 1451590Srgrimes * Any changes to these definitions should be made also in the getcap(3) 1461590Srgrimes * library routines. 1471590Srgrimes */ 1481590Srgrimes#define RECOK (char)0 1491590Srgrimes#define TCERR (char)1 1501590Srgrimes#define SHADOW (char)2 1511590Srgrimes 1521590Srgrimes/* 15377586Sru * Db_build() builds the name and capability databases according to the 1541590Srgrimes * details above. 1551590Srgrimes */ 156227154Sedstatic void 157100812Sdwmalonedb_build(char **ifiles) 1581590Srgrimes{ 1591590Srgrimes DBT key, data; 1601590Srgrimes recno_t reccnt; 1611590Srgrimes size_t len, bplen; 1621590Srgrimes int st; 1631590Srgrimes char *bp, *p, *t; 1641590Srgrimes 1651590Srgrimes data.data = NULL; 1661590Srgrimes key.data = NULL; 1671590Srgrimes for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) { 1681590Srgrimes 1691590Srgrimes /* 1701590Srgrimes * Allocate enough memory to store record, terminating 1711590Srgrimes * NULL and one extra byte. 1721590Srgrimes */ 1731590Srgrimes len = strlen(bp); 1741590Srgrimes if (bplen <= len + 2) { 1751590Srgrimes bplen += MAX(256, len + 2); 1761590Srgrimes if ((data.data = realloc(data.data, bplen)) == NULL) 17753508Scharnier errx(1, "malloc failed"); 1781590Srgrimes } 1791590Srgrimes 1801590Srgrimes /* Find the end of the name field. */ 1811590Srgrimes if ((p = strchr(bp, ':')) == NULL) { 18237453Sbde warnx("no name field: %.*s", (int)MIN(len, 20), bp); 1831590Srgrimes continue; 1841590Srgrimes } 1851590Srgrimes 1861590Srgrimes /* First byte of stored record indicates status. */ 1871590Srgrimes switch(st) { 1881590Srgrimes case 1: 1891590Srgrimes ((char *)(data.data))[0] = RECOK; 1901590Srgrimes break; 1911590Srgrimes case 2: 1921590Srgrimes ((char *)(data.data))[0] = TCERR; 19379010Sdd warnx("record not tc expanded: %.*s", (int)(p - bp), 19479010Sdd bp); 1951590Srgrimes break; 1961590Srgrimes } 1971590Srgrimes 1981590Srgrimes /* Create the stored record. */ 1991590Srgrimes memmove(&((u_char *)(data.data))[1], bp, len + 1); 2001590Srgrimes data.size = len + 2; 2011590Srgrimes 2021590Srgrimes /* Store the record under the name field. */ 2031590Srgrimes key.data = bp; 2041590Srgrimes key.size = p - bp; 2051590Srgrimes 2061590Srgrimes switch(capdbp->put(capdbp, &key, &data, R_NOOVERWRITE)) { 2071590Srgrimes case -1: 2081590Srgrimes err(1, "put"); 2091590Srgrimes /* NOTREACHED */ 2101590Srgrimes case 1: 2111590Srgrimes warnx("ignored duplicate: %.*s", 21237453Sbde (int)key.size, (char *)key.data); 2131590Srgrimes continue; 2141590Srgrimes } 2151590Srgrimes ++reccnt; 2161590Srgrimes 2171590Srgrimes /* If only one name, ignore the rest. */ 21877586Sru *p = '\0'; 21977586Sru if (strchr(bp, '|') == NULL) 2201590Srgrimes continue; 22177586Sru *p = ':'; 2221590Srgrimes 2231590Srgrimes /* The rest of the names reference the entire name. */ 2241590Srgrimes ((char *)(data.data))[0] = SHADOW; 2251590Srgrimes memmove(&((u_char *)(data.data))[1], key.data, key.size); 2261590Srgrimes data.size = key.size + 1; 2271590Srgrimes 2281590Srgrimes /* Store references for other names. */ 2291590Srgrimes for (p = t = bp;; ++p) { 2301590Srgrimes if (p > t && (*p == ':' || *p == '|')) { 2311590Srgrimes key.size = p - t; 2321590Srgrimes key.data = t; 2331590Srgrimes switch(capdbp->put(capdbp, 2341590Srgrimes &key, &data, R_NOOVERWRITE)) { 2351590Srgrimes case -1: 2361590Srgrimes err(1, "put"); 2371590Srgrimes /* NOTREACHED */ 2381590Srgrimes case 1: 2391590Srgrimes warnx("ignored duplicate: %.*s", 24037453Sbde (int)key.size, (char *)key.data); 2411590Srgrimes } 2421590Srgrimes t = p + 1; 2431590Srgrimes } 2441590Srgrimes if (*p == ':') 2451590Srgrimes break; 2461590Srgrimes } 2471590Srgrimes } 2481590Srgrimes 2491590Srgrimes switch(st) { 2501590Srgrimes case -1: 2511590Srgrimes err(1, "file argument"); 2521590Srgrimes /* NOTREACHED */ 2531590Srgrimes case -2: 2541590Srgrimes errx(1, "potential reference loop detected"); 2551590Srgrimes /* NOTREACHED */ 2561590Srgrimes } 2571590Srgrimes 2581590Srgrimes if (verbose) 2591590Srgrimes (void)printf("cap_mkdb: %d capability records\n", reccnt); 2601590Srgrimes} 2611590Srgrimes 262227154Sedstatic void 263100812Sdwmaloneusage(void) 2641590Srgrimes{ 2651590Srgrimes (void)fprintf(stderr, 266142262Sru "usage: cap_mkdb [-b | -l] [-v] [-f outfile] file ...\n"); 2671590Srgrimes exit(1); 2681590Srgrimes} 269