/* Copyright (c) 1983 Regents of the University of California */
static char sccsid
[] = "@(#)restore.c 3.6 (Berkeley) 83/01/16";
static struct entry
*removelist
; /* list of nodes to be deleted */
* Mark entries to be removed.
register struct entry
*ep
;
vprintf(stdout
, "Mark entries to be removed.\n");
for (i
= ROOTINO
; i
< maxino
; i
++) {
for ( ; ep
!= NIL
; ep
= ep
->e_links
) {
dprintf(stdout
, "%s: REMOVE\n", myname(ep
));
if (ep
->e_type
== LEAF
) {
* List entries on the tape.
listfile(name
, ino
, type
)
if (BIT(ino
, dumpmap
) == 0) {
vprintf(stdout
, "%s\t", type
== LEAF
? "leaf" : "dir");
fprintf(stdout
, "%10d\t%s\n", ino
, name
);
* Request that new entries be extracted.
register struct entry
*ep
;
if (BIT(ino
, dumpmap
) == 0) {
vprintf(stdout
, "%s: not on the tape\n", name
);
sprintf(buf
, "./%u", ino
);
(void) genliteraldir(name
, ino
);
if (strcmp(name
, myname(ep
)) == 0)
ep
= addentry(name
, ino
, type
);
* For each directory entry on the incremental tape, determine which
* category it falls into as follows:
* KEEP - entries that are to be left alone.
* NEW - new entries to be added.
* EXTRACT - files that must be updated with new contents.
* LINK - new links to be added.
* Renames are done at the same time.
nodeupdates(name
, ino
, type
)
register struct entry
*ep
, *np
, *ip
;
char keybuf
[32], *keyval
= &keybuf
[1];
* 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.
strcat(keybuf
, "|ONTAPE");
strcat(keybuf
, "|INOFND");
for (ep
= ip
; ep
!= NIL
; ep
= ep
->e_links
)
if ((key
& (INOFND
|NAMEFND
) == (INOFND
|NAMEFND
)) && ip
!= np
) {
dprintf(stdout
, "[%s] %s: mktempname\n", keyval
, name
);
strcat(keybuf
, "|NAMEFND");
(((key
& INOFND
) && ip
->e_type
!= type
) ||
((key
& NAMEFND
) && np
->e_type
!= type
))) {
(void) strcat(keybuf
, "|MODECHG");
dprintf(stdout
, "[%s] %s: KEEP\n", keyval
, name
);
ep
= addentry(name
, ino
, type
);
dprintf(stdout
, "[%s] %s: KEEP|NEW\n", keyval
, name
);
dprintf(stdout
, "[%s] %s: EXTRACT\n", keyval
, name
);
if (ip
->e_flags
& KEEP
) {
panic("%s linked to directory %s\n",
ep
= addentry(name
, ino
, type
|LINK
);
dprintf(stdout
, "[%s] %s: NEW\n", keyval
, name
);
renameit(myname(ip
), name
);
dprintf(stdout
, "[%s] %s: RENAME\n", keyval
, name
);
case ONTAPE
|NAMEFND
|MODECHG
:
np
= addentry(name
, ino
, type
);
case ONTAPE
|INOFND
|NAMEFND
:
dprintf(stdout
, "[%s] %s: KEEP|EXTRACT\n", keyval
, name
);
case ONTAPE
|INOFND
|MODECHG
:
case ONTAPE
|INOFND
|NAMEFND
|MODECHG
:
badentry(ip
, "not removed");
case INOFND
|NAMEFND
|MODECHG
:
panic("[%s] %s: inconsistent state\n", keyval
, name
);
panic("[%s] %s: impossible state\n", keyval
, name
);
* Find unreferenced link names.
register struct entry
*ep
, *np
;
vprintf(stdout
, "Find unreferenced names.\n");
for (i
= ROOTINO
; i
< maxino
; i
++) {
if (ep
== NIL
|| ep
->e_type
== LEAF
|| !BIT(i
, dumpmap
))
for (np
= ep
->e_entries
; np
!= NIL
; np
= np
->e_sibling
) {
"%s: remove unreferenced name\n",
* Remove old nodes (directories).
register struct entry
*ep
;
vprintf(stdout
, "Remove old nodes (directories).\n");
for (ep
= removelist
; ep
!= NIL
; ep
= ep
->e_next
) {
if (ep
->e_entries
== NIL
) {
dprintf(stdout
, "%s: removed\n", myname(ep
));
for (ep
= removelist
; ep
!= NIL
; ep
= ep
->e_next
)
badentry(ep
, "cannot remove, non-empty");
register struct entry
*ep
;
vprintf(stdout
, "Continue extraction of new leaves\n");
vprintf(stdout
, "Extract new leaves.\n");
dumpsymtable(symtabfile
, volno
);
first
= lowerbnd(ROOTINO
);
while (curfile
.ino
< maxino
) {
while (first
< curfile
.ino
) {
panic("%d: bad first\n", first
);
fprintf(stderr
, "%s: not found on tape\n", myname(ep
));
ep
->e_flags
&= ~(NEW
|EXTRACT
);
if (first
!= curfile
.ino
)
panic("expected next file %d, got %d\n",
ep
= lookupino(curfile
.ino
);
panic("unknown file on tape\n");
if ((ep
->e_flags
& (NEW
|EXTRACT
)) == 0)
badentry(ep
, "unexpected file on tape");
if ((ep
->e_flags
& EXTRACT
) != 0) {
ep
->e_flags
&= ~(NEW
|EXTRACT
);
dumpsymtable(symtabfile
, volno
);
* Efficiently extract a subset of the files on a tape
register ino_t first
, next
, last
;
register struct entry
*ep
;
vprintf(stdout
, "Extract requested files\n");
first
= lowerbnd(ROOTINO
);
last
= upperbnd(maxino
- 1);
* Check to see if any files remain to be extracted
* Reject any volumes with inodes greater
* than the last one needed
while (curfile
.ino
> last
) {
* Decide on the next inode needed.
* Skip across the inodes until it is found
* or an out of order volume change is encountered
next
= lowerbnd(curfile
.ino
);
while (next
> curfile
.ino
&& volno
== curvol
)
} while (volno
== curvol
+ 1);
* If volume change out of order occurred the
* current state must be re calculated
* If the current inode is greater than the one we were
* looking for then we missed the one we were looking for.
* Since we only attempt to extract files listed in the
* dump map, the file must have been lost due to a tape
* read error. Thus we report all requested files between
* the one we were looking for, and the one we found as
* missing, and delete their request flags.
while (next
< curfile
.ino
) {
panic("corrupted symbol table\n");
fprintf(stderr
, "%s: not found on tape\n", myname(ep
));
* The current inode is the one that we are looking for,
* so extract it per its requested name.
if (next
== curfile
.ino
&& next
<= last
) {
panic("corrupted symbol table\n");
register struct entry
*np
, *ep
;
vprintf(stdout
, "Add links\n");
for (i
= ROOTINO
; i
< maxino
; i
++) {
for (np
= ep
->e_links
; np
!= NIL
; np
= np
->e_links
) {
(void) strcpy(name
, myname(ep
));
if (ep
->e_type
== NODE
) {
vprintf(stdout
, "changing hard link to directory to a symbolic link:");
linkit(name
, myname(np
), SYMLINK
);
linkit(name
, myname(np
), HARDLINK
);
* Check the symbol table.
register struct entry
*ep
;
vprintf(stdout
, "Check the symbol table.\n");
for (i
= ROOTINO
; i
< maxino
; i
++) {
for (ep
= lookupino(i
); ep
!= NIL
; ep
= ep
->e_links
) {
badentry(ep
, "incomplete operations");
* Compare with the directory structure on the tape
verifyfile(name
, ino
, type
)
panic("missing name %s\n", name
);
for (np
= lookupino(ino
); np
!= NIL
; np
= np
->e_links
)
panic("missing inumber %d\n", ino
);
if (ep
->e_type
== LEAF
&& type
!= LEAF
)
badentry(ep
, "type should be LEAF");