xref: /original-bsd/usr.sbin/mtree/verify.c (revision e718337e)
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.8 (Berkeley) 11/14/90";
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 
21 extern NODE *root;
22 
23 static char path[MAXPATHLEN];
24 
25 verify()
26 {
27 	vwalk();
28 	miss(root, path);
29 }
30 
31 vwalk()
32 {
33 	extern int ftsoptions, dflag, eflag, rflag;
34 	register FTS *t;
35 	register FTSENT *p;
36 	register NODE *ep, *level;
37 	char *argv[2];
38 	int ftsdepth = 0, specdepth = 0;
39 
40 	argv[0] = ".";
41 	argv[1] = (char *)NULL;
42 	if (!(t = fts_open(argv, ftsoptions, (int (*)())NULL))) {
43 		(void)fprintf(stderr,
44 		    "mtree: fts_open: %s.\n", strerror(errno));
45 		exit(1);
46 	}
47 	level = root;
48 	while (p = fts_read(t)) {
49 		switch(p->fts_info) {
50 		case FTS_D:
51 			if (!strcmp(p->fts_name, "."))
52 				continue;
53 			ftsdepth++;
54 			break;
55 		case FTS_DC:
56 			(void)fprintf(stderr,
57 			    "mtree: directory cycle: %s.\n", RP(p));
58 			continue;
59 		case FTS_DNR:
60 		case FTS_DNX:
61 			(void)fprintf(stderr,
62 			    "mtree: %s: unable to read or search.\n", RP(p));
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_ERR:
72 			(void)fprintf(stderr, "mtree: %s: %s.\n",
73 			    RP(p), strerror(errno));
74 			continue;
75 		case FTS_NS:
76 			(void)fprintf(stderr,
77 			    "mtree: can't stat: %s.\n", RP(p));
78 			continue;
79 		default:
80 			if (dflag)
81 				continue;
82 		}
83 
84 		for (ep = level; ep; ep = ep->next)
85 			if (ep->flags & F_MAGIC && fnmatch(ep->name,
86 			    p->fts_name, FNM_PATHNAME|FNM_QUOTE) ||
87 			    !strcmp(ep->name, p->fts_name)) {
88 				ep->flags |= F_VISIT;
89 				if (ep->flags & F_IGN) {
90 					(void)fts_set(t, p, FTS_SKIP);
91 					continue;
92 				}
93 				compare(ep->name, ep, p);
94 				if (ep->child && ep->type == F_DIR &&
95 				    p->fts_info == FTS_D) {
96 					level = ep->child;
97 					specdepth++;
98 				}
99 				break;
100 			}
101 
102 		if (ep)
103 			continue;
104 		if (!eflag) {
105 			(void)printf("extra: %s", RP(p));
106 			if (rflag) {
107 				if (unlink(p->fts_accpath)) {
108 					(void)printf(", not removed: %s",
109 					    strerror(errno));
110 				} else
111 					(void)printf(", removed");
112 			}
113 			(void)putchar('\n');
114 		}
115 		(void)fts_set(t, p, FTS_SKIP);
116 	}
117 	(void)fts_close(t);
118 }
119 
120 miss(p, tail)
121 	register NODE *p;
122 	register char *tail;
123 {
124 	extern int dflag, uflag;
125 	register int create;
126 	register char *tp;
127 
128 	for (; p; p = p->next) {
129 		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
130 			continue;
131 		(void)strcpy(tail, p->name);
132 		if (!(p->flags & F_VISIT))
133 			(void)printf("missing: %s", path);
134 		if (p->type != F_DIR) {
135 			putchar('\n');
136 			continue;
137 		}
138 
139 		create = 0;
140 		if (!(p->flags & F_VISIT) && uflag)
141 #define	MINBITS	(F_GROUP|F_MODE|F_OWNER)
142 			if ((p->flags & MINBITS) != MINBITS)
143 				(void)printf(" (not created -- group, mode or owner not specified)");
144 			else if (mkdir(path, S_IRWXU))
145 				(void)printf(" (not created: %s)",
146 				    strerror(errno));
147 			else {
148 				create = 1;
149 				(void)printf(" (created)");
150 			}
151 
152 		if (!(p->flags & F_VISIT))
153 			(void)putchar('\n');
154 
155 		for (tp = tail; *tp; ++tp);
156 		*tp = '/';
157 		miss(p->child, tp + 1);
158 		*tp = '\0';
159 
160 		if (!create)
161 			continue;
162 		if (chown(path, p->st_uid, p->st_gid)) {
163 			(void)printf("%s: owner/group/mode not modified: %s\n",
164 			    path, strerror(errno));
165 			continue;
166 		}
167 		if (chmod(path, p->st_mode))
168 			(void)printf("%s: permissions not set: %s\n",
169 			    path, strerror(errno));
170 	}
171 }
172