date and time created 88/07/21 17:35:30 by marc
[unix-history] / usr / src / sbin / restore / restore.c
CommitLineData
8c5eec2f
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
e0519353 6
8c5eec2f 7#ifndef lint
8e31210a 8static char sccsid[] = "@(#)restore.c 5.4 (Berkeley) %G%";
8c5eec2f 9#endif not lint
ebd1f727 10
e0519353
KM
11#include "restore.h"
12
e0519353 13/*
ec28ac4a
KM
14 * This implements the 't' option.
15 * List entries on the tape.
e0519353 16 */
ec28ac4a 17long
e0519353
KM
18listfile(name, ino, type)
19 char *name;
20 ino_t ino;
21 int type;
22{
ec28ac4a 23 long descend = hflag ? GOOD : FAIL;
e0519353
KM
24
25 if (BIT(ino, dumpmap) == 0) {
ec28ac4a 26 return (descend);
e0519353 27 }
a08c9679 28 vprintf(stdout, "%s", type == LEAF ? "leaf" : "dir ");
e0519353 29 fprintf(stdout, "%10d\t%s\n", ino, name);
ec28ac4a 30 return (descend);
e0519353
KM
31}
32
33/*
ec28ac4a
KM
34 * This implements the 'x' option.
35 * Request that new entries be extracted.
e0519353 36 */
ec28ac4a 37long
e0519353
KM
38addfile(name, ino, type)
39 char *name;
40 ino_t ino;
41 int type;
42{
43 register struct entry *ep;
ec28ac4a 44 long descend = hflag ? GOOD : FAIL;
e0519353
KM
45 char buf[100];
46
47 if (BIT(ino, dumpmap) == 0) {
8e31210a 48 dprintf(stdout, "%s: not on the tape\n", name);
ec28ac4a 49 return (descend);
e0519353 50 }
0dd9c990 51 if (!mflag) {
ec28ac4a 52 (void) sprintf(buf, "./%u", ino);
0dd9c990
KM
53 name = buf;
54 if (type == NODE) {
a08c9679 55 (void) genliteraldir(name, ino);
ec28ac4a 56 return (descend);
0dd9c990
KM
57 }
58 }
0dd9c990
KM
59 ep = lookupino(ino);
60 if (ep != NIL) {
7432ff81
KM
61 if (strcmp(name, myname(ep)) == 0) {
62 ep->e_flags |= NEW;
ec28ac4a 63 return (descend);
7432ff81 64 }
0dd9c990
KM
65 type |= LINK;
66 }
67 ep = addentry(name, ino, type);
7432ff81 68 if (type == NODE)
0dd9c990 69 newnode(ep);
7432ff81
KM
70 ep->e_flags |= NEW;
71 return (descend);
72}
73
74/*
75 * This is used by the 'i' option to undo previous requests made by addfile.
76 * Delete entries from the request queue.
77 */
78/* ARGSUSED */
79long
80deletefile(name, ino, type)
81 char *name;
82 ino_t ino;
83 int type;
84{
85 long descend = hflag ? GOOD : FAIL;
86 struct entry *ep;
87
88 if (BIT(ino, dumpmap) == 0) {
ec28ac4a 89 return (descend);
e0519353 90 }
7432ff81
KM
91 ep = lookupino(ino);
92 if (ep != NIL)
93 ep->e_flags &= ~NEW;
ec28ac4a
KM
94 return (descend);
95}
96
97/*
98 * The following four routines implement the incremental
99 * restore algorithm. The first removes old entries, the second
100 * does renames and calculates the extraction list, the third
101 * cleans up link names missed by the first two, and the final
102 * one deletes old directories.
103 *
104 * Directories cannot be immediately deleted, as they may have
105 * other files in them which need to be moved out first. As
106 * directories to be deleted are found, they are put on the
107 * following deletion list. After all deletions and renames
108 * are done, this list is actually deleted.
109 */
110static struct entry *removelist;
111
112/*
113 * Remove unneeded leaves from the old tree.
114 * Remove directories from the lookup chains.
115 */
116removeoldleaves()
117{
118 register struct entry *ep;
119 register ino_t i;
120
121 vprintf(stdout, "Mark entries to be removed.\n");
122 for (i = ROOTINO + 1; i < maxino; i++) {
123 ep = lookupino(i);
124 if (ep == NIL)
125 continue;
126 if (BIT(i, clrimap))
127 continue;
128 for ( ; ep != NIL; ep = ep->e_links) {
129 dprintf(stdout, "%s: REMOVE\n", myname(ep));
130 if (ep->e_type == LEAF) {
131 removeleaf(ep);
132 freeentry(ep);
133 } else {
134 mktempname(ep);
135 deleteino(ep->e_ino);
136 ep->e_next = removelist;
137 removelist = ep;
138 }
139 }
140 }
e0519353
KM
141}
142
143/*
a08c9679
KM
144 * For each directory entry on the incremental tape, determine which
145 * category it falls into as follows:
e0519353
KM
146 * KEEP - entries that are to be left alone.
147 * NEW - new entries to be added.
148 * EXTRACT - files that must be updated with new contents.
a08c9679
KM
149 * LINK - new links to be added.
150 * Renames are done at the same time.
e0519353 151 */
ec28ac4a 152long
a08c9679 153nodeupdates(name, ino, type)
e0519353
KM
154 char *name;
155 ino_t ino;
156 int type;
157{
158 register struct entry *ep, *np, *ip;
ec28ac4a 159 long descend = GOOD;
c7774b2e 160 int lookuptype = 0;
e0519353
KM
161 int key = 0;
162 /* key values */
ec28ac4a
KM
163# define ONTAPE 0x1 /* inode is on the tape */
164# define INOFND 0x2 /* inode already exists */
165# define NAMEFND 0x4 /* name already exists */
166# define MODECHG 0x8 /* mode of inode changed */
55f85ba7 167 extern char *keyval();
e0519353
KM
168
169 /*
170 * This routine is called once for each element in the
5c5f44c7 171 * directory hierarchy, with a full path name.
e0519353
KM
172 * The "type" value is incorrectly specified as LEAF for
173 * directories that are not on the dump tape.
c7774b2e
KM
174 *
175 * Check to see if the file is on the tape.
e0519353 176 */
55f85ba7 177 if (BIT(ino, dumpmap))
e0519353 178 key |= ONTAPE;
c7774b2e
KM
179 /*
180 * Check to see if the name exists, and if the name is a link.
181 */
e0519353 182 np = lookupname(name);
c7774b2e 183 if (np != NIL) {
e0519353 184 key |= NAMEFND;
c7774b2e
KM
185 ip = lookupino(np->e_ino);
186 if (ip == NULL)
187 panic("corrupted symbol table\n");
188 if (ip != np)
189 lookuptype = LINK;
190 }
191 /*
192 * Check to see if the inode exists, and if one of its links
193 * corresponds to the name (if one was found).
194 */
e0519353
KM
195 ip = lookupino(ino);
196 if (ip != NIL) {
197 key |= INOFND;
c7774b2e 198 for (ep = ip->e_links; ep != NIL; ep = ep->e_links) {
e0519353
KM
199 if (ep == np) {
200 ip = ep;
201 break;
202 }
c7774b2e 203 }
e0519353 204 }
ec28ac4a 205 /*
c7774b2e
KM
206 * If both a name and an inode are found, but they do not
207 * correspond to the same file, then both the inode that has
208 * been found and the inode corresponding to the name that
209 * has been found need to be renamed. The current pathname
210 * is the new name for the inode that has been found. Since
211 * all files to be deleted have already been removed, the
212 * named file is either a now unneeded link, or it must live
213 * under a new name in this dump level. If it is a link, it
214 * can be removed. If it is not a link, it is given a
215 * temporary name in anticipation that it will be renamed
216 * when it is later found by inode number.
ec28ac4a 217 */
a08c9679 218 if (((key & (INOFND|NAMEFND)) == (INOFND|NAMEFND)) && ip != np) {
c7774b2e
KM
219 if (lookuptype == LINK) {
220 removeleaf(np);
221 freeentry(np);
222 } else {
223 dprintf(stdout, "name/inode conflict, mktempname %s\n",
224 myname(np));
225 mktempname(np);
226 }
e0519353
KM
227 np = NIL;
228 key &= ~NAMEFND;
229 }
e0519353
KM
230 if ((key & ONTAPE) &&
231 (((key & INOFND) && ip->e_type != type) ||
55f85ba7 232 ((key & NAMEFND) && np->e_type != type)))
e0519353 233 key |= MODECHG;
ec28ac4a
KM
234
235 /*
236 * Decide on the disposition of the file based on its flags.
237 * Note that we have already handled the case in which
238 * a name and inode are found that correspond to different files.
239 * Thus if both NAMEFND and INOFND are set then ip == np.
240 */
e0519353
KM
241 switch (key) {
242
ec28ac4a
KM
243 /*
244 * A previously existing file has been found.
245 * Mark it as KEEP so that other links to the inode can be
246 * detected, and so that it will not be reclaimed by the search
247 * for unreferenced names.
248 */
e0519353
KM
249 case INOFND|NAMEFND:
250 ip->e_flags |= KEEP;
55f85ba7
KM
251 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
252 flagvalues(ip));
e0519353
KM
253 break;
254
b029b198
KM
255 /*
256 * A file on the tape has a name which is the same as a name
257 * corresponding to a different file in the previous dump.
258 * Since all files to be deleted have already been removed,
c7774b2e
KM
259 * this file is either a now unneeded link, or it must live
260 * under a new name in this dump level. If it is a link, it
261 * can simply be removed. If it is not a link, it is given a
262 * temporary name in anticipation that it will be renamed
263 * when it is later found by inode number (see INOFND case
264 * below). The entry is then treated as a new file.
b029b198
KM
265 */
266 case ONTAPE|NAMEFND:
267 case ONTAPE|NAMEFND|MODECHG:
c7774b2e
KM
268 if (lookuptype == LINK) {
269 removeleaf(np);
270 freeentry(np);
271 } else {
272 mktempname(np);
273 }
b029b198
KM
274 /* fall through */
275
ec28ac4a
KM
276 /*
277 * A previously non-existent file.
278 * Add it to the file system, and request its extraction.
279 * If it is a directory, create it immediately.
280 * (Since the name is unused there can be no conflict)
281 */
e0519353
KM
282 case ONTAPE:
283 ep = addentry(name, ino, type);
a08c9679
KM
284 if (type == NODE)
285 newnode(ep);
7432ff81 286 ep->e_flags |= NEW|KEEP;
55f85ba7
KM
287 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
288 flagvalues(ep));
e0519353
KM
289 break;
290
ec28ac4a
KM
291 /*
292 * A file with the same inode number, but a different
293 * name has been found. If the other name has not already
294 * been found (indicated by the KEEP flag, see above) then
295 * this must be a new name for the file, and it is renamed.
296 * If the other name has been found then this must be a
297 * link to the file. Hard links to directories are not
298 * permitted, and are either deleted or converted to
299 * symbolic links. Finally, if the file is on the tape,
300 * a request is made to extract it.
301 */
e0519353 302 case ONTAPE|INOFND:
55f85ba7 303 if (type == LEAF && (ip->e_flags & KEEP) == 0)
a08c9679 304 ip->e_flags |= EXTRACT;
e0519353
KM
305 /* fall through */
306 case INOFND:
ec28ac4a
KM
307 if ((ip->e_flags & KEEP) == 0) {
308 renameit(myname(ip), name);
309 moveentry(ip, name);
310 ip->e_flags |= KEEP;
429cf058 311 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
55f85ba7 312 flagvalues(ip));
e0519353
KM
313 break;
314 }
ec28ac4a
KM
315 if (ip->e_type == NODE) {
316 descend = FAIL;
317 fprintf(stderr,
318 "deleted hard link %s to directory %s\n",
319 name, myname(ip));
320 break;
321 }
322 ep = addentry(name, ino, type|LINK);
323 ep->e_flags |= NEW;
55f85ba7
KM
324 dprintf(stdout, "[%s] %s: %s|LINK\n", keyval(key), name,
325 flagvalues(ep));
e0519353
KM
326 break;
327
ec28ac4a 328 /*
b029b198 329 * A previously known file which is to be updated.
ec28ac4a 330 */
e0519353 331 case ONTAPE|INOFND|NAMEFND:
c7774b2e 332 if (type == LEAF && lookuptype != LINK)
a08c9679
KM
333 np->e_flags |= EXTRACT;
334 np->e_flags |= KEEP;
55f85ba7
KM
335 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
336 flagvalues(np));
e0519353
KM
337 break;
338
ec28ac4a
KM
339 /*
340 * An inode is being reused in a completely different way.
341 * Normally an extract can simply do an "unlink" followed
342 * by a "creat". Here we must do effectively the same
343 * thing. The complications arise because we cannot really
344 * delete a directory since it may still contain files
345 * that we need to rename, so we delete it from the symbol
346 * table, and put it on the list to be deleted eventually.
347 * Conversely if a directory is to be created, it must be
348 * done immediately, rather than waiting until the
349 * extraction phase.
350 */
e0519353
KM
351 case ONTAPE|INOFND|MODECHG:
352 case ONTAPE|INOFND|NAMEFND|MODECHG:
a08c9679
KM
353 if (ip->e_flags & KEEP) {
354 badentry(ip, "cannot KEEP and change modes");
355 break;
356 }
357 if (ip->e_type == LEAF) {
358 /* changing from leaf to node */
359 removeleaf(ip);
360 freeentry(ip);
361 ip = addentry(name, ino, type);
362 newnode(ip);
363 } else {
364 /* changing from node to leaf */
0b50ecdc
KM
365 if ((ip->e_flags & TMPNAME) == 0)
366 mktempname(ip);
a08c9679
KM
367 deleteino(ip->e_ino);
368 ip->e_next = removelist;
369 removelist = ip;
370 ip = addentry(name, ino, type);
a08c9679 371 }
7432ff81 372 ip->e_flags |= NEW|KEEP;
55f85ba7
KM
373 dprintf(stdout, "[%s] %s: %s\n", keyval(key), name,
374 flagvalues(ip));
e0519353
KM
375 break;
376
ec28ac4a
KM
377 /*
378 * A hard link to a diirectory that has been removed.
379 * Ignore it.
380 */
381 case NAMEFND:
55f85ba7
KM
382 dprintf(stdout, "[%s] %s: Extraneous name\n", keyval(key),
383 name);
ec28ac4a
KM
384 descend = FAIL;
385 break;
386
aa306496
KM
387 /*
388 * If we find a directory entry for a file that is not on
389 * the tape, then we must have found a file that was created
390 * while the dump was in progress. Since we have no contents
391 * for it, we discard the name knowing that it will be on the
392 * next incremental tape.
393 */
394 case NIL:
50746be0
KM
395 fprintf(stderr, "%s: (inode %d) not found on tape\n",
396 name, ino);
aa306496
KM
397 break;
398
ec28ac4a
KM
399 /*
400 * If any of these arise, something is grievously wrong with
401 * the current state of the symbol table.
402 */
e0519353
KM
403 case INOFND|NAMEFND|MODECHG:
404 case NAMEFND|MODECHG:
405 case INOFND|MODECHG:
55f85ba7 406 panic("[%s] %s: inconsistent state\n", keyval(key), name);
e0519353
KM
407 break;
408
ec28ac4a
KM
409 /*
410 * These states "cannot" arise for any state of the symbol table.
411 */
e0519353
KM
412 case ONTAPE|MODECHG:
413 case MODECHG:
414 default:
55f85ba7 415 panic("[%s] %s: impossible state\n", keyval(key), name);
e0519353
KM
416 break;
417 }
ec28ac4a 418 return (descend);
e0519353
KM
419}
420
55f85ba7
KM
421/*
422 * Calculate the active flags in a key.
423 */
424char *
425keyval(key)
426 int key;
427{
428 static char keybuf[32];
429
7432ff81 430 (void) strcpy(keybuf, "|NIL");
55f85ba7
KM
431 keybuf[0] = '\0';
432 if (key & ONTAPE)
433 (void) strcat(keybuf, "|ONTAPE");
434 if (key & INOFND)
435 (void) strcat(keybuf, "|INOFND");
436 if (key & NAMEFND)
437 (void) strcat(keybuf, "|NAMEFND");
438 if (key & MODECHG)
439 (void) strcat(keybuf, "|MODECHG");
440 return (&keybuf[1]);
441}
442
e0519353 443/*
ec28ac4a 444 * Find unreferenced link names.
e0519353 445 */
a08c9679 446findunreflinks()
e0519353
KM
447{
448 register struct entry *ep, *np;
a08c9679 449 register ino_t i;
e0519353
KM
450
451 vprintf(stdout, "Find unreferenced names.\n");
452 for (i = ROOTINO; i < maxino; i++) {
453 ep = lookupino(i);
429cf058 454 if (ep == NIL || ep->e_type == LEAF || BIT(i, dumpmap) == 0)
e0519353
KM
455 continue;
456 for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
457 if (np->e_flags == 0) {
a08c9679
KM
458 dprintf(stdout,
459 "%s: remove unreferenced name\n",
460 myname(np));
461 removeleaf(np);
462 freeentry(np);
e0519353
KM
463 }
464 }
465 }
0b50ecdc
KM
466 /*
467 * Any leaves remaining in removed directories is unreferenced.
468 */
469 for (ep = removelist; ep != NIL; ep = ep->e_next) {
470 for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
471 if (np->e_type == LEAF) {
472 if (np->e_flags != 0)
473 badentry(np, "unreferenced with flags");
474 dprintf(stdout,
475 "%s: remove unreferenced name\n",
476 myname(np));
477 removeleaf(np);
478 freeentry(np);
479 }
480 }
481 }
e0519353
KM
482}
483
760da7d2 484/*
ec28ac4a
KM
485 * Remove old nodes (directories).
486 * Note that this routine runs in O(N*D) where:
487 * N is the number of directory entries to be removed.
488 * D is the maximum depth of the tree.
489 * If N == D this can be quite slow. If the list were
490 * topologically sorted, the deletion could be done in
491 * time O(N).
760da7d2 492 */
a08c9679 493removeoldnodes()
760da7d2 494{
a08c9679
KM
495 register struct entry *ep, **prev;
496 long change;
760da7d2
KM
497
498 vprintf(stdout, "Remove old nodes (directories).\n");
a08c9679
KM
499 do {
500 change = 0;
501 prev = &removelist;
502 for (ep = removelist; ep != NIL; ep = *prev) {
503 if (ep->e_entries != NIL) {
504 prev = &ep->e_next;
505 continue;
506 }
507 *prev = ep->e_next;
508 removenode(ep);
760da7d2 509 freeentry(ep);
a08c9679
KM
510 change++;
511 }
512 } while (change);
513 for (ep = removelist; ep != NIL; ep = ep->e_next)
514 badentry(ep, "cannot remove, non-empty");
e0519353
KM
515}
516
517/*
ec28ac4a
KM
518 * This is the routine used to extract files for the 'r' command.
519 * Extract new leaves.
e0519353
KM
520 */
521createleaves(symtabfile)
522 char *symtabfile;
523{
524 register struct entry *ep;
525 ino_t first;
526 long curvol;
527
a08c9679 528 if (command == 'R') {
e0519353 529 vprintf(stdout, "Continue extraction of new leaves\n");
a08c9679 530 } else {
e0519353 531 vprintf(stdout, "Extract new leaves.\n");
a08c9679
KM
532 dumpsymtable(symtabfile, volno);
533 }
e0519353
KM
534 first = lowerbnd(ROOTINO);
535 curvol = volno;
536 while (curfile.ino < maxino) {
a08c9679 537 first = lowerbnd(first);
ec28ac4a
KM
538 /*
539 * If the next available file is not the one which we
540 * expect then we have missed one or more files. Since
541 * we do not request files that were not on the tape,
404966c7
KM
542 * the lost files must have been due to a tape read error,
543 * or a file that was removed while the dump was in progress.
ec28ac4a 544 */
e0519353
KM
545 while (first < curfile.ino) {
546 ep = lookupino(first);
547 if (ep == NIL)
548 panic("%d: bad first\n", first);
549 fprintf(stderr, "%s: not found on tape\n", myname(ep));
a08c9679
KM
550 ep->e_flags &= ~(NEW|EXTRACT);
551 first = lowerbnd(first);
e0519353 552 }
404966c7
KM
553 /*
554 * If we find files on the tape that have no corresponding
555 * directory entries, then we must have found a file that
556 * was created while the dump was in progress. Since we have
557 * no name for it, we discard it knowing that it will be
558 * on the next incremental tape.
559 */
29b92570
KM
560 if (first != curfile.ino) {
561 fprintf(stderr, "expected next file %d, got %d\n",
e0519353 562 first, curfile.ino);
29b92570
KM
563 skipfile();
564 goto next;
565 }
e0519353
KM
566 ep = lookupino(curfile.ino);
567 if (ep == NIL)
568 panic("unknown file on tape\n");
a08c9679 569 if ((ep->e_flags & (NEW|EXTRACT)) == 0)
e0519353 570 badentry(ep, "unexpected file on tape");
ec28ac4a
KM
571 /*
572 * If the file is to be extracted, then the old file must
573 * be removed since its type may change from one leaf type
574 * to another (eg "file" to "character special").
575 */
a08c9679
KM
576 if ((ep->e_flags & EXTRACT) != 0) {
577 removeleaf(ep);
578 ep->e_flags &= ~REMOVED;
579 }
ec28ac4a 580 (void) extractfile(myname(ep));
a08c9679 581 ep->e_flags &= ~(NEW|EXTRACT);
ec28ac4a
KM
582 /*
583 * We checkpoint the restore after every tape reel, so
584 * as to simplify the amount of work re quired by the
585 * 'R' command.
586 */
29b92570 587 next:
e0519353
KM
588 if (curvol != volno) {
589 dumpsymtable(symtabfile, volno);
a08c9679 590 skipmaps();
e0519353
KM
591 curvol = volno;
592 }
593 }
594}
595
596/*
c7774b2e
KM
597 * This is the routine used to extract files for the 'x' and 'i' commands.
598 * Efficiently extract a subset of the files on a tape.
e0519353
KM
599 */
600createfiles()
601{
602 register ino_t first, next, last;
603 register struct entry *ep;
604 long curvol;
605
606 vprintf(stdout, "Extract requested files\n");
9f13f26d 607 curfile.action = SKIP;
74025ab9 608 getvol((long)1);
5c5f44c7
KM
609 skipmaps();
610 skipdirs();
e0519353 611 first = lowerbnd(ROOTINO);
9f13f26d 612 last = upperbnd(maxino - 1);
e0519353
KM
613 for (;;) {
614 first = lowerbnd(first);
615 last = upperbnd(last);
5c5f44c7
KM
616 /*
617 * Check to see if any files remain to be extracted
618 */
e0519353
KM
619 if (first > last)
620 return;
5c5f44c7
KM
621 /*
622 * Reject any volumes with inodes greater
623 * than the last one needed
624 */
e0519353
KM
625 while (curfile.ino > last) {
626 curfile.action = SKIP;
627 getvol((long)0);
5c5f44c7
KM
628 skipmaps();
629 skipdirs();
e0519353 630 }
5c5f44c7
KM
631 /*
632 * Decide on the next inode needed.
633 * Skip across the inodes until it is found
634 * or an out of order volume change is encountered
635 */
e0519353
KM
636 next = lowerbnd(curfile.ino);
637 do {
638 curvol = volno;
639 while (next > curfile.ino && volno == curvol)
640 skipfile();
5c5f44c7
KM
641 skipmaps();
642 skipdirs();
e0519353 643 } while (volno == curvol + 1);
5c5f44c7
KM
644 /*
645 * If volume change out of order occurred the
7432ff81 646 * current state must be recalculated
5c5f44c7 647 */
e0519353
KM
648 if (volno != curvol)
649 continue;
5c5f44c7
KM
650 /*
651 * If the current inode is greater than the one we were
652 * looking for then we missed the one we were looking for.
653 * Since we only attempt to extract files listed in the
7432ff81
KM
654 * dump map, the lost files must have been due to a tape
655 * read error, or a file that was removed while the dump
656 * was in progress. Thus we report all requested files
657 * between the one we were looking for, and the one we
658 * found as missing, and delete their request flags.
5c5f44c7 659 */
e0519353
KM
660 while (next < curfile.ino) {
661 ep = lookupino(next);
662 if (ep == NIL)
663 panic("corrupted symbol table\n");
664 fprintf(stderr, "%s: not found on tape\n", myname(ep));
665 ep->e_flags &= ~NEW;
5c5f44c7 666 next = lowerbnd(next);
e0519353 667 }
5c5f44c7
KM
668 /*
669 * The current inode is the one that we are looking for,
670 * so extract it per its requested name.
671 */
74025ab9 672 if (next == curfile.ino && next <= last) {
e0519353
KM
673 ep = lookupino(next);
674 if (ep == NIL)
675 panic("corrupted symbol table\n");
ec28ac4a 676 (void) extractfile(myname(ep));
e0519353 677 ep->e_flags &= ~NEW;
e526193a
KM
678 if (volno != curvol)
679 skipmaps();
e0519353
KM
680 }
681 }
682}
683
684/*
ec28ac4a 685 * Add links.
e0519353
KM
686 */
687createlinks()
688{
689 register struct entry *np, *ep;
a08c9679 690 register ino_t i;
e0519353
KM
691 char name[BUFSIZ];
692
693 vprintf(stdout, "Add links\n");
694 for (i = ROOTINO; i < maxino; i++) {
695 ep = lookupino(i);
696 if (ep == NIL)
697 continue;
698 for (np = ep->e_links; np != NIL; np = np->e_links) {
404966c7
KM
699 if ((np->e_flags & NEW) == 0)
700 continue;
a08c9679 701 (void) strcpy(name, myname(ep));
e0519353 702 if (ep->e_type == NODE) {
d5e50c65 703 (void) linkit(name, myname(np), SYMLINK);
e0519353 704 } else {
d5e50c65 705 (void) linkit(name, myname(np), HARDLINK);
e0519353 706 }
9f13f26d 707 np->e_flags &= ~NEW;
e0519353
KM
708 }
709 }
710}
711
712/*
ec28ac4a
KM
713 * Check the symbol table.
714 * We do this to insure that all the requested work was done, and
715 * that no temporary names remain.
e0519353
KM
716 */
717checkrestore()
718{
719 register struct entry *ep;
a08c9679 720 register ino_t i;
e0519353
KM
721
722 vprintf(stdout, "Check the symbol table.\n");
723 for (i = ROOTINO; i < maxino; i++) {
a7d37956 724 for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
e0519353 725 ep->e_flags &= ~KEEP;
c7774b2e 726 if (ep->e_type == NODE)
a7d37956 727 ep->e_flags &= ~(NEW|EXISTED);
e0519353
KM
728 if (ep->e_flags != NULL)
729 badentry(ep, "incomplete operations");
730 }
731 }
732}
733
734/*
ec28ac4a
KM
735 * Compare with the directory structure on the tape
736 * A paranoid check that things are as they should be.
e0519353 737 */
ec28ac4a 738long
e0519353
KM
739verifyfile(name, ino, type)
740 char *name;
741 ino_t ino;
742 int type;
743{
744 struct entry *np, *ep;
ec28ac4a 745 long descend = GOOD;
e0519353
KM
746
747 ep = lookupname(name);
ec28ac4a
KM
748 if (ep == NIL) {
749 fprintf(stderr, "Warning: missing name %s\n", name);
750 return (FAIL);
751 }
752 np = lookupino(ino);
753 if (np != ep)
754 descend = FAIL;
755 for ( ; np != NIL; np = np->e_links)
e0519353
KM
756 if (np == ep)
757 break;
758 if (np == NIL)
759 panic("missing inumber %d\n", ino);
760 if (ep->e_type == LEAF && type != LEAF)
761 badentry(ep, "type should be LEAF");
ec28ac4a 762 return (descend);
e0519353 763}