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.
7 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
8 /* All Rights Reserved */
11 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
12 * Use is subject to license terms.
17 #include <byteorder.h>
20 #include <sys/errno.h>
22 #include <sys/sysmacros.h> /* for expdev */
25 #include <priv_utils.h>
28 #define MAXINO 65535 /* KLUDGE */
32 static size_t fssize
= MAXBSIZE
; /* preferred size of writes to filesystem */
34 static int continuemap
= 0;
37 daddr32_t rec_position
;
38 static char *archivefile
; /* used in metamucil.c */
39 static int bct
; /* block # index into tape record buffer */
40 static int numtrec
; /* # of logical blocks in current tape record */
41 static char *tbf
= NULL
;
42 static size_t tbfsize
= 0;
44 static union u_spcl endoftapemark
;
45 static struct s_spcl dumpinfo
;
46 static long blksread
; /* # of logical blocks actually read/touched */
47 static long tapea
; /* current logical block # on tape */
48 static uchar_t tapesread
[MAXTAPES
];
49 static jmp_buf restart
;
50 static int gettingfile
= 0; /* restart has a valid frame */
52 static char *map
, *beginmap
;
54 static char lnkbuf
[MAXPATHLEN
+ 2];
56 static int inodeinfo
; /* Have starting volume information */
57 static int hostinfo
; /* Have dump host information */
59 static int autoload_tape(void);
60 static void setdumpnum(void);
61 static void metacheck(struct s_spcl
*);
62 static void xtrmeta(char *, size_t);
63 static void metaskip(char *, size_t);
64 static void xtrfile(char *, size_t);
65 static void xtrskip(char *, size_t);
66 static void xtrlnkfile(char *, size_t);
67 static void xtrlnkskip(char *, size_t);
68 static void xtrmap(char *, size_t);
69 static void xtrmapskip(char *, size_t);
70 static void readtape(char *);
71 static int checkvol(struct s_spcl
*, int);
72 static void accthdr(struct s_spcl
*);
73 static int ishead(struct s_spcl
*);
74 static int checktype(struct s_spcl
*, int);
75 static void metaset(char *name
);
78 * Set up an input source
81 setinput(char *source
, char *archive
)
85 archivefile
= archive
;
87 ntrec
= ((CARTRIDGETREC
> HIGHDENSITYTREC
) ?
88 (NTREC
> CARTRIDGETREC
? NTREC
: CARTRIDGETREC
) :
89 (NTREC
> HIGHDENSITYTREC
? NTREC
: HIGHDENSITYTREC
));
90 saved_ntrec
= (ntrec
* (tp_bsize
/DEV_BSIZE
));
97 (void) fprintf(stderr
,
98 gettext("Internal consistency check failed.\n"));
102 if (strlen(source
) > (sizeof (magtape
) - 1)) {
103 (void) fprintf(stderr
, gettext("Tape name too long\n"));
106 /* Not remote, no need for privileges */
108 if (strcmp(source
, "-") == 0) {
110 * Since input is coming from a pipe we must establish
111 * our own connection to the terminal.
113 terminal
= fopen("/dev/tty", "r");
114 if (terminal
== NULL
) {
117 gettext("Cannot open(\"/dev/tty\")");
120 terminal
= fopen("/dev/null", "r");
121 if (terminal
== NULL
) {
124 "Cannot open(\"/dev/null\")");
132 (void) fprintf(stderr
, gettext(
133 "Cannot specify an archive file when reading from a pipe\n"));
137 (void) strcpy(magtape
, source
);
141 newtapebuf(size_t size
)
145 nsize
= size
* tp_bsize
;
147 if (nsize
<= tbfsize
)
150 tbf
= (char *)malloc(nsize
);
152 (void) fprintf(stderr
,
153 gettext("Cannot allocate space for buffer\n"));
160 * Verify that the tape drive can be accessed and
161 * that it actually is a dump tape.
170 char *syment
= RESTORESYMTABLE
;
172 vprintf(stdout
, gettext("Verify volume and initialize maps\n"));
174 mt
= open(archivefile
, O_RDONLY
|O_LARGEFILE
);
183 else if ((mt
= open(magtape
, O_RDONLY
|O_LARGEFILE
)) < 0) {
191 if (!pipein
&& !bflag
)
193 findtapeblksize(ARCHIVE_FILE
);
195 findtapeblksize(TAPE_FILE
);
197 tape_rec_size
= saved_ntrec
* DEV_BSIZE
;
201 * Get the first header. If c_magic is NOT NFS_MAGIC or if
202 * the checksum is in error, it will fail. The magic could then
203 * be either OFS_MAGIC or MTB_MAGIC. If OFS_MAGIC, assume we
204 * have an old dump, and try to convert it. If it is MTB_MAGIC, we
205 * procees this after.
207 if ((gethead(&spcl
) == FAIL
) && (spcl
.c_magic
!= MTB_MAGIC
)) {
208 bct
--; /* push back this block */
212 if (gethead(&spcl
) == FAIL
) {
213 (void) fprintf(stderr
,
214 gettext("Volume is not in dump format\n"));
217 (void) fprintf(stderr
,
218 gettext("Converting to new file system format.\n"));
221 * The above gethead will have failed if the magic is
222 * MTB_MAGIC. If that is true, we need to adjust tp_bsize.
223 * We have assumed to this time that tp_bsize was 1024, if
224 * this is a newer dump, get the real tp_bsize from the header,
225 * and recalculate ntrec, numtrec.
227 if (spcl
.c_magic
== MTB_MAGIC
) {
228 tp_bsize
= spcl
.c_tpbsize
;
229 if ((tp_bsize
% TP_BSIZE_MIN
!= 0) ||
230 (tp_bsize
> TP_BSIZE_MAX
)) {
231 (void) fprintf(stderr
,
232 gettext("Volume is not in dump format\n"));
235 ntrec
= (tape_rec_size
/tp_bsize
);
238 bct
--; /* push back this block */
241 /* we have to re-do this in case checksum is wrong */
242 if (gethead(&spcl
) == FAIL
) {
243 (void) fprintf(stderr
,
244 gettext("Volume is not in dump format\n"));
249 byteorder_banner(byteorder
, stdout
);
251 endoftapemark
.s_spcl
.c_magic
= cvtflag
? OFS_MAGIC
:
252 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
);
253 endoftapemark
.s_spcl
.c_type
= TS_END
;
256 * include this since the `resync' loop in findinode
257 * expects to find a header with the c_date field
260 endoftapemark
.s_spcl
.c_date
= spcl
.c_date
;
262 ip
= (int32_t *)&endoftapemark
;
263 /*LINTED [assertion always true]*/
264 assert((sizeof (endoftapemark
) % sizeof (int32_t)) == 0);
265 j
= sizeof (endoftapemark
) / sizeof (int32_t);
271 endoftapemark
.s_spcl
.c_checksum
= CHECKSUM
- i
;
273 if (vflag
&& command
!= 't')
275 dumptime
= spcl
.c_ddate
;
276 dumpdate
= spcl
.c_date
;
277 if (stat(".", &stbuf
) < 0) {
278 perror(gettext("cannot stat ."));
281 if (stbuf
.st_blksize
>= tp_bsize
&& stbuf
.st_blksize
<= MAXBSIZE
) {
282 /* LINTED: value fits in a size_t */
283 fssize
= stbuf
.st_blksize
;
288 if (checkvol(&spcl
, 1) == FAIL
) {
289 (void) fprintf(stderr
,
290 gettext("This is not volume 1 of the dump\n"));
293 if (readhdr(&spcl
) == FAIL
)
294 panic(gettext("no header after volume mark!\n"));
296 findinode(&spcl
); /* sets curfile, resyncs the tape if need be */
297 if (checktype(&spcl
, TS_CLRI
) == FAIL
) {
298 (void) fprintf(stderr
,
299 gettext("Cannot find file removal list\n"));
302 maxino
= (unsigned)((spcl
.c_count
* tp_bsize
* NBBY
) + 1);
303 dprintf(stdout
, "maxino = %lu\n", maxino
);
305 * Allocate space for at least MAXINO inodes to allow us
306 * to restore partial dump tapes written before dump was
307 * fixed to write out the entire inode map.
309 if (maxino
> ULONG_MAX
) {
310 (void) fprintf(stderr
,
311 gettext("file system too large\n"));
314 /* LINTED maxino size-checked above */
315 mapsize
= (size_t)d_howmany(maxino
> MAXINO
? maxino
: MAXINO
, NBBY
);
316 beginmap
= map
= calloc((size_t)1, mapsize
);
317 if (map
== (char *)NIL
) {
318 (void) fprintf(stderr
,
319 gettext("no memory for file removal list\n"));
322 endmap
= map
+ mapsize
;
324 curfile
.action
= USING
;
326 getfile(xtrmap
, xtrmapskip
);
329 if (checktype(&spcl
, TS_BITS
) == FAIL
) {
330 /* if we have TS_CLRI then no TS_BITS then a TS_END */
331 /* then we have an empty dump file */
332 if (gethead(&spcl
) == GOOD
&&
333 checktype(&spcl
, TS_END
) == GOOD
) {
334 if ((command
== 'r') || (command
== 'R')) {
335 initsymtable(syment
);
336 dumpsymtable(syment
, volno
);
340 /* otherwise we have an error */
341 (void) fprintf(stderr
, gettext("Cannot find file dump list\n"));
344 /* LINTED maxino size-checked above */
345 mapsize
= (size_t)d_howmany(maxino
, NBBY
);
346 beginmap
= map
= calloc((size_t)1, mapsize
);
348 (void) fprintf(stderr
,
349 gettext("no memory for file dump list\n"));
352 endmap
= map
+ mapsize
;
354 curfile
.action
= USING
;
356 getfile(xtrmap
, xtrmapskip
);
361 * Initialize fssize variable for 'R' command to work.
368 if (stat(".", &stbuf
) < 0) {
369 perror(gettext("cannot stat ."));
372 if (stbuf
.st_blksize
>= tp_bsize
&& stbuf
.st_blksize
<= MAXBSIZE
) {
373 /* LINTED: value fits in a size_t */
374 fssize
= stbuf
.st_blksize
;
381 * Prompt user to load a new dump volume.
382 * "Nextvol" is the next suggested volume to use.
383 * This suggested volume is enforced when doing full
384 * or incremental restores, but can be overrridden by
385 * the user when only extracting a subset of the files.
387 * first_time is used with archive files and can have 1 of 3 states:
388 * FT_STATE_1 Tape has not been read yet
389 * FT_STATE_2 Tape has been read but not positioned past directory
391 * FT_STATE_3 Tape has been read and is reading file information
401 long savecnt
, savetapea
, wantnext
;
403 union u_spcl tmpspcl
;
404 #define tmpbuf tmpspcl.s_spcl
405 char buf
[TP_BSIZE_MAX
];
406 static int first_time
= FT_STATE_1
;
409 (void) fprintf(stderr
, gettext(
410 "Internal consistency failure in getvol: tbf is NULL\n"));
415 for (i
= 0; i
< MAXTAPES
; i
++)
421 panic(gettext("changing volumes on pipe input\n"));
426 savecnt
= blksread
; /* ignore volume verification tape i/o */
430 done(1); /* pipes do not get a second chance */
431 if (command
== 'R' || command
== 'r' || curfile
.action
!= SKIP
) {
440 if ((volno
== 1) && (nextvol
== 1)) {
441 tapesread
[volno
-1]++;
444 if (autoload_tape()) {
451 while (newvol
<= 0) {
454 for (i
= 0; i
< MAXTAPES
; i
++)
458 (void) fprintf(stderr
, "%s", gettext(
459 "You have not read any volumes yet.\n\
460 Unless you know which volume your file(s) are on you should start\n\
461 with the last volume and work towards the first.\n"));
463 (void) fprintf(stderr
,
464 gettext("You have read volumes"));
465 (void) strcpy(tbf
, ": ");
466 for (i
= 0; i
< MAXTAPES
; i
++)
468 (void) fprintf(stderr
, "%s%ld",
470 (void) strcpy(tbf
, ", ");
472 (void) fprintf(stderr
, "\n");
475 (void) fprintf(stderr
,
476 gettext("Specify next volume #: "));
477 (void) fflush(stderr
);
478 /* LINTED tbfsize is limited to a few MB */
479 (void) fgets(tbf
, (int)tbfsize
, terminal
);
480 } while (!feof(terminal
) && tbf
[0] == '\n');
485 (void) fprintf(stderr
, gettext(
486 "Volume numbers are positive numerics\n"));
488 if (newvol
> MAXTAPES
) {
489 (void) fprintf(stderr
, gettext(
490 "This program can only deal with %d volumes\n"),
495 if (newvol
== volno
) {
496 tapesread
[volno
-1]++;
499 closemt(ALLOW_OFFLINE
);
501 * XXX: if we are switching devices, we should probably try
502 * the device once without prompting to enable unattended
505 (void) fprintf(stderr
, gettext(
506 "Mount volume %d\nthen enter volume name (default: %s) "),
508 (void) fflush(stderr
);
509 /* LINTED tbfsize is limited to a few MB */
510 (void) fgets(tbf
, (int)tbfsize
, terminal
);
514 * XXX We don't allow rotating among tape hosts, just drives.
516 if (tbf
[0] != '\n') {
517 (void) strncpy(magtape
, tbf
, sizeof (magtape
));
518 magtape
[sizeof (magtape
) - 1] = '\0';
519 /* LINTED unsigned -> signed conversion ok */
520 i
= (int)strlen(magtape
);
521 if (magtape
[i
- 1] == '\n')
522 magtape
[i
- 1] = '\0';
524 if ((mt
= open(magtape
, O_RDONLY
|O_LARGEFILE
)) == -1) {
526 (void) fprintf(stderr
, gettext("Cannot open %s: %s\n"),
527 magtape
, strerror(error
));
535 if (!pipein
&& !bflag
&& archivefile
&& (first_time
== FT_STATE_1
)) {
536 first_time
= FT_STATE_2
;
537 findtapeblksize(TAPE_FILE
);
539 if (readhdr(&tmpbuf
) == FAIL
) {
540 (void) fprintf(stderr
,
541 gettext("volume is not in dump format\n"));
545 if (checkvol(&tmpbuf
, volno
) == FAIL
) {
546 (void) fprintf(stderr
, gettext("Wrong volume (%d)\n"),
552 if (((time_t)(tmpbuf
.c_date
) != dumpdate
) ||
553 ((time_t)(tmpbuf
.c_ddate
) != dumptime
)) {
555 time_t lc_date
= (time_t)tmpbuf
.c_date
;
558 * This is used to save the return value from lctime(),
559 * since that's volatile across lctime() invocations.
561 tmp_ct
= strdup(lctime(&lc_date
));
562 if (tmp_ct
== NULL
) {
563 (void) fprintf(stderr
, gettext(
564 "Cannot allocate space for time string\n"));
568 (void) fprintf(stderr
,
569 gettext("Wrong dump date\n\tgot: %s\twanted: %s"),
570 tmp_ct
, lctime(&dumpdate
));
575 tapesread
[volno
-1]++;
579 * If continuing from the previous volume, skip over any
580 * blocks read already at the end of the previous volume.
582 * If coming to this volume at random, skip to the beginning
583 * of the next record.
585 if (tmpbuf
.c_type
== TS_TAPE
&& (tmpbuf
.c_flags
& DR_NEWHEADER
)) {
587 if (archivefile
&& first_time
== FT_STATE_2
) {
588 first_time
= FT_STATE_3
;
590 recsread
= tmpbuf
.c_firstrec
;
591 tapea
= tmpbuf
.c_tapea
;
593 "restore skipping %d records\n",
595 for (i
= tmpbuf
.c_count
; i
> 0; i
--)
597 } else if (tmpbuf
.c_firstrec
!= 0) {
601 if (archivefile
&& first_time
== FT_STATE_2
) {
603 * subtract 2, 1 for archive file's TS_END
604 * and 1 for tape's TS_TAPE
606 first_time
= FT_STATE_3
;
607 i
= tapea
- tmpbuf
.c_tapea
- 2;
609 i
= tapea
- tmpbuf
.c_tapea
;
612 dprintf(stdout
, gettext(
613 "restore skipping %d duplicate records\n"),
616 dprintf(stdout
, gettext(
617 "restore duplicate record botch (%d)\n"),
622 tapea
= savetapea
+ 1; /* <= (void) gethead() below */
625 if (curfile
.action
== USING
) {
627 panic(gettext("active file into volume 1\n"));
630 (void) gethead(&spcl
);
631 findinode(&spcl
); /* do we always restart files in full? */
632 if (gettingfile
) { /* i.e. will we lose metadata? */
634 longjmp(restart
, 1); /* will this set f1 & f2? */
639 * handle multiple dumps per tape by skipping forward to the
640 * appropriate one. Note we don't use absolute positioning,
641 * as that may take a very long time.
649 if (dumpnum
== 1 || volno
!= 1)
652 (void) fprintf(stderr
,
653 gettext("Cannot have multiple dumps on pipe input\n"));
657 tcom
.mt_count
= dumpnum
- 1;
658 retval
= ioctl(mt
, (int)MTIOCTOP
, (char *)&tcom
);
660 perror("ioctl MTFSF");
668 static char *epoch
= NULL
;
671 epoch
= strdup(gettext("the epoch\n"));
673 (void) fprintf(stderr
, gettext("Out of memory\n"));
678 date
= (time_t)dumpinfo
.c_date
;
679 (void) fprintf(stdout
,
680 gettext("Dump date: %s"), lctime(&date
));
682 date
= (time_t)dumpinfo
.c_ddate
;
683 (void) fprintf(stdout
, gettext("Dumped from: %s"),
684 (dumpinfo
.c_ddate
== 0) ? epoch
: lctime(&date
));
686 (void) fprintf(stdout
,
687 gettext("Level %d dump of %s on %.*s:%s\n"),
688 dumpinfo
.c_level
, dumpinfo
.c_filesys
,
689 sizeof (dumpinfo
.c_host
), dumpinfo
.c_host
, dumpinfo
.c_dev
);
690 (void) fprintf(stdout
,
691 gettext("Label: %.*s\n"),
692 sizeof (dumpinfo
.c_label
), dumpinfo
.c_label
);
695 (void) fprintf(stdout
,
696 gettext("Starting inode numbers by volume:\n"));
697 for (i
= 1; i
<= dumpinfo
.c_volume
; i
++)
698 (void) fprintf(stdout
, gettext("\tVolume %d: %6d\n"),
699 i
, dumpinfo
.c_inos
[i
]);
704 extractfile(char *name
)
706 static int complained_chown
= 0;
707 static int complained_lchown
= 0;
708 static int complained_chmod
= 0;
709 static int complained_utime
= 0;
710 static int complained_mknod
= 0;
723 curfile
.action
= USING
;
724 timep
[0] = (time_t)curfile
.dip
->di_atime
;
725 timep
[1] = (time_t)curfile
.dip
->di_mtime
;
726 mode
= curfile
.dip
->di_mode
;
728 uid
= curfile
.dip
->di_suid
== UID_LONG
?
729 curfile
.dip
->di_uid
: (uid_t
)curfile
.dip
->di_suid
;
730 gid
= curfile
.dip
->di_sgid
== GID_LONG
?
731 curfile
.dip
->di_gid
: (gid_t
)curfile
.dip
->di_sgid
;
733 resolve(name
, &dfd
, &rname
);
734 if (dfd
!= AT_FDCWD
) {
735 if (fchdir(dfd
) < 0) {
737 (void) fprintf(stderr
, gettext(
738 "%s: unable to set attribute context: %s\n"),
739 rname
, strerror(saverr
));
746 switch (mode
& IFMT
) {
749 (void) fprintf(stderr
, gettext("%s: unknown file mode 0%lo\n"),
750 rname
, (ulong_t
)(mode
&IFMT
));
756 vprintf(stdout
, gettext("skipped socket %s\n"), rname
);
763 ep
= lookupname(name
);
764 if (ep
== NIL
|| ep
->e_flags
& EXTRACT
) {
766 "directory %s was not restored\n"),
776 vprintf(stdout
, gettext("extract file %s\n"), rname
);
777 result
= genliteraldir(rname
, curfile
.ino
);
783 getfile(xtrlnkfile
, xtrlnkskip
);
785 vprintf(stdout
, gettext(
786 "%s: zero length symbolic link (ignored)\n"),
791 if ((result
= lf_linkit(lnkbuf
, rname
, SYMLINK
)) != GOOD
)
794 /* 1254700: set uid/gid (previously missing) */
795 if (lchown(rname
, uid
, gid
) < 0 && !complained_lchown
) {
799 "Unable to restore ownership of symlink %s: %s\n");
800 (void) fprintf(stderr
, errmsg
,
801 rname
, strerror(saverr
));
802 (void) fprintf(stderr
, gettext(
803 "Additional such failures will be ignored.\n"));
804 complained_lchown
= 1;
813 vprintf(stdout
, gettext("extract special file %s\n"), rname
);
814 /* put device rdev into dev_t expanded format */
815 /* XXX does this always do the right thing? */
816 /* XXX does dump do the right thing? */
817 if (((curfile
.dip
->di_ordev
& 0xFFFF0000) == 0) ||
818 ((curfile
.dip
->di_ordev
& 0xFFFF0000) == 0xFFFF0000)) {
819 full_dev
= expdev((unsigned)(curfile
.dip
->di_ordev
));
821 /* LINTED sign extension ok */
822 full_dev
= (unsigned)(curfile
.dip
->di_ordev
);
825 if (mknod(rname
, mode
, full_dev
) < 0) {
829 if ((stat64(rname
, s
)) ||
830 ((s
->st_mode
& S_IFMT
) != (mode
& S_IFMT
)) ||
831 (s
->st_rdev
!= full_dev
)) {
832 if (saverr
!= EPERM
|| !complained_mknod
) {
833 (void) fprintf(stderr
, "%s: ", rname
);
834 (void) fflush(stderr
);
837 "cannot create special file"));
838 if (saverr
== EPERM
) {
839 (void) fprintf(stderr
, gettext(
840 "Additional such failures will be ignored.\n"));
841 complained_mknod
= 1;
849 if (chown(rname
, uid
, gid
) < 0 && !complained_chown
) {
853 "Unable to restore ownership of %s: %s\n");
854 (void) fprintf(stderr
, errmsg
,
855 rname
, strerror(saverr
));
856 (void) fprintf(stderr
, gettext(
857 "Additional such failures will be ignored.\n"));
858 complained_chown
= 1;
860 if (chmod(rname
, mode
) < 0 && !complained_chmod
) {
863 "Unable to restore permissions on %s: %s\n");
864 (void) fprintf(stderr
, errmsg
,
865 rname
, strerror(saverr
));
866 (void) fprintf(stderr
, gettext(
867 "Additional such failures will be ignored.\n"));
868 complained_chmod
= 1;
871 metaset(rname
); /* skipfile() got the metadata, if any */
872 if (utime(rname
, (struct utimbuf
*)timep
) < 0 &&
876 "Unable to restore times on %s: %s\n");
877 (void) fprintf(stderr
, errmsg
,
878 rname
, strerror(saverr
));
879 (void) fprintf(stderr
, gettext(
880 "Additional such failures will be ignored.\n"));
881 complained_utime
= 1;
887 vprintf(stdout
, gettext("extract file %s\n"), rname
);
890 * perform a restrictive creat(2) initally, we'll
891 * fchmod(2) according to the archive later after
892 * we've written the blocks.
894 ofile
= creat64(rname
, 0600);
898 errmsg
= gettext("cannot create file");
899 (void) fprintf(stderr
, "%s: ", rname
);
900 (void) fflush(stderr
);
907 if (fchown(ofile
, uid
, gid
) < 0 && !complained_chown
) {
911 "Unable to restore ownership of %s: %s\n");
912 (void) fprintf(stderr
, errmsg
,
913 rname
, strerror(saverr
));
914 (void) fprintf(stderr
, gettext(
915 "Additional such failures will be ignored.\n"));
916 complained_chown
= 1;
919 getfile(xtrfile
, xtrskip
);
923 * the fchmod(2) has to come after getfile() as some POSIX
924 * implementations clear the S_ISUID and S_ISGID bits of the
925 * file after every write(2).
927 if (fchmod(ofile
, mode
) < 0 && !complained_chmod
) {
930 "Unable to restore permissions on %s: %s\n");
931 (void) fprintf(stderr
, errmsg
,
932 rname
, strerror(saverr
));
933 (void) fprintf(stderr
, gettext(
934 "Additional such failures will be ignored.\n"));
935 complained_chmod
= 1;
939 * Some errors don't get reported until we close(2), so
941 * XXX unlink the file if an error is reported?
943 if (close(ofile
) < 0) {
945 errmsg
= gettext("error closing file");
946 (void) fprintf(stderr
, "%s: ", rname
);
947 (void) fflush(stderr
);
953 if (utime(rname
, (struct utimbuf
*)timep
) < 0 &&
957 "Unable to restore times on %s: %s\n");
958 (void) fprintf(stderr
, errmsg
,
959 rname
, strerror(saverr
));
960 (void) fprintf(stderr
, gettext(
961 "Additional such failures will be ignored.\n"));
962 complained_utime
= 1;
968 if (dfd
!= AT_FDCWD
) {
976 * skip over bit maps on the tape
982 while (checktype(&spcl
, TS_CLRI
) == GOOD
||
983 checktype(&spcl
, TS_BITS
) == GOOD
)
989 * skip over a file on the tape
994 curfile
.action
= SKIP
;
998 * Do the file extraction, calling the supplied functions
1002 getfile(void (*f1
)(), void (*f2
)())
1006 offset_t size
= (offset_t
)spcl
.c_dinode
.di_size
;
1007 static char clearedbuf
[MAXBSIZE
];
1008 char buf
[TP_BSIZE_MAX
];
1010 char junk
[TP_BSIZE_MAX
];
1012 assert(MAXBSIZE
>= tp_bsize
);
1014 metaset(NULL
); /* flush old metadata */
1015 if (checktype(&spcl
, TS_END
) == GOOD
) {
1016 panic(gettext("ran off end of volume\n"));
1019 if (ishead(&spcl
) == FAIL
) {
1020 panic(gettext("not at beginning of a file\n"));
1023 metacheck(&spcl
); /* check for metadata in header */
1024 if (!gettingfile
&& setjmp(restart
) != 0) {
1025 gettingfile
= 0; /* paranoia; longjmp'er should do */
1030 if ((spcl
.c_dinode
.di_mode
& IFMT
) == IFSHAD
) {
1034 for (i
= 0, bufptr
= buf
; i
< spcl
.c_count
; i
++) {
1035 if ((i
>= TP_NINDIR
) || (spcl
.c_addr
[i
])) {
1039 if (curblk
== (fssize
/ tp_bsize
)) {
1040 (*f1
)(buf
, size
> tp_bsize
?
1042 /* LINTED size <= tp_bsize */
1043 (curblk
- 1) * tp_bsize
+ (size_t)size
);
1049 (*f1
)(buf
, size
> tp_bsize
?
1050 (size_t)(curblk
* tp_bsize
) :
1051 /* LINTED size <= tp_bsize */
1052 (curblk
- 1) * tp_bsize
+ (size_t)size
);
1056 (*f2
)(clearedbuf
, size
> tp_bsize
?
1057 /* LINTED size <= tp_bsize */
1058 (long)tp_bsize
: (size_t)size
);
1060 if ((size
-= tp_bsize
) <= 0) {
1061 for (i
++; i
< spcl
.c_count
; i
++)
1062 if ((i
>= TP_NINDIR
) || (spcl
.c_addr
[i
]))
1069 * Ok to cast size to size_t here. The above for loop reads
1070 * data into the buffer then writes it to the output file. The
1071 * call to f1 here is to write out the data that's in the
1072 * buffer that has not yet been written to the file.
1073 * This will be less than N-KB of data, since the
1074 * above loop writes to the file in filesystem-
1077 /* LINTED: size fits into a size_t at this point */
1078 (*f1
)(buf
, (curblk
* tp_bsize
) + (size_t)size
);
1083 if ((readhdr(&spcl
) == GOOD
) && (checktype(&spcl
, TS_ADDR
) == GOOD
)) {
1085 size
= (offset_t
)spcl
.c_count
* tp_bsize
;
1087 else if ((size
<= 0) &&
1088 ((spcl
.c_dinode
.di_mode
& IFMT
) == IFSHAD
)) {
1089 /* LINTED unsigned to signed conversion ok */
1090 size
= spcl
.c_dinode
.di_size
;
1097 gettext("Missing address (header) block for %s\n"),
1104 * The next routines are called during file extraction to
1105 * put the data into the right form and place.
1108 xtrfile(char *buf
, size_t size
)
1110 if (write(ofile
, buf
, (size_t)size
) == -1) {
1112 (void) fprintf(stderr
,
1113 gettext("write error extracting inode %d, name %s\n"),
1114 curfile
.ino
, curfile
.name
);
1122 * Even though size is a size_t, it's seeking to a relative
1123 * offset. Thus, the seek could go beyond 2 GB, so lseek64 is needed.
1128 xtrskip(char *buf
, size_t size
)
1130 if (lseek64(ofile
, (offset_t
)size
, 1) == -1) {
1132 (void) fprintf(stderr
,
1133 gettext("seek error extracting inode %d, name %s\n"),
1134 curfile
.ino
, curfile
.name
);
1141 /* these are local to the next five functions */
1142 static char *metadata
= NULL
;
1143 static size_t metasize
= 0;
1146 metacheck(struct s_spcl
*head
)
1148 if (! (head
->c_flags
& DR_HASMETA
))
1150 if ((metadata
= malloc(metasize
= (size_t)sizeof (head
->c_shadow
)))
1152 (void) fprintf(stderr
,
1153 gettext("Cannot malloc for metadata\n"));
1156 bcopy(&(head
->c_shadow
), metadata
, metasize
);
1160 xtrmeta(char *buf
, size_t size
)
1162 if ((metadata
== NULL
) && ((spcl
.c_dinode
.di_mode
& IFMT
) != IFSHAD
))
1164 if ((metadata
= realloc(metadata
, metasize
+ size
)) == NULL
) {
1165 (void) fprintf(stderr
,
1166 gettext("Cannot malloc for metadata\n"));
1169 bcopy(buf
, metadata
+ metasize
, size
);
1175 metaskip(char *buf
, size_t size
)
1177 if (metadata
== NULL
)
1179 if ((metadata
= realloc(metadata
, metasize
+ size
)) == NULL
) {
1180 (void) fprintf(stderr
,
1181 gettext("Cannot malloc for metadata\n"));
1184 bzero(metadata
+ metasize
, size
);
1191 if (metadata
== NULL
)
1194 metaproc(name
, metadata
, metasize
);
1195 (void) free(metadata
);
1210 fsd_acl(name
, aclp
, size
)
1214 static aclent_t
*aclent
= NULL
;
1228 /*LINTED [aclp is malloc'd]*/
1229 diskacl
= (ufs_acl_t
*)aclp
;
1230 /* LINTED: result fits in an int */
1231 j
= size
/ sizeof (*diskacl
);
1232 normacls(byteorder
, diskacl
, j
);
1236 aclent
= reallocarray(aclent
, n
, sizeof (*aclent
));
1237 if (aclent
== NULL
) {
1238 (void) fprintf(stderr
, gettext("Cannot malloc acl list\n"));
1244 aclent
[i
].a_type
= diskacl
[j
].acl_tag
;
1245 aclent
[i
].a_id
= diskacl
[j
].acl_who
;
1246 aclent
[i
].a_perm
= diskacl
[j
].acl_perm
;
1251 set_aclp
= acl_to_aclp(ACLENT_T
, aclent
, n
);
1252 if (set_aclp
== NULL
) {
1253 (void) fprintf(stderr
, gettext("Cannot build acl_t\n"));
1257 if (acl_set(name
, set_aclp
) == -1) {
1258 static int once
= 0;
1261 * Treat some errors from the acl subsystem specially to
1262 * avoid being too noisy:
1264 * ENOSYS - ACLs not supported on this file system
1265 * EPERM - not the owner or not privileged
1267 * The following is also supported for backwards compat.
1268 * since acl(2) used to return the wrong errno:
1270 * EINVAL - not the owner of the object
1272 if (errno
== ENOSYS
|| errno
== EPERM
|| errno
== EINVAL
) {
1277 gettext("setacl failed: %s\n"),
1282 fprintf(stderr
, gettext("setacl on %s failed: %s\n"),
1283 name
, strerror(saverr
));
1289 static struct fsdtypes
{
1294 {FSD_DFACL
, fsd_acl
},
1299 metaproc(char *name
, char *mdata
, size_t msize
)
1301 struct fsdtypes
*fsdtype
;
1306 * for the whole shadow inode, dispatch each piece
1307 * to the appropriate function.
1310 /* LINTED (c - mdata) fits into a size_t */
1311 while ((size_t)(c
- mdata
) < msize
) {
1312 /*LINTED [mdata is malloc'd]*/
1313 fsd
= (ufs_fsd_t
*)c
;
1314 assert((fsd
->fsd_size
% 4) == 0);
1315 /* LINTED: lint thinks pointers are signed */
1316 c
+= FSD_RECSZ(fsd
, fsd
->fsd_size
);
1317 if ((fsd
->fsd_type
== FSD_FREE
) ||
1318 ((unsigned)(fsd
->fsd_size
) <= sizeof (ufs_fsd_t
)) ||
1319 (c
> (mdata
+ msize
)))
1321 for (fsdtype
= fsdtypes
; fsdtype
->type
; fsdtype
++)
1322 if (fsdtype
->type
== fsd
->fsd_type
)
1323 (*fsdtype
->function
)(name
, fsd
->fsd_data
,
1324 (unsigned)(fsd
->fsd_size
) -
1325 sizeof (fsd
->fsd_type
) -
1326 sizeof (fsd
->fsd_size
));
1327 /* ^^^ be sure to change if fsd ever changes ^^^ */
1330 /* reset the state of all the functions */
1331 for (fsdtype
= fsdtypes
; fsdtype
->type
; fsdtype
++)
1332 (*fsdtype
->function
)(NULL
, NULL
, 0);
1336 xtrlnkfile(char *buf
, size_t size
)
1338 /* LINTED: signed/unsigned mix ok */
1340 if (pathlen
> MAXPATHLEN
) {
1341 (void) fprintf(stderr
,
1342 gettext("symbolic link name: %s->%s%s; too long %d\n"),
1343 curfile
.name
, lnkbuf
, buf
, pathlen
);
1347 (void) strcat(lnkbuf
, buf
);
1348 /* add an extra NULL to make this a legal complex string */
1349 lnkbuf
[pathlen
+1] = '\0';
1354 xtrlnkskip(char *buf
, size_t size
)
1356 (void) fprintf(stderr
,
1357 gettext("unallocated block in symbolic link %s\n"),
1363 xtrmap(char *buf
, size_t size
)
1365 if ((map
+size
) > endmap
) {
1366 int64_t mapsize
, increment
;
1369 if (spcl
.c_type
!= TS_ADDR
) {
1370 (void) fprintf(stderr
,
1371 gettext("xtrmap: current record not TS_ADDR\n"));
1374 if ((spcl
.c_count
< 0) || (spcl
.c_count
> TP_NINDIR
)) {
1375 (void) fprintf(stderr
,
1376 gettext("xtrmap: illegal c_count field (%d)\n"),
1381 increment
= d_howmany(
1382 ((spcl
.c_count
* tp_bsize
* NBBY
) + 1), NBBY
);
1383 mapsize
= endmap
- beginmap
+ increment
;
1384 if (mapsize
> UINT_MAX
) {
1385 (void) fprintf(stderr
,
1386 gettext("xtrmap: maximum bitmap size exceeded"));
1390 diff
= map
- beginmap
;
1391 /* LINTED mapsize checked above */
1392 beginmap
= realloc(beginmap
, (size_t)mapsize
);
1393 if (beginmap
== NULL
) {
1394 (void) fprintf(stderr
,
1395 gettext("xtrmap: realloc failed\n"));
1398 map
= beginmap
+ diff
;
1399 endmap
= beginmap
+ mapsize
;
1400 /* LINTED endmap - map cannot exceed 32 bits */
1401 bzero(map
, (size_t)(endmap
- map
));
1402 maxino
= NBBY
* mapsize
+ 1;
1405 bcopy(buf
, map
, size
);
1406 /* LINTED character pointers aren't signed */
1412 xtrmapskip(char *buf
, size_t size
)
1414 (void) fprintf(stderr
, gettext("hole in map\n"));
1420 null(char *buf
, size_t size
)
1425 * Do the tape i/o, dealing with volume changes
1435 int32_t expected_magic
;
1438 (void) fprintf(stderr
, gettext(
1439 "Internal consistency failure in readtape: tbf is NULL\n"));
1442 expected_magic
= ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
);
1445 if (bct
< numtrec
) {
1447 * check for old-dump floppy EOM -- it may appear in
1448 * the middle of a buffer. The Dflag used to be used for
1449 * this, but since it doesn't hurt to always do this we
1450 * got rid of the Dflag.
1452 /*LINTED [tbf = malloc()]*/
1453 sp
= &((union u_spcl
*)&tbf
[bct
*tp_bsize
])->s_spcl
;
1454 if (sp
->c_magic
== expected_magic
&& sp
->c_type
== TS_EOM
&&
1455 (time_t)(sp
->c_date
) == dumpdate
&&
1456 (time_t)(sp
->c_ddate
) == dumptime
) {
1457 for (i
= 0; i
< ntrec
; i
++)
1458 /*LINTED [tbf = malloc()]*/
1460 &tbf
[i
*tp_bsize
])->c_magic
= 0;
1466 bcopy(&tbf
[(bct
++*tp_bsize
)], b
, (size_t)tp_bsize
);
1471 /*LINTED [assertion always true]*/
1472 assert(sizeof (union u_spcl
) == TP_BSIZE_MAX
);
1473 for (i
= 0; i
< ntrec
; i
++)
1474 /*LINTED [tbf = malloc()]*/
1475 ((struct s_spcl
*)&tbf
[i
*sizeof (struct s_spcl
)])->c_magic
= 0;
1477 /* LINTED unsigned/signed assignment ok */
1480 /* LINTED unsigned/signed assignment ok */
1481 cnt
= ntrec
*tp_bsize
;
1484 i
= read(mt
, &tbf
[rd
], cnt
);
1486 * Check for mid-tape short read error.
1487 * If found, return rest of buffer.
1489 if (numtrec
< ntrec
&& i
!= 0) {
1490 /* LINTED unsigned/signed assignment ok */
1495 * Handle partial block read.
1497 if (i
> 0 && i
!= ntrec
*tp_bsize
) {
1505 if (i
% tp_bsize
!= 0)
1507 "partial block read: %d should be %d\n"),
1508 i
, ntrec
* tp_bsize
);
1509 numtrec
= i
/ tp_bsize
;
1512 * it's possible to read only 512 bytes
1513 * from a QIC device...
1519 * Handle read error.
1522 switch (curfile
.action
) {
1524 (void) fprintf(stderr
, gettext(
1525 "Read error while trying to set up volume\n"));
1528 (void) fprintf(stderr
, gettext(
1529 "Read error while trying to resynchronize\n"));
1532 (void) fprintf(stderr
, gettext(
1533 "Read error while restoring %s\n"),
1537 (void) fprintf(stderr
, gettext(
1538 "Read error while skipping over inode %d\n"),
1542 if (!yflag
&& !reply(gettext("continue")))
1544 /* LINTED: unsigned->signed conversion ok */
1545 i
= (int)(ntrec
*tp_bsize
);
1546 bzero(tbf
, (size_t)i
);
1547 if (lseek64(mt
, (offset_t
)i
, 1) == (off64_t
)-1) {
1548 perror(gettext("continuation failed"));
1553 * Handle end of tape. The Dflag used to be used, but since it doesn't
1554 * hurt to always check we got rid if it.
1558 * if the first record in the buffer just read is EOM,
1561 /*LINTED [tbf = malloc()]*/
1562 sp
= &((union u_spcl
*)tbf
)->s_spcl
;
1563 if (i
!= 0 && sp
->c_magic
== expected_magic
&& sp
->c_type
== TS_EOM
&&
1564 (time_t)(sp
->c_date
) == dumpdate
&&
1565 (time_t)(sp
->c_ddate
) == dumptime
) {
1575 readtape(b
); /* XXX tail recursion, not goto top? */
1578 /* XXX if panic returns, should we round rd up? */
1579 /* XXX if we do, then we should zero the intervening space */
1580 if (rd
% tp_bsize
!= 0)
1581 panic(gettext("partial block read: %d should be %d\n"),
1582 rd
, ntrec
* tp_bsize
);
1583 bcopy((char *)&endoftapemark
, &tbf
[rd
], (size_t)tp_bsize
);
1586 bcopy(&tbf
[(bct
++*tp_bsize
)], b
, (size_t)tp_bsize
);
1594 findtapeblksize(int arfile
)
1599 (void) fprintf(stderr
, gettext(
1600 "Internal consistency failure in findtapeblksize: "
1602 assert(tbf
!= NULL
);
1606 for (i
= 0; i
< ntrec
; i
++)
1607 /*LINTED [tbf = malloc()]*/
1608 ((struct s_spcl
*)&tbf
[i
* tp_bsize
])->c_magic
= 0;
1610 tape_rec_size
= read(mt
, tbf
, ntrec
* tp_bsize
);
1613 if (tape_rec_size
== (ssize_t
)-1) {
1615 char *errmsg
= gettext("Media read error");
1620 if (tape_rec_size
% tp_bsize
!= 0) {
1621 (void) fprintf(stderr
, gettext(
1622 "Record size (%d) is not a multiple of dump block size (%d)\n"),
1623 tape_rec_size
, tp_bsize
);
1626 ntrec
= (int)tape_rec_size
/ tp_bsize
;
1627 /* LINTED unsigned/signed assignment ok */
1629 vprintf(stdout
, gettext("Media block size is %d\n"), ntrec
*2);
1635 /* LINTED unsigned/signed assignment ok */
1643 * If mode == FORCE_OFFLINE then we're not done but
1644 * we need to change tape. So, rewind and unload current
1645 * tape before loading the new one.
1648 static struct mtop mtop
= { MTOFFL
, 0 };
1652 if (offline
|| mode
== FORCE_OFFLINE
)
1653 (void) fprintf(stderr
, gettext("Rewinding tape\n"));
1655 char buffy
[MAXBSIZE
];
1657 while (read(mt
, buffy
, sizeof (buffy
)) > 0) {
1659 /*LINTED [assertion always true]*/
1664 * Only way to tell if this is a floppy is to issue an ioctl
1665 * but why waste one - if the eject fails, tough!
1667 if (offline
|| mode
== FORCE_OFFLINE
)
1668 (void) ioctl(mt
, MTIOCTOP
, &mtop
);
1669 (void) ioctl(mt
, FDEJECT
, 0);
1676 checkvol(struct s_spcl
*b
, int t
)
1679 if (b
->c_volume
!= t
)
1685 readhdr(struct s_spcl
*b
)
1688 if (gethead(b
) == FAIL
) {
1689 dprintf(stdout
, gettext("readhdr fails at %ld blocks\n"),
1697 * read the tape into buf, then return whether or
1698 * or not it is a header block.
1701 gethead(struct s_spcl
*buf
)
1705 char dummy
[TP_BSIZE_MIN
];
1716 unsigned short odi_mode
;
1733 readtape((char *)(&u_ospcl
.s_ospcl
));
1734 bzero((char *)buf
, (size_t)TP_BSIZE_MIN
);
1735 buf
->c_type
= u_ospcl
.s_ospcl
.c_type
;
1736 buf
->c_date
= u_ospcl
.s_ospcl
.c_date
;
1737 buf
->c_ddate
= u_ospcl
.s_ospcl
.c_ddate
;
1738 buf
->c_volume
= u_ospcl
.s_ospcl
.c_volume
;
1739 buf
->c_tapea
= u_ospcl
.s_ospcl
.c_tapea
;
1740 buf
->c_inumber
= u_ospcl
.s_ospcl
.c_inumber
;
1741 buf
->c_checksum
= u_ospcl
.s_ospcl
.c_checksum
;
1742 buf
->c_magic
= u_ospcl
.s_ospcl
.c_magic
;
1743 buf
->c_dinode
.di_mode
= u_ospcl
.s_ospcl
.c_dinode
.odi_mode
;
1744 /* LINTED: unsigned/signed combination ok */
1745 buf
->c_dinode
.di_nlink
= u_ospcl
.s_ospcl
.c_dinode
.odi_nlink
;
1746 buf
->c_dinode
.di_size
=
1747 (unsigned)(u_ospcl
.s_ospcl
.c_dinode
.odi_size
);
1748 buf
->c_dinode
.di_uid
= u_ospcl
.s_ospcl
.c_dinode
.odi_uid
;
1749 buf
->c_dinode
.di_gid
= u_ospcl
.s_ospcl
.c_dinode
.odi_gid
;
1750 buf
->c_dinode
.di_suid
= UID_LONG
;
1751 buf
->c_dinode
.di_sgid
= GID_LONG
;
1752 buf
->c_dinode
.di_ordev
= u_ospcl
.s_ospcl
.c_dinode
.odi_rdev
;
1753 buf
->c_dinode
.di_atime
= u_ospcl
.s_ospcl
.c_dinode
.odi_atime
;
1754 buf
->c_dinode
.di_mtime
= u_ospcl
.s_ospcl
.c_dinode
.odi_mtime
;
1755 buf
->c_dinode
.di_ctime
= u_ospcl
.s_ospcl
.c_dinode
.odi_ctime
;
1756 buf
->c_count
= u_ospcl
.s_ospcl
.c_count
;
1757 bcopy(u_ospcl
.s_ospcl
.c_baddr
, buf
->c_addr
,
1758 sizeof (u_ospcl
.s_ospcl
.c_baddr
));
1760 /*CONSTANTCONDITION*/
1761 assert(sizeof (u_ospcl
.s_ospcl
) < sizeof (union u_spcl
));
1763 /* we byte-swap the new spclrec, but checksum the old */
1764 /* (see comments in normspcl()) */
1765 if (normspcl(byteorder
, buf
,
1766 (int *)(&u_ospcl
.s_ospcl
), sizeof (u_ospcl
.s_ospcl
),
1770 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
);
1772 readtape((char *)buf
);
1773 if (normspcl(byteorder
, buf
, (int *)buf
, tp_bsize
,
1774 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
)))
1778 switch (buf
->c_type
) {
1783 * Have to patch up missing information in bit map headers
1786 buf
->c_dinode
.di_size
= (offset_t
)buf
->c_count
* tp_bsize
;
1787 for (i
= 0; i
< buf
->c_count
&& i
< TP_NINDIR
; i
++)
1793 if (dumpinfo
.c_date
== 0) {
1794 dumpinfo
.c_date
= spcl
.c_date
;
1795 dumpinfo
.c_ddate
= spcl
.c_ddate
;
1797 if (!hostinfo
&& spcl
.c_host
[0] != '\0') {
1798 bcopy(spcl
.c_label
, dumpinfo
.c_label
,
1799 sizeof (spcl
.c_label
));
1800 bcopy(spcl
.c_filesys
, dumpinfo
.c_filesys
,
1801 sizeof (spcl
.c_filesys
));
1802 bcopy(spcl
.c_dev
, dumpinfo
.c_dev
,
1803 sizeof (spcl
.c_dev
));
1804 bcopy(spcl
.c_host
, dumpinfo
.c_host
,
1805 sizeof (spcl
.c_host
));
1806 dumpinfo
.c_level
= spcl
.c_level
;
1808 if (c_label
!= NULL
&&
1809 strncmp(c_label
, spcl
.c_label
,
1810 sizeof (spcl
.c_label
))
1812 (void) fprintf(stderr
, gettext(
1813 "Incorrect tape label. Expected `%s', got `%.*s'\n"),
1815 sizeof (spcl
.c_label
), spcl
.c_label
);
1819 if (!inodeinfo
&& (spcl
.c_flags
& DR_INODEINFO
)) {
1820 dumpinfo
.c_volume
= spcl
.c_volume
;
1821 bcopy(spcl
.c_inos
, dumpinfo
.c_inos
,
1822 sizeof (spcl
.c_inos
));
1833 panic(gettext("%s: unknown inode type %d\n"),
1834 "gethead", buf
->c_type
);
1843 * Check that a header is where it belongs and predict the next header
1846 accthdr(struct s_spcl
*header
)
1848 static ino_t previno
= (ino_t
)(unsigned)-1;
1849 static int prevtype
;
1850 static long predict
;
1853 if (header
->c_type
== TS_TAPE
) {
1854 if (header
->c_firstrec
)
1855 (void) fprintf(stderr
,
1856 gettext("Volume header begins with record %d"),
1857 header
->c_firstrec
);
1859 (void) fprintf(stderr
, gettext("Volume header"));
1860 (void) fprintf(stderr
, "\n");
1861 previno
= (ino_t
)(unsigned)-1;
1864 if (previno
== (ino_t
)(unsigned)-1)
1868 (void) fprintf(stderr
, gettext("Dump mask header"));
1871 (void) fprintf(stderr
, gettext("Remove mask header"));
1874 (void) fprintf(stderr
,
1875 gettext("File header, ino %d at record %d"),
1876 previno
, rec_position
);
1879 (void) fprintf(stderr
,
1880 gettext("File continuation header, ino %d"),
1884 (void) fprintf(stderr
, gettext("End of media header"));
1887 if (predict
!= blksread
- 1)
1888 (void) fprintf(stderr
,
1889 gettext("; predicted %ld blocks, got %ld blocks"),
1890 predict
, blksread
- 1);
1891 (void) fprintf(stderr
, "\n");
1894 if (header
->c_type
!= TS_END
)
1895 for (i
= 0; i
< header
->c_count
; i
++)
1896 if ((i
>= TP_NINDIR
) || (header
->c_addr
[i
] != 0))
1900 prevtype
= header
->c_type
;
1901 previno
= header
->c_inumber
;
1905 * Try to determine which volume a file resides on.
1908 volnumber(ino_t inum
)
1914 for (i
= 1; i
<= dumpinfo
.c_volume
; i
++)
1915 if (inum
< (ino_t
)(unsigned)(dumpinfo
.c_inos
[i
]))
1921 * Find an inode header.
1922 * Note that *header must be stable storage, as curfile will end up with
1926 findinode(struct s_spcl
*header
)
1930 char buf
[TP_BSIZE_MAX
];
1932 curfile
.name
= gettext("<name unknown>");
1933 curfile
.action
= UNKNOWN
;
1937 if (ishead(header
) == FAIL
) {
1939 while (gethead(header
) == FAIL
||
1940 (time_t)(header
->c_date
) != dumpdate
)
1944 if (checktype(header
, TS_ADDR
) == GOOD
) {
1946 * Skip up to the beginning of the next record
1948 for (i
= 0; i
< header
->c_count
; i
++)
1949 if ((i
>= TP_NINDIR
) || (header
->c_addr
[i
]))
1951 (void) gethead(header
);
1954 if (checktype(header
, TS_INODE
) == GOOD
) {
1955 curfile
.dip
= &header
->c_dinode
;
1956 if (curfile
.dip
->di_suid
!= UID_LONG
)
1957 curfile
.dip
->di_uid
= curfile
.dip
->di_suid
;
1958 if (curfile
.dip
->di_sgid
!= GID_LONG
)
1959 curfile
.dip
->di_gid
= curfile
.dip
->di_sgid
;
1960 curfile
.ino
= header
->c_inumber
;
1961 curfile
.ts
= TS_INODE
;
1964 if (checktype(header
, TS_END
) == GOOD
) {
1965 curfile
.ino
= maxino
;
1966 curfile
.ts
= TS_END
;
1969 if (checktype(header
, TS_CLRI
) == GOOD
) {
1970 curfile
.name
= gettext("<file removal list>");
1971 curfile
.ts
= TS_CLRI
;
1974 if (checktype(header
, TS_BITS
) == GOOD
) {
1975 curfile
.name
= gettext("<file dump list>");
1976 curfile
.ts
= TS_BITS
;
1979 while (gethead(header
) == FAIL
)
1983 (void) fprintf(stderr
,
1984 gettext("resync restore, skipped %d blocks\n"),
1989 * return whether or not the buffer contains a header block
1992 ishead(struct s_spcl
*buf
)
1995 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
))
2001 checktype(struct s_spcl
*b
, int t
)
2009 * If autoloading is enabled, attempt to do it. If we succeed,
2015 int result
= 0; /* assume failure */
2021 * Wait for the tape to autoload. Note that the delay
2022 * period doesn't take into account however long it takes
2023 * for the open to fail (measured at 21 seconds for an
2024 * Exabyte 8200 under 2.7 on an Ultra 2).
2027 /* rewind tape and offline drive before loading new tape */
2028 closemt(FORCE_OFFLINE
);
2029 (void) fprintf(stderr
,
2030 gettext("Attempting to autoload next volume\n"));
2031 for (tries
= 0; tries
< autoload_tries
; tries
++) {
2032 if ((fd
= open(magtape
, O_RDONLY
|O_LARGEFILE
,
2038 (void) sleep(autoload_period
);
2041 /* Assume caller will deal with manual change-over */
2042 (void) fprintf(stderr
,
2043 gettext("Autoload timed out\n"));
2045 if ((mt
= open(magtape
, O_RDONLY
|O_LARGEFILE
)) == -1) {
2046 (void) fprintf(stderr
, gettext(
2047 "Autoload could not re-open tape\n"));
2050 (void) fprintf(stderr
, gettext(