Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Mar 2002 02:30:49 +0300 (MSK)
From:      "Andrew L. Neporada" <andr@dgap.mipt.ru>
To:        freebsd-bugs@freebsd.org
Cc:        freebsd-hackers@freebsd.org
Subject:   [PATCH] exit status of mtree(1)
Message-ID:  <20020310015221.J11778-200000@nas.dgap.mipt.ru>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
According to man page, mtree should exit with a status of 0 on success
(directory matches spec.), 1 if any error occurred and 2 in the case of
directory with spec. mismatch. But our mtree(1) is badly broken here
(see f.e. bin/28424).

Attached patch solves (I hope) this problem. This patch also introduces
slightly enhanced exit status reporting:

0 - directory matches spec, success
1 - "hard error" -- spec/dir not found, wrong options, etc.
2 - directory/spec mismatch that was fixed successfully
3 - unfixed directory/spec mismatch

Please comment/review.

				Andrew.

[-- Attachment #2 --]
Index: compare.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/mtree/compare.c,v
retrieving revision 1.20
diff -u -r1.20 compare.c
--- compare.c	6 Oct 2000 12:48:55 -0000	1.20
+++ compare.c	7 Mar 2002 22:56:25 -0000
@@ -62,6 +62,7 @@
 
 extern int uflag;
 extern int lineno;
+extern int rval;
 
 static char *ftype __P((u_int));
 
@@ -115,6 +116,7 @@
 typeerr:		LABEL;
 			(void)printf("\ttype expected %s found %s\n",
 			    ftype(s->type), inotype(p->fts_statp->st_mode));
+			FAILED;
 			return (label);
 		}
 		break;
@@ -124,11 +126,13 @@
 		LABEL;
 		(void)printf("%suser expected %lu found %lu",
 		    tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid);
+		FIXED;
 		if (uflag)
-			if (chown(p->fts_accpath, s->st_uid, -1))
+			if (chown(p->fts_accpath, s->st_uid, -1)) {
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
-			else
+				FAILED;
+			} else
 				(void)printf(" modified\n");
 		else
 			(void)printf("\n");
@@ -138,11 +142,13 @@
 		LABEL;
 		(void)printf("%sgid expected %lu found %lu",
 		    tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid);
+		FIXED;
 		if (uflag)
-			if (chown(p->fts_accpath, -1, s->st_gid))
+			if (chown(p->fts_accpath, -1, s->st_gid)) {
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
-			else
+				FAILED;
+			} else
 				(void)printf(" modified\n");
 		else
 			(void)printf("\n");
@@ -154,11 +160,13 @@
 		LABEL;
 		(void)printf("%spermissions expected %#o found %#o",
 		    tab, s->st_mode, p->fts_statp->st_mode & MBITS);
+		FIXED;
 		if (uflag)
-			if (chmod(p->fts_accpath, s->st_mode))
+			if (chmod(p->fts_accpath, s->st_mode)) {
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
-			else
+				FAILED;
+			} else
 				(void)printf(" modified\n");
 		else
 			(void)printf("\n");
@@ -169,6 +177,7 @@
 		LABEL;
 		(void)printf("%slink_count expected %u found %u\n",
 		    tab, s->st_nlink, p->fts_statp->st_nlink);
+		FAILED;
 		tab = "\t";
 	}
 	if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size &&
@@ -176,6 +185,7 @@
 		LABEL;
 		(void)printf("%ssize expected %qd found %qd\n",
 		    tab, s->st_size, p->fts_statp->st_size);
