1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static char sccsid[] = "@(#)verify.c 5.9 (Berkeley) 3/12/91"; 36 #endif /* not lint */ 37 38 #include <sys/param.h> 39 #include <sys/stat.h> 40 #include <dirent.h> 41 #include <fts.h> 42 #include <unistd.h> 43 #include <errno.h> 44 #include <stdio.h> 45 #include <fnmatch.h> 46 #include "mtree.h" 47 48 extern NODE *root; 49 50 static char path[MAXPATHLEN]; 51 52 verify() 53 { 54 vwalk(); 55 miss(root, path); 56 } 57 58 vwalk() 59 { 60 extern int ftsoptions, dflag, eflag, rflag; 61 register FTS *t; 62 register FTSENT *p; 63 register NODE *ep, *level; 64 char *argv[2]; 65 int ftsdepth = 0, specdepth = 0; 66 67 argv[0] = "."; 68 argv[1] = (char *)NULL; 69 if (!(t = fts_open(argv, ftsoptions, (int (*)())NULL))) { 70 (void)fprintf(stderr, 71 "mtree: fts_open: %s.\n", strerror(errno)); 72 exit(1); 73 } 74 level = root; 75 while (p = fts_read(t)) { 76 switch(p->fts_info) { 77 case FTS_D: 78 if (!strcmp(p->fts_name, ".")) 79 continue; 80 ftsdepth++; 81 break; 82 case FTS_DP: 83 ftsdepth--; 84 if (specdepth > ftsdepth) { 85 for (level = level->parent; level->prev; 86 level = level->prev); 87 specdepth--; 88 } 89 continue; 90 case FTS_DNR: 91 case FTS_ERR: 92 case FTS_NS: 93 (void)fprintf(stderr, "mtree: %s: %s.\n", 94 RP(p), strerror(errno)); 95 continue; 96 default: 97 if (dflag) 98 continue; 99 } 100 101 for (ep = level; ep; ep = ep->next) 102 if (ep->flags & F_MAGIC && !fnmatch(ep->name, 103 p->fts_name, FNM_PATHNAME) || 104 !strcmp(ep->name, p->fts_name)) { 105 ep->flags |= F_VISIT; 106 if (ep->flags & F_IGN) { 107 (void)fts_set(t, p, FTS_SKIP); 108 continue; 109 } 110 compare(ep->name, ep, p); 111 if (ep->child && ep->type == F_DIR && 112 p->fts_info == FTS_D) { 113 level = ep->child; 114 specdepth++; 115 } 116 break; 117 } 118 119 if (ep) 120 continue; 121 if (!eflag) { 122 (void)printf("extra: %s", RP(p)); 123 if (rflag) { 124 if (unlink(p->fts_accpath)) { 125 (void)printf(", not removed: %s", 126 strerror(errno)); 127 } else 128 (void)printf(", removed"); 129 } 130 (void)putchar('\n'); 131 } 132 (void)fts_set(t, p, FTS_SKIP); 133 } 134 (void)fts_close(t); 135 } 136 137 miss(p, tail) 138 register NODE *p; 139 register char *tail; 140 { 141 extern int dflag, uflag; 142 register int create; 143 register char *tp; 144 145 for (; p; p = p->next) { 146 if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) 147 continue; 148 (void)strcpy(tail, p->name); 149 if (!(p->flags & F_VISIT)) 150 (void)printf("missing: %s", path); 151 if (p->type != F_DIR) { 152 putchar('\n'); 153 continue; 154 } 155 156 create = 0; 157 if (!(p->flags & F_VISIT) && uflag) 158 #define MINBITS (F_GROUP|F_MODE|F_OWNER) 159 if ((p->flags & MINBITS) != MINBITS) 160 (void)printf(" (not created -- group, mode or owner not specified)"); 161 else if (mkdir(path, S_IRWXU)) 162 (void)printf(" (not created: %s)", 163 strerror(errno)); 164 else { 165 create = 1; 166 (void)printf(" (created)"); 167 } 168 169 if (!(p->flags & F_VISIT)) 170 (void)putchar('\n'); 171 172 for (tp = tail; *tp; ++tp); 173 *tp = '/'; 174 miss(p->child, tp + 1); 175 *tp = '\0'; 176 177 if (!create) 178 continue; 179 if (chown(path, p->st_uid, p->st_gid)) { 180 (void)printf("%s: owner/group/mode not modified: %s\n", 181 path, strerror(errno)); 182 continue; 183 } 184 if (chmod(path, p->st_mode)) 185 (void)printf("%s: permissions not set: %s\n", 186 path, strerror(errno)); 187 } 188 } 189