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