fix errorneous error message from ifconfig (tef@cgl.ucsf.edu (Tom Ferrin))
[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
aa306496 8static char sccsid[] = "@(#)restore.c 5.2 (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) {
48 vprintf(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:
395 fprintf(stderr, "%s: not found on tape\n", name);
396 break;
397
ec28ac4a
KM
398 /*
399 * If any of these arise, something is grievously wrong with
400 * the current state of the symbol table.
401 */
e0519353
KM
402 case INOFND|NAMEFND|MODECHG:
403 case NAMEFND|MODECHG:
404 case INOFND|MODECHG:
55f85ba7 405 panic("[%s] %s: inconsistent state\n", keyval(key), name);
e0519353
KM
406 break;
407
ec28ac4a
KM
408 /*
409 * These states "cannot" arise for any state of the symbol table.
410 */
e0519353
KM
411 case ONTAPE|MODECHG:
412 case MODECHG:
413 default:
55f85ba7 414 panic("[%s] %s: impossible state\n", keyval(key), name);
e0519353
KM
415 break;
416 }
ec28ac4a 417 return (descend);
e0519353
KM
418}
419
55f85ba7
KM
420/*
421 * Calculate the active flags in a key.
422 */
423char *
424keyval(key)
425 int key;
426{
427 static char keybuf[32];
428
7432ff81 429 (void) strcpy(keybuf, "|NIL");
55f85ba7
KM
430 keybuf[0] = '\0';
431 if (key & ONTAPE)
432 (void) strcat(keybuf, "|ONTAPE");
433 if (key & INOFND)
434 (void) strcat(keybuf, "|INOFND");
435 if (key & NAMEFND)
436 (void) strcat(keybuf, "|NAMEFND");
437 if (key & MODECHG)
438 (void) strcat(keybuf, "|MODECHG");
439 return (&keybuf[1]);
440}
441
e0519353 442/*
ec28ac4a 443 * Find unreferenced link names.
e0519353 444 */
a08c9679 445findunreflinks()
e0519353
KM
446{
447 register struct entry *ep, *np;
a08c9679 448 register ino_t i;
e0519353
KM
449
450 vprintf(stdout, "Find unreferenced names.\n");
451 for (i = ROOTINO; i < maxino; i++) {
452 ep = lookupino(i);
429cf058 453 if (ep == NIL || ep->e_type == LEAF || BIT(i, dumpmap) == 0)
e0519353
KM
454 continue;
455 for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
456 if (np->e_flags == 0) {
a08c9679
KM
457 dprintf(stdout,
458 "%s: remove unreferenced name\n",
459 myname(np));
460 removeleaf(np);
461 freeentry(np);
e0519353
KM
462 }
463 }
464 }
0b50ecdc
KM
465 /*
466 * Any leaves remaining in removed directories is unreferenced.
467 */
468 for (ep = removelist; ep != NIL; ep = ep->e_next) {
469 for (np = ep->e_entries; np != NIL; np = np->e_sibling) {
470 if (np->e_type == LEAF) {
471 if (np->e_flags != 0)
472 badentry(np, "unreferenced with flags");
473 dprintf(stdout,
474 "%s: remove unreferenced name\n",
475 myname(np));
476 removeleaf(np);
477 freeentry(np);
478 }
479 }
480 }
e0519353
KM
481}
482
760da7d2 483/*
ec28ac4a
KM
484 * Remove old nodes (directories).
485 * Note that this routine runs in O(N*D) where:
486 * N is the number of directory entries to be removed.
487 * D is the maximum depth of the tree.
488 * If N == D this can be quite slow. If the list were
489 * topologically sorted, the deletion could be done in
490 * time O(N).
760da7d2 491 */
a08c9679 492removeoldnodes()
760da7d2 493{
a08c9679
KM
494 register struct entry *ep, **prev;
495 long change;
760da7d2
KM
496
497 vprintf(stdout, "Remove old nodes (directories).\n");
a08c9679
KM
498 do {
499 change = 0;
500 prev = &removelist;
501 for (ep = removelist; ep != NIL; ep = *prev) {
502 if (ep->e_entries != NIL) {
503 prev = &ep->e_next;
504 continue;
505 }
506 *prev = ep->e_next;
507 removenode(ep);
760da7d2 508 freeentry(ep);
a08c9679
KM
509 change++;
510 }
511 } while (change);
512 for (ep = removelist; ep != NIL; ep = ep->e_next)
513 badentry(ep, "cannot remove, non-empty");
e0519353
KM
514}
515
516/*
ec28ac4a
KM
517 * This is the routine used to extract files for the 'r' command.
518 * Extract new leaves.
e0519353
KM
519 */
520createleaves(symtabfile)
521 char *symtabfile;
522{
523 register struct entry *ep;
524 ino_t first;
525 long curvol;
526
a08c9679 527 if (command == 'R') {
e0519353 528 vprintf(stdout, "Continue extraction of new leaves\n");
a08c9679 529 } else {
e0519353 530 vprintf(stdout, "Extract new leaves.\n");
a08c9679
KM
531 dumpsymtable(symtabfile, volno);
532 }
e0519353
KM
533 first = lowerbnd(ROOTINO);
534 curvol = volno;
535 while (curfile.ino < maxino) {
a08c9679 536 first = lowerbnd(first);
ec28ac4a
KM
537 /*
538 * If the next available file is not the one which we
539 * expect then we have missed one or more files. Since
540 * we do not request files that were not on the tape,
404966c7
KM
541 * the lost files must have been due to a tape read error,
542 * or a file that was removed while the dump was in progress.
ec28ac4a 543 */
e0519353
KM
544 while (first < curfile.ino) {
545 ep = lookupino(first);
546 if (ep == NIL)
547 panic("%d: bad first\n", first);
548 fprintf(stderr, "%s: not found on tape\n", myname(ep));
a08c9679
KM
549 ep->e_flags &= ~(NEW|EXTRACT);
550 first = lowerbnd(first);
e0519353 551 }
404966c7
KM
552 /*
553 * If we find files on the tape that have no corresponding
554 * directory entries, then we must have found a file that
555 * was created while the dump was in progress. Since we have
556 * no name for it, we discard it knowing that it will be
557 * on the next incremental tape.
558 */
29b92570
KM
559 if (first != curfile.ino) {
560 fprintf(stderr, "expected next file %d, got %d\n",
e0519353 561 first, curfile.ino);
29b92570
KM
562 skipfile();
563 goto next;
564 }
e0519353
KM
565 ep = lookupino(curfile.ino);
566 if (ep == NIL)
567 panic("unknown file on tape\n");
a08c9679 568 if ((ep->e_flags & (NEW|EXTRACT)) == 0)
e0519353 569 badentry(ep, "unexpected file on tape");
ec28ac4a
KM
570 /*
571 * If the file is to be extracted, then the old file must
572 * be removed since its type may change from one leaf type
573 * to another (eg "file" to "character special").
574 */
a08c9679
KM
575 if ((ep->e_flags & EXTRACT) != 0) {
576 removeleaf(ep);
577 ep->e_flags &= ~REMOVED;
578 }
ec28ac4a 579 (void) extractfile(myname(ep));
a08c9679 580 ep->e_flags &= ~(NEW|EXTRACT);
ec28ac4a
KM
581 /*
582 * We checkpoint the restore after every tape reel, so
583 * as to simplify the amount of work re quired by the
584 * 'R' command.
585 */
29b92570 586 next:
e0519353
KM
587 if (curvol != volno) {
588 dumpsymtable(symtabfile, volno);
a08c9679 589 skipmaps();
e0519353
KM
590 curvol = volno;
591 }
592 }
593}
594
595/*
c7774b2e
KM
596 * This is the routine used to extract files for the 'x' and 'i' commands.
597 * Efficiently extract a subset of the files on a tape.
e0519353
KM
598 */
599createfiles()
600{
601 register ino_t first, next, last;
602 register struct entry *ep;
603 long curvol;
604
605 vprintf(stdout, "Extract requested files\n");
9f13f26d 606 curfile.action = SKIP;
74025ab9 607 getvol((long)1);
5c5f44c7
KM
608 skipmaps();
609 skipdirs();
e0519353 610 first = lowerbnd(ROOTINO);
9f13f26d 611 last = upperbnd(maxino - 1);
e0519353
KM
612 for (;;) {
613 first = lowerbnd(first);
614 last = upperbnd(last);
5c5f44c7
KM
615 /*
616 * Check to see if any files remain to be extracted
617 */
e0519353
KM
618 if (first > last)
619 return;
5c5f44c7
KM
620 /*
621 * Reject any volumes with inodes greater
622 * than the last one needed
623 */
e0519353
KM
624 while (curfile.ino > last) {
625 curfile.action = SKIP;
626 getvol((long)0);
5c5f44c7
KM
627 skipmaps();
628 skipdirs();
e0519353 629 }
5c5f44c7
KM
630 /*
631 * Decide on the next inode needed.
632 * Skip across the inodes until it is found
633 * or an out of order volume change is encountered
634 */
e0519353
KM
635 next = lowerbnd(curfile.ino);
636 do {
637 curvol = volno;
638 while (next > curfile.ino && volno == curvol)
639 skipfile();
5c5f44c7
KM
640 skipmaps();
641 skipdirs();
e0519353 642 } while (volno == curvol + 1);
5c5f44c7
KM
643 /*
644 * If volume change out of order occurred the
7432ff81 645 * current state must be recalculated
5c5f44c7 646 */
e0519353
KM
647 if (volno != curvol)
648 continue;
5c5f44c7
KM
649 /*
650 * If the current inode is greater than the one we were
651 * looking for then we missed the one we were looking for.
652 * Since we only attempt to extract files listed in the
7432ff81
KM
653 * dump map, the lost files must have been due to a tape
654 * read error, or a file that was removed while the dump
655 * was in progress. Thus we report all requested files
656 * between the one we were looking for, and the one we
657 * found as missing, and delete their request flags.
5c5f44c7 658 */
e0519353
KM
659 while (next < curfile.ino) {
660 ep = lookupino(next);
661 if (ep == NIL)
662 panic("corrupted symbol table\n");
663 fprintf(stderr, "%s: not found on tape\n", myname(ep));
664 ep->e_flags &= ~NEW;
5c5f44c7 665 next = lowerbnd(next);
e0519353 666 }
5c5f44c7
KM
667 /*
668 * The current inode is the one that we are looking for,
669 * so extract it per its requested name.
670 */
74025ab9 671 if (next == curfile.ino && next <= last) {
e0519353
KM
672 ep = lookupino(next);
673 if (ep == NIL)
674 panic("corrupted symbol table\n");
ec28ac4a 675 (void) extractfile(myname(ep));
e0519353 676 ep->e_flags &= ~NEW;
e526193a
KM
677 if (volno != curvol)
678 skipmaps();
e0519353
KM
679 }
680 }
681}
682
683/*
ec28ac4a 684 * Add links.
e0519353
KM
685 */
686createlinks()
687{
688 register struct entry *np, *ep;
a08c9679 689 register ino_t i;
e0519353
KM
690 char name[BUFSIZ];
691
692 vprintf(stdout, "Add links\n");
693 for (i = ROOTINO; i < maxino; i++) {
694 ep = lookupino(i);
695 if (ep == NIL)
696 continue;
697 for (np = ep->e_links; np != NIL; np = np->e_links) {
404966c7
KM
698 if ((np->e_flags & NEW) == 0)
699 continue;
a08c9679 700 (void) strcpy(name, myname(ep));
e0519353 701 if (ep->e_type == NODE) {
d5e50c65 702 (void) linkit(name, myname(np), SYMLINK);
e0519353 703 } else {
d5e50c65 704 (void) linkit(name, myname(np), HARDLINK);
e0519353 705 }
9f13f26d 706 np->e_flags &= ~NEW;
e0519353
KM
707 }
708 }
709}
710
711/*
ec28ac4a
KM
712 * Check the symbol table.
713 * We do this to insure that all the requested work was done, and
714 * that no temporary names remain.
e0519353
KM
715 */
716checkrestore()
717{
718 register struct entry *ep;
a08c9679 719 register ino_t i;
e0519353
KM
720
721 vprintf(stdout, "Check the symbol table.\n");
722 for (i = ROOTINO; i < maxino; i++) {
a7d37956 723 for (ep = lookupino(i); ep != NIL; ep = ep->e_links) {
e0519353 724 ep->e_flags &= ~KEEP;
c7774b2e 725 if (ep->e_type == NODE)
a7d37956 726 ep->e_flags &= ~(NEW|EXISTED);
e0519353
KM
727 if (ep->e_flags != NULL)
728 badentry(ep, "incomplete operations");
729 }
730 }
731}
732
733/*
ec28ac4a
KM
734 * Compare with the directory structure on the tape
735 * A paranoid check that things are as they should be.
e0519353 736 */
ec28ac4a 737long
e0519353
KM
738verifyfile(name, ino, type)
739 char *name;
740 ino_t ino;
741 int type;
742{
743 struct entry *np, *ep;
ec28ac4a 744 long descend = GOOD;
e0519353
KM
745
746 ep = lookupname(name);
ec28ac4a
KM
747 if (ep == NIL) {
748 fprintf(stderr, "Warning: missing name %s\n", name);
749 return (FAIL);
750 }
751 np = lookupino(ino);
752 if (np != ep)
753 descend = FAIL;
754 for ( ; np != NIL; np = np->e_links)
e0519353
KM
755 if (np == ep)
756 break;
757 if (np == NIL)
758 panic("missing inumber %d\n", ino);
759 if (ep->e_type == LEAF && type != LEAF)
760 badentry(ep, "type should be LEAF");
ec28ac4a 761 return (descend);
e0519353 762}