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