2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * @(#)spec.c 8.1 (Berkeley) 6/6/93
30 * $FreeBSD: src/usr.sbin/mtree/spec.c,v 1.13.2.1 2000/06/28 02:33:17 joe Exp $
31 * $DragonFly: src/usr.sbin/mtree/spec.c,v 1.6 2004/08/30 19:27:22 eirikn Exp $
34 #include <sys/types.h>
48 int lineno; /* Current spec line number. */
50 static void set(char *, NODE *);
51 static void unset(char *, NODE *);
62 centry = last = root = NULL;
63 bzero(&ginfo, sizeof(ginfo));
65 for (lineno = 1; fgets(buf, sizeof(buf), stdin);
66 ++lineno, c_cur = c_next, c_next = 0) {
67 /* Skip empty lines. */
71 /* Find end of line. */
72 if ((p = strchr(buf, '\n')) == NULL)
73 errx(1, "line %d too long", lineno);
75 /* See if next line is continuation line. */
81 /* Null-terminate the line. */
84 /* Skip leading whitespace. */
85 for (p = buf; *p && isspace(*p); ++p);
87 /* If nothing but whitespace or comment char, continue. */
92 fprintf(stderr, "line %d: {%s}\n", lineno, p);
99 /* Grab file name, "$", "set", or "unset". */
100 if ((p = strtok(p, "\n\t ")) == NULL)
101 errx(1, "line %d: missing field", lineno);
106 if (strcmp(p + 1, "set"))
111 if (strcmp(p + 1, "unset"))
118 errx(1, "line %d: slash character in file name",
121 if (!strcmp(p, "..")) {
122 /* Don't go up, if haven't gone down. */
125 if (last->type != F_DIR || last->flags & F_DONE) {
130 last->flags |= F_DONE;
133 noparent: errx(1, "line %d: no parent node", lineno);
136 if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
140 if (strpbrk(p, MAGIC))
141 centry->flags |= F_MAGIC;
142 if (strunvis(centry->name, p) == -1) {
143 warnx("filename %s is ill-encoded and literally used",
145 strcpy(centry->name, p);
150 last = root = centry;
152 } else if (last->type == F_DIR && !(last->flags & F_DONE)) {
153 centry->parent = last;
154 last = last->child = centry;
156 centry->parent = last->parent;
158 last = last->next = centry;
165 set(char *t, NODE *ip)
168 char *kw, *val = NULL;
175 for (; (kw = strtok(t, "= \t\n")); t = NULL) {
176 ip->flags |= type = parsekey(kw, &value);
177 if (value && (val = strtok(NULL, " \t\n")) == NULL)
178 errx(1, "line %d: missing value", lineno);
181 ip->cksum = strtoul(val, &ep, 10);
183 errx(1, "line %d: invalid checksum %s",
187 ip->md5digest = strdup(val);
193 ip->sha1digest = strdup(val);
194 if(!ip->sha1digest) {
199 ip->rmd160digest = strdup(val);
200 if(!ip->rmd160digest) {
205 if (strcmp("none", val) == 0)
207 else if (strtofflags(&val, &ip->st_flags, NULL) != 0)
208 errx(1, "line %d: invalid flag %s",lineno, val);
211 ip->st_gid = strtoul(val, &ep, 10);
213 errx(1, "line %d: invalid gid %s", lineno, val);
216 if ((gr = getgrnam(val)) == NULL)
217 errx(1, "line %d: unknown group %s", lineno, val);
218 ip->st_gid = gr->gr_gid;
221 /* just set flag bit */
224 if ((m = setmode(val)) == NULL)
225 errx(1, "line %d: invalid file mode %s",
227 ip->st_mode = getmode(m, 0);
231 ip->st_nlink = strtoul(val, &ep, 10);
233 errx(1, "line %d: invalid link count %s",
237 ip->st_size = strtoq(val, &ep, 10);
239 errx(1, "line %d: invalid size %s",
243 if ((ip->slink = strdup(val)) == NULL)
247 ip->st_mtimespec.tv_sec = strtoul(val, &ep, 10);
249 errx(1, "line %d: invalid time %s",
252 ip->st_mtimespec.tv_nsec = strtoul(val, &ep, 10);
254 errx(1, "line %d: invalid time %s",
260 if (!strcmp(val, "block"))
264 if (!strcmp(val, "char"))
268 if (!strcmp(val, "dir"))
272 if (!strcmp(val, "file"))
274 if (!strcmp(val, "fifo"))
278 if (!strcmp(val, "link"))
282 if (!strcmp(val, "socket"))
286 errx(1, "line %d: unknown file type %s",
291 ip->st_uid = strtoul(val, &ep, 10);
293 errx(1, "line %d: invalid uid %s", lineno, val);
296 if ((pw = getpwnam(val)) == NULL)
297 errx(1, "line %d: unknown user %s", lineno, val);
298 ip->st_uid = pw->pw_uid;
305 unset(char *t, NODE *ip)
309 while ((p = strtok(t, "\n\t ")))
310 ip->flags &= ~parsekey(p, NULL);