summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mtree/verify.c
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1995-07-24 02:52:42 +0000
committerbde <bde@FreeBSD.org>1995-07-24 02:52:42 +0000
commit7b0390d6653e2e74b4455cee7f795e4f2c942f65 (patch)
treef4634d131c03d9bc8fd15104ed43ac772c9bf961 /usr.sbin/mtree/verify.c
parent7eb50587264f13987580e882594c9d0263902702 (diff)
downloadFreeBSD-src-7b0390d6653e2e74b4455cee7f795e4f2c942f65.zip
FreeBSD-src-7b0390d6653e2e74b4455cee7f795e4f2c942f65.tar.gz
Use p->fts_level instead of unsuccessfully trying to keep track of the
level ourself. We failed for unreadable directories. E.g., `mtree -d -f /etc/mtree/BSD.usr.dist -p /usr' run by `nobody' was confused after it couldn't descend into /usr/games/hide. It looked for /usr/include and subsequent directories in /usr/games. Don't search for `extra' files when the spec depth is less than the fts level. The spec depth isn't incremented for leaf nodes because that would give a NULL level pointer and make it inconvenient to go back to the parent level. Leaf nodes are built for directories that are empty in the spec. Since they are empty in the spec, all files in them are extra. The search looked for files one spec level too high, so for `mtree -d -f /etc/mtree/BSD.usr.dist -p /usr', obj/sbin matched ./sbin and wasn't considered extra, so it was descended into and lots of bogus extra things in it were found. This was harmful for `mtree -U' (as reported in pr623) and worse for `mtree -r'. Use rmdir(), not unlink(), to remove `extra' directories. unlink() succeeds for root but unlinking directories normally damages the file system. Report `fts_errno' instead of `errno' when the former applies.
Diffstat (limited to 'usr.sbin/mtree/verify.c')
-rw-r--r--usr.sbin/mtree/verify.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/usr.sbin/mtree/verify.c b/usr.sbin/mtree/verify.c
index 3e7c08f..e435eb0 100644
--- a/usr.sbin/mtree/verify.c
+++ b/usr.sbin/mtree/verify.c
@@ -74,7 +74,7 @@ vwalk()
register FTS *t;
register FTSENT *p;
register NODE *ep, *level;
- int ftsdepth, specdepth, rval;
+ int specdepth, rval;
char *argv[2];
argv[0] = ".";
@@ -82,15 +82,13 @@ vwalk()
if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
err("fts_open: %s", strerror(errno));
level = root;
- ftsdepth = specdepth = rval = 0;
+ specdepth = rval = 0;
while ((p = fts_read(t))) {
switch(p->fts_info) {
case FTS_D:
- ++ftsdepth;
break;
case FTS_DP:
- --ftsdepth;
- if (specdepth > ftsdepth) {
+ if (specdepth > p->fts_level) {
for (level = level->parent; level->prev;
level = level->prev);
--specdepth;
@@ -100,13 +98,15 @@ vwalk()
case FTS_ERR:
case FTS_NS:
(void)fprintf(stderr, "mtree: %s: %s\n",
- RP(p), strerror(errno));
+ RP(p), strerror(p->fts_errno));
continue;
default:
if (dflag)
continue;
}
+ if (specdepth != p->fts_level)
+ goto extra;
for (ep = level; ep; ep = ep->next)
if ((ep->flags & F_MAGIC &&
!fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) ||
@@ -126,10 +126,12 @@ vwalk()
if (ep)
continue;
+extra:
if (!eflag) {
(void)printf("extra: %s", RP(p));
if (rflag) {
- if (unlink(p->fts_accpath)) {
+ if ((S_ISDIR(p->fts_statp->st_mode)
+ ? rmdir : unlink)(p->fts_accpath)) {
(void)printf(", not removed: %s",
strerror(errno));
} else
OpenPOWER on IntegriCloud