+		FAILED;
 		tab = "\t";
 	}
 	/*
@@ -190,6 +200,7 @@
 		    tab, ctime(&s->st_mtimespec.tv_sec));
 		(void)printf("found %.24s\n",
 		    ctime(&p->fts_statp->st_mtimespec.tv_sec));
+		FAILED;
 		tab = "\t";
 	}
 	if (s->flags & F_CKSUM) {
@@ -197,12 +208,14 @@
 			LABEL;
 			(void)printf("%scksum: %s: %s\n",
 			    tab, p->fts_accpath, strerror(errno));
+			FAILED;
 			tab = "\t";
 		} else if (crc(fd, &val, &len)) {
 			(void)close(fd);
 			LABEL;
 			(void)printf("%scksum: %s: %s\n",
 			    tab, p->fts_accpath, strerror(errno));
+			FAILED;
 			tab = "\t";
 		} else {
 			(void)close(fd);
@@ -210,6 +223,7 @@
 				LABEL;
 				(void)printf("%scksum expected %lu found %lu\n",
 				    tab, s->cksum, val);
+				FAILED;
 			}
 			tab = "\t";
 		}
@@ -229,12 +243,14 @@
 		fflags = flags_to_string(p->fts_statp->st_flags);
 		(void)printf(" found \"%s\"", fflags);
 		free(fflags);
+		FIXED;
 
 		if (uflag)
-			if (chflags(p->fts_accpath, s->st_flags))
+			if (chflags(p->fts_accpath, s->st_flags)) {
 				(void)printf(" not modified: %s\n",
 				    strerror(errno));
-			else
+				FAILED;
+			} else
 				(void)printf(" modified\n");
 		else
 			(void)printf("\n");
@@ -249,11 +265,13 @@
 			LABEL;
 			printf("%sMD5: %s: %s\n", tab, p->fts_accpath,
 			       strerror(errno));
+			FAILED;
 			tab = "\t";
 		} else if (strcmp(new_digest, s->md5digest)) {
 			LABEL;
 			printf("%sMD5 expected %s found %s\n", tab, s->md5digest,
 			       new_digest);
+			FAILED;
 			tab = "\t";
 		}
 	}
@@ -267,11 +285,13 @@
 			LABEL;
 			printf("%sSHA-1: %s: %s\n", tab, p->fts_accpath,
 			       strerror(errno));
+			FAILED;
 			tab = "\t";
 		} else if (strcmp(new_digest, s->sha1digest)) {
 			LABEL;
 			printf("%sSHA-1 expected %s found %s\n", 
 			       tab, s->sha1digest, new_digest);
+			FAILED;
 			tab = "\t";
 		}
 	}
@@ -285,11 +305,13 @@
 			LABEL;
 			printf("%sRIPEMD160: %s: %s\n", tab,
 			       p->fts_accpath, strerror(errno));
+			FAILED;
 			tab = "\t";
 		} else if (strcmp(new_digest, s->rmd160digest)) {
 			LABEL;
 			printf("%sRIPEMD160 expected %s found %s\n",
 			       tab, s->rmd160digest, new_digest);
+			FAILED;
 			tab = "\t";
 		}
 	}
@@ -300,6 +322,7 @@
 		LABEL;
 		(void)printf("%slink_ref expected %s found %s\n",
 		      tab, cp, s->slink);
+		FAILED;
 	}
 	return (label);
 }
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/mtree/extern.h,v
retrieving revision 1.5
diff -u -r1.5 extern.h
--- extern.h	17 Jun 2000 14:19:33 -0000	1.5
+++ extern.h	7 Mar 2002 22:56:25 -0000
@@ -43,7 +43,7 @@
 u_int	 parsekey __P((char *, int *));
 char	*rlink __P((char *));
 NODE	*spec __P((void));
-int	 verify __P((void));
+void	 verify __P((void));
 
 int	 check_excludes __P((const char *, const char *));
 void	 init_excludes __P((void));
Index: mtree.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/mtree/mtree.c,v
retrieving revision 1.18
diff -u -r1.18 mtree.c
--- mtree.c	25 Sep 2000 16:24:22 -0000	1.18
+++ mtree.c	9 Mar 2002 21:06:47 -0000
@@ -59,6 +59,7 @@
 
 int ftsoptions = FTS_PHYSICAL;
 int cflag, dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, Uflag;
+int rval;
 u_int keys;
 char fullpath[MAXPATHLEN];
 
@@ -71,7 +72,6 @@
 {
 	int ch;
 	char *dir, *p;
-	int status;
 
 	dir = NULL;
 	keys = KEYDEFAULT;
@@ -164,10 +164,10 @@
 		cwalk();
 		exit(0);
 	}
-	status = verify();
-	if (Uflag & (status == MISMATCHEXIT))
-		status = 0;
-	exit(status);
+	verify();
+	if (Uflag & (rval == MISMATCHFIXED))
+		rval = 0;
+	exit(rval);
 }
 
 static void
Index: mtree.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/mtree/mtree.h,v
retrieving revision 1.5
diff -u -r1.5 mtree.h
--- mtree.h	9 Dec 1999 20:38:35 -0000	1.5
+++ mtree.h	9 Mar 2002 20:47:08 -0000
@@ -40,7 +40,10 @@
 #define	KEYDEFAULT \
 	(F_GID | F_MODE | F_NLINK | F_SIZE | F_SLINK | F_TIME | F_UID | F_FLAGS)
 
-#define	MISMATCHEXIT	2
+#define	MISMATCHFIXED	2
+#define	FIXFAILED	3
+#define	FIXED	if (rval != FIXFAILED) rval = MISMATCHFIXED;
+#define	FAILED	rval = FIXFAILED;
 
 typedef struct _node {
 	struct _node	*parent, *child;	/* up, down */
