file_cmds-321.100.10.0.1.tar.gz
[apple/file_cmds.git] / mtree / verify.c
index 4ad32029f4baabcc4dd470e6f796502a4a60f438..49780983059c80a6baca2874e7499939e5f74136 100644 (file)
@@ -45,29 +45,42 @@ __FBSDID("$FreeBSD: src/usr.sbin/mtree/verify.c,v 1.24 2005/08/11 15:43:55 brian
 #include <stdio.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <removefile.h>
+#include "metrics.h"
 #include "mtree.h"
 #include "extern.h"
 
 static NODE *root;
 static char path[MAXPATHLEN];
 
-static void    miss(NODE *, char *);
+static int     miss(NODE *, char *, size_t path_length);
 static int     vwalk(void);
 
 int
 mtree_verifyspec(FILE *fi)
 {
-       int rval;
+       int rval, mval;
+       size_t path_length = 0;
 
        root = mtree_readspec(fi);
        rval = vwalk();
-       miss(root, path);
-       return (rval);
+       mval = miss(root, path, path_length);
+       
+       if (rval != 0) {
+               RECORD_FAILURE(60, WARN_MISMATCH);
+               return rval;
+       } else {
+               if (mval != 0) {
+                       RECORD_FAILURE(61, WARN_MISMATCH);
+               }
+               return mval;
+       }
 }
 
 static int
 vwalk(void)
 {
+       int error = 0;
        FTS *t;
        FTSENT *p;
        NODE *ep, *level;
@@ -77,8 +90,11 @@ vwalk(void)
 
        argv[0] = dot;
        argv[1] = NULL;
-       if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
-               err(1, "line %d: fts_open", lineno);
+       if ((t = fts_open(argv, ftsoptions, NULL)) == NULL) {
+               error = errno;
+               RECORD_FAILURE(62, error);
+               errc(1, error, "line %d: fts_open", lineno);
+       }
        level = root;
        specdepth = rval = 0;
        while ((p = fts_read(t))) {
@@ -91,6 +107,10 @@ vwalk(void)
                case FTS_SL:
                        break;
                case FTS_DP:
+                       if (level == NULL) {
+                               RECORD_FAILURE(63, EINVAL);
+                               errx(1 , "invalid root in vwalk");
+                       }
                        if (specdepth > p->fts_level) {
                                for (level = level->parent; level->prev;
                                      level = level->prev);
@@ -115,8 +135,10 @@ vwalk(void)
                            !strcmp(ep->name, p->fts_name)) {
                                ep->flags |= F_VISIT;
                                if ((ep->flags & F_NOCHANGE) == 0 &&
-                                   compare(ep->name, ep, p))
+                                   compare(ep->name, ep, p)) {
+                                       RECORD_FAILURE(64, WARN_MISMATCH);
                                        rval = MISMATCHEXIT;
+                               }
                                if (ep->flags & F_IGN)
                                        (void)fts_set(t, p, FTS_SKIP);
                                else if (ep->child && ep->type == F_DIR &&
@@ -132,45 +154,92 @@ vwalk(void)
 extra:
                if (!eflag) {
                        (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));
-                               } else
-                                       (void)printf(", removed");
+                               /* rflag implies: delete stuff if "extra" is observed" */
+                               if (mflag) {
+                                       /* -mflag is used for sealing & verification -- use removefile for recursive behavior */
+                                       removefile_state_t rmstate;
+                                       rmstate = removefile_state_alloc();
+                                       if (removefile(p->fts_accpath, rmstate, (REMOVEFILE_RECURSIVE))) {
+                                               error = errno;
+                                               RECORD_FAILURE(65, error);
+                                               errx (1, "\n error deleting item (or descendant) at path %s (%s)", RP(p), strerror(error));
+                                       }
+                                       else {
+                                               /* removefile success */
+                                               (void) printf(", removed");
+                                       }
+                                       removefile_state_free(rmstate);
+
+                               }
+                               else {
+                                       /* legacy: use rmdir/unlink if "-m" not specified */
+                                       int syserr = 0;
+
+                                       if (S_ISDIR(p->fts_statp->st_mode)){
+                                               syserr = rmdir(p->fts_accpath);
+                                       }
+                                       else {
+                                               syserr = unlink(p->fts_accpath);
+                                       }
+
+                                       /* log failures */
+                                       if (syserr) {
+                                               error = errno;
+                                               RECORD_FAILURE(66, error);
+                                               (void) printf(", not removed :%s", strerror(error));
+                                       }
+                               }
+                       } else if (mflag) {
+                               RECORD_FAILURE(68956, WARN_MISMATCH);
+                               errx(1, "cannot generate the XML dictionary");
                        }
                        (void)putchar('\n');
                }
                (void)fts_set(t, p, FTS_SKIP);
        }
        (void)fts_close(t);
-       if (sflag)
+       if (sflag) {
+               RECORD_FAILURE(67, WARN_CHECKSUM);
                warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total);
