From 33ea52b638f1c2f33326dd8fceaa30c87fc2280a Mon Sep 17 00:00:00 2001 From: mycroft Date: Wed, 28 Dec 1994 02:21:43 +0000 Subject: [PATCH] Mostly sync with CSRG. --- sbin/restore/dirs.c | 36 +++++++++++----------- sbin/restore/interactive.c | 49 +++++++++++++++++++++--------- sbin/restore/main.c | 6 ++-- sbin/restore/restore.8 | 8 +++-- sbin/restore/restore.c | 48 ++++++++++++++++++++++++----- sbin/restore/restore.h | 8 +++-- sbin/restore/symtab.c | 14 ++++----- sbin/restore/tape.c | 62 +++++++++++++++++++++++--------------- sbin/restore/utilities.c | 43 ++++++++++++++++++++++++-- 9 files changed, 191 insertions(+), 83 deletions(-) diff --git a/sbin/restore/dirs.c b/sbin/restore/dirs.c index c178cf769b34..a39bb8c9f211 100644 --- a/sbin/restore/dirs.c +++ b/sbin/restore/dirs.c @@ -37,8 +37,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)dirs.c 8.2 (Berkeley) 1/21/94";*/ -static char *rcsid = "$Id: dirs.c,v 1.10 1994/09/23 14:27:53 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)dirs.c 8.5 (Berkeley) 8/31/94";*/ +static char *rcsid = "$Id: dirs.c,v 1.11 1994/12/28 02:21:43 mycroft Exp $"; #endif /* not lint */ #include @@ -82,9 +82,10 @@ static struct inotab *inotab[HASHSIZE]; struct modeinfo { ino_t ino; struct timeval timep[2]; - short mode; - short uid; - short gid; + mode_t mode; + uid_t uid; + gid_t gid; + int flags; }; /* @@ -259,7 +260,7 @@ treescan(pname, ino, todo) /* * a zero inode signals end of directory */ - while (dp != NULL && dp->d_ino != 0) { + while (dp != NULL) { locname[namelen] = '\0'; if (namelen + dp->d_namlen >= MAXPATHLEN) { fprintf(stderr, "%s%s: name exceeds %d char\n", @@ -272,8 +273,6 @@ treescan(pname, ino, todo) dp = rst_readdir(dirp); bpt = rst_telldir(dirp); } - if (dp == NULL) - fprintf(stderr, "corrupted directory: %s.\n", locname); } /* @@ -321,7 +320,7 @@ searchdir(inum, name) len = strlen(name); do { dp = rst_readdir(dirp); - if (dp == NULL || dp->d_ino == 0) + if (dp == NULL) return (NULL); } while (dp->d_namlen != len || strncmp(dp->d_name, name, len) != 0); return (dp); @@ -354,12 +353,13 @@ putdir(buf, size) if (Bcvt) swabst((u_char *)"ls", (u_char *) dp); if (oldinofmt && dp->d_ino != 0) { -#if BYTE_ORDER == BIG_ENDIAN - if (Bcvt) -#else - if (!Bcvt) -#endif - dp->d_namlen = dp->d_type; +# if BYTE_ORDER == BIG_ENDIAN + if (Bcvt) + dp->d_namlen = dp->d_type; +# else + if (!Bcvt) + dp->d_namlen = dp->d_type; +# endif dp->d_type = DT_UNKNOWN; } i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); @@ -497,8 +497,8 @@ rst_readdir(dirp) return (NULL); } dirp->dd_loc += dp->d_reclen; - if (dp->d_ino == 0 && strcmp(dp->d_name, "/") != 0) - continue; + if (dp->d_ino == 0 && strcmp(dp->d_name, "/") == 0) + return (NULL); if (dp->d_ino >= maxino) { dprintf(stderr, "corrupted directory: bad inum %d\n", dp->d_ino); @@ -617,6 +617,7 @@ setdirmodes(flags) cp = myname(ep); (void) chown(cp, node.uid, node.gid); (void) chmod(cp, node.mode); + (void) chflags(cp, node.flags); utimes(cp, node.timep); ep->e_flags &= ~NEW; } @@ -714,6 +715,7 @@ allocinotab(ino, dip, seekpt) node.timep[1].tv_sec = dip->di_mtime.ts_sec; node.timep[1].tv_usec = dip->di_mtime.ts_nsec / 1000; node.mode = dip->di_mode; + node.flags = dip->di_flags; node.uid = dip->di_uid; node.gid = dip->di_gid; (void) fwrite((char *)&node, 1, sizeof(struct modeinfo), mf); diff --git a/sbin/restore/interactive.c b/sbin/restore/interactive.c index 921cafc34ede..fd08ebc721f3 100644 --- a/sbin/restore/interactive.c +++ b/sbin/restore/interactive.c @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)interactive.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: interactive.c,v 1.5 1994/09/23 14:27:54 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)interactive.c 8.3 (Berkeley) 9/13/94";*/ +static char *rcsid = "$Id: interactive.c,v 1.6 1994/12/28 02:21:45 mycroft Exp $"; #endif /* not lint */ #include @@ -86,7 +86,7 @@ static void formatf __P((struct afile *, int)); static void getcmd __P((char *, char *, char *, struct arglist *)); struct dirent *glob_readdir __P((RST_DIR *dirp)); static int glob_stat __P((const char *, struct stat *)); -static void mkentry __P((struct direct *, struct afile *)); +static void mkentry __P((char *, struct direct *, struct afile *)); static void printlist __P((char *, char *)); /* @@ -497,15 +497,17 @@ printlist(name, basename) register struct direct *dp; struct afile single; RST_DIR *dirp; - int entries, len; + int entries, len, namelen; + char locname[MAXPATHLEN + 1]; dp = pathsearch(name); - if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)) + if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) || + (!vflag && dp->d_ino == WINO)) return; if ((dirp = rst_opendir(name)) == NULL) { entries = 1; list = &single; - mkentry(dp, list); + mkentry(name, dp, list); len = strlen(basename) + 1; if (strlen(name) - len > single.len) { freename(single.fname); @@ -527,17 +529,28 @@ printlist(name, basename) fprintf(stderr, "%s:\n", name); entries = 0; listp = list; + (void) strncpy(locname, name, MAXPATHLEN); + (void) strncat(locname, "/", MAXPATHLEN); + namelen = strlen(locname); while (dp = rst_readdir(dirp)) { - if (dp == NULL || dp->d_ino == 0) + if (dp == NULL) break; if (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) continue; - if (vflag == 0 && - (strcmp(dp->d_name, ".") == 0 || + if (!vflag && (dp->d_ino == WINO || + strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) continue; - mkentry(dp, listp++); - entries++; + locname[namelen] = '\0'; + if (namelen + dp->d_namlen >= MAXPATHLEN) { + fprintf(stderr, "%s%s: name exceeds %d char\n", + locname, dp->d_name, MAXPATHLEN); + } else { + (void) strncat(locname, dp->d_name, + (int)dp->d_namlen); + mkentry(locname, dp, listp++); + entries++; + } } rst_closedir(dirp); if (entries == 0) { @@ -560,7 +573,8 @@ printlist(name, basename) * Read the contents of a directory. */ static void -mkentry(dp, fp) +mkentry(name, dp, fp) + char *name; struct direct *dp; register struct afile *fp; { @@ -575,7 +589,7 @@ mkentry(dp, fp) fp->len = cp - fp->fname; if (dflag && TSTINO(fp->fnum, dumpmap) == 0) fp->prefix = '^'; - else if ((np = lookupino(fp->fnum)) != NULL && (np->e_flags & NEW)) + else if ((np = lookupname(name)) != NULL && (np->e_flags & NEW)) fp->prefix = '*'; else fp->prefix = ' '; @@ -603,6 +617,10 @@ mkentry(dp, fp) fp->postfix = '#'; break; + case DT_WHT: + fp->postfix = '%'; + break; + case DT_UNKNOWN: case DT_DIR: if (inodetype(dp->d_ino) == NODE) @@ -698,7 +716,7 @@ glob_readdir(dirp) static struct dirent adirent; while ((dp = rst_readdir(dirp)) != NULL) { - if (dp->d_ino == 0) + if (!vflag && dp->d_ino == WINO) continue; if (dflag || TSTINO(dp->d_ino, dumpmap)) break; @@ -722,7 +740,8 @@ glob_stat(name, stp) register struct direct *dp; dp = pathsearch(name); - if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0)) + if (dp == NULL || (!dflag && TSTINO(dp->d_ino, dumpmap) == 0) || + (!vflag && dp->d_ino == WINO)) return (-1); if (inodetype(dp->d_ino) == NODE) stp->st_mode = IFDIR; diff --git a/sbin/restore/main.c b/sbin/restore/main.c index 6d47f6fbf579..ea6e1a5825f4 100644 --- a/sbin/restore/main.c +++ b/sbin/restore/main.c @@ -38,8 +38,8 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)main.c 8.2 (Berkeley) 1/7/94";*/ -static char *rcsid = "$Id: main.c,v 1.4 1994/06/08 19:33:37 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)main.c 8.3 (Berkeley) 9/13/94";*/ +static char *rcsid = "$Id: main.c,v 1.5 1994/12/28 02:21:46 mycroft Exp $"; #endif /* not lint */ #include @@ -67,7 +67,7 @@ long dumpnum = 1; long volno = 0; long ntrec; char *dumpmap; -char *clrimap; +char *usedinomap; ino_t maxino; time_t dumptime; time_t dumpdate; diff --git a/sbin/restore/restore.8 b/sbin/restore/restore.8 index 68cc68890b6f..f798a7d69486 100644 --- a/sbin/restore/restore.8 +++ b/sbin/restore/restore.8 @@ -29,10 +29,10 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" from: @(#)restore.8 8.2 (Berkeley) 12/11/93 -.\" $Id: restore.8,v 1.6 1994/06/08 19:33:39 mycroft Exp $ +.\" from: @(#)restore.8 8.3 (Berkeley) 6/1/94 +.\" $Id: restore.8,v 1.7 1994/12/28 02:21:47 mycroft Exp $ .\" -.Dd December 11, 1993 +.Dd June 1, 1994 .Dt RESTORE 8 .Os BSD 4 .Sh NAME @@ -159,6 +159,7 @@ Note that the key replaces the function of the old .Xr dumpdir 8 program. +.ne 1i .It Cm i This mode allows interactive restoration of files from a dump. After reading in the directory information from the dump, @@ -273,6 +274,7 @@ extracts the actual directory, rather than the files that it references. This prevents hierarchical restoration of complete subtrees from the dump. +.ne 1i .It Cm m .Nm Restore will extract by inode numbers rather than by file name. diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c index f5864c83a263..4c067af2cb1c 100644 --- a/sbin/restore/restore.c +++ b/sbin/restore/restore.c @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)restore.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: restore.c,v 1.4 1994/06/08 19:33:41 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)restore.c 8.3 (Berkeley) 9/13/94";*/ +static char *rcsid = "$Id: restore.c,v 1.5 1994/12/28 02:21:49 mycroft Exp $"; #endif /* not lint */ #include @@ -86,6 +86,8 @@ addfile(name, ino, type) dprintf(stdout, "%s: not on the tape\n", name); return (descend); } + if (ino == WINO && command == 'i' && !vflag) + return (descend); if (!mflag) { (void) sprintf(buf, "./%u", ino); name = buf; @@ -125,9 +127,13 @@ deletefile(name, ino, type) if (TSTINO(ino, dumpmap) == 0) return (descend); - ep = lookupino(ino); - if (ep != NULL) + ep = lookupname(name); + if (ep != NULL) { ep->e_flags &= ~NEW; + ep->e_flags |= REMOVED; + if (ep->e_type != NODE) + freeentry(ep); + } return (descend); } @@ -147,21 +153,38 @@ deletefile(name, ino, type) static struct entry *removelist; /* + * Remove invalid whiteouts from the old tree. * Remove unneeded leaves from the old tree. * Remove directories from the lookup chains. */ void removeoldleaves() { - register struct entry *ep; - register ino_t i; + register struct entry *ep, *nextep; + register ino_t i, mydirino; vprintf(stdout, "Mark entries to be removed.\n"); + if (ep = lookupino(WINO)) { + vprintf(stdout, "Delete whiteouts\n"); + for ( ; ep != NULL; ep = nextep) { + nextep = ep->e_links; + mydirino = ep->e_parent->e_ino; + /* + * We remove all whiteouts that are in directories + * that have been removed or that have been dumped. + */ + if (TSTINO(mydirino, usedinomap) && + !TSTINO(mydirino, dumpmap)) + continue; + delwhiteout(ep); + freeentry(ep); + } + } for (i = ROOTINO + 1; i < maxino; i++) { ep = lookupino(i); if (ep == NULL) continue; - if (TSTINO(i, clrimap)) + if (TSTINO(i, usedinomap)) continue; for ( ; ep != NULL; ep = ep->e_links) { dprintf(stdout, "%s: REMOVE\n", myname(ep)); @@ -746,6 +769,15 @@ createlinks() register ino_t i; char name[BUFSIZ]; + if (ep = lookupino(WINO)) { + vprintf(stdout, "Add whiteouts\n"); + for ( ; ep != NULL; ep = ep->e_links) { + if ((ep->e_flags & NEW) == 0) + continue; + (void) addwhiteout(myname(ep)); + ep->e_flags &= ~NEW; + } + } vprintf(stdout, "Add links\n"); for (i = ROOTINO; i < maxino; i++) { ep = lookupino(i); @@ -777,7 +809,7 @@ checkrestore() register ino_t i; vprintf(stdout, "Check the symbol table.\n"); - for (i = ROOTINO; i < maxino; i++) { + for (i = WINO; i < maxino; i++) { for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { ep->e_flags &= ~KEEP; if (ep->e_type == NODE) diff --git a/sbin/restore/restore.h b/sbin/restore/restore.h index 266526b19dc7..878f89f5eac6 100644 --- a/sbin/restore/restore.h +++ b/sbin/restore/restore.h @@ -35,8 +35,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)restore.h 8.2 (Berkeley) 1/21/94 - * $Id: restore.h,v 1.5 1994/06/08 19:33:43 mycroft Exp $ + * from: @(#)restore.h 8.3 (Berkeley) 9/13/94 + * $Id: restore.h,v 1.6 1994/12/28 02:21:50 mycroft Exp $ */ /* @@ -54,7 +54,7 @@ extern int yflag; /* always try to recover from tape errors */ * Global variables */ extern char *dumpmap; /* map of inodes on this dump tape */ -extern char *clrimap; /* map of inodes to be deleted */ +extern char *usedinomap; /* map of inodes that are in use on this fs */ extern ino_t maxino; /* highest numbered inode in this file system */ extern long dumpnum; /* location of the dump on this tape */ extern long volno; /* current volume being read */ @@ -130,6 +130,8 @@ typedef struct rstdirdesc RST_DIR; */ #define TSTINO(ino, map) \ (map[(u_int)((ino) - 1) / NBBY] & (1 << ((u_int)((ino) - 1) % NBBY))) +#define SETINO(ino, map) \ + map[(u_int)((ino) - 1) / NBBY] |= 1 << ((u_int)((ino) - 1) % NBBY) #define dprintf if (dflag) fprintf #define vprintf if (vflag) fprintf diff --git a/sbin/restore/symtab.c b/sbin/restore/symtab.c index d2fea259600f..c36b48127216 100644 --- a/sbin/restore/symtab.c +++ b/sbin/restore/symtab.c @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)symtab.c 8.1 (Berkeley) 6/5/93";*/ -static char *rcsid = "$Id: symtab.c,v 1.5 1994/09/23 14:27:56 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)symtab.c 8.2 (Berkeley) 9/13/94";*/ +static char *rcsid = "$Id: symtab.c,v 1.6 1994/12/28 02:21:52 mycroft Exp $"; #endif /* not lint */ /* @@ -84,7 +84,7 @@ lookupino(inum) { register struct entry *ep; - if (inum < ROOTINO || inum >= maxino) + if (inum < WINO || inum >= maxino) return (NULL); for (ep = entry[inum % entrytblsize]; ep != NULL; ep = ep->e_next) if (ep->e_ino == inum) @@ -102,7 +102,7 @@ addino(inum, np) { struct entry **epp; - if (inum < ROOTINO || inum >= maxino) + if (inum < WINO || inum >= maxino) panic("addino: out of range %d\n", inum); epp = &entry[inum % entrytblsize]; np->e_ino = inum; @@ -124,7 +124,7 @@ deleteino(inum) register struct entry *next; struct entry **prev; - if (inum < ROOTINO || inum >= maxino) + if (inum < WINO || inum >= maxino) panic("deleteino: out of range %d\n", inum); prev = &entry[inum % entrytblsize]; for (next = *prev; next != NULL; next = next->e_next) { @@ -471,7 +471,7 @@ dumpsymtable(filename, checkpt) * Assign indicies to each entry * Write out the string entries */ - for (i = ROOTINO; i < maxino; i++) { + for (i = WINO; i <= maxino; i++) { for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { ep->e_index = mynum++; (void) fwrite(ep->e_name, sizeof(char), @@ -483,7 +483,7 @@ dumpsymtable(filename, checkpt) */ tep = &temp; stroff = 0; - for (i = ROOTINO; i < maxino; i++) { + for (i = WINO; i <= maxino; i++) { for (ep = lookupino(i); ep != NULL; ep = ep->e_links) { memcpy(tep, ep, (long)sizeof(struct entry)); tep->e_name = (char *)stroff; diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c index 6da48782f2b7..585c300b54de 100644 --- a/sbin/restore/tape.c +++ b/sbin/restore/tape.c @@ -37,8 +37,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)tape.c 8.3 (Berkeley) 4/1/94";*/ -static char *rcsid = "$Id: tape.c,v 1.13 1994/09/23 14:27:57 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)tape.c 8.6 (Berkeley) 9/13/94";*/ +static char *rcsid = "$Id: tape.c,v 1.14 1994/12/28 02:21:53 mycroft Exp $"; #endif /* not lint */ #include @@ -251,8 +251,8 @@ setup() dprintf(stdout, "maxino = %d\n", maxino); map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); if (map == NULL) - panic("no memory for file removal list\n"); - clrimap = map; + panic("no memory for active inode map\n"); + usedinomap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); if (spcl.c_type != TS_BITS) { @@ -265,6 +265,13 @@ setup() dumpmap = map; curfile.action = USING; getfile(xtrmap, xtrmapskip); + /* + * If there may be whiteout entries on the tape, pretend that the + * whiteout inode exists, so that the whiteout entries can be + * extracted. + */ + if (oldinofmt == 0) + SETINO(WINO, dumpmap); } /* @@ -501,7 +508,8 @@ int extractfile(name) char *name; { - int mode; + int flags; + mode_t mode; struct timeval timep[2]; struct entry *ep; @@ -512,6 +520,7 @@ extractfile(name) timep[1].tv_sec = curfile.dip->di_mtime.ts_sec; timep[1].tv_usec = curfile.dip->di_mtime.ts_nsec / 1000; mode = curfile.dip->di_mode; + flags = curfile.dip->di_flags; switch (mode & IFMT) { default: @@ -546,24 +555,6 @@ extractfile(name) } return (linkit(lnkbuf, name, SYMLINK)); - case IFIFO: - vprintf(stdout, "extract fifo %s\n", name); - if (Nflag) { - skipfile(); - return (GOOD); - } - if (mkfifo(name, mode) < 0) { - fprintf(stderr, "%s: cannot create fifo: %s\n", - name, strerror(errno)); - skipfile(); - return (FAIL); - } - (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); - (void) chmod(name, mode); - skipfile(); - utimes(name, timep); - return (GOOD); - case IFCHR: case IFBLK: vprintf(stdout, "extract special file %s\n", name); @@ -579,6 +570,26 @@ extractfile(name) } (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); (void) chmod(name, mode); + (void) chflags(name, flags); + skipfile(); + utimes(name, timep); + return (GOOD); + + case IFIFO: + vprintf(stdout, "extract fifo %s\n", name); + if (Nflag) { + skipfile(); + return (GOOD); + } + if (mkfifo(name, mode) < 0) { + fprintf(stderr, "%s: cannot create fifo: %s\n", + name, strerror(errno)); + skipfile(); + return (FAIL); + } + (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); + (void) chmod(name, mode); + (void) chflags(name, flags); skipfile(); utimes(name, timep); return (GOOD); @@ -598,6 +609,7 @@ extractfile(name) } (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); (void) fchmod(ofile, mode); + (void) fchflags(ofile, flags); getfile(xtrfile, xtrskip); (void) close(ofile); utimes(name, timep); @@ -1139,10 +1151,10 @@ accthdr(header) goto newcalc; switch (prevtype) { case TS_BITS: - fprintf(stderr, "Dump mask header"); + fprintf(stderr, "Dumped inodes map header"); break; case TS_CLRI: - fprintf(stderr, "Remove mask header"); + fprintf(stderr, "Used inodes map header"); break; case TS_INODE: fprintf(stderr, "File header, ino %d", previno); diff --git a/sbin/restore/utilities.c b/sbin/restore/utilities.c index 19d573d1d183..aa90b732429f 100644 --- a/sbin/restore/utilities.c +++ b/sbin/restore/utilities.c @@ -32,8 +32,8 @@ */ #ifndef lint -/*static char sccsid[] = "from: @(#)utilities.c 8.2 (Berkeley) 3/25/94";*/ -static char *rcsid = "$Id: utilities.c,v 1.6 1994/09/23 14:27:59 mycroft Exp $"; +/*static char sccsid[] = "from: @(#)utilities.c 8.4 (Berkeley) 10/18/94";*/ +static char *rcsid = "$Id: utilities.c,v 1.7 1994/12/28 02:21:55 mycroft Exp $"; #endif /* not lint */ #include @@ -230,6 +230,45 @@ linkit(existing, new, type) return (GOOD); } +/* + * Create a whiteout. + */ +int +addwhiteout(name) + char *name; +{ + + if (!Nflag && mknod(name, S_IFWHT, 0) < 0) { + fprintf(stderr, "warning: cannot create whiteout %s: %s\n", + name, strerror(errno)); + return (FAIL); + } + vprintf(stdout, "Create whiteout %s\n", name); + return (GOOD); +} + +/* + * Delete a whiteout. + */ +void +delwhiteout(ep) + register struct entry *ep; +{ + char *name; + + if (ep->e_type != LEAF) + badentry(ep, "delwhiteout: not a leaf"); + ep->e_flags |= REMOVED; + ep->e_flags &= ~TMPNAME; + name = myname(ep); + if (!Nflag && undelete(name) < 0) { + fprintf(stderr, "warning: cannot delete whiteout %s: %s\n", + name, strerror(errno)); + return; + } + vprintf(stdout, "Delete whiteout %s\n", name); +} + /* * find lowest number file (above "start") that needs to be extracted */