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