1*2cc3d62fSchristos /* $NetBSD: misc.c,v 1.35 2024/12/05 17:17:43 christos Exp $ */ 294f5a744Scgd 3476023b5Scgd /*- 482f956cdScgd * Copyright (c) 1991, 1993 582f956cdScgd * The Regents of the University of California. All rights reserved. 6476023b5Scgd * 7476023b5Scgd * Redistribution and use in source and binary forms, with or without 8476023b5Scgd * modification, are permitted provided that the following conditions 9476023b5Scgd * are met: 10476023b5Scgd * 1. Redistributions of source code must retain the above copyright 11476023b5Scgd * notice, this list of conditions and the following disclaimer. 12476023b5Scgd * 2. Redistributions in binary form must reproduce the above copyright 13476023b5Scgd * notice, this list of conditions and the following disclaimer in the 14476023b5Scgd * documentation and/or other materials provided with the distribution. 15326b2259Sagc * 3. Neither the name of the University nor the names of its contributors 16476023b5Scgd * may be used to endorse or promote products derived from this software 17476023b5Scgd * without specific prior written permission. 18476023b5Scgd * 19476023b5Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20476023b5Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21476023b5Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22476023b5Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23476023b5Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24476023b5Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25476023b5Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26476023b5Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27476023b5Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28476023b5Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29476023b5Scgd * SUCH DAMAGE. 30476023b5Scgd * 3182f956cdScgd * @(#)misc.c 8.1 (Berkeley) 6/6/93 32476023b5Scgd */ 33476023b5Scgd 34b2f78261Sjmc #if HAVE_NBTOOL_CONFIG_H 35b2f78261Sjmc #include "nbtool_config.h" 36b2f78261Sjmc #endif 37b2f78261Sjmc 384eb76530Slukem #include <sys/cdefs.h> 3976834aefStv #if defined(__RCSID) && !defined(lint) 40*2cc3d62fSchristos __RCSID("$NetBSD: misc.c,v 1.35 2024/12/05 17:17:43 christos Exp $"); 414eb76530Slukem #endif /* not lint */ 424eb76530Slukem 43476023b5Scgd #include <sys/types.h> 44476023b5Scgd #include <sys/stat.h> 457cbb4e05Ssimonb 467cbb4e05Ssimonb #include <stdarg.h> 47476023b5Scgd #include <stdio.h> 4857566f70Slukem #include <stdlib.h> 4957566f70Slukem #include <string.h> 507cbb4e05Ssimonb 51476023b5Scgd #include "extern.h" 52476023b5Scgd 53357b7495Schristos enum flavor flavor = F_MTREE; 54357b7495Schristos 55476023b5Scgd typedef struct _key { 56c0e6fdedSlukem const char *name; /* key name */ 57476023b5Scgd u_int val; /* value */ 58476023b5Scgd 59476023b5Scgd #define NEEDVALUE 0x01 60476023b5Scgd u_int flags; 61476023b5Scgd } KEY; 62476023b5Scgd 63c0e6fdedSlukem /* NB: the following tables must be sorted lexically. */ 64476023b5Scgd static KEY keylist[] = { 654eb76530Slukem {"cksum", F_CKSUM, NEEDVALUE}, 66bc1697fcSlukem {"device", F_DEV, NEEDVALUE}, 67f2fb63efSmrg {"flags", F_FLAGS, NEEDVALUE}, 684eb76530Slukem {"gid", F_GID, NEEDVALUE}, 694eb76530Slukem {"gname", F_GNAME, NEEDVALUE}, 704eb76530Slukem {"ignore", F_IGN, 0}, 714eb76530Slukem {"link", F_SLINK, NEEDVALUE}, 722e6cacfaSjwise {"md5", F_MD5, NEEDVALUE}, 73e8b2f332Slukem {"md5digest", F_MD5, NEEDVALUE}, 744eb76530Slukem {"mode", F_MODE, NEEDVALUE}, 754eb76530Slukem {"nlink", F_NLINK, NEEDVALUE}, 76b73d92b0Schristos {"nochange", F_NOCHANGE, 0}, 774eb76530Slukem {"optional", F_OPT, 0}, 788a1488a1Schristos {"ripemd160digest", F_RMD160, NEEDVALUE}, 79e8b2f332Slukem {"rmd160", F_RMD160, NEEDVALUE}, 80e8b2f332Slukem {"rmd160digest",F_RMD160, NEEDVALUE}, 81e8b2f332Slukem {"sha1", F_SHA1, NEEDVALUE}, 82e8b2f332Slukem {"sha1digest", F_SHA1, NEEDVALUE}, 83aae00d5aSelad {"sha256", F_SHA256, NEEDVALUE}, 84aae00d5aSelad {"sha256digest",F_SHA256, NEEDVALUE}, 85aae00d5aSelad {"sha384", F_SHA384, NEEDVALUE}, 86aae00d5aSelad {"sha384digest",F_SHA384, NEEDVALUE}, 87aae00d5aSelad {"sha512", F_SHA512, NEEDVALUE}, 88aae00d5aSelad {"sha512digest",F_SHA512, NEEDVALUE}, 89fe7c56c5Stron {"size", F_SIZE, NEEDVALUE}, 90fe7c56c5Stron {"tags", F_TAGS, NEEDVALUE}, 91fe7c56c5Stron {"time", F_TIME, NEEDVALUE}, 92fe7c56c5Stron {"type", F_TYPE, NEEDVALUE}, 93fe7c56c5Stron {"uid", F_UID, NEEDVALUE}, 94fe7c56c5Stron {"uname", F_UNAME, NEEDVALUE} 95476023b5Scgd }; 96476023b5Scgd 97c0e6fdedSlukem static KEY typelist[] = { 98a3522b31Schristos {"block", F_BLOCK, 0}, 99a3522b31Schristos {"char", F_CHAR, 0}, 100a3522b31Schristos {"dir", F_DIR, 0}, 1014ce31f7cSchristos #ifdef S_IFDOOR 102a3522b31Schristos {"door", F_DOOR, 0}, 1034ce31f7cSchristos #endif 104a3522b31Schristos {"fifo", F_FIFO, 0}, 105a3522b31Schristos {"file", F_FILE, 0}, 106a3522b31Schristos {"link", F_LINK, 0}, 107a3522b31Schristos {"socket", F_SOCK, 0}, 108c0e6fdedSlukem }; 109c0e6fdedSlukem 11057566f70Slukem slist_t excludetags, includetags; 11157566f70Slukem int keys = KEYDEFAULT; 11257566f70Slukem 11357566f70Slukem 114*2cc3d62fSchristos static int keycompare(const void *, const void *); 1154eb76530Slukem 116476023b5Scgd u_int 117c0e6fdedSlukem parsekey(const char *name, int *needvaluep) 118476023b5Scgd { 119d8c78c60Slukem static int allbits; 120476023b5Scgd KEY *k, tmp; 121476023b5Scgd 122d8c78c60Slukem if (allbits == 0) { 123c5eb4ab6Slukem size_t i; 124d8c78c60Slukem 125d8c78c60Slukem for (i = 0; i < sizeof(keylist) / sizeof(KEY); i++) 126d8c78c60Slukem allbits |= keylist[i].val; 127d8c78c60Slukem } 128476023b5Scgd tmp.name = name; 129d8c78c60Slukem if (strcmp(name, "all") == 0) 130d8c78c60Slukem return (allbits); 131476023b5Scgd k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY), 132476023b5Scgd sizeof(KEY), keycompare); 133476023b5Scgd if (k == NULL) 1347c30045cSlukem mtree_err("unknown keyword `%s'", name); 135476023b5Scgd 136476023b5Scgd if (needvaluep) 137476023b5Scgd *needvaluep = k->flags & NEEDVALUE ? 1 : 0; 1382e6cacfaSjwise 139476023b5Scgd return (k->val); 140476023b5Scgd } 141476023b5Scgd 142c0e6fdedSlukem u_int 143c0e6fdedSlukem parsetype(const char *name) 144c0e6fdedSlukem { 145c0e6fdedSlukem KEY *k, tmp; 146c0e6fdedSlukem 147c0e6fdedSlukem tmp.name = name; 148c0e6fdedSlukem k = (KEY *)bsearch(&tmp, typelist, sizeof(typelist) / sizeof(KEY), 149c0e6fdedSlukem sizeof(KEY), keycompare); 150c0e6fdedSlukem if (k == NULL) 1517c30045cSlukem mtree_err("unknown file type `%s'", name); 152c0e6fdedSlukem 153c0e6fdedSlukem return (k->val); 154c0e6fdedSlukem } 155c0e6fdedSlukem 156*2cc3d62fSchristos static int 1577cbb4e05Ssimonb keycompare(const void *a, const void *b) 158476023b5Scgd { 1597cbb4e05Ssimonb 16098df36b3Slukem return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name)); 161476023b5Scgd } 162476023b5Scgd 163476023b5Scgd void 164c45946d2Swsanchez mtree_err(const char *fmt, ...) 165476023b5Scgd { 166476023b5Scgd va_list ap; 1677cbb4e05Ssimonb 168476023b5Scgd va_start(ap, fmt); 16957566f70Slukem vwarnx(fmt, ap); 170476023b5Scgd va_end(ap); 171c55aa0f9Slukem if (mtree_lineno) 17257566f70Slukem warnx("failed at line %lu of the specification", 173c55aa0f9Slukem (u_long) mtree_lineno); 174476023b5Scgd exit(1); 175476023b5Scgd /* NOTREACHED */ 176476023b5Scgd } 1774da22cb4Slukem 1784da22cb4Slukem void 1794da22cb4Slukem addtag(slist_t *list, char *elem) 1804da22cb4Slukem { 1814da22cb4Slukem 1824da22cb4Slukem #define TAG_CHUNK 20 1834da22cb4Slukem 1844da22cb4Slukem if ((list->count % TAG_CHUNK) == 0) { 1854da22cb4Slukem char **new; 1864da22cb4Slukem 1874da22cb4Slukem new = (char **)realloc(list->list, (list->count + TAG_CHUNK) 1884da22cb4Slukem * sizeof(char *)); 1894da22cb4Slukem if (new == NULL) 1904da22cb4Slukem mtree_err("memory allocation error"); 1914da22cb4Slukem list->list = new; 1924da22cb4Slukem } 1934da22cb4Slukem list->list[list->count] = elem; 1944da22cb4Slukem list->count++; 1954da22cb4Slukem } 1964da22cb4Slukem 1974da22cb4Slukem void 1984da22cb4Slukem parsetags(slist_t *list, char *args) 1994da22cb4Slukem { 2004da22cb4Slukem char *p, *e; 201*2cc3d62fSchristos size_t len; 2024da22cb4Slukem 2034da22cb4Slukem if (args == NULL) { 2044da22cb4Slukem addtag(list, NULL); 2054da22cb4Slukem return; 2064da22cb4Slukem } 2074da22cb4Slukem while ((p = strsep(&args, ",")) != NULL) { 2084da22cb4Slukem if (*p == '\0') 2094da22cb4Slukem continue; 2104da22cb4Slukem len = strlen(p) + 3; /* "," + p + ",\0" */ 2114da22cb4Slukem if ((e = malloc(len)) == NULL) 2124da22cb4Slukem mtree_err("memory allocation error"); 2134da22cb4Slukem snprintf(e, len, ",%s,", p); 2144da22cb4Slukem addtag(list, e); 2154da22cb4Slukem } 2164da22cb4Slukem } 2174da22cb4Slukem 2184da22cb4Slukem /* 2194da22cb4Slukem * matchtags 2204da22cb4Slukem * returns 0 if there's a match from the exclude list in the node's tags, 2214da22cb4Slukem * or there's an include list and no match. 2224da22cb4Slukem * return 1 otherwise. 2234da22cb4Slukem */ 2244da22cb4Slukem int 2254da22cb4Slukem matchtags(NODE *node) 2264da22cb4Slukem { 2274da22cb4Slukem int i; 2284da22cb4Slukem 2294da22cb4Slukem if (node->tags) { 2304da22cb4Slukem for (i = 0; i < excludetags.count; i++) 2314da22cb4Slukem if (strstr(node->tags, excludetags.list[i])) 2324da22cb4Slukem break; 2334da22cb4Slukem if (i < excludetags.count) 2344da22cb4Slukem return (0); 2354da22cb4Slukem 2364da22cb4Slukem for (i = 0; i < includetags.count; i++) 2374da22cb4Slukem if (strstr(node->tags, includetags.list[i])) 2384da22cb4Slukem break; 2394da22cb4Slukem if (i > 0 && i == includetags.count) 2404da22cb4Slukem return (0); 2414da22cb4Slukem } else if (includetags.count > 0) { 2424da22cb4Slukem return (0); 2434da22cb4Slukem } 2444da22cb4Slukem return (1); 2454da22cb4Slukem } 24657566f70Slukem 24757566f70Slukem u_int 24857566f70Slukem nodetoino(u_int type) 24957566f70Slukem { 25057566f70Slukem 25157566f70Slukem switch (type) { 25257566f70Slukem case F_BLOCK: 25357566f70Slukem return S_IFBLK; 25457566f70Slukem case F_CHAR: 25557566f70Slukem return S_IFCHR; 25657566f70Slukem case F_DIR: 25757566f70Slukem return S_IFDIR; 25857566f70Slukem case F_FIFO: 25957566f70Slukem return S_IFIFO; 26057566f70Slukem case F_FILE: 26157566f70Slukem return S_IFREG; 26257566f70Slukem case F_LINK: 26357566f70Slukem return S_IFLNK; 264b2f78261Sjmc #ifdef S_IFSOCK 26557566f70Slukem case F_SOCK: 26657566f70Slukem return S_IFSOCK; 267b2f78261Sjmc #endif 26857566f70Slukem default: 26957566f70Slukem printf("unknown type %d", type); 27057566f70Slukem abort(); 27157566f70Slukem } 27257566f70Slukem /* NOTREACHED */ 27357566f70Slukem } 27457566f70Slukem 27557566f70Slukem const char * 27657566f70Slukem nodetype(u_int type) 27757566f70Slukem { 27857566f70Slukem 27957566f70Slukem return (inotype(nodetoino(type))); 28057566f70Slukem } 28157566f70Slukem 28257566f70Slukem 28357566f70Slukem const char * 28457566f70Slukem inotype(u_int type) 28557566f70Slukem { 28657566f70Slukem 28757566f70Slukem switch (type & S_IFMT) { 28857566f70Slukem case S_IFBLK: 28957566f70Slukem return ("block"); 29057566f70Slukem case S_IFCHR: 29157566f70Slukem return ("char"); 29257566f70Slukem case S_IFDIR: 29357566f70Slukem return ("dir"); 29457566f70Slukem case S_IFIFO: 29557566f70Slukem return ("fifo"); 29657566f70Slukem case S_IFREG: 29757566f70Slukem return ("file"); 29857566f70Slukem case S_IFLNK: 29957566f70Slukem return ("link"); 300b2f78261Sjmc #ifdef S_IFSOCK 30157566f70Slukem case S_IFSOCK: 30257566f70Slukem return ("socket"); 303b2f78261Sjmc #endif 3044ce31f7cSchristos #ifdef S_IFDOOR 3054ce31f7cSchristos case S_IFDOOR: 3064ce31f7cSchristos return ("door"); 3074ce31f7cSchristos #endif 30857566f70Slukem default: 30957566f70Slukem return ("unknown"); 31057566f70Slukem } 31157566f70Slukem /* NOTREACHED */ 31257566f70Slukem } 313