#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;
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))) {
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);
!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 &&
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');
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)
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)");
}
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)
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;
}