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