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.
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;
+               }
        }
 }

Reply via email to