xref: /minix3/usr.sbin/mtree/misc.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
184d9c625SLionel Sambuc /*	$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $	*/
2d433a562SThomas Veerman 
3d433a562SThomas Veerman /*-
4d433a562SThomas Veerman  * Copyright (c) 1991, 1993
5d433a562SThomas Veerman  *	The Regents of the University of California.  All rights reserved.
6d433a562SThomas Veerman  *
7d433a562SThomas Veerman  * Redistribution and use in source and binary forms, with or without
8d433a562SThomas Veerman  * modification, are permitted provided that the following conditions
9d433a562SThomas Veerman  * are met:
10d433a562SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
11d433a562SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
12d433a562SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
13d433a562SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
14d433a562SThomas Veerman  *    documentation and/or other materials provided with the distribution.
15d433a562SThomas Veerman  * 3. Neither the name of the University nor the names of its contributors
16d433a562SThomas Veerman  *    may be used to endorse or promote products derived from this software
17d433a562SThomas Veerman  *    without specific prior written permission.
18d433a562SThomas Veerman  *
19d433a562SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20d433a562SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21d433a562SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22d433a562SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23d433a562SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24d433a562SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25d433a562SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26d433a562SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27d433a562SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28d433a562SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29d433a562SThomas Veerman  * SUCH DAMAGE.
30d433a562SThomas Veerman  *
31d433a562SThomas Veerman  *	@(#)misc.c	8.1 (Berkeley) 6/6/93
32d433a562SThomas Veerman  */
33d433a562SThomas Veerman 
34d433a562SThomas Veerman #if HAVE_NBTOOL_CONFIG_H
35d433a562SThomas Veerman #include "nbtool_config.h"
36d433a562SThomas Veerman #endif
37d433a562SThomas Veerman 
38d433a562SThomas Veerman #include <sys/cdefs.h>
39d433a562SThomas Veerman #if defined(__RCSID) && !defined(lint)
4084d9c625SLionel Sambuc __RCSID("$NetBSD: misc.c,v 1.34 2012/12/20 19:09:25 christos Exp $");
41d433a562SThomas Veerman #endif /* not lint */
42d433a562SThomas Veerman 
43d433a562SThomas Veerman #include <sys/types.h>
44d433a562SThomas Veerman #include <sys/stat.h>
45d433a562SThomas Veerman 
46d433a562SThomas Veerman #include <stdarg.h>
47d433a562SThomas Veerman #include <stdio.h>
48d433a562SThomas Veerman #include <stdlib.h>
49d433a562SThomas Veerman #include <string.h>
50d433a562SThomas Veerman 
51d433a562SThomas Veerman #include "extern.h"
52d433a562SThomas Veerman 
5384d9c625SLionel Sambuc #if 1 /* defined(__minix): LSC: our mkfs doesn't understand escaped names,
5484d9c625SLionel Sambuc 	 so always default to netbsd6 escaping mode. */
5584d9c625SLionel Sambuc enum flavor	flavor = F_NETBSD6;
5684d9c625SLionel Sambuc #else
5784d9c625SLionel Sambuc enum flavor	flavor = F_MTREE;
5884d9c625SLionel Sambuc #endif /* defined(__minix) */
59*0a6a1f1dSLionel Sambuc 
60d433a562SThomas Veerman typedef struct _key {
61d433a562SThomas Veerman 	const char	*name;		/* key name */
62d433a562SThomas Veerman 	u_int		val;		/* value */
63d433a562SThomas Veerman 
64d433a562SThomas Veerman #define	NEEDVALUE	0x01
65d433a562SThomas Veerman 	u_int		flags;
66d433a562SThomas Veerman } KEY;
67d433a562SThomas Veerman 
68d433a562SThomas Veerman /* NB: the following tables must be sorted lexically. */
69d433a562SThomas Veerman static KEY keylist[] = {
70d433a562SThomas Veerman 	{"cksum",	F_CKSUM,	NEEDVALUE},
71d433a562SThomas Veerman 	{"device",	F_DEV,		NEEDVALUE},
72d433a562SThomas Veerman 	{"flags",	F_FLAGS,	NEEDVALUE},
73d433a562SThomas Veerman 	{"gid",		F_GID,		NEEDVALUE},
74d433a562SThomas Veerman 	{"gname",	F_GNAME,	NEEDVALUE},
75d433a562SThomas Veerman 	{"ignore",	F_IGN,		0},
76d433a562SThomas Veerman 	{"link",	F_SLINK,	NEEDVALUE},
77d433a562SThomas Veerman 	{"md5",		F_MD5,		NEEDVALUE},
78d433a562SThomas Veerman 	{"md5digest",	F_MD5,		NEEDVALUE},
79d433a562SThomas Veerman 	{"mode",	F_MODE,		NEEDVALUE},
80d433a562SThomas Veerman 	{"nlink",	F_NLINK,	NEEDVALUE},
81a8ef0910SBen Gras 	{"nochange",	F_NOCHANGE,	0},
82d433a562SThomas Veerman 	{"optional",	F_OPT,		0},
83a8ef0910SBen Gras 	{"ripemd160digest", F_RMD160,	NEEDVALUE},
84d433a562SThomas Veerman 	{"rmd160",	F_RMD160,	NEEDVALUE},
85d433a562SThomas Veerman 	{"rmd160digest",F_RMD160,	NEEDVALUE},
86d433a562SThomas Veerman 	{"sha1",	F_SHA1,		NEEDVALUE},
87d433a562SThomas Veerman 	{"sha1digest",	F_SHA1,		NEEDVALUE},
88d433a562SThomas Veerman 	{"sha256",	F_SHA256,	NEEDVALUE},
89d433a562SThomas Veerman 	{"sha256digest",F_SHA256,	NEEDVALUE},
90d433a562SThomas Veerman 	{"sha384",	F_SHA384,	NEEDVALUE},
91d433a562SThomas Veerman 	{"sha384digest",F_SHA384,	NEEDVALUE},
92d433a562SThomas Veerman 	{"sha512",	F_SHA512,	NEEDVALUE},
93d433a562SThomas Veerman 	{"sha512digest",F_SHA512,	NEEDVALUE},
94d433a562SThomas Veerman 	{"size",	F_SIZE,		NEEDVALUE},
95d433a562SThomas Veerman 	{"tags",	F_TAGS,		NEEDVALUE},
96d433a562SThomas Veerman 	{"time",	F_TIME,		NEEDVALUE},
97d433a562SThomas Veerman 	{"type",	F_TYPE,		NEEDVALUE},
98d433a562SThomas Veerman 	{"uid",		F_UID,		NEEDVALUE},
99d433a562SThomas Veerman 	{"uname",	F_UNAME,	NEEDVALUE}
100d433a562SThomas Veerman };
101d433a562SThomas Veerman 
102d433a562SThomas Veerman static KEY typelist[] = {
103d433a562SThomas Veerman 	{"block",	F_BLOCK,	0},
104d433a562SThomas Veerman 	{"char",	F_CHAR,		0},
105d433a562SThomas Veerman 	{"dir",		F_DIR,		0},
106d433a562SThomas Veerman #ifdef S_IFDOOR
107d433a562SThomas Veerman 	{"door",	F_DOOR,		0},
108d433a562SThomas Veerman #endif
109d433a562SThomas Veerman 	{"fifo",	F_FIFO,		0},
110d433a562SThomas Veerman 	{"file",	F_FILE,		0},
111d433a562SThomas Veerman 	{"link",	F_LINK,		0},
112d433a562SThomas Veerman 	{"socket",	F_SOCK,		0},
113d433a562SThomas Veerman };
114d433a562SThomas Veerman 
115d433a562SThomas Veerman slist_t	excludetags, includetags;
116d433a562SThomas Veerman int	keys = KEYDEFAULT;
117d433a562SThomas Veerman 
118d433a562SThomas Veerman 
119d433a562SThomas Veerman int keycompare(const void *, const void *);
120d433a562SThomas Veerman 
121d433a562SThomas Veerman u_int
parsekey(const char * name,int * needvaluep)122d433a562SThomas Veerman parsekey(const char *name, int *needvaluep)
123d433a562SThomas Veerman {
124d433a562SThomas Veerman 	static int allbits;
125d433a562SThomas Veerman 	KEY *k, tmp;
126d433a562SThomas Veerman 
127d433a562SThomas Veerman 	if (allbits == 0) {
128d433a562SThomas Veerman 		size_t i;
129d433a562SThomas Veerman 
130d433a562SThomas Veerman 		for (i = 0; i < sizeof(keylist) / sizeof(KEY); i++)
131d433a562SThomas Veerman 			allbits |= keylist[i].val;
132d433a562SThomas Veerman 	}
133d433a562SThomas Veerman 	tmp.name = name;
134d433a562SThomas Veerman 	if (strcmp(name, "all") == 0)
135d433a562SThomas Veerman 		return (allbits);
136d433a562SThomas Veerman 	k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
137d433a562SThomas Veerman 	    sizeof(KEY), keycompare);
138d433a562SThomas Veerman 	if (k == NULL)
139d433a562SThomas Veerman 		mtree_err("unknown keyword `%s'", name);
140d433a562SThomas Veerman 
141d433a562SThomas Veerman 	if (needvaluep)
142d433a562SThomas Veerman 		*needvaluep = k->flags & NEEDVALUE ? 1 : 0;
143d433a562SThomas Veerman 
144d433a562SThomas Veerman 	return (k->val);
145d433a562SThomas Veerman }
146d433a562SThomas Veerman 
147d433a562SThomas Veerman u_int
parsetype(const char * name)148d433a562SThomas Veerman parsetype(const char *name)
149d433a562SThomas Veerman {
150d433a562SThomas Veerman 	KEY *k, tmp;
151d433a562SThomas Veerman 
152d433a562SThomas Veerman 	tmp.name = name;
153d433a562SThomas Veerman 	k = (KEY *)bsearch(&tmp, typelist, sizeof(typelist) / sizeof(KEY),
154d433a562SThomas Veerman 	    sizeof(KEY), keycompare);
155d433a562SThomas Veerman 	if (k == NULL)
156d433a562SThomas Veerman 		mtree_err("unknown file type `%s'", name);
157d433a562SThomas Veerman 
158d433a562SThomas Veerman 	return (k->val);
159d433a562SThomas Veerman }
160d433a562SThomas Veerman 
161d433a562SThomas Veerman int
keycompare(const void * a,const void * b)162d433a562SThomas Veerman keycompare(const void *a, const void *b)
163d433a562SThomas Veerman {
164d433a562SThomas Veerman 
165d433a562SThomas Veerman 	return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name));
166d433a562SThomas Veerman }
167d433a562SThomas Veerman 
168d433a562SThomas Veerman void
mtree_err(const char * fmt,...)169d433a562SThomas Veerman mtree_err(const char *fmt, ...)
170d433a562SThomas Veerman {
171d433a562SThomas Veerman 	va_list ap;
172d433a562SThomas Veerman 
173d433a562SThomas Veerman 	va_start(ap, fmt);
174d433a562SThomas Veerman 	vwarnx(fmt, ap);
175d433a562SThomas Veerman 	va_end(ap);
176d433a562SThomas Veerman 	if (mtree_lineno)
177d433a562SThomas Veerman 		warnx("failed at line %lu of the specification",
178d433a562SThomas Veerman 		    (u_long) mtree_lineno);
179d433a562SThomas Veerman 	exit(1);
180d433a562SThomas Veerman 	/* NOTREACHED */
181d433a562SThomas Veerman }
182d433a562SThomas Veerman 
183d433a562SThomas Veerman void
addtag(slist_t * list,char * elem)184d433a562SThomas Veerman addtag(slist_t *list, char *elem)
185d433a562SThomas Veerman {
186d433a562SThomas Veerman 
187d433a562SThomas Veerman #define	TAG_CHUNK 20
188d433a562SThomas Veerman 
189d433a562SThomas Veerman 	if ((list->count % TAG_CHUNK) == 0) {
190d433a562SThomas Veerman 		char **new;
191d433a562SThomas Veerman 
192d433a562SThomas Veerman 		new = (char **)realloc(list->list, (list->count + TAG_CHUNK)
193d433a562SThomas Veerman 		    * sizeof(char *));
194d433a562SThomas Veerman 		if (new == NULL)
195d433a562SThomas Veerman 			mtree_err("memory allocation error");
196d433a562SThomas Veerman 		list->list = new;
197d433a562SThomas Veerman 	}
198d433a562SThomas Veerman 	list->list[list->count] = elem;
199d433a562SThomas Veerman 	list->count++;
200d433a562SThomas Veerman }
201d433a562SThomas Veerman 
202d433a562SThomas Veerman void
parsetags(slist_t * list,char * args)203d433a562SThomas Veerman parsetags(slist_t *list, char *args)
204d433a562SThomas Veerman {
205d433a562SThomas Veerman 	char	*p, *e;
206d433a562SThomas Veerman 	int	len;
207d433a562SThomas Veerman 
208d433a562SThomas Veerman 	if (args == NULL) {
209d433a562SThomas Veerman 		addtag(list, NULL);
210d433a562SThomas Veerman 		return;
211d433a562SThomas Veerman 	}
212d433a562SThomas Veerman 	while ((p = strsep(&args, ",")) != NULL) {
213d433a562SThomas Veerman 		if (*p == '\0')
214d433a562SThomas Veerman 			continue;
215d433a562SThomas Veerman 		len = strlen(p) + 3;	/* "," + p + ",\0" */
216d433a562SThomas Veerman 		if ((e = malloc(len)) == NULL)
217d433a562SThomas Veerman 			mtree_err("memory allocation error");
218d433a562SThomas Veerman 		snprintf(e, len, ",%s,", p);
219d433a562SThomas Veerman 		addtag(list, e);
220d433a562SThomas Veerman 	}
221d433a562SThomas Veerman }
222d433a562SThomas Veerman 
223d433a562SThomas Veerman /*
224d433a562SThomas Veerman  * matchtags
225d433a562SThomas Veerman  *	returns 0 if there's a match from the exclude list in the node's tags,
226d433a562SThomas Veerman  *	or there's an include list and no match.
227d433a562SThomas Veerman  *	return 1 otherwise.
228d433a562SThomas Veerman  */
229d433a562SThomas Veerman int
matchtags(NODE * node)230d433a562SThomas Veerman matchtags(NODE *node)
231d433a562SThomas Veerman {
232d433a562SThomas Veerman 	int	i;
233d433a562SThomas Veerman 
234d433a562SThomas Veerman 	if (node->tags) {
235d433a562SThomas Veerman 		for (i = 0; i < excludetags.count; i++)
236d433a562SThomas Veerman 			if (strstr(node->tags, excludetags.list[i]))
237d433a562SThomas Veerman 				break;
238d433a562SThomas Veerman 		if (i < excludetags.count)
239d433a562SThomas Veerman 			return (0);
240d433a562SThomas Veerman 
241d433a562SThomas Veerman 		for (i = 0; i < includetags.count; i++)
242d433a562SThomas Veerman 			if (strstr(node->tags, includetags.list[i]))
243d433a562SThomas Veerman 				break;
244d433a562SThomas Veerman 		if (i > 0 && i == includetags.count)
245d433a562SThomas Veerman 			return (0);
246d433a562SThomas Veerman 	} else if (includetags.count > 0) {
247d433a562SThomas Veerman 		return (0);
248d433a562SThomas Veerman 	}
249d433a562SThomas Veerman 	return (1);
250d433a562SThomas Veerman }
251d433a562SThomas Veerman 
252d433a562SThomas Veerman u_int
nodetoino(u_int type)253d433a562SThomas Veerman nodetoino(u_int type)
254d433a562SThomas Veerman {
255d433a562SThomas Veerman 
256d433a562SThomas Veerman 	switch (type) {
257d433a562SThomas Veerman 	case F_BLOCK:
258d433a562SThomas Veerman 		return S_IFBLK;
259d433a562SThomas Veerman 	case F_CHAR:
260d433a562SThomas Veerman 		return S_IFCHR;
261d433a562SThomas Veerman 	case F_DIR:
262d433a562SThomas Veerman 		return S_IFDIR;
263d433a562SThomas Veerman 	case F_FIFO:
264d433a562SThomas Veerman 		return S_IFIFO;
265d433a562SThomas Veerman 	case F_FILE:
266d433a562SThomas Veerman 		return S_IFREG;
267d433a562SThomas Veerman 	case F_LINK:
268d433a562SThomas Veerman 		return S_IFLNK;
269d433a562SThomas Veerman #ifdef S_IFSOCK
270d433a562SThomas Veerman 	case F_SOCK:
271d433a562SThomas Veerman 		return S_IFSOCK;
272d433a562SThomas Veerman #endif
273d433a562SThomas Veerman 	default:
274d433a562SThomas Veerman 		printf("unknown type %d", type);
275d433a562SThomas Veerman 		abort();
276d433a562SThomas Veerman 	}
277d433a562SThomas Veerman 	/* NOTREACHED */
278d433a562SThomas Veerman }
279d433a562SThomas Veerman 
280d433a562SThomas Veerman const char *
nodetype(u_int type)281d433a562SThomas Veerman nodetype(u_int type)
282d433a562SThomas Veerman {
283d433a562SThomas Veerman 
284d433a562SThomas Veerman 	return (inotype(nodetoino(type)));
285d433a562SThomas Veerman }
286d433a562SThomas Veerman 
287d433a562SThomas Veerman 
288d433a562SThomas Veerman const char *
inotype(u_int type)289d433a562SThomas Veerman inotype(u_int type)
290d433a562SThomas Veerman {
291d433a562SThomas Veerman 
292d433a562SThomas Veerman 	switch (type & S_IFMT) {
293d433a562SThomas Veerman 	case S_IFBLK:
294d433a562SThomas Veerman 		return ("block");
295d433a562SThomas Veerman 	case S_IFCHR:
296d433a562SThomas Veerman 		return ("char");
297d433a562SThomas Veerman 	case S_IFDIR:
298d433a562SThomas Veerman 		return ("dir");
299d433a562SThomas Veerman 	case S_IFIFO:
300d433a562SThomas Veerman 		return ("fifo");
301d433a562SThomas Veerman 	case S_IFREG:
302d433a562SThomas Veerman 		return ("file");
303d433a562SThomas Veerman 	case S_IFLNK:
304d433a562SThomas Veerman 		return ("link");
305d433a562SThomas Veerman #ifdef S_IFSOCK
306d433a562SThomas Veerman 	case S_IFSOCK:
307d433a562SThomas Veerman 		return ("socket");
308d433a562SThomas Veerman #endif
309d433a562SThomas Veerman #ifdef S_IFDOOR
310d433a562SThomas Veerman 	case S_IFDOOR:
311d433a562SThomas Veerman 		return ("door");
312d433a562SThomas Veerman #endif
313d433a562SThomas Veerman 	default:
314d433a562SThomas Veerman 		return ("unknown");
315d433a562SThomas Veerman 	}
316d433a562SThomas Veerman 	/* NOTREACHED */
317d433a562SThomas Veerman }
318