fix silly indirect-through-zero bug
[unix-history] / usr / src / usr.sbin / mtree / verify.c
CommitLineData
0a578b0d
KB
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
fc48cb7f 9static char sccsid[] = "@(#)verify.c 5.9 (Berkeley) %G%";
0a578b0d
KB
10#endif /* not lint */
11
cdae27a7 12#include <sys/param.h>
0a578b0d 13#include <sys/stat.h>
0a578b0d 14#include <dirent.h>
cdae27a7 15#include <fts.h>
7e5e86d9 16#include <unistd.h>
cdae27a7 17#include <errno.h>
0a578b0d
KB
18#include <stdio.h>
19#include "mtree.h"
20
6e4c29b1 21extern NODE *root;
0a578b0d 22
cdae27a7 23static char path[MAXPATHLEN];
0a578b0d
KB
24
25verify()
26{
cdae27a7
KB
27 vwalk();
28 miss(root, path);
0a578b0d
KB
29}
30
cdae27a7 31vwalk()
0a578b0d 32{
cdae27a7
KB
33 extern int ftsoptions, dflag, eflag, rflag;
34 register FTS *t;
35 register FTSENT *p;
6e4c29b1 36 register NODE *ep, *level;
037978a6 37 char *argv[2];
0badc11f 38 int ftsdepth = 0, specdepth = 0;
0a578b0d 39
037978a6
KB
40 argv[0] = ".";
41 argv[1] = (char *)NULL;
5ce44ab4 42 if (!(t = fts_open(argv, ftsoptions, (int (*)())NULL))) {
cdae27a7 43 (void)fprintf(stderr,
5ce44ab4 44 "mtree: fts_open: %s.\n", strerror(errno));
0a578b0d
KB
45 exit(1);
46 }
cdae27a7 47 level = root;
5ce44ab4 48 while (p = fts_read(t)) {
cdae27a7
KB
49 switch(p->fts_info) {
50 case FTS_D:
51 if (!strcmp(p->fts_name, "."))
52 continue;
0badc11f 53 ftsdepth++;
cdae27a7 54 break;
cdae27a7 55 case FTS_DP:
0badc11f
TH
56 ftsdepth--;
57 if (specdepth > ftsdepth) {
58 for (level = level->parent; level->prev;
59 level = level->prev);
60 specdepth--;
61 }
cdae27a7 62 continue;
fc48cb7f 63 case FTS_DNR:
cdae27a7 64 case FTS_ERR:
fc48cb7f 65 case FTS_NS:
cdae27a7
KB
66 (void)fprintf(stderr, "mtree: %s: %s.\n",
67 RP(p), strerror(errno));
68 continue;
cdae27a7
KB
69 default:
70 if (dflag)
71 continue;
0a578b0d 72 }
cdae27a7
KB
73
74 for (ep = level; ep; ep = ep->next)
7e5e86d9
KB
75 if (ep->flags & F_MAGIC && fnmatch(ep->name,
76 p->fts_name, FNM_PATHNAME|FNM_QUOTE) ||
77 !strcmp(ep->name, p->fts_name)) {
0a578b0d 78 ep->flags |= F_VISIT;
6e4c29b1 79 if (ep->flags & F_IGN) {
5ce44ab4 80 (void)fts_set(t, p, FTS_SKIP);
cdae27a7
KB
81 continue;
82 }
6e4c29b1
KB
83 compare(ep->name, ep, p);
84 if (ep->child && ep->type == F_DIR &&
0badc11f 85 p->fts_info == FTS_D) {
cdae27a7 86 level = ep->child;
0badc11f
TH
87 specdepth++;
88 }
cdae27a7 89 break;
0a578b0d 90 }
0badc11f 91
cdae27a7
KB
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");
0a578b0d 102 }
cdae27a7 103 (void)putchar('\n');
0a578b0d 104 }
5ce44ab4 105 (void)fts_set(t, p, FTS_SKIP);
0a578b0d 106 }
5ce44ab4 107 (void)fts_close(t);
0a578b0d
KB
108}
109
cdae27a7 110miss(p, tail)
6e4c29b1 111 register NODE *p;
0a578b0d
KB
112 register char *tail;
113{
114 extern int dflag, uflag;
115 register int create;
cdae27a7 116 register char *tp;
0a578b0d 117
cdae27a7 118 for (; p; p = p->next) {
6e4c29b1 119 if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
cdae27a7
KB
120 continue;
121 (void)strcpy(tail, p->name);
6e4c29b1 122 if (!(p->flags & F_VISIT))
cdae27a7 123 (void)printf("missing: %s", path);
6e4c29b1 124 if (p->type != F_DIR) {
cdae27a7 125 putchar('\n');
0a578b0d 126 continue;
cdae27a7
KB
127 }
128
0a578b0d 129 create = 0;
6e4c29b1 130 if (!(p->flags & F_VISIT) && uflag)
cdae27a7 131#define MINBITS (F_GROUP|F_MODE|F_OWNER)
6e4c29b1 132 if ((p->flags & MINBITS) != MINBITS)
cdae27a7
KB
133 (void)printf(" (not created -- group, mode or owner not specified)");
134 else if (mkdir(path, S_IRWXU))
135 (void)printf(" (not created: %s)",
0a578b0d
KB
136 strerror(errno));
137 else {
138 create = 1;
cdae27a7 139 (void)printf(" (created)");
0a578b0d 140 }
0a578b0d 141
6e4c29b1 142 if (!(p->flags & F_VISIT))
cdae27a7 143 (void)putchar('\n');
0a578b0d 144
cdae27a7
KB
145 for (tp = tail; *tp; ++tp);
146 *tp = '/';
147 miss(p->child, tp + 1);
148 *tp = '\0';
0a578b0d 149
cdae27a7
KB
150 if (!create)
151 continue;
6e4c29b1 152 if (chown(path, p->st_uid, p->st_gid)) {
cdae27a7
KB
153 (void)printf("%s: owner/group/mode not modified: %s\n",
154 path, strerror(errno));
155 continue;
156 }
6e4c29b1 157 if (chmod(path, p->st_mode))
cdae27a7
KB
158 (void)printf("%s: permissions not set: %s\n",
159 path, strerror(errno));
160 }
0a578b0d 161}