compare.c revision 1553
1/*- 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. 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 35static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; 36#endif /* not lint */ 37 38#include <sys/param.h> 39#include <sys/stat.h> 40#include <fcntl.h> 41#include <fts.h> 42#include <errno.h> 43#include <stdio.h> 44#include <time.h> 45#include <unistd.h> 46#include "mtree.h" 47#include "extern.h" 48 49extern int uflag; 50 51static char *ftype __P((u_int)); 52 53#define INDENTNAMELEN 8 54#define LABEL \ 55 if (!label++) { \ 56 len = printf("%s: ", RP(p)); \ 57 if (len > INDENTNAMELEN) { \ 58 tab = "\t"; \ 59 (void)printf("\n"); \ 60 } else { \ 61 tab = ""; \ 62 (void)printf("%*s", INDENTNAMELEN - len, ""); \ 63 } \ 64 } 65 66int 67compare(name, s, p) 68 char *name; 69 register NODE *s; 70 register FTSENT *p; 71{ 72 extern int uflag; 73 u_long len, val; 74 int fd, label; 75 char *cp, *tab; 76 77 label = 0; 78 switch(s->type) { 79 case F_BLOCK: 80 if (!S_ISBLK(p->fts_statp->st_mode)) 81 goto typeerr; 82 break; 83 case F_CHAR: 84 if (!S_ISCHR(p->fts_statp->st_mode)) 85 goto typeerr; 86 break; 87 case F_DIR: 88 if (!S_ISDIR(p->fts_statp->st_mode)) 89 goto typeerr; 90 break; 91 case F_FIFO: 92 if (!S_ISFIFO(p->fts_statp->st_mode)) 93 goto typeerr; 94 break; 95 case F_FILE: 96 if (!S_ISREG(p->fts_statp->st_mode)) 97 goto typeerr; 98 break; 99 case F_LINK: 100 if (!S_ISLNK(p->fts_statp->st_mode)) 101 goto typeerr; 102 break; 103 case F_SOCK: 104 if (!S_ISSOCK(p->fts_statp->st_mode)) { 105typeerr: LABEL; 106 (void)printf("\ttype (%s, %s)\n", 107 ftype(s->type), inotype(p->fts_statp->st_mode)); 108 } 109 break; 110 } 111 /* Set the uid/gid first, then set the mode. */ 112 if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) { 113 LABEL; 114 (void)printf("%suser (%u, %u", 115 tab, s->st_uid, p->fts_statp->st_uid); 116 if (uflag) 117 if (chown(p->fts_accpath, s->st_uid, -1)) 118 (void)printf(", not modified: %s)\n", 119 strerror(errno)); 120 else 121 (void)printf(", modified)\n"); 122 else 123 (void)printf(")\n"); 124 tab = "\t"; 125 } 126 if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) { 127 LABEL; 128 (void)printf("%sgid (%u, %u", 129 tab, s->st_gid, p->fts_statp->st_gid); 130 if (uflag) 131 if (chown(p->fts_accpath, -1, s->st_gid)) 132 (void)printf(", not modified: %s)\n", 133 strerror(errno)); 134 else 135 (void)printf(", modified)\n"); 136 else 137 (void)printf(")\n"); 138 tab = "\t"; 139 } 140 if (s->flags & F_MODE && 141 s->st_mode != (p->fts_statp->st_mode & MBITS)) { 142 LABEL; 143 (void)printf("%spermissions (%#o, %#o", 144 tab, s->st_mode, p->fts_statp->st_mode & MBITS); 145 if (uflag) 146 if (chmod(p->fts_accpath, s->st_mode)) 147 (void)printf(", not modified: %s)\n", 148 strerror(errno)); 149 else 150 (void)printf(", modified)\n"); 151 else 152 (void)printf(")\n"); 153 tab = "\t"; 154 } 155 if (s->flags & F_NLINK && s->type != F_DIR && 156 s->st_nlink != p->fts_statp->st_nlink) { 157 LABEL; 158 (void)printf("%slink count (%u, %u)\n", 159 tab, s->st_nlink, p->fts_statp->st_nlink); 160 tab = "\t"; 161 } 162 if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) { 163 LABEL; 164 (void)printf("%ssize (%qd, %qd)\n", 165 tab, s->st_size, p->fts_statp->st_size); 166 tab = "\t"; 167 } 168 /* 169 * XXX 170 * Catches nano-second differences, but doesn't display them. 171 */ 172 if (s->flags & F_TIME && 173 s->st_mtimespec.ts_sec != p->fts_statp->st_mtimespec.ts_sec || 174 s->st_mtimespec.ts_nsec != p->fts_statp->st_mtimespec.ts_nsec) { 175 LABEL; 176 (void)printf("%smodification time (%.24s, ", 177 tab, ctime(&s->st_mtimespec.ts_sec)); 178 (void)printf("%.24s)\n", 179 ctime(&p->fts_statp->st_mtimespec.ts_sec)); 180 tab = "\t"; 181 } 182 if (s->flags & F_CKSUM) 183 if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) { 184 LABEL; 185 (void)printf("%scksum: %s: %s\n", 186 tab, p->fts_accpath, strerror(errno)); 187 tab = "\t"; 188 } else if (crc(fd, &val, &len)) { 189 (void)close(fd); 190 LABEL; 191 (void)printf("%scksum: %s: %s\n", 192 tab, p->fts_accpath, strerror(errno)); 193 tab = "\t"; 194 } else { 195 (void)close(fd); 196 if (s->cksum != val) { 197 LABEL; 198 (void)printf("%scksum (%lu, %lu)\n", 199 tab, s->cksum, val); 200 } 201 tab = "\t"; 202 } 203 if (s->flags & F_SLINK && strcmp(cp = rlink(name), s->slink)) { 204 LABEL; 205 (void)printf("%slink ref (%s, %s)\n", tab, cp, s->slink); 206 } 207 return (label); 208} 209 210char * 211inotype(type) 212 u_int type; 213{ 214 switch(type & S_IFMT) { 215 case S_IFBLK: 216 return ("block"); 217 case S_IFCHR: 218 return ("char"); 219 case S_IFDIR: 220 return ("dir"); 221 case S_IFIFO: 222 return ("fifo"); 223 case S_IFREG: 224 return ("file"); 225 case S_IFLNK: 226 return ("link"); 227 case S_IFSOCK: 228 return ("socket"); 229 default: 230 return ("unknown"); 231 } 232 /* NOTREACHED */ 233} 234 235static char * 236ftype(type) 237 u_int type; 238{ 239 switch(type) { 240 case F_BLOCK: 241 return ("block"); 242 case F_CHAR: 243 return ("char"); 244 case F_DIR: 245 return ("dir"); 246 case F_FIFO: 247 return ("fifo"); 248 case F_FILE: 249 return ("file"); 250 case F_LINK: 251 return ("link"); 252 case F_SOCK: 253 return ("socket"); 254 default: 255 return ("unknown"); 256 } 257 /* NOTREACHED */ 258} 259 260char * 261rlink(name) 262 char *name; 263{ 264 static char lbuf[MAXPATHLEN]; 265 register int len; 266 267 if ((len = readlink(name, lbuf, sizeof(lbuf))) == -1) 268 err("%s: %s", name, strerror(errno)); 269 lbuf[len] = '\0'; 270 return (lbuf); 271} 272