Home | History | Annotate | Line # | Download | only in mtree
spec.c revision 1.1
      1 /*-
      2  * Copyright (c) 1989 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      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. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char sccsid[] = "@(#)spec.c	5.14 (Berkeley) 3/2/91";
     36 #endif /* not lint */
     37 
     38 #include <sys/types.h>
     39 #include <pwd.h>
     40 #include <grp.h>
     41 #include <stdio.h>
     42 #include <errno.h>
     43 #include <ctype.h>
     44 #include "mtree.h"
     45 
     46 extern NODE *root;			/* root of the tree */
     47 
     48 static int lineno;			/* current spec line number */
     49 
     50 spec()
     51 {
     52 	register NODE *centry, *last;
     53 	register char *p;
     54 	NODE ginfo, *emalloc();
     55 	char buf[2048];
     56 
     57 	bzero((void *)&ginfo, sizeof(ginfo));
     58 	for (lineno = 1; fgets(buf, sizeof(buf), stdin); ++lineno) {
     59 		if (!(p = index(buf, '\n'))) {
     60 			(void)fprintf(stderr,
     61 			    "mtree: line %d too long.\n", lineno);
     62 			exit(1);
     63 		}
     64 		*p = '\0';
     65 		for (p = buf; *p && isspace(*p); ++p);
     66 		if (!*p || *p == '#')
     67 			continue;
     68 
     69 		/* grab file name, "$", "set", or "unset" */
     70 		if (!(p = strtok(p, "\n\t ")))
     71 			specerr();
     72 
     73 		if (p[0] == '/')
     74 			switch(p[1]) {
     75 			case 's':
     76 				if (strcmp(p + 1, "set"))
     77 					break;
     78 				set(&ginfo);
     79 				continue;
     80 			case 'u':
     81 				if (strcmp(p + 1, "unset"))
     82 					break;
     83 				unset(&ginfo);
     84 				continue;
     85 			}
     86 
     87 		if (index(p, '/')) {
     88 			(void)fprintf(stderr,
     89 			    "mtree: file names may not contain slashes.\n");
     90 			specerr();
     91 		}
     92 
     93 		if (!strcmp(p, "..")) {
     94 			/* don't go up, if haven't gone down */
     95 			if (!root)
     96 				noparent();
     97 			if (last->type != F_DIR || last->flags & F_DONE) {
     98 				if (last == root)
     99 					noparent();
    100 				last = last->parent;
    101 			}
    102 			last->flags |= F_DONE;
    103 			continue;
    104 		}
    105 
    106 		centry = emalloc(sizeof(NODE) + strlen(p));
    107 		*centry = ginfo;
    108 		(void)strcpy(centry->name, p);
    109 #define	MAGIC	"?*["
    110 		if (strpbrk(p, MAGIC))
    111 			centry->flags |= F_MAGIC;
    112 		set(centry);
    113 
    114 		if (!root) {
    115 			last = root = centry;
    116 			root->parent = root;
    117 		} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
    118 			centry->parent = last;
    119 			last = last->child = centry;
    120 		} else {
    121 			centry->parent = last->parent;
    122 			centry->prev = last;
    123 			last = last->next = centry;
    124 		}
    125 	}
    126 }
    127 
    128 set(ip)
    129 	register NODE *ip;
    130 {
    131 	register int type;
    132 	register char *kw, *val;
    133 	gid_t getgroup();
    134 	uid_t getowner();
    135 	long atol(), strtol();
    136 
    137 	while (kw = strtok((char *)NULL, "= \t\n")) {
    138 		ip->flags |= type = key(kw);
    139 		val = strtok((char *)NULL, " \t\n");
    140 		if (!val)
    141 			specerr();
    142 		switch(type) {
    143 		case F_CKSUM:
    144 			ip->cksum = atol(val);
    145 			break;
    146 		case F_GROUP:
    147 			ip->st_gid = getgroup(val);
    148 			break;
    149 		case F_IGN:
    150 			/* just set flag bit */
    151 			break;
    152 		case F_MODE: {
    153 			mode_t *m, *setmode();
    154 
    155 			if (!(m = setmode(val))) {
    156 				(void)fprintf(stderr,
    157 				    "mtree: invalid file mode %s.\n", val);
    158 				specerr();
    159 			}
    160 			ip->st_mode = getmode(m, 0);
    161 			break;
    162 		}
    163 		case F_NLINK:
    164 			ip->st_nlink = atoi(val);
    165 			break;
    166 		case F_OWNER:
    167 			ip->st_uid = getowner(val);
    168 			break;
    169 		case F_SIZE:
    170 			ip->st_size = atol(val);
    171 			break;
    172 		case F_SLINK:
    173 			if (!(ip->slink = strdup(val)))
    174 				nomem();
    175 			break;
    176 		case F_TIME:
    177 			ip->st_mtime = atol(val);
    178 			break;
    179 		case F_TYPE:
    180 			switch(*val) {
    181 			case 'b':
    182 				if (!strcmp(val, "block"))
    183 					ip->type = F_BLOCK;
    184 				break;
    185 			case 'c':
    186 				if (!strcmp(val, "char"))
    187 					ip->type = F_CHAR;
    188 				break;
    189 			case 'd':
    190 				if (!strcmp(val, "dir"))
    191 					ip->type = F_DIR;
    192 				break;
    193 			case 'f':
    194 				if (!strcmp(val, "file"))
    195 					ip->type = F_FILE;
    196 				if (!strcmp(val, "fifo"))
    197 					ip->type = F_FIFO;
    198 				break;
    199 			case 'l':
    200 				if (!strcmp(val, "link"))
    201 					ip->type = F_LINK;
    202 				break;
    203 			case 's':
    204 				if (!strcmp(val, "socket"))
    205 					ip->type = F_SOCK;
    206 				break;
    207 			default:
    208 				(void)fprintf(stderr,
    209 				    "mtree: unknown file type %s.\n", val);
    210 				specerr();
    211 			}
    212 			break;
    213 		}
    214 	}
    215 }
    216 
    217 unset(ip)
    218 	register NODE *ip;
    219 {
    220 	register char *p;
    221 
    222 	while (p = strtok((char *)NULL, "\n\t "))
    223 		ip->flags &= ~key(p);
    224 }
    225 
    226 key(p)
    227 	char *p;
    228 {
    229 	switch(*p) {
    230 	case 'c':
    231 		if (!strcmp(p, "cksum"))
    232 			return(F_CKSUM);
    233 		break;
    234 	case 'g':
    235 		if (!strcmp(p, "group"))
    236 			return(F_GROUP);
    237 		break;
    238 	case 'i':
    239 		if (!strcmp(p, "ignore"))
    240 			return(F_IGN);
    241 		break;
    242 	case 'l':
    243 		if (!strcmp(p, "link"))
    244 			return(F_SLINK);
    245 		break;
    246 	case 'm':
    247 		if (!strcmp(p, "mode"))
    248 			return(F_MODE);
    249 		break;
    250 	case 'n':
    251 		if (!strcmp(p, "nlink"))
    252 			return(F_NLINK);
    253 		break;
    254 	case 'o':
    255 		if (!strcmp(p, "owner"))
    256 			return(F_OWNER);
    257 		break;
    258 	case 's':
    259 		if (!strcmp(p, "size"))
    260 			return(F_SIZE);
    261 		break;
    262 	case 't':
    263 		if (!strcmp(p, "type"))
    264 			return(F_TYPE);
    265 		if (!strcmp(p, "time"))
    266 			return(F_TIME);
    267 		break;
    268 	}
    269 	(void)fprintf(stderr, "mtree: unknown keyword %s.\n", p);
    270 	specerr();
    271 	/* NOTREACHED */
    272 }
    273 
    274 
    275 uid_t
    276 getowner(p)
    277 	register char *p;
    278 {
    279 	struct passwd *pw;
    280 	int val;
    281 
    282 	if (isdigit(*p)) {
    283 		if ((val = atoi(p)) >= 0)
    284 			return((uid_t)val);
    285 		(void)fprintf(stderr, "mtree: illegal uid value %s.\n", p);
    286 	} else if (pw = getpwnam(p))
    287 		return(pw->pw_uid);
    288 	else
    289 		(void)fprintf(stderr, "mtree: unknown user %s.\n", p);
    290 	specerr();
    291 	/* NOTREACHED */
    292 }
    293 
    294 gid_t
    295 getgroup(p)
    296 	register char *p;
    297 {
    298 	struct group *gr;
    299 	int val;
    300 
    301 	if (isdigit(*p)) {
    302 		if ((val = atoi(p)) >= 0)
    303 			return((gid_t)val);
    304 		(void)fprintf(stderr, "mtree: illegal gid value %s.\n", p);
    305 	} else if (gr = getgrnam(p))
    306 		return(gr->gr_gid);
    307 	else
    308 		(void)fprintf(stderr, "mtree: unknown group %s.\n", p);
    309 	specerr();
    310 	/* NOTREACHED */
    311 }
    312 
    313 noparent()
    314 {
    315 	(void)fprintf(stderr, "mtree: no parent node.\n");
    316 	specerr();
    317 }
    318 
    319 specerr()
    320 {
    321 	(void)fprintf(stderr,
    322 	    "mtree: line %d of the specification is incorrect.\n", lineno);
    323 	exit(1);
    324 }
    325 
    326 NODE *
    327 emalloc(size)
    328 	int size;
    329 {
    330 	void *p;
    331 
    332 	/* NOSTRICT */
    333 	if (!(p = malloc((u_int)size)))
    334 		nomem();
    335 	bzero(p, size);
    336 	return((NODE *)p);
    337 }
    338 
    339 nomem()
    340 {
    341 	(void)fprintf(stderr, "mtree: %s.\n", strerror(ENOMEM));
    342 	exit(1);
    343 }
    344