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