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