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>
21 #include <sys/errno.h>
23 #include <sys/sysmacros.h> /* for expdev */
26 #include <priv_utils.h>
29 #define MAXINO 65535 /* KLUDGE */
33 static size_t fssize
= MAXBSIZE
; /* preferred size of writes to filesystem */
35 static int continuemap
= 0;
38 char *host
; /* used in dumprmt.c */
39 daddr32_t rec_position
;
40 static char *archivefile
; /* used in metamucil.c */
41 static int bct
; /* block # index into tape record buffer */
42 static int numtrec
; /* # of logical blocks in current tape record */
43 static char *tbf
= NULL
;
44 static size_t tbfsize
= 0;
46 static union u_spcl endoftapemark
;
47 static struct s_spcl dumpinfo
;
48 static long blksread
; /* # of logical blocks actually read/touched */
49 static long tapea
; /* current logical block # on tape */
50 static uchar_t tapesread
[MAXTAPES
];
51 static jmp_buf restart
;
52 static int gettingfile
= 0; /* restart has a valid frame */
54 static char *map
, *beginmap
;
56 static char lnkbuf
[MAXPATHLEN
+ 2];
58 static int inodeinfo
; /* Have starting volume information */
59 static int hostinfo
; /* Have dump host information */
61 static int autoload_tape(void);
62 static void setdumpnum(void);
63 static void metacheck(struct s_spcl
*);
64 static void xtrmeta(char *, size_t);
65 static void metaskip(char *, size_t);
66 static void xtrfile(char *, size_t);
67 static void xtrskip(char *, size_t);
68 static void xtrlnkfile(char *, size_t);
69 static void xtrlnkskip(char *, size_t);
70 static void xtrmap(char *, size_t);
71 static void xtrmapskip(char *, size_t);
72 static void readtape(char *);
73 static int checkvol(struct s_spcl
*, int);
74 static void accthdr(struct s_spcl
*);
75 static int ishead(struct s_spcl
*);
76 static int checktype(struct s_spcl
*, int);
77 static void metaset(char *name
);
80 * Set up an input source
83 setinput(char *source
, char *archive
)
87 archivefile
= archive
;
89 ntrec
= ((CARTRIDGETREC
> HIGHDENSITYTREC
) ?
90 (NTREC
> CARTRIDGETREC
? NTREC
: CARTRIDGETREC
) :
91 (NTREC
> HIGHDENSITYTREC
? NTREC
: HIGHDENSITYTREC
));
92 saved_ntrec
= (ntrec
* (tp_bsize
/DEV_BSIZE
));
99 (void) fprintf(stderr
,
100 gettext("Internal consistency check failed.\n"));
104 if (strchr(source
, ':')) {
108 tape
= strchr(host
, ':');
110 if (strlen(tape
) > (sizeof (magtape
) - 1)) {
111 (void) fprintf(stderr
, gettext("Tape name too long\n"));
114 (void) strcpy(magtape
, tape
);
115 if (rmthost(host
, ntrec
) == 0)
118 if (strlen(source
) > (sizeof (magtape
) - 1)) {
119 (void) fprintf(stderr
, gettext("Tape name too long\n"));
122 /* Not remote, no need for privileges */
125 if (strcmp(source
, "-") == 0) {
127 * Since input is coming from a pipe we must establish
128 * our own connection to the terminal.
130 terminal
= fopen("/dev/tty", "r");
131 if (terminal
== NULL
) {
134 gettext("Cannot open(\"/dev/tty\")");
137 terminal
= fopen("/dev/null", "r");
138 if (terminal
== NULL
) {
141 "Cannot open(\"/dev/null\")");
149 (void) fprintf(stderr
, gettext(
150 "Cannot specify an archive file when reading from a pipe\n"));
154 (void) strcpy(magtape
, source
);
159 newtapebuf(size_t size
)
163 nsize
= size
* tp_bsize
;
165 if (nsize
<= tbfsize
)
169 tbf
= (char *)malloc(nsize
);
171 (void) fprintf(stderr
,
172 gettext("Cannot allocate space for buffer\n"));
179 * Verify that the tape drive can be accessed and
180 * that it actually is a dump tape.
189 char *syment
= RESTORESYMTABLE
;
191 vprintf(stdout
, gettext("Verify volume and initialize maps\n"));
193 mt
= open(archivefile
, O_RDONLY
|O_LARGEFILE
);
200 if ((mt
= rmtopen(magtape
, O_RDONLY
)) < 0) {
208 else if ((mt
= open(magtape
, O_RDONLY
|O_LARGEFILE
)) < 0) {
216 if (!pipein
&& !bflag
)
218 findtapeblksize(ARCHIVE_FILE
);
220 findtapeblksize(TAPE_FILE
);
222 tape_rec_size
= saved_ntrec
* DEV_BSIZE
;
226 * Get the first header. If c_magic is NOT NFS_MAGIC or if
227 * the checksum is in error, it will fail. The magic could then
228 * be either OFS_MAGIC or MTB_MAGIC. If OFS_MAGIC, assume we
229 * have an old dump, and try to convert it. If it is MTB_MAGIC, we
230 * procees this after.
232 if ((gethead(&spcl
) == FAIL
) && (spcl
.c_magic
!= MTB_MAGIC
)) {
233 bct
--; /* push back this block */
237 if (gethead(&spcl
) == FAIL
) {
238 (void) fprintf(stderr
,
239 gettext("Volume is not in dump format\n"));
242 (void) fprintf(stderr
,
243 gettext("Converting to new file system format.\n"));
246 * The above gethead will have failed if the magic is
247 * MTB_MAGIC. If that is true, we need to adjust tp_bsize.
248 * We have assumed to this time that tp_bsize was 1024, if
249 * this is a newer dump, get the real tp_bsize from the header,
250 * and recalculate ntrec, numtrec.
252 if (spcl
.c_magic
== MTB_MAGIC
) {
253 tp_bsize
= spcl
.c_tpbsize
;
254 if ((tp_bsize
% TP_BSIZE_MIN
!= 0) ||
255 (tp_bsize
> TP_BSIZE_MAX
)) {
256 (void) fprintf(stderr
,
257 gettext("Volume is not in dump format\n"));
260 ntrec
= (tape_rec_size
/tp_bsize
);
263 bct
--; /* push back this block */
266 /* we have to re-do this in case checksum is wrong */
267 if (gethead(&spcl
) == FAIL
) {
268 (void) fprintf(stderr
,
269 gettext("Volume is not in dump format\n"));
274 byteorder_banner(byteorder
, stdout
);
276 endoftapemark
.s_spcl
.c_magic
= cvtflag
? OFS_MAGIC
:
277 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
);
278 endoftapemark
.s_spcl
.c_type
= TS_END
;
281 * include this since the `resync' loop in findinode
282 * expects to find a header with the c_date field
285 endoftapemark
.s_spcl
.c_date
= spcl
.c_date
;
287 ip
= (int32_t *)&endoftapemark
;
288 /*LINTED [assertion always true]*/
289 assert((sizeof (endoftapemark
) % sizeof (int32_t)) == 0);
290 j
= sizeof (endoftapemark
) / sizeof (int32_t);
296 endoftapemark
.s_spcl
.c_checksum
= CHECKSUM
- i
;
298 if (vflag
&& command
!= 't')
300 dumptime
= spcl
.c_ddate
;
301 dumpdate
= spcl
.c_date
;
302 if (stat(".", &stbuf
) < 0) {
303 perror(gettext("cannot stat ."));
306 if (stbuf
.st_blksize
>= tp_bsize
&& stbuf
.st_blksize
<= MAXBSIZE
) {
307 /* LINTED: value fits in a size_t */
308 fssize
= stbuf
.st_blksize
;
313 if (checkvol(&spcl
, 1) == FAIL
) {
314 (void) fprintf(stderr
,
315 gettext("This is not volume 1 of the dump\n"));
318 if (readhdr(&spcl
) == FAIL
)
319 panic(gettext("no header after volume mark!\n"));
321 findinode(&spcl
); /* sets curfile, resyncs the tape if need be */
322 if (checktype(&spcl
, TS_CLRI
) == FAIL
) {
323 (void) fprintf(stderr
,
324 gettext("Cannot find file removal list\n"));
327 maxino
= (unsigned)((spcl
.c_count
* tp_bsize
* NBBY
) + 1);
328 dprintf(stdout
, "maxino = %lu\n", maxino
);
330 * Allocate space for at least MAXINO inodes to allow us
331 * to restore partial dump tapes written before dump was
332 * fixed to write out the entire inode map.
334 if (maxino
> ULONG_MAX
) {
335 (void) fprintf(stderr
,
336 gettext("file system too large\n"));
339 /* LINTED maxino size-checked above */
340 mapsize
= (size_t)d_howmany(maxino
> MAXINO
? maxino
: MAXINO
, NBBY
);
341 beginmap
= map
= calloc((size_t)1, mapsize
);
342 if (map
== (char *)NIL
) {
343 (void) fprintf(stderr
,
344 gettext("no memory for file removal list\n"));
347 endmap
= map
+ mapsize
;
349 curfile
.action
= USING
;
351 getfile(xtrmap
, xtrmapskip
);
354 if (checktype(&spcl
, TS_BITS
) == FAIL
) {
355 /* if we have TS_CLRI then no TS_BITS then a TS_END */
356 /* then we have an empty dump file */
357 if (gethead(&spcl
) == GOOD
&&
358 checktype(&spcl
, TS_END
) == GOOD
) {
359 if ((command
== 'r') || (command
== 'R')) {
360 initsymtable(syment
);
361 dumpsymtable(syment
, volno
);
365 /* otherwise we have an error */
366 (void) fprintf(stderr
, gettext("Cannot find file dump list\n"));
369 /* LINTED maxino size-checked above */
370 mapsize
= (size_t)d_howmany(maxino
, NBBY
);
371 beginmap
= map
= calloc((size_t)1, mapsize
);
372 if (map
== (char *)NULL
) {
373 (void) fprintf(stderr
,
374 gettext("no memory for file dump list\n"));
377 endmap
= map
+ mapsize
;
379 curfile
.action
= USING
;
381 getfile(xtrmap
, xtrmapskip
);
386 * Initialize fssize variable for 'R' command to work.
393 if (stat(".", &stbuf
) < 0) {
394 perror(gettext("cannot stat ."));
397 if (stbuf
.st_blksize
>= tp_bsize
&& stbuf
.st_blksize
<= MAXBSIZE
) {
398 /* LINTED: value fits in a size_t */
399 fssize
= stbuf
.st_blksize
;
406 * Prompt user to load a new dump volume.
407 * "Nextvol" is the next suggested volume to use.
408 * This suggested volume is enforced when doing full
409 * or incremental restores, but can be overrridden by
410 * the user when only extracting a subset of the files.
412 * first_time is used with archive files and can have 1 of 3 states:
413 * FT_STATE_1 Tape has not been read yet
414 * FT_STATE_2 Tape has been read but not positioned past directory
416 * FT_STATE_3 Tape has been read and is reading file information
426 long savecnt
, savetapea
, wantnext
;
428 union u_spcl tmpspcl
;
429 #define tmpbuf tmpspcl.s_spcl
430 char buf
[TP_BSIZE_MAX
];
431 static int first_time
= FT_STATE_1
;
434 (void) fprintf(stderr
, gettext(
435 "Internal consistency failure in getvol: tbf is NULL\n"));
440 for (i
= 0; i
< MAXTAPES
; i
++)
446 panic(gettext("changing volumes on pipe input\n"));
451 savecnt
= blksread
; /* ignore volume verification tape i/o */
455 done(1); /* pipes do not get a second chance */
456 if (command
== 'R' || command
== 'r' || curfile
.action
!= SKIP
) {
465 if ((volno
== 1) && (nextvol
== 1)) {
466 tapesread
[volno
-1]++;
469 if (autoload_tape()) {
476 while (newvol
<= 0) {
479 for (i
= 0; i
< MAXTAPES
; i
++)
483 (void) fprintf(stderr
, "%s", gettext(
484 "You have not read any volumes yet.\n\
485 Unless you know which volume your file(s) are on you should start\n\
486 with the last volume and work towards the first.\n"));
488 (void) fprintf(stderr
,
489 gettext("You have read volumes"));
490 (void) strcpy(tbf
, ": ");
491 for (i
= 0; i
< MAXTAPES
; i
++)
493 (void) fprintf(stderr
, "%s%ld",
495 (void) strcpy(tbf
, ", ");
497 (void) fprintf(stderr
, "\n");
500 (void) fprintf(stderr
,
501 gettext("Specify next volume #: "));
502 (void) fflush(stderr
);
503 /* LINTED tbfsize is limited to a few MB */
504 (void) fgets(tbf
, (int)tbfsize
, terminal
);
505 } while (!feof(terminal
) && tbf
[0] == '\n');
510 (void) fprintf(stderr
, gettext(
511 "Volume numbers are positive numerics\n"));
513 if (newvol
> MAXTAPES
) {
514 (void) fprintf(stderr
, gettext(
515 "This program can only deal with %d volumes\n"),
520 if (newvol
== volno
) {
521 tapesread
[volno
-1]++;
524 closemt(ALLOW_OFFLINE
);
526 * XXX: if we are switching devices, we should probably try
527 * the device once without prompting to enable unattended
531 (void) fprintf(stderr
, gettext(
532 "Mount volume %d\nthen enter volume name on host %s (default: %s) "),
533 newvol
, host
, magtape
);
535 (void) fprintf(stderr
, gettext(
536 "Mount volume %d\nthen enter volume name (default: %s) "),
538 (void) fflush(stderr
);
539 /* LINTED tbfsize is limited to a few MB */
540 (void) fgets(tbf
, (int)tbfsize
, terminal
);
544 * XXX We don't allow rotating among tape hosts, just drives.
546 if (tbf
[0] != '\n') {
547 (void) strncpy(magtape
, tbf
, sizeof (magtape
));
548 magtape
[sizeof (magtape
) - 1] = '\0';
549 /* LINTED unsigned -> signed conversion ok */
550 i
= (int)strlen(magtape
);
551 if (magtape
[i
- 1] == '\n')
552 magtape
[i
- 1] = '\0';
554 if ((host
!= NULL
&& (mt
= rmtopen(magtape
, O_RDONLY
)) == -1) ||
556 (mt
= open(magtape
, O_RDONLY
|O_LARGEFILE
)) == -1)) {
558 (void) fprintf(stderr
, gettext("Cannot open %s: %s\n"),
559 magtape
, strerror(error
));
567 if (!pipein
&& !bflag
&& archivefile
&& (first_time
== FT_STATE_1
)) {
568 first_time
= FT_STATE_2
;
569 findtapeblksize(TAPE_FILE
);
571 if (readhdr(&tmpbuf
) == FAIL
) {
572 (void) fprintf(stderr
,
573 gettext("volume is not in dump format\n"));
577 if (checkvol(&tmpbuf
, volno
) == FAIL
) {
578 (void) fprintf(stderr
, gettext("Wrong volume (%d)\n"),
584 if (((time_t)(tmpbuf
.c_date
) != dumpdate
) ||
585 ((time_t)(tmpbuf
.c_ddate
) != dumptime
)) {
587 time_t lc_date
= (time_t)tmpbuf
.c_date
;
590 * This is used to save the return value from lctime(),
591 * since that's volatile across lctime() invocations.
593 tmp_ct
= strdup(lctime(&lc_date
));
594 if (tmp_ct
== (char *)0) {
595 (void) fprintf(stderr
, gettext(
596 "Cannot allocate space for time string\n"));
600 (void) fprintf(stderr
,
601 gettext("Wrong dump date\n\tgot: %s\twanted: %s"),
602 tmp_ct
, lctime(&dumpdate
));
607 tapesread
[volno
-1]++;
611 * If continuing from the previous volume, skip over any
612 * blocks read already at the end of the previous volume.
614 * If coming to this volume at random, skip to the beginning
615 * of the next record.
617 if (tmpbuf
.c_type
== TS_TAPE
&& (tmpbuf
.c_flags
& DR_NEWHEADER
)) {
619 if (archivefile
&& first_time
== FT_STATE_2
) {
620 first_time
= FT_STATE_3
;
622 recsread
= tmpbuf
.c_firstrec
;
623 tapea
= tmpbuf
.c_tapea
;
625 "restore skipping %d records\n",
627 for (i
= tmpbuf
.c_count
; i
> 0; i
--)
629 } else if (tmpbuf
.c_firstrec
!= 0) {
633 if (archivefile
&& first_time
== FT_STATE_2
) {
635 * subtract 2, 1 for archive file's TS_END
636 * and 1 for tape's TS_TAPE
638 first_time
= FT_STATE_3
;
639 i
= tapea
- tmpbuf
.c_tapea
- 2;
641 i
= tapea
- tmpbuf
.c_tapea
;
644 dprintf(stdout
, gettext(
645 "restore skipping %d duplicate records\n"),
648 dprintf(stdout
, gettext(
649 "restore duplicate record botch (%d)\n"),
654 tapea
= savetapea
+ 1; /* <= (void) gethead() below */
657 if (curfile
.action
== USING
) {
659 panic(gettext("active file into volume 1\n"));
662 (void) gethead(&spcl
);
663 findinode(&spcl
); /* do we always restart files in full? */
664 if (gettingfile
) { /* i.e. will we lose metadata? */
666 longjmp(restart
, 1); /* will this set f1 & f2? */
671 * handle multiple dumps per tape by skipping forward to the
672 * appropriate one. Note we don't use absolute positioning,
673 * as that may take a very long time.
681 if (dumpnum
== 1 || volno
!= 1)
684 (void) fprintf(stderr
,
685 gettext("Cannot have multiple dumps on pipe input\n"));
689 tcom
.mt_count
= dumpnum
- 1;
691 retval
= rmtioctl(MTFSF
, dumpnum
- 1);
693 retval
= ioctl(mt
, (int)MTIOCTOP
, (char *)&tcom
);
695 perror("ioctl MTFSF");
703 static char *epoch
= NULL
;
706 epoch
= strdup(gettext("the epoch\n"));
708 (void) fprintf(stderr
, gettext("Out of memory\n"));
713 date
= (time_t)dumpinfo
.c_date
;
714 (void) fprintf(stdout
,
715 gettext("Dump date: %s"), lctime(&date
));
717 date
= (time_t)dumpinfo
.c_ddate
;
718 (void) fprintf(stdout
, gettext("Dumped from: %s"),
719 (dumpinfo
.c_ddate
== 0) ? epoch
: lctime(&date
));
721 (void) fprintf(stdout
,
722 gettext("Level %d dump of %s on %.*s:%s\n"),
723 dumpinfo
.c_level
, dumpinfo
.c_filesys
,
724 sizeof (dumpinfo
.c_host
), dumpinfo
.c_host
, dumpinfo
.c_dev
);
725 (void) fprintf(stdout
,
726 gettext("Label: %.*s\n"),
727 sizeof (dumpinfo
.c_label
), dumpinfo
.c_label
);
730 (void) fprintf(stdout
,
731 gettext("Starting inode numbers by volume:\n"));
732 for (i
= 1; i
<= dumpinfo
.c_volume
; i
++)
733 (void) fprintf(stdout
, gettext("\tVolume %d: %6d\n"),
734 i
, dumpinfo
.c_inos
[i
]);
739 extractfile(char *name
)
741 static int complained_chown
= 0;
742 static int complained_lchown
= 0;
743 static int complained_chmod
= 0;
744 static int complained_utime
= 0;
745 static int complained_mknod
= 0;
758 curfile
.action
= USING
;
759 timep
[0] = (time_t)curfile
.dip
->di_atime
;
760 timep
[1] = (time_t)curfile
.dip
->di_mtime
;
761 mode
= curfile
.dip
->di_mode
;
763 uid
= curfile
.dip
->di_suid
== UID_LONG
?
764 curfile
.dip
->di_uid
: (uid_t
)curfile
.dip
->di_suid
;
765 gid
= curfile
.dip
->di_sgid
== GID_LONG
?
766 curfile
.dip
->di_gid
: (gid_t
)curfile
.dip
->di_sgid
;
768 resolve(name
, &dfd
, &rname
);
769 if (dfd
!= AT_FDCWD
) {
770 if (fchdir(dfd
) < 0) {
772 (void) fprintf(stderr
, gettext(
773 "%s: unable to set attribute context: %s\n"),
774 rname
, strerror(saverr
));
781 switch (mode
& IFMT
) {
784 (void) fprintf(stderr
, gettext("%s: unknown file mode 0%lo\n"),
785 rname
, (ulong_t
)(mode
&IFMT
));
791 vprintf(stdout
, gettext("skipped socket %s\n"), rname
);
798 ep
= lookupname(name
);
799 if (ep
== NIL
|| ep
->e_flags
& EXTRACT
) {
801 "directory %s was not restored\n"),
811 vprintf(stdout
, gettext("extract file %s\n"), rname
);
812 result
= genliteraldir(rname
, curfile
.ino
);
818 getfile(xtrlnkfile
, xtrlnkskip
);
820 vprintf(stdout
, gettext(
821 "%s: zero length symbolic link (ignored)\n"),
826 if ((result
= lf_linkit(lnkbuf
, rname
, SYMLINK
)) != GOOD
)
829 /* 1254700: set uid/gid (previously missing) */
830 if (lchown(rname
, uid
, gid
) < 0 && !complained_lchown
) {
834 "Unable to restore ownership of symlink %s: %s\n");
835 (void) fprintf(stderr
, errmsg
,
836 rname
, strerror(saverr
));
837 (void) fprintf(stderr
, gettext(
838 "Additional such failures will be ignored.\n"));
839 complained_lchown
= 1;
848 vprintf(stdout
, gettext("extract special file %s\n"), rname
);
849 /* put device rdev into dev_t expanded format */
850 /* XXX does this always do the right thing? */
851 /* XXX does dump do the right thing? */
852 if (((curfile
.dip
->di_ordev
& 0xFFFF0000) == 0) ||
853 ((curfile
.dip
->di_ordev
& 0xFFFF0000) == 0xFFFF0000)) {
854 full_dev
= expdev((unsigned)(curfile
.dip
->di_ordev
));
856 /* LINTED sign extension ok */
857 full_dev
= (unsigned)(curfile
.dip
->di_ordev
);
860 if (mknod(rname
, mode
, full_dev
) < 0) {
864 if ((stat64(rname
, s
)) ||
865 ((s
->st_mode
& S_IFMT
) != (mode
& S_IFMT
)) ||
866 (s
->st_rdev
!= full_dev
)) {
867 if (saverr
!= EPERM
|| !complained_mknod
) {
868 (void) fprintf(stderr
, "%s: ", rname
);
869 (void) fflush(stderr
);
872 "cannot create special file"));
873 if (saverr
== EPERM
) {
874 (void) fprintf(stderr
, gettext(
875 "Additional such failures will be ignored.\n"));
876 complained_mknod
= 1;
884 if (chown(rname
, uid
, gid
) < 0 && !complained_chown
) {
888 "Unable to restore ownership of %s: %s\n");
889 (void) fprintf(stderr
, errmsg
,
890 rname
, strerror(saverr
));
891 (void) fprintf(stderr
, gettext(
892 "Additional such failures will be ignored.\n"));
893 complained_chown
= 1;
895 if (chmod(rname
, mode
) < 0 && !complained_chmod
) {
898 "Unable to restore permissions on %s: %s\n");
899 (void) fprintf(stderr
, errmsg
,
900 rname
, strerror(saverr
));
901 (void) fprintf(stderr
, gettext(
902 "Additional such failures will be ignored.\n"));
903 complained_chmod
= 1;
906 metaset(rname
); /* skipfile() got the metadata, if any */
907 if (utime(rname
, (struct utimbuf
*)timep
) < 0 &&
911 "Unable to restore times on %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_utime
= 1;
922 vprintf(stdout
, gettext("extract file %s\n"), rname
);
925 * perform a restrictive creat(2) initally, we'll
926 * fchmod(2) according to the archive later after
927 * we've written the blocks.
929 ofile
= creat64(rname
, 0600);
933 errmsg
= gettext("cannot create file");
934 (void) fprintf(stderr
, "%s: ", rname
);
935 (void) fflush(stderr
);
942 if (fchown(ofile
, uid
, gid
) < 0 && !complained_chown
) {
946 "Unable to restore ownership of %s: %s\n");
947 (void) fprintf(stderr
, errmsg
,
948 rname
, strerror(saverr
));
949 (void) fprintf(stderr
, gettext(
950 "Additional such failures will be ignored.\n"));
951 complained_chown
= 1;
954 getfile(xtrfile
, xtrskip
);
958 * the fchmod(2) has to come after getfile() as some POSIX
959 * implementations clear the S_ISUID and S_ISGID bits of the
960 * file after every write(2).
962 if (fchmod(ofile
, mode
) < 0 && !complained_chmod
) {
965 "Unable to restore permissions on %s: %s\n");
966 (void) fprintf(stderr
, errmsg
,
967 rname
, strerror(saverr
));
968 (void) fprintf(stderr
, gettext(
969 "Additional such failures will be ignored.\n"));
970 complained_chmod
= 1;
974 * Some errors don't get reported until we close(2), so
976 * XXX unlink the file if an error is reported?
978 if (close(ofile
) < 0) {
980 errmsg
= gettext("error closing file");
981 (void) fprintf(stderr
, "%s: ", rname
);
982 (void) fflush(stderr
);
988 if (utime(rname
, (struct utimbuf
*)timep
) < 0 &&
992 "Unable to restore times on %s: %s\n");
993 (void) fprintf(stderr
, errmsg
,
994 rname
, strerror(saverr
));
995 (void) fprintf(stderr
, gettext(
996 "Additional such failures will be ignored.\n"));
997 complained_utime
= 1;
1003 if (dfd
!= AT_FDCWD
) {
1011 * skip over bit maps on the tape
1017 while (checktype(&spcl
, TS_CLRI
) == GOOD
||
1018 checktype(&spcl
, TS_BITS
) == GOOD
)
1024 * skip over a file on the tape
1029 curfile
.action
= SKIP
;
1030 getfile(null
, null
);
1033 * Do the file extraction, calling the supplied functions
1037 getfile(void (*f1
)(), void (*f2
)())
1041 offset_t size
= (offset_t
)spcl
.c_dinode
.di_size
;
1042 static char clearedbuf
[MAXBSIZE
];
1043 char buf
[TP_BSIZE_MAX
];
1045 char junk
[TP_BSIZE_MAX
];
1047 assert(MAXBSIZE
>= tp_bsize
);
1049 metaset(NULL
); /* flush old metadata */
1050 if (checktype(&spcl
, TS_END
) == GOOD
) {
1051 panic(gettext("ran off end of volume\n"));
1054 if (ishead(&spcl
) == FAIL
) {
1055 panic(gettext("not at beginning of a file\n"));
1058 metacheck(&spcl
); /* check for metadata in header */
1059 if (!gettingfile
&& setjmp(restart
) != 0) {
1060 gettingfile
= 0; /* paranoia; longjmp'er should do */
1065 if ((spcl
.c_dinode
.di_mode
& IFMT
) == IFSHAD
) {
1069 for (i
= 0, bufptr
= buf
; i
< spcl
.c_count
; i
++) {
1070 if ((i
>= TP_NINDIR
) || (spcl
.c_addr
[i
])) {
1074 if (curblk
== (fssize
/ tp_bsize
)) {
1075 (*f1
)(buf
, size
> tp_bsize
?
1077 /* LINTED size <= tp_bsize */
1078 (curblk
- 1) * tp_bsize
+ (size_t)size
);
1084 (*f1
)(buf
, size
> tp_bsize
?
1085 (size_t)(curblk
* tp_bsize
) :
1086 /* LINTED size <= tp_bsize */
1087 (curblk
- 1) * tp_bsize
+ (size_t)size
);
1091 (*f2
)(clearedbuf
, size
> tp_bsize
?
1092 /* LINTED size <= tp_bsize */
1093 (long)tp_bsize
: (size_t)size
);
1095 if ((size
-= tp_bsize
) <= 0) {
1096 for (i
++; i
< spcl
.c_count
; i
++)
1097 if ((i
>= TP_NINDIR
) || (spcl
.c_addr
[i
]))
1104 * Ok to cast size to size_t here. The above for loop reads
1105 * data into the buffer then writes it to the output file. The
1106 * call to f1 here is to write out the data that's in the
1107 * buffer that has not yet been written to the file.
1108 * This will be less than N-KB of data, since the
1109 * above loop writes to the file in filesystem-
1112 /* LINTED: size fits into a size_t at this point */
1113 (*f1
)(buf
, (curblk
* tp_bsize
) + (size_t)size
);
1118 if ((readhdr(&spcl
) == GOOD
) && (checktype(&spcl
, TS_ADDR
) == GOOD
)) {
1120 size
= (offset_t
)spcl
.c_count
* tp_bsize
;
1122 else if ((size
<= 0) &&
1123 ((spcl
.c_dinode
.di_mode
& IFMT
) == IFSHAD
)) {
1124 /* LINTED unsigned to signed conversion ok */
1125 size
= spcl
.c_dinode
.di_size
;
1132 gettext("Missing address (header) block for %s\n"),
1139 * The next routines are called during file extraction to
1140 * put the data into the right form and place.
1143 xtrfile(char *buf
, size_t size
)
1145 if (write(ofile
, buf
, (size_t)size
) == -1) {
1147 (void) fprintf(stderr
,
1148 gettext("write error extracting inode %d, name %s\n"),
1149 curfile
.ino
, curfile
.name
);
1157 * Even though size is a size_t, it's seeking to a relative
1158 * offset. Thus, the seek could go beyond 2 GB, so lseek64 is needed.
1163 xtrskip(char *buf
, size_t size
)
1165 if (lseek64(ofile
, (offset_t
)size
, 1) == -1) {
1167 (void) fprintf(stderr
,
1168 gettext("seek error extracting inode %d, name %s\n"),
1169 curfile
.ino
, curfile
.name
);
1176 /* these are local to the next five functions */
1177 static char *metadata
= NULL
;
1178 static size_t metasize
= 0;
1181 metacheck(struct s_spcl
*head
)
1183 if (! (head
->c_flags
& DR_HASMETA
))
1185 if ((metadata
= malloc(metasize
= (size_t)sizeof (head
->c_shadow
)))
1187 (void) fprintf(stderr
,
1188 gettext("Cannot malloc for metadata\n"));
1191 bcopy(&(head
->c_shadow
), metadata
, metasize
);
1195 xtrmeta(char *buf
, size_t size
)
1197 if ((metadata
== NULL
) && ((spcl
.c_dinode
.di_mode
& IFMT
) != IFSHAD
))
1199 if ((metadata
= realloc(metadata
, metasize
+ size
)) == NULL
) {
1200 (void) fprintf(stderr
,
1201 gettext("Cannot malloc for metadata\n"));
1204 bcopy(buf
, metadata
+ metasize
, size
);
1210 metaskip(char *buf
, size_t size
)
1212 if (metadata
== NULL
)
1214 if ((metadata
= realloc(metadata
, metasize
+ size
)) == NULL
) {
1215 (void) fprintf(stderr
,
1216 gettext("Cannot malloc for metadata\n"));
1219 bzero(metadata
+ metasize
, size
);
1226 if (metadata
== NULL
)
1229 metaproc(name
, metadata
, metasize
);
1230 (void) free(metadata
);
1245 fsd_acl(name
, aclp
, size
)
1249 static aclent_t
*aclent
= NULL
;
1264 /*LINTED [aclp is malloc'd]*/
1265 diskacl
= (ufs_acl_t
*)aclp
;
1266 /* LINTED: result fits in an int */
1267 j
= size
/ sizeof (*diskacl
);
1268 normacls(byteorder
, diskacl
, j
);
1272 aclent
= realloc(aclent
, n
* (size_t)sizeof (*aclent
));
1273 if (aclent
== NULL
) {
1274 (void) fprintf(stderr
, gettext("Cannot malloc acl list\n"));
1280 aclent
[i
].a_type
= diskacl
[j
].acl_tag
;
1281 aclent
[i
].a_id
= diskacl
[j
].acl_who
;
1282 aclent
[i
].a_perm
= diskacl
[j
].acl_perm
;
1287 set_aclp
= acl_to_aclp(ACLENT_T
, aclent
, n
);
1288 if (set_aclp
== NULL
) {
1289 (void) fprintf(stderr
, gettext("Cannot build acl_t\n"));
1293 if (acl_set(name
, set_aclp
) == -1) {
1294 static int once
= 0;
1297 * Treat some errors from the acl subsystem specially to
1298 * avoid being too noisy:
1300 * ENOSYS - ACLs not supported on this file system
1301 * EPERM - not the owner or not privileged
1303 * The following is also supported for backwards compat.
1304 * since acl(2) used to return the wrong errno:
1306 * EINVAL - not the owner of the object
1308 if (errno
== ENOSYS
|| errno
== EPERM
|| errno
== EINVAL
) {
1313 gettext("setacl failed: %s\n"),
1318 fprintf(stderr
, gettext("setacl on %s failed: %s\n"),
1319 name
, strerror(saverr
));
1325 static struct fsdtypes
{
1330 {FSD_DFACL
, fsd_acl
},
1335 metaproc(char *name
, char *mdata
, size_t msize
)
1337 struct fsdtypes
*fsdtype
;
1342 * for the whole shadow inode, dispatch each piece
1343 * to the appropriate function.
1346 /* LINTED (c - mdata) fits into a size_t */
1347 while ((size_t)(c
- mdata
) < msize
) {
1348 /*LINTED [mdata is malloc'd]*/
1349 fsd
= (ufs_fsd_t
*)c
;
1350 assert((fsd
->fsd_size
% 4) == 0);
1351 /* LINTED: lint thinks pointers are signed */
1352 c
+= FSD_RECSZ(fsd
, fsd
->fsd_size
);
1353 if ((fsd
->fsd_type
== FSD_FREE
) ||
1354 ((unsigned)(fsd
->fsd_size
) <= sizeof (ufs_fsd_t
)) ||
1355 (c
> (mdata
+ msize
)))
1357 for (fsdtype
= fsdtypes
; fsdtype
->type
; fsdtype
++)
1358 if (fsdtype
->type
== fsd
->fsd_type
)
1359 (*fsdtype
->function
)(name
, fsd
->fsd_data
,
1360 (unsigned)(fsd
->fsd_size
) -
1361 sizeof (fsd
->fsd_type
) -
1362 sizeof (fsd
->fsd_size
));
1363 /* ^^^ be sure to change if fsd ever changes ^^^ */
1366 /* reset the state of all the functions */
1367 for (fsdtype
= fsdtypes
; fsdtype
->type
; fsdtype
++)
1368 (*fsdtype
->function
)(NULL
, NULL
, 0);
1372 xtrlnkfile(char *buf
, size_t size
)
1374 /* LINTED: signed/unsigned mix ok */
1376 if (pathlen
> MAXPATHLEN
) {
1377 (void) fprintf(stderr
,
1378 gettext("symbolic link name: %s->%s%s; too long %d\n"),
1379 curfile
.name
, lnkbuf
, buf
, pathlen
);
1383 (void) strcat(lnkbuf
, buf
);
1384 /* add an extra NULL to make this a legal complex string */
1385 lnkbuf
[pathlen
+1] = '\0';
1390 xtrlnkskip(char *buf
, size_t size
)
1392 (void) fprintf(stderr
,
1393 gettext("unallocated block in symbolic link %s\n"),
1399 xtrmap(char *buf
, size_t size
)
1401 if ((map
+size
) > endmap
) {
1402 int64_t mapsize
, increment
;
1405 if (spcl
.c_type
!= TS_ADDR
) {
1406 (void) fprintf(stderr
,
1407 gettext("xtrmap: current record not TS_ADDR\n"));
1410 if ((spcl
.c_count
< 0) || (spcl
.c_count
> TP_NINDIR
)) {
1411 (void) fprintf(stderr
,
1412 gettext("xtrmap: illegal c_count field (%d)\n"),
1417 increment
= d_howmany(
1418 ((spcl
.c_count
* tp_bsize
* NBBY
) + 1), NBBY
);
1419 mapsize
= endmap
- beginmap
+ increment
;
1420 if (mapsize
> UINT_MAX
) {
1421 (void) fprintf(stderr
,
1422 gettext("xtrmap: maximum bitmap size exceeded"));
1426 diff
= map
- beginmap
;
1427 /* LINTED mapsize checked above */
1428 beginmap
= realloc(beginmap
, (size_t)mapsize
);
1429 if (beginmap
== NULL
) {
1430 (void) fprintf(stderr
,
1431 gettext("xtrmap: realloc failed\n"));
1434 map
= beginmap
+ diff
;
1435 endmap
= beginmap
+ mapsize
;
1436 /* LINTED endmap - map cannot exceed 32 bits */
1437 bzero(map
, (size_t)(endmap
- map
));
1438 maxino
= NBBY
* mapsize
+ 1;
1441 bcopy(buf
, map
, size
);
1442 /* LINTED character pointers aren't signed */
1448 xtrmapskip(char *buf
, size_t size
)
1450 (void) fprintf(stderr
, gettext("hole in map\n"));
1456 null(char *buf
, size_t size
)
1461 * Do the tape i/o, dealing with volume changes
1471 int32_t expected_magic
;
1474 (void) fprintf(stderr
, gettext(
1475 "Internal consistency failure in readtape: tbf is NULL\n"));
1478 expected_magic
= ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
);
1481 if (bct
< numtrec
) {
1483 * check for old-dump floppy EOM -- it may appear in
1484 * the middle of a buffer. The Dflag used to be used for
1485 * this, but since it doesn't hurt to always do this we
1486 * got rid of the Dflag.
1488 /*LINTED [tbf = malloc()]*/
1489 sp
= &((union u_spcl
*)&tbf
[bct
*tp_bsize
])->s_spcl
;
1490 if (sp
->c_magic
== expected_magic
&& sp
->c_type
== TS_EOM
&&
1491 (time_t)(sp
->c_date
) == dumpdate
&&
1492 (time_t)(sp
->c_ddate
) == dumptime
) {
1493 for (i
= 0; i
< ntrec
; i
++)
1494 /*LINTED [tbf = malloc()]*/
1496 &tbf
[i
*tp_bsize
])->c_magic
= 0;
1502 bcopy(&tbf
[(bct
++*tp_bsize
)], b
, (size_t)tp_bsize
);
1507 /*LINTED [assertion always true]*/
1508 assert(sizeof (union u_spcl
) == TP_BSIZE_MAX
);
1509 for (i
= 0; i
< ntrec
; i
++)
1510 /*LINTED [tbf = malloc()]*/
1511 ((struct s_spcl
*)&tbf
[i
*sizeof (struct s_spcl
)])->c_magic
= 0;
1513 /* LINTED unsigned/signed assignment ok */
1516 /* LINTED unsigned/signed assignment ok */
1517 cnt
= ntrec
*tp_bsize
;
1521 i
= rmtread(&tbf
[rd
], cnt
);
1523 i
= read(mt
, &tbf
[rd
], cnt
);
1525 * Check for mid-tape short read error.
1526 * If found, return rest of buffer.
1528 if (numtrec
< ntrec
&& i
!= 0) {
1529 /* LINTED unsigned/signed assignment ok */
1534 * Handle partial block read.
1536 if (i
> 0 && i
!= ntrec
*tp_bsize
) {
1544 if (i
% tp_bsize
!= 0)
1546 "partial block read: %d should be %d\n"),
1547 i
, ntrec
* tp_bsize
);
1548 numtrec
= i
/ tp_bsize
;
1551 * it's possible to read only 512 bytes
1552 * from a QIC device...
1558 * Handle read error.
1561 switch (curfile
.action
) {
1563 (void) fprintf(stderr
, gettext(
1564 "Read error while trying to set up volume\n"));
1567 (void) fprintf(stderr
, gettext(
1568 "Read error while trying to resynchronize\n"));
1571 (void) fprintf(stderr
, gettext(
1572 "Read error while restoring %s\n"),
1576 (void) fprintf(stderr
, gettext(
1577 "Read error while skipping over inode %d\n"),
1581 if (!yflag
&& !reply(gettext("continue")))
1583 /* LINTED: unsigned->signed conversion ok */
1584 i
= (int)(ntrec
*tp_bsize
);
1585 bzero(tbf
, (size_t)i
);
1586 if ((host
!= 0 && rmtseek(i
, 1) < 0) ||
1587 (host
== 0 && (lseek64(mt
, (offset_t
)i
, 1) ==
1589 perror(gettext("continuation failed"));
1594 * Handle end of tape. The Dflag used to be used, but since it doesn't
1595 * hurt to always check we got rid if it.
1599 * if the first record in the buffer just read is EOM,
1602 /*LINTED [tbf = malloc()]*/
1603 sp
= &((union u_spcl
*)tbf
)->s_spcl
;
1604 if (i
!= 0 && sp
->c_magic
== expected_magic
&& sp
->c_type
== TS_EOM
&&
1605 (time_t)(sp
->c_date
) == dumpdate
&&
1606 (time_t)(sp
->c_ddate
) == dumptime
) {
1616 readtape(b
); /* XXX tail recursion, not goto top? */
1619 /* XXX if panic returns, should we round rd up? */
1620 /* XXX if we do, then we should zero the intervening space */
1621 if (rd
% tp_bsize
!= 0)
1622 panic(gettext("partial block read: %d should be %d\n"),
1623 rd
, ntrec
* tp_bsize
);
1624 bcopy((char *)&endoftapemark
, &tbf
[rd
], (size_t)tp_bsize
);
1627 bcopy(&tbf
[(bct
++*tp_bsize
)], b
, (size_t)tp_bsize
);
1635 findtapeblksize(int arfile
)
1640 (void) fprintf(stderr
, gettext(
1641 "Internal consistency failure in findtapeblksize: "
1643 assert(tbf
!= NULL
);
1647 for (i
= 0; i
< ntrec
; i
++)
1648 /*LINTED [tbf = malloc()]*/
1649 ((struct s_spcl
*)&tbf
[i
* tp_bsize
])->c_magic
= 0;
1651 if (host
&& arfile
== TAPE_FILE
)
1652 tape_rec_size
= rmtread(tbf
, ntrec
* tp_bsize
);
1654 tape_rec_size
= read(mt
, tbf
, ntrec
* tp_bsize
);
1657 if (tape_rec_size
== (ssize_t
)-1) {
1659 char *errmsg
= gettext("Media read error");
1664 if (tape_rec_size
% tp_bsize
!= 0) {
1665 (void) fprintf(stderr
, gettext(
1666 "Record size (%d) is not a multiple of dump block size (%d)\n"),
1667 tape_rec_size
, tp_bsize
);
1670 ntrec
= (int)tape_rec_size
/ tp_bsize
;
1671 /* LINTED unsigned/signed assignment ok */
1673 vprintf(stdout
, gettext("Media block size is %d\n"), ntrec
*2);
1679 /* LINTED unsigned/signed assignment ok */
1687 * If mode == FORCE_OFFLINE then we're not done but
1688 * we need to change tape. So, rewind and unload current
1689 * tape before loading the new one.
1692 static struct mtop mtop
= { MTOFFL
, 0 };
1696 if (offline
|| mode
== FORCE_OFFLINE
)
1697 (void) fprintf(stderr
, gettext("Rewinding tape\n"));
1699 if (offline
|| mode
== FORCE_OFFLINE
)
1700 (void) rmtioctl(MTOFFL
, 1);
1702 } else if (pipein
) {
1703 char buffy
[MAXBSIZE
];
1705 while (read(mt
, buffy
, sizeof (buffy
)) > 0) {
1707 /*LINTED [assertion always true]*/
1712 * Only way to tell if this is a floppy is to issue an ioctl
1713 * but why waste one - if the eject fails, tough!
1715 if (offline
|| mode
== FORCE_OFFLINE
)
1716 (void) ioctl(mt
, MTIOCTOP
, &mtop
);
1717 (void) ioctl(mt
, FDEJECT
, 0);
1724 checkvol(struct s_spcl
*b
, int t
)
1727 if (b
->c_volume
!= t
)
1733 readhdr(struct s_spcl
*b
)
1736 if (gethead(b
) == FAIL
) {
1737 dprintf(stdout
, gettext("readhdr fails at %ld blocks\n"),
1745 * read the tape into buf, then return whether or
1746 * or not it is a header block.
1749 gethead(struct s_spcl
*buf
)
1753 char dummy
[TP_BSIZE_MIN
];
1764 unsigned short odi_mode
;
1781 readtape((char *)(&u_ospcl
.s_ospcl
));
1782 bzero((char *)buf
, (size_t)TP_BSIZE_MIN
);
1783 buf
->c_type
= u_ospcl
.s_ospcl
.c_type
;
1784 buf
->c_date
= u_ospcl
.s_ospcl
.c_date
;
1785 buf
->c_ddate
= u_ospcl
.s_ospcl
.c_ddate
;
1786 buf
->c_volume
= u_ospcl
.s_ospcl
.c_volume
;
1787 buf
->c_tapea
= u_ospcl
.s_ospcl
.c_tapea
;
1788 buf
->c_inumber
= u_ospcl
.s_ospcl
.c_inumber
;
1789 buf
->c_checksum
= u_ospcl
.s_ospcl
.c_checksum
;
1790 buf
->c_magic
= u_ospcl
.s_ospcl
.c_magic
;
1791 buf
->c_dinode
.di_mode
= u_ospcl
.s_ospcl
.c_dinode
.odi_mode
;
1792 /* LINTED: unsigned/signed combination ok */
1793 buf
->c_dinode
.di_nlink
= u_ospcl
.s_ospcl
.c_dinode
.odi_nlink
;
1794 buf
->c_dinode
.di_size
=
1795 (unsigned)(u_ospcl
.s_ospcl
.c_dinode
.odi_size
);
1796 buf
->c_dinode
.di_uid
= u_ospcl
.s_ospcl
.c_dinode
.odi_uid
;
1797 buf
->c_dinode
.di_gid
= u_ospcl
.s_ospcl
.c_dinode
.odi_gid
;
1798 buf
->c_dinode
.di_suid
= UID_LONG
;
1799 buf
->c_dinode
.di_sgid
= GID_LONG
;
1800 buf
->c_dinode
.di_ordev
= u_ospcl
.s_ospcl
.c_dinode
.odi_rdev
;
1801 buf
->c_dinode
.di_atime
= u_ospcl
.s_ospcl
.c_dinode
.odi_atime
;
1802 buf
->c_dinode
.di_mtime
= u_ospcl
.s_ospcl
.c_dinode
.odi_mtime
;
1803 buf
->c_dinode
.di_ctime
= u_ospcl
.s_ospcl
.c_dinode
.odi_ctime
;
1804 buf
->c_count
= u_ospcl
.s_ospcl
.c_count
;
1805 bcopy(u_ospcl
.s_ospcl
.c_baddr
, buf
->c_addr
,
1806 sizeof (u_ospcl
.s_ospcl
.c_baddr
));
1808 /*CONSTANTCONDITION*/
1809 assert(sizeof (u_ospcl
.s_ospcl
) < sizeof (union u_spcl
));
1811 /* we byte-swap the new spclrec, but checksum the old */
1812 /* (see comments in normspcl()) */
1813 if (normspcl(byteorder
, buf
,
1814 (int *)(&u_ospcl
.s_ospcl
), sizeof (u_ospcl
.s_ospcl
),
1818 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
);
1820 readtape((char *)buf
);
1821 if (normspcl(byteorder
, buf
, (int *)buf
, tp_bsize
,
1822 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
)))
1826 switch (buf
->c_type
) {
1831 * Have to patch up missing information in bit map headers
1834 buf
->c_dinode
.di_size
= (offset_t
)buf
->c_count
* tp_bsize
;
1835 for (i
= 0; i
< buf
->c_count
&& i
< TP_NINDIR
; i
++)
1841 if (dumpinfo
.c_date
== 0) {
1842 dumpinfo
.c_date
= spcl
.c_date
;
1843 dumpinfo
.c_ddate
= spcl
.c_ddate
;
1845 if (!hostinfo
&& spcl
.c_host
[0] != '\0') {
1846 bcopy(spcl
.c_label
, dumpinfo
.c_label
,
1847 sizeof (spcl
.c_label
));
1848 bcopy(spcl
.c_filesys
, dumpinfo
.c_filesys
,
1849 sizeof (spcl
.c_filesys
));
1850 bcopy(spcl
.c_dev
, dumpinfo
.c_dev
,
1851 sizeof (spcl
.c_dev
));
1852 bcopy(spcl
.c_host
, dumpinfo
.c_host
,
1853 sizeof (spcl
.c_host
));
1854 dumpinfo
.c_level
= spcl
.c_level
;
1856 if (c_label
!= NULL
&&
1857 strncmp(c_label
, spcl
.c_label
,
1858 sizeof (spcl
.c_label
))
1860 (void) fprintf(stderr
, gettext(
1861 "Incorrect tape label. Expected `%s', got `%.*s'\n"),
1863 sizeof (spcl
.c_label
), spcl
.c_label
);
1867 if (!inodeinfo
&& (spcl
.c_flags
& DR_INODEINFO
)) {
1868 dumpinfo
.c_volume
= spcl
.c_volume
;
1869 bcopy(spcl
.c_inos
, dumpinfo
.c_inos
,
1870 sizeof (spcl
.c_inos
));
1881 panic(gettext("%s: unknown inode type %d\n"),
1882 "gethead", buf
->c_type
);
1891 * Check that a header is where it belongs and predict the next header
1894 accthdr(struct s_spcl
*header
)
1896 static ino_t previno
= (ino_t
)(unsigned)-1;
1897 static int prevtype
;
1898 static long predict
;
1901 if (header
->c_type
== TS_TAPE
) {
1902 if (header
->c_firstrec
)
1903 (void) fprintf(stderr
,
1904 gettext("Volume header begins with record %d"),
1905 header
->c_firstrec
);
1907 (void) fprintf(stderr
, gettext("Volume header"));
1908 (void) fprintf(stderr
, "\n");
1909 previno
= (ino_t
)(unsigned)-1;
1912 if (previno
== (ino_t
)(unsigned)-1)
1916 (void) fprintf(stderr
, gettext("Dump mask header"));
1919 (void) fprintf(stderr
, gettext("Remove mask header"));
1922 (void) fprintf(stderr
,
1923 gettext("File header, ino %d at record %d"),
1924 previno
, rec_position
);
1927 (void) fprintf(stderr
,
1928 gettext("File continuation header, ino %d"),
1932 (void) fprintf(stderr
, gettext("End of media header"));
1935 if (predict
!= blksread
- 1)
1936 (void) fprintf(stderr
,
1937 gettext("; predicted %ld blocks, got %ld blocks"),
1938 predict
, blksread
- 1);
1939 (void) fprintf(stderr
, "\n");
1942 if (header
->c_type
!= TS_END
)
1943 for (i
= 0; i
< header
->c_count
; i
++)
1944 if ((i
>= TP_NINDIR
) || (header
->c_addr
[i
] != 0))
1948 prevtype
= header
->c_type
;
1949 previno
= header
->c_inumber
;
1953 * Try to determine which volume a file resides on.
1956 volnumber(ino_t inum
)
1962 for (i
= 1; i
<= dumpinfo
.c_volume
; i
++)
1963 if (inum
< (ino_t
)(unsigned)(dumpinfo
.c_inos
[i
]))
1969 * Find an inode header.
1970 * Note that *header must be stable storage, as curfile will end up with
1974 findinode(struct s_spcl
*header
)
1978 char buf
[TP_BSIZE_MAX
];
1980 curfile
.name
= gettext("<name unknown>");
1981 curfile
.action
= UNKNOWN
;
1982 curfile
.dip
= (struct dinode
*)NULL
;
1985 if (ishead(header
) == FAIL
) {
1987 while (gethead(header
) == FAIL
||
1988 (time_t)(header
->c_date
) != dumpdate
)
1992 if (checktype(header
, TS_ADDR
) == GOOD
) {
1994 * Skip up to the beginning of the next record
1996 for (i
= 0; i
< header
->c_count
; i
++)
1997 if ((i
>= TP_NINDIR
) || (header
->c_addr
[i
]))
1999 (void) gethead(header
);
2002 if (checktype(header
, TS_INODE
) == GOOD
) {
2003 curfile
.dip
= &header
->c_dinode
;
2004 if (curfile
.dip
->di_suid
!= UID_LONG
)
2005 curfile
.dip
->di_uid
= curfile
.dip
->di_suid
;
2006 if (curfile
.dip
->di_sgid
!= GID_LONG
)
2007 curfile
.dip
->di_gid
= curfile
.dip
->di_sgid
;
2008 curfile
.ino
= header
->c_inumber
;
2009 curfile
.ts
= TS_INODE
;
2012 if (checktype(header
, TS_END
) == GOOD
) {
2013 curfile
.ino
= maxino
;
2014 curfile
.ts
= TS_END
;
2017 if (checktype(header
, TS_CLRI
) == GOOD
) {
2018 curfile
.name
= gettext("<file removal list>");
2019 curfile
.ts
= TS_CLRI
;
2022 if (checktype(header
, TS_BITS
) == GOOD
) {
2023 curfile
.name
= gettext("<file dump list>");
2024 curfile
.ts
= TS_BITS
;
2027 while (gethead(header
) == FAIL
)
2031 (void) fprintf(stderr
,
2032 gettext("resync restore, skipped %d blocks\n"),
2037 * return whether or not the buffer contains a header block
2040 ishead(struct s_spcl
*buf
)
2043 ((tp_bsize
== TP_BSIZE_MIN
) ? NFS_MAGIC
: MTB_MAGIC
))
2049 checktype(struct s_spcl
*b
, int t
)
2057 * If autoloading is enabled, attempt to do it. If we succeed,
2063 int result
= 0; /* assume failure */
2069 * Wait for the tape to autoload. Note that the delay
2070 * period doesn't take into account however long it takes
2071 * for the open to fail (measured at 21 seconds for an
2072 * Exabyte 8200 under 2.7 on an Ultra 2).
2075 /* rewind tape and offline drive before loading new tape */
2076 closemt(FORCE_OFFLINE
);
2077 (void) fprintf(stderr
,
2078 gettext("Attempting to autoload next volume\n"));
2079 for (tries
= 0; tries
< autoload_tries
; tries
++) {
2081 if (rmtopen(magtape
, O_RDONLY
) >= 0) {
2087 if ((fd
= open(magtape
, O_RDONLY
|O_LARGEFILE
,
2094 (void) sleep(autoload_period
);
2097 /* Assume caller will deal with manual change-over */
2098 (void) fprintf(stderr
,
2099 gettext("Autoload timed out\n"));
2101 if ((host
!= NULL
&&
2102 (mt
= rmtopen(magtape
, O_RDONLY
)) == -1) ||
2104 (mt
= open(magtape
, O_RDONLY
|O_LARGEFILE
)) == -1)) {
2105 (void) fprintf(stderr
, gettext(
2106 "Autoload could not re-open tape\n"));
2109 (void) fprintf(stderr
, gettext(