GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/restore/restore.c Lines: 0 305 0.0 %
Date: 2017-11-07 Branches: 0 255 0.0 %

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