Fix markup. Fix backslashes to surive roff.
[netbsd-mini2440.git] / sbin / restore / restore.c
blob6b1e0d145d5169f112f75b4b3ddc8aac410fd285
1 /* $NetBSD: restore.c,v 1.19 2005/08/19 02:07:19 christos Exp $ */
3 /*
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)restore.c 8.3 (Berkeley) 9/13/94";
36 #else
37 __RCSID("$NetBSD: restore.c,v 1.19 2005/08/19 02:07:19 christos Exp $");
38 #endif
39 #endif /* not lint */
41 #include <sys/types.h>
42 #include <sys/stat.h>
44 #include <ufs/ufs/dinode.h>
46 #include <stdio.h>
47 #include <string.h>
49 #include "restore.h"
50 #include "extern.h"
52 static char *keyval(int);
55 * This implements the 't' option.
56 * List entries on the tape.
58 long
59 listfile(const char *name, ino_t ino, int type)
61 long descend = hflag ? GOOD : FAIL;
63 if (TSTINO(ino, dumpmap) == 0)
64 return (descend);
65 vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
66 fprintf(stdout, "%10llu\t%s\n", (unsigned long long)ino, name);
67 return (descend);
71 * This implements the 'x' option.
72 * Request that new entries be extracted.
74 long
75 addfile(const char *name, ino_t ino, int type)
77 struct entry *ep;
78 long descend = hflag ? GOOD : FAIL;
79 char buf[100];
81 if (TSTINO(ino, dumpmap) == 0) {
82 dprintf(stdout, "%s: not on the tape\n", name);
83 return (descend);
85 if (ino == WINO && command == 'i' && !vflag)
86 return (descend);
87 if (!mflag) {
88 (void) snprintf(buf, sizeof(buf), "./%llu",
89 (unsigned long long)ino);
90 name = buf;
91 if (type == NODE) {
92 (void) genliteraldir(name, ino);
93 return (descend);
96 ep = lookupino(ino);
97 if (ep != NULL) {
98 if (strcmp(name, myname(ep)) == 0) {
99 ep->e_flags |= NEW;
100 return (descend);
102 type |= LINK;
104 ep = addentry(name, ino, type);
105 if (type == NODE)
106 newnode(ep);
107 ep->e_flags |= NEW;
108 return (descend);
112 * This is used by the 'i' option to undo previous requests made by addfile.
113 * Delete entries from the request queue.
115 /* ARGSUSED */
116 long
117 deletefile(const char *name, ino_t ino, int type __unused)
119 long descend = hflag ? GOOD : FAIL;
120 struct entry *ep;
122 if (TSTINO(ino, dumpmap) == 0)
123 return (descend);
124 ep = lookupname(name);
125 if (ep != NULL) {
126 ep->e_flags &= ~NEW;
127 ep->e_flags |= REMOVED;
128 if (ep->e_type != NODE)
129 freeentry(ep);
131 return (descend);
135 * The following four routines implement the incremental
136 * restore algorithm. The first removes old entries, the second
137 * does renames and calculates the extraction list, the third
138 * cleans up link names missed by the first two, and the final
139 * one deletes old directories.
141 * Directories cannot be immediately deleted, as they may have
142 * other files in them which need to be moved out first. As
143 * directories to be deleted are found, they are put on the
144 * following deletion list. After all deletions and renames
145 * are done, this list is actually deleted.
147 static struct entry *removelist;
150 * Remove invalid whiteouts from the old tree.
151 * Remove unneeded leaves from the old tree.
152 * Remove directories from the lookup chains.
154 void
155 removeoldleaves(void)
157 struct entry *ep, *nextep;
158 ino_t i, mydirino;
160 vprintf(stdout, "Mark entries to be removed.\n");
161 if ((ep = lookupino(WINO)) != NULL) {
162 vprintf(stdout, "Delete whiteouts\n");
163 for ( ; ep != NULL; ep = nextep) {
164 nextep = ep->e_links;
165 mydirino = ep->e_parent->e_ino;
167 * We remove all whiteouts that are in directories
168 * that have been removed or that have been dumped.
170 if (TSTINO(mydirino, usedinomap) &&
171 !TSTINO(mydirino, dumpmap))
172 continue;
173 delwhiteout(ep);
174 freeentry(ep);
177 for (i = ROOTINO + 1; i < maxino; i++) {
178 ep = lookupino(i);
179 if (ep == NULL)
180 continue;
181 if (TSTINO(i, usedinomap))
182 continue;
183 for ( ; ep != NULL; ep = ep->e_links) {
184 dprintf(stdout, "%s: REMOVE\n", myname(ep));
185 if (ep->e_type == LEAF) {
186 removeleaf(ep);
187 freeentry(ep);
188 } else {
189 mktempname(ep);
190 deleteino(ep->e_ino);
191 ep->e_next = removelist;
192 removelist = ep;
199 * For each directory entry on the incremental tape, determine which
200 * category it falls into as follows:
201 * KEEP - entries that are to be left alone.
202 * NEW - new entries to be added.
203 * EXTRACT - files that must be updated with new contents.
204 * LINK - new links to be added.
205 * Renames are done at the same time.
207 long
208 nodeupdates(const char *name, ino_t ino, int type)
210 struct entry *ep, *np, *ip;
211 long descend = GOOD;
212 int lookuptype = 0;
213 int key = 0;
214 /* key values */
215 # define ONTAPE 0x1 /* inode is on the tape */
216 # define INOFND 0x2 /* inode already exists */
217 # define NAMEFND 0x4 /* name already exists */
218 # define MODECHG 0x8 /* mode of inode changed */
221 * This routine is called once for each element in the
222 * directory hierarchy, with a full path name.
223 * The "type" value is incorrectly specified as LEAF for
224 * directories that are not on the dump tape.
226 * Check to see if the file is on the tape.
228 if (TSTINO(ino, dumpmap))
229 key |= ONTAPE;
231 * Check to see if the name exists, and if the name is a link.
233 np = lookupname(name);
234 if (np != NULL) {
235 key |= NAMEFND;
236 ip = lookupino(np->e_ino);
237 if (ip == NULL)
238 panic("corrupted symbol table\n");
239 if (ip != np)
240 lookuptype = LINK;
243 * Check to see if the inode exists, and if one of its links
244 * corresponds to the name (if one was found).
246 ip = lookupino(ino);
247 if (ip != NULL) {
248 key |= INOFND;
249 for (ep = ip->e_links; ep != NULL; ep = ep->e_links) {
250 if (ep == np) {
251 ip = ep;
252 break;
257 * If both a name and an inode are found, but they do not
258 * correspond to the same file, then both the inode that has
259 * been found and the inode corresponding to the name that
260 * has been found need to be renamed. The current pathname
261 * is the new name for the inode that has been found. Since
262 * all files to be deleted have already been removed, the
263 * named file is either a now unneeded link, or it must live
264 * under a new name in this dump level. If it is a link, it
265 * can be removed. If it is not a link, it is given a
266 * temporary name in anticipation that it will be renamed
267 * when it is later found by inode number.
269 if (((key & (INOFND|NAMEFND)) == (INOFND|NAMEFND)) && ip != np) {
270 if (lookuptype == LINK) {
271 removeleaf(np);
272 freeentry(np);
273 } else {
274 dprintf(stdout, "name/inode conflict, mktempname %s\n",
275 myname(np));
276 mktempname(np);
278 np = NULL;
279 key &= ~NAMEFND;
281 if ((key & ONTAPE) &&
282 (((key & INOFND) && ip->e_type != type) ||
283 ((key & NAMEFND) && np->e_type != type)))
284 key |= MODECHG;
287 * Decide on the disposition of the file based on its flags.
288 * Note that we have already handled the case in which
289 * a name and inode are found that correspond to different files.
290 * Thus if both NAMEFND and INOFND are set then ip == np.
292 switch (key) {
295 * A previously existing file has been found.
296 * Mark it as KEEP so that other links to the inode can be
297 * detected, and so that it will not be reclaimed by the search
298 * for unreferenced names.
300 case INOFND|NAMEFND:
301 ip->e_flags |= KEEP;
302 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
303 flagvalues(ip));
304 break;
307 * A file on the tape has a name which is the same as a name
308 * corresponding to a different file in the previous dump.
309 * Since all files to be deleted have already been removed,
310 * this file is either a now unneeded link, or it must live
311 * under a new name in this dump level. If it is a link, it
312 * can simply be removed. If it is not a link, it is given a
313 * temporary name in anticipation that it will be renamed
314 * when it is later found by inode number (see INOFND case
315 * below). The entry is then treated as a new file.
317 case ONTAPE|NAMEFND:
318 case ONTAPE|NAMEFND|MODECHG:
319 if (lookuptype == LINK) {
320 removeleaf(np);
321 freeentry(np);
322 } else {
323 mktempname(np);
325 /* fall through */
328 * A previously non-existent file.
329 * Add it to the file system, and request its extraction.
330 * If it is a directory, create it immediately.
331 * (Since the name is unused there can be no conflict)
333 case ONTAPE:
334 ep = addentry(name, ino, type);
335 if (type == NODE)
336 newnode(ep);
337 ep->e_flags |= NEW|KEEP;
338 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
339 flagvalues(ep));
340 break;
343 * A file with the same inode number, but a different
344 * name has been found. If the other name has not already
345 * been found (indicated by the KEEP flag, see above) then
346 * this must be a new name for the file, and it is renamed.
347 * If the other name has been found then this must be a
348 * link to the file. Hard links to directories are not
349 * permitted, and are either deleted or converted to
350 * symbolic links. Finally, if the file is on the tape,
351 * a request is made to extract it.
353 case ONTAPE|INOFND:
354 if (type == LEAF && (ip->e_flags & KEEP) == 0)
355 ip->e_flags |= EXTRACT;
356 /* fall through */
357 case INOFND:
358 if ((ip->e_flags & KEEP) == 0) {
359 renameit(myname(ip), name);
360 moveentry(ip, name);
361 ip->e_flags |= KEEP;
362 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
363 flagvalues(ip));
364 break;
366 if (ip->e_type == NODE) {
367 descend = FAIL;
368 fprintf(stderr,
369 "deleted hard link %s to directory %s\n",
370 name, myname(ip));
371 break;
373 ep = addentry(name, ino, type|LINK);
374 ep->e_flags |= NEW;
375 dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
376 flagvalues(ep));
377 break;
380 * A previously known file which is to be updated. If it is a link,
381 * then all names referring to the previous file must be removed
382 * so that the subset of them that remain can be recreated.
384 case ONTAPE|INOFND|NAMEFND:
385 if (lookuptype == LINK) {
386 removeleaf(np);
387 freeentry(np);
388 ep = addentry(name, ino, type|LINK);
389 if (type == NODE)
390 newnode(ep);
391 ep->e_flags |= NEW|KEEP;
392 dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
393 flagvalues(ep));
394 break;
396 if (type == LEAF && lookuptype != LINK)
397 np->e_flags |= EXTRACT;
398 np->e_flags |= KEEP;
399 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
400 flagvalues(np));
401 break;
404 * An inode is being reused in a completely different way.
405 * Normally an extract can simply do an "unlink" followed
406 * by a "creat". Here we must do effectively the same
407 * thing. The complications arise because we cannot really
408 * delete a directory since it may still contain files
409 * that we need to rename, so we delete it from the symbol
410 * table, and put it on the list to be deleted eventually.
411 * Conversely if a directory is to be created, it must be
412 * done immediately, rather than waiting until the
413 * extraction phase.
415 case ONTAPE|INOFND|MODECHG:
416 case ONTAPE|INOFND|NAMEFND|MODECHG:
417 if (ip->e_flags & KEEP) {
418 badentry(ip, "cannot KEEP and change modes");
419 break;
421 if (ip->e_type == LEAF) {
422 /* changing from leaf to node */
423 for ( ; ip != NULL; ip = ip->e_links) {
424 if (ip->e_type != LEAF)
425 badentry(ip,
426 "NODE and LEAF links to same inode");
427 removeleaf(ip);
428 freeentry(ip);
430 ip = addentry(name, ino, type);
431 newnode(ip);
432 } else {
433 /* changing from node to leaf */
434 if ((ip->e_flags & TMPNAME) == 0)
435 mktempname(ip);
436 deleteino(ip->e_ino);
437 ip->e_next = removelist;
438 removelist = ip;
439 ip = addentry(name, ino, type);
441 ip->e_flags |= NEW|KEEP;
442 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
443 flagvalues(ip));
444 break;
447 * A hard link to a diirectory that has been removed.
448 * Ignore it.
450 case NAMEFND:
451 dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key),
452 name);
453 descend = FAIL;
454 break;
457 * If we find a directory entry for a file that is not on
458 * the tape, then we must have found a file that was created
459 * while the dump was in progress. Since we have no contents
460 * for it, we discard the name knowing that it will be on the
461 * next incremental tape.
463 case 0:
464 fprintf(stderr, "%s: (inode %llu) not found on tape\n",
465 name, (unsigned long long)ino);
466 break;
469 * If any of these arise, something is grievously wrong with
470 * the current state of the symbol table.
472 case INOFND|NAMEFND|MODECHG:
473 case NAMEFND|MODECHG:
474 case INOFND|MODECHG:
475 fprintf(stderr, "[%s] %s: inconsistent state\n", keyval(key),
476 name);
477 break;
480 * These states "cannot" arise for any state of the symbol table.
482 case ONTAPE|MODECHG:
483 case MODECHG:
484 default:
485 panic("[%s] %s: impossible state\n", keyval(key), name);
486 break;
488 return (descend);
492 * Calculate the active flags in a key.
494 static char *
495 keyval(int key)
497 static char keybuf[32];
499 (void) strcpy(keybuf, "|NIL");
500 keybuf[0] = '\0';
501 if (key & ONTAPE)
502 (void) strcat(keybuf, "|ONTAPE");
503 if (key & INOFND)
504 (void) strcat(keybuf, "|INOFND");
505 if (key & NAMEFND)
506 (void) strcat(keybuf, "|NAMEFND");
507 if (key & MODECHG)
508 (void) strcat(keybuf, "|MODECHG");
509 return (&keybuf[1]);
513 * Find unreferenced link names.
515 void
516 findunreflinks(void)
518 struct entry *ep, *np;
519 ino_t i;
521 vprintf(stdout, "Find unreferenced names.\n");
522 for (i = ROOTINO; i < maxino; i++) {
523 ep = lookupino(i);
524 if (ep == NULL || ep->e_type == LEAF || TSTINO(i, dumpmap) == 0)
525 continue;
526 for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
527 if (np->e_flags == 0) {
528 dprintf(stdout,
529 "%s: remove unreferenced name\n",
530 myname(np));
531 removeleaf(np);
532 freeentry(np);
537 * Any leaves remaining in removed directories is unreferenced.
539 for (ep = removelist; ep != NULL; ep = ep->e_next) {
540 for (np = ep->e_entries; np != NULL; np = np->e_sibling) {
541 if (np->e_type == LEAF) {
542 if (np->e_flags != 0)
543 badentry(np, "unreferenced with flags");
544 dprintf(stdout,
545 "%s: remove unreferenced name\n",
546 myname(np));
547 removeleaf(np);
548 freeentry(np);
555 * Remove old nodes (directories).
556 * Note that this routine runs in O(N*D) where:
557 * N is the number of directory entries to be removed.
558 * D is the maximum depth of the tree.
559 * If N == D this can be quite slow. If the list were
560 * topologically sorted, the deletion could be done in
561 * time O(N).
563 void
564 removeoldnodes(void)
566 struct entry *ep, **prev;
567 long change;
569 vprintf(stdout, "Remove old nodes (directories).\n");
570 do {
571 change = 0;
572 prev = &removelist;
573 for (ep = removelist; ep != NULL; ep = *prev) {
574 if (ep->e_entries != NULL) {
575 prev = &ep->e_next;
576 continue;
578 *prev = ep->e_next;
579 removenode(ep);
580 freeentry(ep);
581 change++;
583 } while (change);
584 for (ep = removelist; ep != NULL; ep = ep->e_next)
585 badentry(ep, "cannot remove, non-empty");
589 * This is the routine used to extract files for the 'r' command.
590 * Extract new leaves.
592 void
593 createleaves(const char *symtabfile)
595 struct entry *ep;
596 ino_t first;
597 long curvol;
599 if (command == 'R') {
600 vprintf(stdout, "Continue extraction of new leaves\n");
601 } else {
602 vprintf(stdout, "Extract new leaves.\n");
603 dumpsymtable(symtabfile, volno);
605 first = lowerbnd(ROOTINO);
606 curvol = volno;
607 while (curfile.ino < maxino) {
608 first = lowerbnd(first);
610 * If the next available file is not the one which we
611 * expect then we have missed one or more files. Since
612 * we do not request files that were not on the tape,
613 * the lost files must have been due to a tape read error,
614 * or a file that was removed while the dump was in progress.
616 while (first < curfile.ino) {
617 ep = lookupino(first);
618 if (ep == NULL)
619 panic("%llu: bad first\n",
620 (unsigned long long)first);
621 fprintf(stderr, "%s: not found on tape\n", myname(ep));
622 ep->e_flags &= ~(NEW|EXTRACT);
623 first = lowerbnd(first);
626 * If we find files on the tape that have no corresponding
627 * directory entries, then we must have found a file that
628 * was created while the dump was in progress. Since we have
629 * no name for it, we discard it knowing that it will be
630 * on the next incremental tape.
632 if (first != curfile.ino) {
633 fprintf(stderr, "expected next file %llu, got %llu\n",
634 (unsigned long long)first,
635 (unsigned long long)curfile.ino);
636 skipfile();
637 goto next;
639 ep = lookupino(curfile.ino);
640 if (ep == NULL)
641 panic("unknown file on tape\n");
642 if ((ep->e_flags & (NEW|EXTRACT)) == 0)
643 badentry(ep, "unexpected file on tape");
645 * If the file is to be extracted, then the old file must
646 * be removed since its type may change from one leaf type
647 * to another (eg "file" to "character special").
649 if ((ep->e_flags & EXTRACT) != 0) {
650 removeleaf(ep);
651 ep->e_flags &= ~REMOVED;
653 (void) extractfile(myname(ep));
654 ep->e_flags &= ~(NEW|EXTRACT);
656 * We checkpoint the restore after every tape reel, so
657 * as to simplify the amount of work re quired by the
658 * 'R' command.
660 next:
661 if (curvol != volno) {
662 dumpsymtable(symtabfile, volno);
663 skipmaps();
664 curvol = volno;
670 * This is the routine used to extract files for the 'x' and 'i' commands.
671 * Efficiently extract a subset of the files on a tape.
673 void
674 createfiles(void)
676 ino_t first, next, last;
677 struct entry *ep;
678 long curvol;
680 vprintf(stdout, "Extract requested files\n");
681 curfile.action = SKIP;
682 getvol((long)1);
683 skipmaps();
684 skipdirs();
685 first = lowerbnd(ROOTINO);
686 last = upperbnd(maxino - 1);
688 new_volume:
690 * Decide on the next inode needed in this volume.
692 next = lowerbnd(curfile.ino);
693 for (;;) {
694 first = lowerbnd(first);
695 last = upperbnd(last);
697 * Check to see if any files remain to be extracted
699 if (first > last)
700 return;
702 * Reject any volumes with inodes greater
703 * than the last one needed
705 if (curfile.ino > last) {
706 do {
707 curfile.action = SKIP;
708 getvol((long)0);
709 skipmaps();
710 skipdirs();
711 } while (curfile.ino > last);
712 goto new_volume;
715 * Skip across the inodes until the next inode is found
716 * or an out of order volume change is encountered
718 do {
719 curvol = volno;
720 while (next > curfile.ino && volno == curvol)
721 skipfile();
722 skipmaps();
723 skipdirs();
724 } while (volno == curvol + 1);
726 * If volume change out of order occurred the
727 * current state must be recalculated
729 if (volno != curvol)
730 goto new_volume;
732 * If the current inode is greater than the one we were
733 * looking for then we missed the one we were looking for.
734 * Since we only attempt to extract files listed in the
735 * dump map, the lost files must have been due to a tape
736 * read error, or a file that was removed while the dump
737 * was in progress. Thus we report all requested files
738 * between the one we were looking for, and the one we
739 * found as missing, and delete their request flags.
741 while (next < curfile.ino) {
742 ep = lookupino(next);
743 if (ep == NULL)
744 panic("corrupted symbol table\n");
745 fprintf(stderr, "%s: not found on tape\n", myname(ep));
746 ep->e_flags &= ~NEW;
747 next = lowerbnd(next);
750 * The current inode is the one that we are looking for,
751 * so extract it per its requested name.
753 if (next == curfile.ino && next <= last) {
754 ep = lookupino(next);
755 if (ep == NULL)
756 panic("corrupted symbol table\n");
757 (void) extractfile(myname(ep));
758 ep->e_flags &= ~NEW;
759 if (volno != curvol) {
760 skipmaps();
761 goto new_volume;
764 * Decide the next inode. Note that curfile.ino
765 * already updated to the next file on the tape,
766 * and we can't used it since it may be greater
767 * than `next'.
769 next = lowerbnd(next);
775 * Add links.
777 void
778 createlinks(void)
780 struct entry *np, *ep;
781 ino_t i;
782 char name[BUFSIZ];
784 if ((ep = lookupino(WINO)) != NULL) {
785 vprintf(stdout, "Add whiteouts\n");
786 for ( ; ep != NULL; ep = ep->e_links) {
787 if ((ep->e_flags & NEW) == 0)
788 continue;
789 (void) addwhiteout(myname(ep));
790 ep->e_flags &= ~NEW;
793 vprintf(stdout, "Add links\n");
794 for (i = ROOTINO; i < maxino; i++) {
795 ep = lookupino(i);
796 if (ep == NULL)
797 continue;
798 for (np = ep->e_links; np != NULL; np = np->e_links) {
799 if ((np->e_flags & NEW) == 0)
800 continue;
801 (void) strcpy(name, myname(ep));
802 if (ep->e_type == NODE) {
803 (void) linkit(name, myname(np), SYMLINK);
804 } else {
805 (void) linkit(name, myname(np), HARDLINK);
807 np->e_flags &= ~NEW;
813 * Check the symbol table.
814 * We do this to insure that all the requested work was done, and
815 * that no temporary names remain.
817 void
818 checkrestore(void)
820 struct entry *ep;
821 ino_t i;
823 vprintf(stdout, "Check the symbol table.\n");
824 for (i = WINO; i < maxino; i++) {
825 for (ep = lookupino(i); ep != NULL; ep = ep->e_links) {
826 ep->e_flags &= ~KEEP;
827 if (ep->e_type == NODE)
828 ep->e_flags &= ~(NEW|EXISTED);
829 if (ep->e_flags != 0)
830 badentry(ep, "incomplete operations");
836 * Compare with the directory structure on the tape
837 * A paranoid check that things are as they should be.
839 long
840 verifyfile(const char *name, ino_t ino, int type)
842 struct entry *np, *ep;
843 long descend = GOOD;
845 ep = lookupname(name);
846 if (ep == NULL) {
847 fprintf(stderr, "Warning: missing name %s\n", name);
848 return (FAIL);
850 np = lookupino(ino);
851 if (np != ep)
852 descend = FAIL;
853 for ( ; np != NULL; np = np->e_links)
854 if (np == ep)
855 break;
856 if (np == NULL)
857 panic("missing inumber %llu\n", (unsigned long long)ino);
858 if (ep->e_type == LEAF && type != LEAF)
859 badentry(ep, "type should be LEAF");
860 return (descend);