Home | History | Annotate | Line # | Download | only in mtree
compare.c revision 1.12
      1 /*	$NetBSD: compare.c,v 1.12 1997/07/11 07:05:29 mikel Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1989, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #ifndef lint
     37 #if 0
     38 static char sccsid[] = "@(#)compare.c	8.1 (Berkeley) 6/6/93";
     39 #else
     40 static char rcsid[] = "$NetBSD: compare.c,v 1.12 1997/07/11 07:05:29 mikel Exp $";
     41 #endif
     42 #endif /* not lint */
     43 
     44 #include <sys/param.h>
     45 #include <sys/stat.h>
     46 #include <fcntl.h>
     47 #include <fts.h>
     48 #include <errno.h>
     49 #include <stdio.h>
     50 #include <time.h>
     51 #include <unistd.h>
     52 #include "mtree.h"
     53 #include "extern.h"
     54 
     55 extern int tflag, uflag;
     56 
     57 static char *ftype __P((u_int));
     58 
     59 #define	INDENTNAMELEN	8
     60 #define	LABEL \
     61 	if (!label++) { \
     62 		len = printf("%s: ", RP(p)); \
     63 		if (len > INDENTNAMELEN) { \
     64 			tab = "\t"; \
     65 			(void)printf("\n"); \
     66 		} else { \
     67 			tab = ""; \
     68 			(void)printf("%*s", INDENTNAMELEN - (int)len, ""); \
     69 		} \
     70 	}
     71 
     72 int
     73 compare(name, s, p)
     74 	char *name;
     75 	register NODE *s;
     76 	register FTSENT *p;
     77 {
     78 	u_long len, val;
     79 	int fd, label;
     80 	char *cp, *tab;
     81 
     82 	label = 0;
     83 	switch(s->type) {
     84 	case F_BLOCK:
     85 		if (!S_ISBLK(p->fts_statp->st_mode))
     86 			goto typeerr;
     87 		break;
     88 	case F_CHAR:
     89 		if (!S_ISCHR(p->fts_statp->st_mode))
     90 			goto typeerr;
     91 		break;
     92 	case F_DIR:
     93 		if (!S_ISDIR(p->fts_statp->st_mode))
     94 			goto typeerr;
     95 		break;
     96 	case F_FIFO:
     97 		if (!S_ISFIFO(p->fts_statp->st_mode))
     98 			goto typeerr;
     99 		break;
    100 	case F_FILE:
    101 		if (!S_ISREG(p->fts_statp->st_mode))
    102 			goto typeerr;
    103 		break;
    104 	case F_LINK:
    105 		if (!S_ISLNK(p->fts_statp->st_mode))
    106 			goto typeerr;
    107 		break;
    108 	case F_SOCK:
    109 		if (!S_ISSOCK(p->fts_statp->st_mode)) {
    110 typeerr:		LABEL;
    111 			(void)printf("\ttype (%s, %s)\n",
    112 			    ftype(s->type), inotype(p->fts_statp->st_mode));
    113 		}
    114 		break;
    115 	}
    116 	/* Set the uid/gid first, then set the mode. */
    117 	if (s->flags & (F_UID | F_UNAME) && s->st_uid != p->fts_statp->st_uid) {
    118 		LABEL;
    119 		(void)printf("%suser (%u, %u",
    120 		    tab, s->st_uid, p->fts_statp->st_uid);
    121 		if (uflag)
    122 			if (chown(p->fts_accpath, s->st_uid, -1))
    123 				(void)printf(", not modified: %s)\n",
    124 				    strerror(errno));
    125 			else
    126 				(void)printf(", modified)\n");
    127 		else
    128 			(void)printf(")\n");
    129 		tab = "\t";
    130 	}
    131 	if (s->flags & (F_GID | F_GNAME) && s->st_gid != p->fts_statp->st_gid) {
    132 		LABEL;
    133 		(void)printf("%sgid (%u, %u",
    134 		    tab, s->st_gid, p->fts_statp->st_gid);
    135 		if (uflag)
    136 			if (chown(p->fts_accpath, -1, s->st_gid))
    137 				(void)printf(", not modified: %s)\n",
    138 				    strerror(errno));
    139 			else
    140 				(void)printf(", modified)\n");
    141 		else
    142 			(void)printf(")\n");
    143 		tab = "\t";
    144 	}
    145 	if (s->flags & F_MODE &&
    146 	    s->st_mode != (p->fts_statp->st_mode & MBITS)) {
    147 		LABEL;
    148 		(void)printf("%spermissions (%#o, %#o",
    149 		    tab, s->st_mode, p->fts_statp->st_mode & MBITS);
    150 		if (uflag)
    151 			if (chmod(p->fts_accpath, s->st_mode))
    152 				(void)printf(", not modified: %s)\n",
    153 				    strerror(errno));
    154 			else
    155 				(void)printf(", modified)\n");
    156 		else
    157 			(void)printf(")\n");
    158 		tab = "\t";
    159 	}
    160 	if (s->flags & F_NLINK && s->type != F_DIR &&
    161 	    s->st_nlink != p->fts_statp->st_nlink) {
    162 		LABEL;
    163 		(void)printf("%slink count (%u, %u)\n",
    164 		    tab, s->st_nlink, p->fts_statp->st_nlink);
    165 		tab = "\t";
    166 	}
    167 	if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size) {
    168 		LABEL;
    169 		(void)printf("%ssize (%qd, %qd)\n",
    170 		    tab, s->st_size, p->fts_statp->st_size);
    171 		tab = "\t";
    172 	}
    173 	/*
    174 	 * XXX
    175 	 * Since utimes(2) only takes a timeval, there's no point in
    176 	 * comparing the low bits of the timespec nanosecond field.  This
    177 	 * will only result in mismatches that we can never fix.
    178 	 *
    179 	 * Doesn't display microsecond differences.
    180 	 */
    181 	if (s->flags & F_TIME) {
    182 		struct timeval tv[2];
    183 
    184 		TIMESPEC_TO_TIMEVAL(&tv[0], &s->st_mtimespec);
    185 		TIMESPEC_TO_TIMEVAL(&tv[1], &p->fts_statp->st_mtimespec);
    186 		if (tv[0].tv_sec != tv[1].tv_sec ||
    187 		    tv[0].tv_usec != tv[1].tv_usec) {
    188 			LABEL;
    189 			(void)printf("%smodification time (%.24s, ",
    190 			    tab, ctime(&s->st_mtimespec.tv_sec));
    191 			(void)printf("%.24s",
    192 			    ctime(&p->fts_statp->st_mtimespec.tv_sec));
    193 			if (tflag) {
    194 				tv[1] = tv[0];
    195 				if (utimes(p->fts_accpath, tv))
    196 					(void)printf(", not modified: %s)\n",
    197 					    strerror(errno));
    198 				else
    199 					(void)printf(", modified)\n");
    200 			} else
    201 				(void)printf(")\n");
    202 			tab = "\t";
    203 		}
    204 	}
    205 	if (s->flags & F_CKSUM)
    206 		if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0) {
    207 			LABEL;
    208 			(void)printf("%scksum: %s: %s\n",
    209 			    tab, p->fts_accpath, strerror(errno));
    210 			tab = "\t";
    211 		} else if (crc(fd, &val, &len)) {
    212 			(void)close(fd);
    213 			LABEL;
    214 			(void)printf("%scksum: %s: %s\n",
    215 			    tab, p->fts_accpath, strerror(errno));
    216 			tab = "\t";
    217 		} else {
    218 			(void)close(fd);
    219 			if (s->cksum != val) {
    220 				LABEL;
    221 				(void)printf("%scksum (%lu, %lu)\n",
    222 				    tab, s->cksum, val);
    223 			}
    224 			tab = "\t";
    225 		}
    226 	if (s->flags & F_SLINK && strcmp(cp = rlink(name), s->slink)) {
    227 		LABEL;
    228 		(void)printf("%slink ref (%s, %s)\n", tab, cp, s->slink);
    229 	}
    230 	return (label);
    231 }
    232 
    233 char *
    234 inotype(type)
    235 	u_int type;
    236 {
    237 	switch(type & S_IFMT) {
    238 	case S_IFBLK:
    239 		return ("block");
    240 	case S_IFCHR:
    241 		return ("char");
    242 	case S_IFDIR:
    243 		return ("dir");
    244 	case S_IFIFO:
    245 		return ("fifo");
    246 	case S_IFREG:
    247 		return ("file");
    248 	case S_IFLNK:
    249 		return ("link");
    250 	case S_IFSOCK:
    251 		return ("socket");
    252 	default:
    253 		return ("unknown");
    254 	}
    255 	/* NOTREACHED */
    256 }
    257 
    258 static char *
    259 ftype(type)
    260 	u_int type;
    261 {
    262 	switch(type) {
    263 	case F_BLOCK:
    264 		return ("block");
    265 	case F_CHAR:
    266 		return ("char");
    267 	case F_DIR:
    268 		return ("dir");
    269 	case F_FIFO:
    270 		return ("fifo");
    271 	case F_FILE:
    272 		return ("file");
    273 	case F_LINK:
    274 		return ("link");
    275 	case F_SOCK:
    276 		return ("socket");
    277 	default:
    278 		return ("unknown");
    279 	}
    280 	/* NOTREACHED */
    281 }
    282 
    283 char *
    284 rlink(name)
    285 	char *name;
    286 {
    287 	static char lbuf[MAXPATHLEN];
    288 	register int len;
    289 
    290 	if ((len = readlink(name, lbuf, sizeof(lbuf))) == -1)
    291 		err("%s: %s", name, strerror(errno));
    292 	lbuf[len] = '\0';
    293 	return (lbuf);
    294 }
    295