xref: /original-bsd/usr.sbin/mtree/verify.c (revision 1d37a0a0)
1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)verify.c	5.10 (Berkeley) 12/11/91";
10 #endif /* not lint */
11 
12 #include <sys/param.h>
13 #include <sys/stat.h>
14 #include <dirent.h>
15 #include <fts.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #include "mtree.h"
20 #include "extern.h"
21 
22 extern int crc_total, ftsoptions;
23 extern int dflag, eflag, rflag, sflag, uflag;
24 extern char fullpath[MAXPATHLEN];
25 
26 static NODE *root;
27 static char path[MAXPATHLEN];
28 
29 static void	miss __P((NODE *, char *));
30 static int	vwalk __P((void));
31 
32 int
33 verify()
34 {
35 	int rval;
36 
37 	root = spec();
38 	rval = vwalk();
39 	miss(root, path);
40 	return (rval);
41 }
42 
43 static int
44 vwalk()
45 {
46 	register FTS *t;
47 	register FTSENT *p;
48 	register NODE *ep, *level;
49 	int ftsdepth, specdepth, rval;
50 	char *argv[2];
51 
52 	argv[0] = ".";
53 	argv[1] = NULL;
54 	if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
55 		err("fts_open: %s", strerror(errno));
56 	level = root;
57 	ftsdepth = specdepth = rval = 0;
58 	while (p = fts_read(t)) {
59 		switch(p->fts_info) {
60 		case FTS_D:
61 			++ftsdepth;
62 			break;
63 		case FTS_DP:
64 			--ftsdepth;
65 			if (specdepth > ftsdepth) {
66 				for (level = level->parent; level->prev;
67 				      level = level->prev);
68 				--specdepth;
69 			}
70 			continue;
71 		case FTS_DNR:
72 		case FTS_ERR:
73 		case FTS_NS:
74 			(void)fprintf(stderr, "mtree: %s: %s\n",
75 			    RP(p), strerror(errno));
76 			continue;
77 		default:
78 			if (dflag)
79 				continue;
80 		}
81 
82 		for (ep = level; ep; ep = ep->next)
83 			if (ep->flags & F_MAGIC && fnmatch(ep->name,
84 			    p->fts_name, FNM_PATHNAME|FNM_QUOTE) ||
85 			    !strcmp(ep->name, p->fts_name)) {
86 				ep->flags |= F_VISIT;
87 				if (ep->flags & F_IGN) {
88 					(void)fts_set(t, p, FTS_SKIP);
89 					continue;
90 				}
91 				if (compare(ep->name, ep, p))
92 					rval = MISMATCHEXIT;
93 				if (ep->child && ep->type == F_DIR &&
94 				    p->fts_info == FTS_D) {
95 					level = ep->child;
96 					++specdepth;
97 				}
98 				break;
99 			}
100 
101 		if (ep)
102 			continue;
103 		if (!eflag) {
104 			(void)printf("extra: %s", RP(p));
105 			if (rflag) {
106 				if (unlink(p->fts_accpath)) {
107 					(void)printf(", not removed: %s",
108 					    strerror(errno));
109 				} else
110 					(void)printf(", removed");
111 			}
112 			(void)putchar('\n');
113 		}
114 		(void)fts_set(t, p, FTS_SKIP);
115 	}
116 	(void)fts_close(t);
117 	if (sflag)
118 		(void)fprintf(stderr,
119 		    "mtree: %s checksum: %lu\n", fullpath, crc_total);
120 	return (rval);
121 }
122 
123 static void
124 miss(p, tail)
125 	register NODE *p;
126 	register char *tail;
127 {
128 	register int create;
129 	register char *tp;
130 
131 	for (; p; p = p->next) {
132 		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
133 			continue;
134 		(void)strcpy(tail, p->name);
135 		if (!(p->flags & F_VISIT))
136 			(void)printf("missing: %s", path);
137 		if (p->type != F_DIR) {
138 			putchar('\n');
139 			continue;
140 		}
141 
142 		create = 0;
143 		if (!(p->flags & F_VISIT) && uflag)
144 			if (!(p->flags & (F_UID | F_UNAME)))
145 			    (void)printf(" (not created: user not specified)");
146 			else if (!(p->flags & (F_GID | F_GNAME)))
147 			    (void)printf(" (not created: group not specified)");
148 			else if (!(p->flags & F_MODE))
149 			    (void)printf(" (not created: mode not specified)");
150 			else if (mkdir(path, S_IRWXU))
151 				(void)printf(" (not created: %s)",
152 				    strerror(errno));
153 			else {
154 				create = 1;
155 				(void)printf(" (created)");
156 			}
157 
158 		if (!(p->flags & F_VISIT))
159 			(void)putchar('\n');
160 
161 		for (tp = tail; *tp; ++tp);
162 		*tp = '/';
163 		miss(p->child, tp + 1);
164 		*tp = '\0';
165 
166 		if (!create)
167 			continue;
168 		if (chown(path, p->st_uid, p->st_gid)) {
169 			(void)printf("%s: user/group/mode not modified: %s\n",
170 			    path, strerror(errno));
171 			continue;
172 		}
173 		if (chmod(path, p->st_mode))
174 			(void)printf("%s: permissions not set: %s\n",
175 			    path, strerror(errno));
176 	}
177 }
178