/*
* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
- * Remy Card <card@Linux.EU.Org>, 1994, 1995, 1996
- *
+ * Remy Card <card@Linux.EU.Org>, 1994-1997
+ * Stelian Pop <pop@cybercable.fr>, 1999-2000
+ * Stelian Pop <pop@cybercable.fr> - Alcôve <www.alcove.fr>, 2000
*/
/*
*/
#ifndef lint
-static char sccsid[] = "@(#)restore.c 8.3 (Berkeley) 9/13/94";
+static const char rcsid[] =
+ "$Id: restore.c,v 1.11 2000/11/10 14:42:25 stelian Exp $";
#endif /* not lint */
#include <sys/types.h>
-#include <sys/stat.h>
#ifdef __linux__
+#include <sys/param.h>
#include <sys/time.h>
#include <linux/ext2_fs.h>
#include <bsdcompat.h>
* List entries on the tape.
*/
long
-listfile(name, ino, type)
- char *name;
- ino_t ino;
- int type;
+listfile(char *name, ino_t ino, int type)
{
long descend = hflag ? GOOD : FAIL;
if (TSTINO(ino, dumpmap) == 0)
return (descend);
- vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
- fprintf(stdout, "%10d\t%s\n", ino, name);
+ Vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
+ fprintf(stdout, "%10lu\t%s\n", (unsigned long)ino, name);
return (descend);
}
* Request that new entries be extracted.
*/
long
-addfile(name, ino, type)
- char *name;
- ino_t ino;
- int type;
+addfile(char *name, ino_t ino, int type)
{
- register struct entry *ep;
+ register struct entry *ep, *np;
long descend = hflag ? GOOD : FAIL;
char buf[100];
if (TSTINO(ino, dumpmap) == 0) {
- dprintf(stdout, "%s: not on the tape\n", name);
+ 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);
+ (void) snprintf(buf, sizeof(buf), "./%lu", (unsigned long)ino);
name = buf;
if (type == NODE) {
(void) genliteraldir(name, ino);
return (descend);
}
type |= LINK;
+ for (np = ep->e_links; np; np = np->e_links)
+ if (strcmp(name, myname(np)) == 0) {
+ np->e_flags |= NEW;
+ return (descend);
+ }
}
ep = addentry(name, ino, type);
if (type == NODE)
*/
/* ARGSUSED */
long
-deletefile(name, ino, type)
- char *name;
- ino_t ino;
- int type;
+deletefile(char *name, ino_t ino, int type)
{
long descend = hflag ? GOOD : FAIL;
struct entry *ep;
return (descend);
}
-/*
+/*
* The following four routines implement the incremental
* restore algorithm. The first removes old entries, the second
* does renames and calculates the extraction list, the third
*
* Directories cannot be immediately deleted, as they may have
* other files in them which need to be moved out first. As
- * directories to be deleted are found, they are put on the
+ * directories to be deleted are found, they are put on the
* following deletion list. After all deletions and renames
* are done, this list is actually deleted.
*/
* Remove directories from the lookup chains.
*/
void
-removeoldleaves()
+removeoldleaves(void)
{
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");
+ 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;
if (TSTINO(i, usedinomap))
continue;
for ( ; ep != NULL; ep = ep->e_links) {
- dprintf(stdout, "%s: REMOVE\n", myname(ep));
+ Dprintf(stdout, "%s: REMOVE\n", myname(ep));
if (ep->e_type == LEAF) {
removeleaf(ep);
freeentry(ep);
* Renames are done at the same time.
*/
long
-nodeupdates(name, ino, type)
- char *name;
- ino_t ino;
- int type;
+nodeupdates(char *name, ino_t ino, int type)
{
register struct entry *ep, *np, *ip;
long descend = GOOD;
# define MODECHG 0x8 /* mode of inode changed */
/*
- * This routine is called once for each element in the
+ * This routine is called once for each element in the
* directory hierarchy, with a full path name.
* The "type" value is incorrectly specified as LEAF for
* directories that are not on the dump tape.
removeleaf(np);
freeentry(np);
} else {
- dprintf(stdout, "name/inode conflict, mktempname %s\n",
+ Dprintf(stdout, "name/inode conflict, mktempname %s\n",
myname(np));
mktempname(np);
}
*/
case INOFND|NAMEFND:
ip->e_flags |= KEEP;
- dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
flagvalues(ip));
break;
if (type == NODE)
newnode(ep);
ep->e_flags |= NEW|KEEP;
- dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
flagvalues(ep));
break;
renameit(myname(ip), name);
moveentry(ip, name);
ip->e_flags |= KEEP;
- dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
flagvalues(ip));
break;
}
}
ep = addentry(name, ino, type|LINK);
ep->e_flags |= NEW;
- dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
flagvalues(ep));
break;
if (type == NODE)
newnode(ep);
ep->e_flags |= NEW|KEEP;
- dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
flagvalues(ep));
break;
}
if (type == LEAF && lookuptype != LINK)
np->e_flags |= EXTRACT;
np->e_flags |= KEEP;
- dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
flagvalues(np));
break;
* that we need to rename, so we delete it from the symbol
* table, and put it on the list to be deleted eventually.
* Conversely if a directory is to be created, it must be
- * done immediately, rather than waiting until the
+ * done immediately, rather than waiting until the
* extraction phase.
*/
case ONTAPE|INOFND|MODECHG:
}
if (ip->e_type == LEAF) {
/* changing from leaf to node */
- removeleaf(ip);
- freeentry(ip);
+ for ( ; ip != NULL; ip = ip->e_links) {
+ if (ip->e_type != LEAF)
+ badentry(ip, "NODE and LEAF links to same inode");
+ removeleaf(ip);
+ freeentry(ip);
+ }
ip = addentry(name, ino, type);
newnode(ip);
} else {
ip = addentry(name, ino, type);
}
ip->e_flags |= NEW|KEEP;
- dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
+ Dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
flagvalues(ip));
break;
/*
- * A hard link to a diirectory that has been removed.
+ * A hard link to a directory that has been removed.
* Ignore it.
*/
case NAMEFND:
- dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key),
+ Dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key),
name);
descend = FAIL;
break;
*/
case NULL:
if (compare_ignore_not_found) break;
- fprintf(stderr, "%s: (inode %d) not found on tape\n",
- name, ino);
+ fprintf(stderr, "%s: (inode %lu) not found on tape\n",
+ name, (unsigned long)ino);
+ compare_errors = 1;
break;
/*
default:
panic("[%s] %s: impossible state\n", keyval(key), name);
break;
- }
+ }
return (descend);
}
* Calculate the active flags in a key.
*/
static char *
-keyval(key)
- int key;
+keyval(int key)
{
static char keybuf[32];
* Find unreferenced link names.
*/
void
-findunreflinks()
+findunreflinks(void)
{
register struct entry *ep, *np;
register ino_t i;
- vprintf(stdout, "Find unreferenced names.\n");
+ Vprintf(stdout, "Find unreferenced names.\n");
for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(i);
if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0)
continue;
for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
if (np->e_flags == 0) {
- dprintf(stdout,
+ Dprintf(stdout,
"%s: remove unreferenced name\n",
myname(np));
removeleaf(np);
if (np->e_type == LEAF) {
if (np->e_flags != 0)
badentry(np, "unreferenced with flags");
- dprintf(stdout,
+ Dprintf(stdout,
"%s: remove unreferenced name\n",
myname(np));
removeleaf(np);
* time O(N).
*/
void
-removeoldnodes()
+removeoldnodes(void)
{
register struct entry *ep, **prev;
long change;
- vprintf(stdout, "Remove old nodes (directories).\n");
+ Vprintf(stdout, "Remove old nodes (directories).\n");
do {
change = 0;
prev = &removelist;
/* current copy of this file on disk. If do_compare is 0, then just */
/* make our caller think we did it--this is used to handle hard links */
/* to files and devices. */
+static void
compare_entry(struct entry *ep, int do_compare)
{
- if ((ep->e_flags & (NEW|EXTRACT)) == 0)
+ if ((ep->e_flags & (NEW|EXTRACT)) == 0) {
badentry(ep, "unexpected file on tape");
+ compare_errors = 1;
+ }
if (do_compare) (void) comparefile(myname(ep));
ep->e_flags &= ~(NEW|EXTRACT);
}
* This is the routine used to compare files for the 'C' command.
*/
void
-compareleaves()
+compareleaves(void)
{
register struct entry *ep;
ino_t first;
if (ep == NULL)
panic("%d: bad first\n", first);
fprintf(stderr, "%s: not found on tape\n", myname(ep));
+ compare_errors = 1;
ep->e_flags &= ~(NEW|EXTRACT);
first = lowerbnd(first);
}
* on the next incremental tape.
*/
if (first != curfile.ino) {
- fprintf(stderr, "expected next file %d, got %d\n",
- first, curfile.ino);
+ fprintf(stderr, "expected next file %ld, got %lu\n",
+ (long)first, (unsigned long)curfile.ino);
+ compare_errors = 1;
skipfile();
goto next;
}
ep = lookupino(curfile.ino);
- if (ep == NULL)
+ if (ep == NULL) {
panic("unknown file on tape\n");
+ compare_errors = 1;
+ }
compare_entry(ep, 1);
for (ep = ep->e_links; ep != NULL; ep = ep->e_links) {
compare_entry(ep, 0);
* Extract new leaves.
*/
void
-createleaves(symtabfile)
- char *symtabfile;
+createleaves(char *symtabfile)
{
register struct entry *ep;
ino_t first;
long curvol;
if (command == 'R') {
- vprintf(stdout, "Continue extraction of new leaves\n");
+ Vprintf(stdout, "Continue extraction of new leaves\n");
} else {
- vprintf(stdout, "Extract new leaves.\n");
+ Vprintf(stdout, "Extract new leaves.\n");
dumpsymtable(symtabfile, volno);
}
first = lowerbnd(ROOTINO);
/*
* If we find files on the tape that have no corresponding
* directory entries, then we must have found a file that
- * was created while the dump was in progress. Since we have
+ * was created while the dump was in progress. Since we have
* no name for it, we discard it knowing that it will be
* on the next incremental tape.
*/
if (first != curfile.ino) {
- fprintf(stderr, "expected next file %d, got %d\n",
- first, curfile.ino);
+ fprintf(stderr, "expected next file %ld, got %lu\n",
+ (long)first, (unsigned long)curfile.ino);
skipfile();
goto next;
}
/*
* If the file is to be extracted, then the old file must
* be removed since its type may change from one leaf type
- * to another (eg "file" to "character special").
+ * to another (e.g. "file" to "character special").
*/
if ((ep->e_flags & EXTRACT) != 0) {
removeleaf(ep);
ep->e_flags &= ~(NEW|EXTRACT);
/*
* We checkpoint the restore after every tape reel, so
- * as to simplify the amount of work re quired by the
+ * as to simplify the amount of work required by the
* 'R' command.
*/
next:
* Efficiently extract a subset of the files on a tape.
*/
void
-createfiles()
+createfiles(void)
{
register ino_t first, next, last;
register struct entry *ep;
long curvol;
- vprintf(stdout, "Extract requested files\n");
+ Vprintf(stdout, "Extract requested files\n");
curfile.action = SKIP;
getvol((long)1);
skipmaps();
* Add links.
*/
void
-createlinks()
+createlinks(void)
{
register struct entry *np, *ep;
register ino_t i;
char name[BUFSIZ];
- if (ep = lookupino(WINO)) {
- vprintf(stdout, "Add whiteouts\n");
+ if ((ep = lookupino(WINO))) {
+ Vprintf(stdout, "Add whiteouts\n");
for ( ; ep != NULL; ep = ep->e_links) {
if ((ep->e_flags & NEW) == 0)
continue;
ep->e_flags &= ~NEW;
}
}
- vprintf(stdout, "Add links\n");
+ Vprintf(stdout, "Add links\n");
for (i = ROOTINO; i < maxino; i++) {
ep = lookupino(i);
if (ep == NULL)
* that no temporary names remain.
*/
void
-checkrestore()
+checkrestore(void)
{
register struct entry *ep;
register ino_t i;
- vprintf(stdout, "Check the symbol table.\n");
+ Vprintf(stdout, "Check the symbol table.\n");
for (i = WINO; i < maxino; i++) {
for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
ep->e_flags &= ~KEEP;
* A paranoid check that things are as they should be.
*/
long
-verifyfile(name, ino, type)
- char *name;
- ino_t ino;
- int type;
+verifyfile(char *name, ino_t ino, int type)
{
struct entry *np, *ep;
long descend = GOOD;