xref: /original-bsd/usr.sbin/mtree/verify.c (revision 2852c678)
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.9 (Berkeley) 03/12/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 
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_DP:
56 			ftsdepth--;
57 			if (specdepth > ftsdepth) {
58 				for (level = level->parent; level->prev;
59 				      level = level->prev);
60 				specdepth--;
61 			}
62 			continue;
63 		case FTS_DNR:
64 		case FTS_ERR:
65 		case FTS_NS:
66 			(void)fprintf(stderr, "mtree: %s: %s.\n",
67 			    RP(p), strerror(errno));
68 			continue;
69 		default:
70 			if (dflag)
71 				continue;
72 		}
73 
74 		for (ep = level; ep; ep = ep->next)
75 			if (ep->flags & F_MAGIC && fnmatch(ep->name,
76 			    p->fts_name, FNM_PATHNAME|FNM_QUOTE) ||
77 			    !strcmp(ep->name, p->fts_name)) {
78 				ep->flags |= F_VISIT;
79 				if (ep->flags & F_IGN) {
80 					(void)fts_set(t, p, FTS_SKIP);
81 					continue;
82 				}
83 				compare(ep->name, ep, p);
84 				if (ep->child && ep->type == F_DIR &&
85 				    p->fts_info == FTS_D) {
86 					level = ep->child;
87 					specdepth++;
88 				}
89 				break;
90 			}
91 
92 		if (ep)
93 			continue;
94 		if (!eflag) {
95 			(void)printf("extra: %s", RP(p));
96 			if (rflag) {
97 				if (unlink(p->fts_accpath)) {
98 					(void)printf(", not removed: %s",
99 					    strerror(errno));
100 				} else
101 					(void)printf(", removed");
102 			}
103 			(void)putchar('\n');
104 		}
105 		(void)fts_set(t, p, FTS_SKIP);
106 	}
107 	(void)fts_close(t);
108 }
109 
110 miss(p, tail)
111 	register NODE *p;
112 	register char *tail;
113 {
114 	extern int dflag, uflag;
115 	register int create;
116 	register char *tp;
117 
118 	for (; p; p = p->next) {
119 		if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
120 			continue;
121 		(void)strcpy(tail, p->name);
122 		if (!(p->flags & F_VISIT))
123 			(void)printf("missing: %s", path);
124 		if (p->type != F_DIR) {
125 			putchar('\n');
126 			continue;
127 		}
128 
129 		create = 0;
130 		if (!(p->flags & F_VISIT) && uflag)
131 #define	MINBITS	(F_GROUP|F_MODE|F_OWNER)
132 			if ((p->flags & MINBITS) != MINBITS)
133 				(void)printf(" (not created -- group, mode or owner not specified)");
134 			else if (mkdir(path, S_IRWXU))
135 				(void)printf(" (not created: %s)",
136 				    strerror(errno));
137 			else {
138 				create = 1;
139 				(void)printf(" (created)");
140 			}
141 
142 		if (!(p->flags & F_VISIT))
143 			(void)putchar('\n');
144 
145 		for (tp = tail; *tp; ++tp);
146 		*tp = '/';
147 		miss(p->child, tp + 1);
148 		*tp = '\0';
149 
150 		if (!create)
151 			continue;
152 		if (chown(path, p->st_uid, p->st_gid)) {
153 			(void)printf("%s: owner/group/mode not modified: %s\n",
154 			    path, strerror(errno));
155 			continue;
156 		}
157 		if (chmod(path, p->st_mode))
158 			(void)printf("%s: permissions not set: %s\n",
159 			    path, strerror(errno));
160 	}
161 }
162