xref: /netbsd-src/usr.sbin/mtree/misc.c (revision 2cc3d62fc0c95918b8048aaa3f6cb9421e8c1a73)
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