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.10 (Berkeley) 12/11/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 #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 (ep->flags & F_IGN) { 88 (void)fts_set(t, p, FTS_SKIP); 89 continue; 90 } 91 if (compare(ep->name, ep, p)) 92 rval = MISMATCHEXIT; 93 if (ep->child && ep->type == F_DIR && 94 p->fts_info == FTS_D) { 95 level = ep->child; 96 ++specdepth; 97 } 98 break; 99 } 100 101 if (ep) 102 continue; 103 if (!eflag) { 104 (void)printf("extra: %s", RP(p)); 105 if (rflag) { 106 if (unlink(p->fts_accpath)) { 107 (void)printf(", not removed: %s", 108 strerror(errno)); 109 } else 110 (void)printf(", removed"); 111 } 112 (void)putchar('\n'); 113 } 114 (void)fts_set(t, p, FTS_SKIP); 115 } 116 (void)fts_close(t); 117 if (sflag) 118 (void)fprintf(stderr, 119 "mtree: %s checksum: %lu\n", fullpath, crc_total); 120 return (rval); 121 } 122 123 static void 124 miss(p, tail) 125 register NODE *p; 126 register char *tail; 127 { 128 register int create; 129 register char *tp; 130 131 for (; p; p = p->next) { 132 if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 133 continue; 134 (void)strcpy(tail, p->name); 135 if (!(p->flags & F_VISIT)) 136 (void)printf("missing: %s", path); 137 if (p->type != F_DIR) { 138 putchar('\n'); 139 continue; 140 } 141 142 create = 0; 143 if (!(p->flags & F_VISIT) && uflag) 144 if (!(p->flags & (F_UID | F_UNAME))) 145 (void)printf(" (not created: user not specified)"); 146 else if (!(p->flags & (F_GID | F_GNAME))) 147 (void)printf(" (not created: group not specified)"); 148 else if (!(p->flags & F_MODE)) 149 (void)printf(" (not created: mode not specified)"); 150 else if (mkdir(path, S_IRWXU)) 151 (void)printf(" (not created: %s)", 152 strerror(errno)); 153 else { 154 create = 1; 155 (void)printf(" (created)"); 156 } 157 158 if (!(p->flags & F_VISIT)) 159 (void)putchar('\n'); 160 161 for (tp = tail; *tp; ++tp); 162 *tp = '/'; 163 miss(p->child, tp + 1); 164 *tp = '\0'; 165 166 if (!create) 167 continue; 168 if (chown(path, p->st_uid, p->st_gid)) { 169 (void)printf("%s: user/group/mode not modified: %s\n", 170 path, strerror(errno)); 171 continue; 172 } 173 if (chmod(path, p->st_mode)) 174 (void)printf("%s: permissions not set: %s\n", 175 path, strerror(errno)); 176 } 177 } 178