+       }
        return (rval);
 }
 
-static void
-miss(NODE *p, char *tail)
+static int
+miss(NODE *p, char *tail, size_t path_length)
 {
        int create;
        char *tp;
        const char *type, *what;
        int serr;
+       int rval = 0;
+       int rrval = 0;
+       size_t file_name_length = 0;
 
        for (; p; p = p->next) {
                if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
                        continue;
+               file_name_length = strnlen(p->name, MAXPATHLEN);
+               path_length += file_name_length;
+               if (path_length >= MAXPATHLEN) {
+                       RECORD_FAILURE(61971, ENAMETOOLONG);
+                       continue;
+               }
                (void)strcpy(tail, p->name);
                if (!(p->flags & F_VISIT)) {
                        /* Don't print missing message if file exists as a
                           symbolic link and the -q flag is set. */
                        struct stat statbuf;
 
-                       if (qflag && stat(path, &statbuf) == 0)
+                       if (qflag && stat(path, &statbuf) == 0) {
                                p->flags |= F_VISIT;
-                       else
+                       } else {
                                (void)printf("%s missing", path);
+                               RECORD_FAILURE(68, WARN_MISMATCH);
+                               rval = MISMATCHEXIT;
+                       }
                }
                if (p->type != F_DIR && p->type != F_LINK) {
                        putchar('\n');
@@ -183,16 +252,19 @@ miss(NODE *p, char *tail)
                else
                        type = "directory";
                if (!(p->flags & F_VISIT) && uflag) {
-                       if (!(p->flags & (F_UID | F_UNAME)))
+                       if (!(p->flags & (F_UID | F_UNAME))) {
                                (void)printf(" (%s not created: user not specified)", type);
-                       else if (!(p->flags & (F_GID | F_GNAME)))
+                       } 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))
+                       } else if (p->type == F_LINK) {
+                               if (symlink(p->slink, path)) {
+                                       serr = errno;
+                                       RECORD_FAILURE(69, serr);
                                        (void)printf(" (symlink not created: %s)\n",
-                                           strerror(errno));
-                               else
+                                           strerror(serr));
+                               } else {
                                        (void)printf(" (created)\n");
+                               }
                                if (lchown(path, p->st_uid, p->st_gid) == -1) {
                                        serr = errno;
                                        if (p->st_uid == (uid_t)-1)
@@ -204,16 +276,20 @@ miss(NODE *p, char *tail)
                                                what = "user";
                                                errno = serr;
                                        }
+                                       serr = errno;
+                                       RECORD_FAILURE(70, serr);
                                        (void)printf("%s: %s not modified: %s"
-                                           "\n", path, what, strerror(errno));
+                                           "\n", path, what, strerror(serr));
                                }
                                continue;
-                       } else if (!(p->flags & F_MODE))
+                       } else if (!(p->flags & F_MODE)) {
                            (void)printf(" (directory not created: mode not specified)");
-                       else if (mkdir(path, S_IRWXU))
+                       } else if (mkdir(path, S_IRWXU)) {
+                               serr = errno;
+                               RECORD_FAILURE(71, serr);
                                (void)printf(" (directory not created: %s)",
-                                   strerror(errno));
-                       else {
+                                   strerror(serr));
+                       else {
                                create = 1;
                                (void)printf(" (created)");
                        }
@@ -223,7 +299,13 @@ miss(NODE *p, char *tail)
 
                for (tp = tail; *tp; ++tp);
                *tp = '/';
-               miss(p->child, tp + 1);
+               ++path_length;
+               rrval = miss(p->child, tp + 1, path_length);
+               if (rrval != 0) {
+                       RECORD_FAILURE(72, WARN_MISMATCH);
+                       rval = rrval;
+               }
+               path_length -= (file_name_length + 1);
                *tp = '\0';
 
                if (!create)
@@ -238,15 +320,24 @@ miss(NODE *p, char *tail)
                                what = "user";
                                errno = serr;
                        }
+                       serr = errno;
+                       RECORD_FAILURE(73, serr);
                        (void)printf("%s: %s not modified: %s\n",
-                           path, what, strerror(errno));
+                           path, what, strerror(serr));
                }
-               if (chmod(path, p->st_mode))
+               if (chmod(path, p->st_mode)) {
+                       serr = errno;
+                       RECORD_FAILURE(74, serr);
                        (void)printf("%s: permissions not set: %s\n",
-                           path, strerror(errno));
+                           path, strerror(serr));
+               }
                if ((p->flags & F_FLAGS) && p->st_flags &&
-                   chflags(path, (u_int)p->st_flags))
+                   chflags(path, (u_int)p->st_flags)) {
+                       serr = errno;
+                       RECORD_FAILURE(75, serr);
                        (void)printf("%s: file flags not set: %s\n",
-                           path, strerror(errno));
+                           path, strerror(serr));
+               }
        }
+       return rval;
 }