Index: verify.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/mtree/verify.c,v
retrieving revision 1.15
diff -u -r1.15 verify.c
--- verify.c	3 Oct 2000 13:13:47 -0000	1.15
+++ verify.c	9 Mar 2002 20:39:41 -0000
@@ -56,31 +56,29 @@
 extern int dflag, eflag, qflag, rflag, sflag, uflag;
 extern char fullpath[MAXPATHLEN];
 extern int lineno;
+extern int rval;
 
 static NODE *root;
 static char path[MAXPATHLEN];
 
 static void	miss __P((NODE *, char *));
-static int	vwalk __P((void));
+static void	vwalk __P((void));
 
-int
+void
 verify()
 {
-	int rval;
-
 	root = spec();
-	rval = vwalk();
+	vwalk();
 	miss(root, path);
-	return (rval);
 }
 
-static int
+void
 vwalk()
 {
 	register FTS *t;
 	register FTSENT *p;
 	register NODE *ep, *level;
-	int specdepth, rval;
+	int specdepth;
 	char *argv[2];
 
 	argv[0] = ".";
@@ -122,9 +120,8 @@
 			    !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
 			    !strcmp(ep->name, p->fts_name)) {
 				ep->flags |= F_VISIT;
-				if ((ep->flags & F_NOCHANGE) == 0 &&
-				    compare(ep->name, ep, p))
-					rval = MISMATCHEXIT;
+				if ((ep->flags & F_NOCHANGE) == 0)
+					(void)compare(ep->name, ep, p);
 				if (ep->flags & F_IGN)
 					(void)fts_set(t, p, FTS_SKIP);
 				else if (ep->child && ep->type == F_DIR &&
@@ -139,15 +136,18 @@
 			continue;
 extra:
 		if (!eflag) {
+			FIXED;
 			(void)printf("%s extra", RP(p));
 			if (rflag) {
 				if ((S_ISDIR(p->fts_statp->st_mode)
 				    ? rmdir : unlink)(p->fts_accpath)) {
 					(void)printf(", not removed: %s",
 					    strerror(errno));
+					FAILED;
 				} else
 					(void)printf(", removed");
-			}
+			} else
+				FAILED;
 			(void)putchar('\n');
 		}
 		(void)fts_set(t, p, FTS_SKIP);
@@ -155,7 +155,6 @@
 	(void)fts_close(t);
 	if (sflag)
 		warnx("%s checksum: %lu", fullpath, crc_total);
-	return (rval);
 }
 
 static void
@@ -178,8 +177,10 @@
  
 			if (qflag && stat(path, &statbuf) == 0)
 				p->flags |= F_VISIT;
-			else
+			else {
 				(void)printf("%s missing", path);
+				FIXED;
+			}
 		}
 		if (p->type != F_DIR && p->type != F_LINK) {
 			putchar('\n');
@@ -197,14 +198,17 @@
 			else if (!(p->flags & (F_GID | F_GNAME)))
 				(void)printf(" (%s not created: group not specified)", type);
 			else if (p->type == F_LINK) {
-				if (symlink(p->slink, path))
+				if (symlink(p->slink, path)) {
 					(void)printf(" (symlink not created: %s)\n",
 					    strerror(errno));
-				else
+					FAILED;
+				} else
 					(void)printf(" (created)\n");
-				if (lchown(path, p->st_uid, p->st_gid))
+				if (lchown(path, p->st_uid, p->st_gid)) {
 					(void)printf("%s: user/group not modified: %s\n",
 					    path, strerror(errno));
+					FAILED;
+				}
 				continue;
 			} else if (!(p->flags & F_MODE))
 			    (void)printf(" (directory not created: mode not specified)");
@@ -215,6 +219,8 @@
 				create = 1;
 				(void)printf(" (created)");
 			}
+			if (!create)
+				FAILED;
 		}
 		if (!(p->flags & F_VISIT))
 			(void)putchar('\n');
@@ -231,14 +237,19 @@
 			    path, strerror(errno));
 			(void)printf("%s: warning: file mode %snot set\n", path,
 			    (p->flags & F_FLAGS) ? "and file flags " : "");
+			FAILED;
 			continue;
 		}
-		if (chmod(path, p->st_mode))
+		if (chmod(path, p->st_mode)) {
 			(void)printf("%s: permissions not set: %s\n",
 			    path, strerror(errno));
+			FAILED;
+		}
 		if ((p->flags & F_FLAGS) && p->st_flags &&
-		    chflags(path, p->st_flags))
+		    chflags(path, p->st_flags)) {
 			(void)printf("%s: file flags not set: %s\n",
 			    path, strerror(errno));
+			FAILED;
+		}
 	}
 }

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020310015221.J11778-200000>