1 /* $NetBSD: tape.c,v 1.62 2009/02/18 13:13:27 yamt Exp $ */
4 * Copyright (c) 1983, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/cdefs.h>
40 static char sccsid
[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
42 __RCSID("$NetBSD: tape.c,v 1.62 2009/02/18 13:13:27 yamt Exp $");
46 #include <sys/param.h>
48 #include <sys/ioctl.h>
52 #include <ufs/ufs/dinode.h>
53 #include <protocols/dumprestore.h>
72 static u_int32_t fssize
= MAXBSIZE
;
74 static int pipein
= 0;
75 static char magtape
[BUFSIZ
];
79 static union u_spcl endoftapemark
;
80 static int blksread
; /* blocks read since last header */
81 static int tpblksread
= 0; /* TP_BSIZE blocks read */
83 static jmp_buf restart
;
84 static int gettingfile
= 0; /* restart has a valid frame */
86 static const char *host
= NULL
;
90 static char lnkbuf
[MAXPATHLEN
+ 1];
93 int oldinofmt
; /* old inode format conversion required */
94 int Bcvt
; /* Swap Bytes (for CCI or sun) */
96 const struct digest_desc
*ddesc
;
97 const struct digest_desc digest_descs
[] = {
99 (void (*)(void *))MD5Init
,
100 (void (*)(void *, const u_char
*, u_int
))MD5Update
,
101 (char *(*)(void *, void *))MD5End
, },
103 (void (*)(void *))SHA1Init
,
104 (void (*)(void *, const u_char
*, u_int
))SHA1Update
,
105 (char *(*)(void *, void *))SHA1End
, },
107 (void (*)(void *))RMD160Init
,
108 (void (*)(void *, const u_char
*, u_int
))RMD160Update
,
109 (char *(*)(void *, void *))RMD160End
, },
113 static union digest_context
{
116 RMD160_CTX dc_rmd160
;
119 union digest_buffer
{
121 char db_sha1
[40 + 1];
122 char db_rmd160
[40 + 1];
125 #define FLUSHTAPEBUF() blkcnt = ntrec + 1
128 char dummy
[TP_BSIZE
];
139 unsigned short odi_mode
;
155 static void accthdr(struct s_spcl
*);
156 static int checksum(int *);
157 static void findinode(struct s_spcl
*);
158 static void findtapeblksize(void);
159 static void getbitmap(char **);
160 static int gethead(struct s_spcl
*);
161 static void readtape(char *);
162 static void setdumpnum(void);
163 static void terminateinput(void);
164 static void xtrfile(char *, long);
165 static void xtrlnkfile(char *, long);
166 static void xtrlnkskip(char *, long);
167 static void xtrskip(char *, long);
168 static void swap_header(struct s_spcl
*);
169 static void swap_old_header(struct s_ospcl
*);
171 const struct digest_desc
*
172 digest_lookup(const char *name
)
174 const struct digest_desc
*dd
;
176 for (dd
= digest_descs
; dd
->dd_name
!= NULL
; dd
++)
177 if (strcasecmp(dd
->dd_name
, name
) == 0)
184 * Set up an input source
187 setinput(const char *source
)
194 newtapebuf(NTREC
> HIGHDENSITYTREC
? NTREC
: HIGHDENSITYTREC
);
198 if ((cp
= strchr(source
, ':')) != NULL
) {
200 /* Ok, because const strings don't have : */
203 if (rmthost(host
) == 0)
207 if (strcmp(source
, "-") == 0) {
209 * Since input is coming from a pipe we must establish
210 * our own connection to the terminal.
212 terminal
= fopen(_PATH_TTY
, "r");
213 if (terminal
== NULL
) {
214 (void)fprintf(stderr
, "cannot open %s: %s\n",
215 _PATH_TTY
, strerror(errno
));
216 terminal
= fopen(_PATH_DEVNULL
, "r");
217 if (terminal
== NULL
) {
218 (void)fprintf(stderr
, "cannot open %s: %s\n",
219 _PATH_DEVNULL
, strerror(errno
));
225 (void) strcpy(magtape
, source
);
229 newtapebuf(long size
)
231 static int tapebufsize
= -1;
234 if (size
<= tapebufsize
)
238 tapebuf
= malloc(size
* TP_BSIZE
);
239 if (tapebuf
== NULL
) {
240 fprintf(stderr
, "Cannot allocate space for tape buffer\n");
247 * Verify that the tape drive can be accessed and
248 * that it actually is a dump tape.
256 vprintf(stdout
, "Verify tape and initialize maps\n");
259 mt
= rmtopen(magtape
, 0, 0);
265 mt
= open(magtape
, O_RDONLY
, 0);
267 fprintf(stderr
, "%s: %s\n", magtape
, strerror(errno
));
273 if (!pipein
&& !bflag
)
275 if (gethead(&spcl
) == FAIL
) {
276 blkcnt
--; /* push back this block */
280 if (gethead(&spcl
) == FAIL
) {
281 fprintf(stderr
, "Tape is not a dump tape\n");
284 fprintf(stderr
, "Converting to new file system format.\n");
287 endoftapemark
.s_spcl
.c_magic
= cvtflag
? OFS_MAGIC
:
289 endoftapemark
.s_spcl
.c_type
= TS_END
;
290 ip
= (int *)&endoftapemark
;
291 j
= sizeof(union u_spcl
) / sizeof(int);
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 fprintf(stderr
, "cannot stat .: %s\n", strerror(errno
));
306 if (stbuf
.st_blksize
>= TP_BSIZE
&& stbuf
.st_blksize
<= MAXBSIZE
)
307 fssize
= stbuf
.st_blksize
;
308 if (((fssize
- 1) & fssize
) != 0) {
309 fprintf(stderr
, "bad block size %d\n", fssize
);
312 if (spcl
.c_volume
!= 1) {
313 fprintf(stderr
, "Tape is not volume 1 of the dump\n");
316 if (gethead(&spcl
) == FAIL
) {
317 dprintf(stdout
, "header read failed at %d blocks\n", blksread
);
318 panic("no header after volume mark!\n");
321 if (spcl
.c_type
!= TS_CLRI
) {
322 fprintf(stderr
, "Cannot find file removal list\n");
325 getbitmap(&usedinomap
);
328 * If there may be whiteout entries on the tape, pretend that the
329 * whiteout inode exists, so that the whiteout entries can be
333 SETINO(WINO
, dumpmap
);
337 * Prompt user to load a new dump volume.
338 * "Nextvol" is the next suggested volume to use.
339 * This suggested volume is enforced when doing full
340 * or incremental restores, but can be overrridden by
341 * the user when only extracting a subset of the files.
346 int newvol
, savecnt
, wantnext
, i
;
347 union u_spcl tmpspcl
;
348 # define tmpbuf tmpspcl.s_spcl
351 newvol
= savecnt
= wantnext
= 0;
358 panic("Changing volumes on pipe input?\n");
366 exit(1); /* pipes do not get a second chance */
367 if (command
== 'R' || command
== 'r' || curfile
.action
!= SKIP
) {
374 while (newvol
<= 0) {
375 if (tapesread
== 0) {
376 fprintf(stderr
, "%s%s%s%s%s",
377 "You have not read any tapes yet.\n",
378 "Unless you know which volume your",
379 " file(s) are on you should start\n",
380 "with the last volume and work",
381 " towards the first.\n");
383 "(Use 1 for the first volume/tape, etc.)\n");
385 fprintf(stderr
, "You have read volumes");
387 for (i
= 1; i
< 32; i
++)
388 if (tapesread
& (1 << i
)) {
389 fprintf(stderr
, "%s%d", buf
, i
);
392 fprintf(stderr
, "\n");
395 fprintf(stderr
, "Specify next volume #: ");
396 (void) fflush(stderr
);
397 (void) fgets(buf
, BUFSIZ
, terminal
);
398 } while (!feof(terminal
) && buf
[0] == '\n');
404 "Volume numbers are positive numerics\n");
407 if (newvol
== volno
) {
408 tapesread
|= 1 << volno
;
412 fprintf(stderr
, "Mount tape volume %d\n", newvol
);
413 fprintf(stderr
, "Enter ``none'' if there are no more tapes\n");
414 fprintf(stderr
, "otherwise enter tape name (default: %s) ", magtape
);
415 (void) fflush(stderr
);
416 (void) fgets(buf
, BUFSIZ
, terminal
);
419 if (!strcmp(buf
, "none\n")) {
423 if (buf
[0] != '\n') {
424 (void) strcpy(magtape
, buf
);
425 magtape
[strlen(magtape
) - 1] = '\0';
429 mt
= rmtopen(magtape
, 0, 0);
432 mt
= open(magtape
, O_RDONLY
, 0);
435 fprintf(stderr
, "Cannot open %s\n", magtape
);
443 if (gethead(&tmpbuf
) == FAIL
) {
444 dprintf(stdout
, "header read failed at %d blocks\n", blksread
);
445 fprintf(stderr
, "tape is not dump tape\n");
449 if (tmpbuf
.c_volume
!= volno
) {
451 "Volume mismatch: expecting %d, tape header claims it is %d\n",
452 volno
, tmpbuf
.c_volume
);
456 if (tmpbuf
.c_date
!= dumpdate
|| tmpbuf
.c_ddate
!= dumptime
) {
457 time_t ttime
= tmpbuf
.c_date
;
458 fprintf(stderr
, "Wrong dump date\n\tgot: %s",
460 fprintf(stderr
, "\twanted: %s", ctime(&dumpdate
));
464 tapesread
|= 1 << volno
;
467 * If continuing from the previous volume, skip over any
468 * blocks read already at the end of the previous volume.
470 * If coming to this volume at random, skip to the beginning
471 * of the next record.
473 dprintf(stdout
, "read %ld recs, tape starts with %ld\n",
474 (long)tpblksread
, (long)tmpbuf
.c_firstrec
);
475 if (tmpbuf
.c_type
== TS_TAPE
&& (tmpbuf
.c_flags
& DR_NEWHEADER
)) {
477 tpblksread
= tmpbuf
.c_firstrec
;
478 for (i
= tmpbuf
.c_count
; i
> 0; i
--)
480 } else if (tmpbuf
.c_firstrec
> 0 &&
481 tmpbuf
.c_firstrec
< tpblksread
- 1) {
483 * -1 since we've read the volume header
485 i
= tpblksread
- tmpbuf
.c_firstrec
- 1;
486 dprintf(stderr
, "Skipping %d duplicate record%s.\n",
487 i
, i
> 1 ? "s" : "");
492 if (curfile
.action
== USING
) {
494 panic("active file into volume 1\n");
498 * Skip up to the beginning of the next record
500 if (tmpbuf
.c_type
== TS_TAPE
&& (tmpbuf
.c_flags
& DR_NEWHEADER
))
501 for (i
= tmpbuf
.c_count
; i
> 0; i
--)
503 (void) gethead(&spcl
);
512 * Handle unexpected EOF.
518 if (gettingfile
&& curfile
.action
== USING
) {
519 printf("Warning: %s %s\n",
520 "End-of-input encountered while extracting", curfile
.name
);
522 curfile
.name
= "<name unknown>";
523 curfile
.action
= UNKNOWN
;
525 curfile
.ino
= maxino
;
533 * handle multiple dumps per tape by skipping forward to the
541 if (dumpnum
== 1 || volno
!= 1)
544 fprintf(stderr
, "Cannot have multiple dumps on pipe input\n");
548 tcom
.mt_count
= dumpnum
- 1;
551 rmtioctl(MTFSF
, dumpnum
- 1);
554 if (ioctl(mt
, (int)MTIOCTOP
, (char *)&tcom
) < 0)
555 fprintf(stderr
, "ioctl MTFSF: %s\n", strerror(errno
));
564 fprintf(stdout
, "Dump date: %s", ctime(&ttime
));
565 ttime
= spcl
.c_ddate
;
566 fprintf(stdout
, "Dumped from: %s",
567 (spcl
.c_ddate
== 0) ? "the epoch\n" : ctime(&ttime
));
568 fprintf(stderr
, "Level %d dump of %s on %s:%s\n",
569 spcl
.c_level
, spcl
.c_filesys
,
570 *spcl
.c_host
? spcl
.c_host
: "[unknown]", spcl
.c_dev
);
571 fprintf(stderr
, "Label: %s\n", spcl
.c_label
);
575 fprintf(Mtreefile
, "#Dump date: %s", ctime(&ttime
));
576 ttime
= spcl
.c_ddate
;
577 fprintf(Mtreefile
, "#Dumped from: %s",
578 (spcl
.c_ddate
== 0) ? "the epoch\n" : ctime(&ttime
));
579 fprintf(Mtreefile
, "#Level %d dump of %s on %s:%s\n",
580 spcl
.c_level
, spcl
.c_filesys
,
581 *spcl
.c_host
? spcl
.c_host
: "[unknown]", spcl
.c_dev
);
582 fprintf(Mtreefile
, "#Label: %s\n", spcl
.c_label
);
583 fprintf(Mtreefile
, "/set uname=root gname=wheel\n");
584 if (ferror(Mtreefile
))
585 err(1, "error writing to mtree file");
590 extractfile(char *name
)
592 union digest_buffer dbuffer
;
597 struct timeval mtimep
[2], ctimep
[2];
602 curfile
.action
= USING
;
603 mtimep
[0].tv_sec
= curfile
.atime_sec
;
604 mtimep
[0].tv_usec
= curfile
.atime_nsec
/ 1000;
605 mtimep
[1].tv_sec
= curfile
.mtime_sec
;
606 mtimep
[1].tv_usec
= curfile
.mtime_nsec
/ 1000;
608 setbirth
= curfile
.birthtime_sec
!= 0;
611 ctimep
[0].tv_sec
= curfile
.atime_sec
;
612 ctimep
[0].tv_usec
= curfile
.atime_nsec
/ 1000;
613 ctimep
[1].tv_sec
= curfile
.birthtime_sec
;
614 ctimep
[1].tv_usec
= curfile
.birthtime_nsec
/ 1000;
619 flags
= curfile
.file_flags
;
620 switch (mode
& IFMT
) {
623 fprintf(stderr
, "%s: unknown file mode 0%o\n", name
, mode
);
628 vprintf(stdout
, "skipped socket %s\n", name
);
634 ep
= lookupname(name
);
635 if (ep
== NULL
|| ep
->e_flags
& EXTRACT
)
636 panic("unextracted directory %s\n", name
);
640 vprintf(stdout
, "extract file %s\n", name
);
641 return (genliteraldir(name
, curfile
.ino
));
646 getfile(xtrlnkfile
, xtrlnkskip
);
649 "%s: zero length symbolic link (ignored)\n", name
);
654 if (linkit(lnkbuf
, name
, SYMLINK
) == GOOD
) {
656 (void) lutimes(name
, ctimep
);
657 (void) lutimes(name
, mtimep
);
658 (void) lchown(name
, uid
, gid
);
659 (void) lchmod(name
, mode
);
661 writemtree(name
, "link",
662 uid
, gid
, mode
, flags
);
664 (void) lchflags(name
, flags
);
671 vprintf(stdout
, "extract special file %s\n", name
);
678 if (mknod(name
, (mode
& (IFCHR
| IFBLK
)) | 0600,
679 (int)curfile
.rdev
) < 0) {
680 fprintf(stderr
, "%s: cannot create special file: %s\n",
681 name
, strerror(errno
));
687 (void) utimes(name
, ctimep
);
688 (void) utimes(name
, mtimep
);
689 (void) chown(name
, uid
, gid
);
690 (void) chmod(name
, mode
);
693 ((mode
& (S_IFBLK
| IFCHR
)) == IFBLK
) ?
695 uid
, gid
, mode
, flags
);
697 (void) chflags(name
, flags
);
701 vprintf(stdout
, "extract fifo %s\n", name
);
708 if (mkfifo(name
, 0600) < 0) {
709 fprintf(stderr
, "%s: cannot create fifo: %s\n",
710 name
, strerror(errno
));
716 (void) utimes(name
, ctimep
);
717 (void) utimes(name
, mtimep
);
718 (void) chown(name
, uid
, gid
);
719 (void) chmod(name
, mode
);
721 writemtree(name
, "fifo",
722 uid
, gid
, mode
, flags
);
724 (void) chflags(name
, flags
);
728 vprintf(stdout
, "extract file %s\n", name
);
731 if (!Nflag
&& (ofile
= open(name
, O_WRONLY
| O_CREAT
| O_TRUNC
,
733 fprintf(stderr
, "%s: cannot create file: %s\n",
734 name
, strerror(errno
));
739 (*ddesc
->dd_init
)(&dcontext
);
740 getfile(xtrfile
, xtrskip
);
742 (*ddesc
->dd_end
)(&dcontext
, &dbuffer
);
743 for (ep
= lookupname(name
); ep
!= NULL
;
745 fprintf(stdout
, "%s (%s) = %s\n",
746 ddesc
->dd_name
, myname(ep
),
752 (void) futimes(ofile
, ctimep
);
753 (void) futimes(ofile
, mtimep
);
754 (void) fchown(ofile
, uid
, gid
);
755 (void) fchmod(ofile
, mode
);
757 writemtree(name
, "file",
758 uid
, gid
, mode
, flags
);
760 (void) fchflags(ofile
, flags
);
768 * skip over bit maps on the tape
774 while (spcl
.c_type
== TS_BITS
|| spcl
.c_type
== TS_CLRI
)
779 * skip over a file on the tape
785 curfile
.action
= SKIP
;
786 getfile(xtrnull
, xtrnull
);
790 * Extract a bitmap from the tape.
791 * The first bitmap sets maxino;
792 * other bitmaps must be of same size.
795 getbitmap(char **map
)
798 size_t volatile size
= spcl
.c_size
;
799 size_t volatile mapsize
= size
;
802 curfile
.action
= USING
;
803 if (spcl
.c_type
== TS_END
)
804 panic("ran off end of tape\n");
805 if (spcl
.c_magic
!= FS_UFS2_MAGIC
)
806 panic("not at beginning of a file\n");
807 if (!gettingfile
&& setjmp(restart
) != 0)
810 mapptr
= *map
= malloc(size
);
813 panic("no memory for %s\n", curfile
.name
);
814 for (i
= 0; i
< spcl
.c_count
&& size
>= TP_BSIZE
; i
++) {
819 if (size
!= 0 || i
!= spcl
.c_count
)
820 panic("%s: inconsistent map size\n", curfile
.name
);
821 if (gethead(&spcl
) == GOOD
&& spcl
.c_type
== TS_ADDR
) {
822 size
= spcl
.c_count
* TP_BSIZE
;
823 *map
= realloc(*map
, mapsize
+ size
);
824 mapptr
= *map
+ mapsize
;
829 maxino
= mapsize
* NBBY
+ 1;
830 else if (maxino
!= mapsize
* NBBY
+ 1)
831 panic("%s: map size changed\n", curfile
.name
);
837 * Extract a file from the tape.
838 * When an allocated block is found it is passed to the fill function;
839 * when an unallocated block (hole) is found, a zeroed buffer is passed
840 * to the skip function.
843 getfile(void (*fill
)(char *buf
, long size
),
844 void (*skip
)(char *buf
, long size
))
848 quad_t
volatile size
;
849 static char clearedbuf
[MAXBSIZE
];
850 char buf
[MAXBSIZE
/ TP_BSIZE
][TP_BSIZE
];
856 if (spcl
.c_type
== TS_END
)
857 panic("ran off end of tape\n");
858 if (spcl
.c_magic
!= FS_UFS2_MAGIC
)
859 panic("not at beginning of a file\n");
860 if (!gettingfile
&& setjmp(restart
) != 0)
864 for (i
= 0; i
< spcl
.c_count
; i
++) {
865 if (spcl
.c_addr
[i
]) {
866 readtape(&buf
[curblk
++][0]);
867 if ((uint32_t)curblk
== fssize
/ TP_BSIZE
) {
868 (*fill
)((char *)buf
, (long)(size
> TP_BSIZE
?
869 fssize
: (curblk
- 1) * TP_BSIZE
+ size
));
874 (*fill
)((char *)buf
, (long)(size
> TP_BSIZE
?
876 (curblk
- 1) * TP_BSIZE
+ size
));
879 (*skip
)(clearedbuf
, (long)(size
> TP_BSIZE
?
882 if ((size
-= TP_BSIZE
) <= 0) {
883 for (i
++; i
< spcl
.c_count
; i
++)
889 if (gethead(&spcl
) == GOOD
&& size
> 0) {
890 if (spcl
.c_type
== TS_ADDR
)
893 "Missing address (header) block for %s at %d blocks\n",
894 curfile
.name
, blksread
);
897 (*fill
)((char *)buf
, (long)((curblk
* TP_BSIZE
) + size
));
898 /* Skip over Linux extended attributes. */
899 if (spcl
.c_type
== TS_INODE
&& (spcl
.c_flags
& DR_EXTATTRIBUTES
)) {
900 for (i
= 0; i
< spcl
.c_count
; i
++)
902 (void)gethead(&spcl
);
909 * Write out the next block of a file.
912 xtrfile(char *buf
, long size
)
916 (*ddesc
->dd_update
)(&dcontext
, buf
, size
);
919 if (write(ofile
, buf
, (int) size
) == -1) {
921 "write error extracting inode %llu, name %s\nwrite: %s\n",
922 (unsigned long long)curfile
.ino
, curfile
.name
,
929 * Skip over a hole in a file.
933 xtrskip(char *buf
, long size
)
937 (*ddesc
->dd_update
)(&dcontext
, buf
, size
);
940 if (lseek(ofile
, size
, SEEK_CUR
) == -1) {
942 "seek error extracting inode %llu, name %s\nlseek: %s\n",
943 (unsigned long long)curfile
.ino
, curfile
.name
,
950 * Collect the next block of a symbolic link.
953 xtrlnkfile(char *buf
, long size
)
957 if (pathlen
> MAXPATHLEN
) {
958 fprintf(stderr
, "symbolic link name: %s->%s%s; too long %d\n",
959 curfile
.name
, lnkbuf
, buf
, pathlen
);
962 (void) strcat(lnkbuf
, buf
);
966 * Skip over a hole in a symbolic link (should never happen).
970 xtrlnkskip(char *buf __unused
, long size __unused
)
973 fprintf(stderr
, "unallocated block in symbolic link %s\n",
979 * Noop, when an extraction function is not needed.
983 xtrnull(char *buf __unused
, long size __unused
)
990 * Read TP_BSIZE blocks from the input.
991 * Handle read errors, and end of media.
997 int cnt
, seek_failed
;
999 if (blkcnt
< numtrec
) {
1000 memmove(buf
, &tapebuf
[(blkcnt
++ * TP_BSIZE
)], (long)TP_BSIZE
);
1005 for (i
= 0; i
< ntrec
; i
++)
1006 ((struct s_spcl
*)&tapebuf
[i
* TP_BSIZE
])->c_magic
= 0;
1009 cnt
= ntrec
* TP_BSIZE
;
1014 i
= rmtread(&tapebuf
[rd
], cnt
);
1017 i
= read(mt
, &tapebuf
[rd
], cnt
);
1019 * Check for mid-tape short read error.
1020 * If found, skip rest of buffer and start with the next.
1022 if (!pipein
&& numtrec
< ntrec
&& i
> 0) {
1023 dprintf(stdout
, "mid-media short read error.\n");
1027 * Handle partial block read.
1029 if (pipein
&& i
== 0 && rd
> 0)
1031 else if (i
> 0 && i
!= ntrec
* TP_BSIZE
) {
1040 * Short read. Process the blocks read.
1042 if (i
% TP_BSIZE
!= 0)
1044 "partial block read: %d should be %d\n",
1045 i
, ntrec
* TP_BSIZE
);
1046 numtrec
= i
/ TP_BSIZE
;
1050 * Handle read error.
1053 fprintf(stderr
, "Tape read error while ");
1054 switch (curfile
.action
) {
1056 fprintf(stderr
, "trying to set up tape\n");
1059 fprintf(stderr
, "trying to resynchronize\n");
1062 fprintf(stderr
, "restoring %s\n", curfile
.name
);
1065 fprintf(stderr
, "skipping over inode %llu\n",
1066 (unsigned long long)curfile
.ino
);
1069 if (!yflag
&& !reply("continue"))
1071 i
= ntrec
* TP_BSIZE
;
1072 memset(tapebuf
, 0, i
);
1075 seek_failed
= (rmtseek(i
, 1) < 0);
1078 seek_failed
= (lseek(mt
, i
, SEEK_CUR
) == (off_t
)-1);
1082 "continuation failed: %s\n", strerror(errno
));
1087 * Handle end of tape.
1090 vprintf(stdout
, "End-of-tape encountered\n");
1099 if (rd
% TP_BSIZE
!= 0)
1100 panic("partial block read: %d should be %d\n",
1101 rd
, ntrec
* TP_BSIZE
);
1103 memmove(&tapebuf
[rd
], &endoftapemark
, (long)TP_BSIZE
);
1106 memmove(buf
, &tapebuf
[(blkcnt
++ * TP_BSIZE
)], (long)TP_BSIZE
);
1112 findtapeblksize(void)
1116 for (i
= 0; i
< ntrec
; i
++)
1117 ((struct s_spcl
*)&tapebuf
[i
* TP_BSIZE
])->c_magic
= 0;
1121 i
= rmtread(tapebuf
, ntrec
* TP_BSIZE
);
1124 i
= read(mt
, tapebuf
, ntrec
* TP_BSIZE
);
1127 fprintf(stderr
, "tape read error: %s\n", strerror(errno
));
1130 if (i
% TP_BSIZE
!= 0) {
1131 fprintf(stderr
, "Tape block size (%ld) %s (%ld)\n",
1132 (long)i
, "is not a multiple of dump block size",
1136 ntrec
= i
/ TP_BSIZE
;
1138 vprintf(stdout
, "Tape block size is %d\n", ntrec
);
1156 * Read the next block from the tape.
1157 * Check to see if it is one of several vintage headers.
1158 * If it is an old style header, convert it to a new style header.
1159 * If it is not any valid header, return an error.
1162 gethead(struct s_spcl
*buf
)
1164 union u_ospcl u_ospcl
;
1167 readtape((char *)buf
);
1168 if (buf
->c_magic
!= NFS_MAGIC
&&
1169 buf
->c_magic
!= FS_UFS2_MAGIC
) {
1170 if (bswap32(buf
->c_magic
) != NFS_MAGIC
&&
1171 bswap32(buf
->c_magic
) != FS_UFS2_MAGIC
)
1174 vprintf(stdout
, "Note: Doing Byte swapping\n");
1178 if (checksum((int *)buf
) == FAIL
)
1185 readtape((char *)(&u_ospcl
.s_ospcl
));
1186 if (checksum((int *)(&u_ospcl
.s_ospcl
)) == FAIL
)
1188 if (u_ospcl
.s_ospcl
.c_magic
!= OFS_MAGIC
) {
1189 if (bswap32(u_ospcl
.s_ospcl
.c_magic
) != OFS_MAGIC
)
1192 vprintf(stdout
, "Note: Doing Byte swapping\n");
1195 swap_old_header(&u_ospcl
.s_ospcl
);
1198 memset(buf
, 0, TP_BSIZE
);
1199 buf
->c_type
= u_ospcl
.s_ospcl
.c_type
;
1200 buf
->c_date
= u_ospcl
.s_ospcl
.c_date
;
1201 buf
->c_ddate
= u_ospcl
.s_ospcl
.c_ddate
;
1202 buf
->c_volume
= u_ospcl
.s_ospcl
.c_volume
;
1203 buf
->c_tapea
= u_ospcl
.s_ospcl
.c_tapea
;
1204 buf
->c_inumber
= u_ospcl
.s_ospcl
.c_inumber
;
1205 buf
->c_checksum
= u_ospcl
.s_ospcl
.c_checksum
;
1206 buf
->c_mode
= u_ospcl
.s_ospcl
.c_odinode
.odi_mode
;
1207 buf
->c_uid
= u_ospcl
.s_ospcl
.c_odinode
.odi_uid
;
1208 buf
->c_gid
= u_ospcl
.s_ospcl
.c_odinode
.odi_gid
;
1209 buf
->c_size
= u_ospcl
.s_ospcl
.c_odinode
.odi_size
;
1210 buf
->c_rdev
= u_ospcl
.s_ospcl
.c_odinode
.odi_rdev
;
1211 buf
->c_atime
= u_ospcl
.s_ospcl
.c_odinode
.odi_atime
;
1212 buf
->c_mtime
= u_ospcl
.s_ospcl
.c_odinode
.odi_mtime
;
1213 buf
->c_count
= u_ospcl
.s_ospcl
.c_count
;
1214 memmove(buf
->c_addr
, u_ospcl
.s_ospcl
.c_addr
, (long)256);
1215 buf
->c_magic
= FS_UFS2_MAGIC
;
1217 switch (buf
->c_type
) {
1222 * Have to patch up missing information in bit map headers
1225 buf
->c_size
= buf
->c_count
* TP_BSIZE
;
1229 if ((buf
->c_flags
& DR_NEWINODEFMT
) == 0)
1237 if (buf
->c_magic
== NFS_MAGIC
) {
1238 buf
->c_tapea
= buf
->c_old_tapea
;
1239 buf
->c_firstrec
= buf
->c_old_firstrec
;
1240 buf
->c_date
= buf
->c_old_date
;
1241 buf
->c_ddate
= buf
->c_old_ddate
;
1242 buf
->c_atime
= buf
->c_old_atime
;
1243 buf
->c_mtime
= buf
->c_old_mtime
;
1244 buf
->c_birthtime
= 0;
1245 buf
->c_birthtimensec
= 0;
1246 buf
->c_atimensec
= buf
->c_mtimensec
= 0;
1253 panic("gethead: unknown inode type %d\n", buf
->c_type
);
1257 buf
->c_magic
= FS_UFS2_MAGIC
;
1260 * If we are restoring a filesystem with old format inodes,
1261 * copy the uid/gid to the new location.
1264 buf
->c_uid
= buf
->c_spare1
[1];
1265 buf
->c_gid
= buf
->c_spare1
[2];
1273 * Check that a header is where it belongs and predict the next header
1276 accthdr(struct s_spcl
*header
)
1278 static ino_t previno
= 0x7fffffff;
1279 static int prevtype
;
1280 static long predict
;
1283 if (header
->c_type
== TS_TAPE
) {
1284 fprintf(stderr
, "Volume header (%s inode format) ",
1285 oldinofmt
? "old" : "new");
1286 if (header
->c_firstrec
)
1287 fprintf(stderr
, "begins with record %lld",
1288 (long long)header
->c_firstrec
);
1289 fprintf(stderr
, "\n");
1290 previno
= 0x7fffffff;
1293 if (previno
== 0x7fffffff)
1297 fprintf(stderr
, "Dumped inodes map header");
1300 fprintf(stderr
, "Used inodes map header");
1303 fprintf(stderr
, "File header, ino %llu",
1304 (unsigned long long)previno
);
1307 fprintf(stderr
, "File continuation header, ino %llu",
1308 (unsigned long long)previno
);
1311 fprintf(stderr
, "End of tape header");
1314 if (predict
!= blksread
- 1)
1315 fprintf(stderr
, "; predicted %ld blocks, got %ld blocks",
1316 (long)predict
, (long)(blksread
- 1));
1317 fprintf(stderr
, "\n");
1320 switch (header
->c_type
) {
1325 blks
= header
->c_count
;
1328 for (i
= 0; i
< header
->c_count
; i
++)
1329 if (header
->c_addr
[i
] != 0)
1335 prevtype
= header
->c_type
;
1336 previno
= header
->c_inumber
;
1340 * Find an inode header.
1341 * Complain if had to skip, and complain is set.
1344 findinode(struct s_spcl
*header
)
1346 static long skipcnt
= 0;
1350 curfile
.name
= "<name unknown>";
1351 curfile
.action
= UNKNOWN
;
1356 if (header
->c_magic
!= FS_UFS2_MAGIC
) {
1358 while (gethead(header
) == FAIL
||
1359 header
->c_date
!= dumpdate
)
1362 switch (header
->c_type
) {
1366 * Skip up to the beginning of the next record
1368 for (i
= 0; i
< header
->c_count
; i
++)
1369 if (header
->c_addr
[i
])
1371 while (gethead(header
) == FAIL
||
1372 header
->c_date
!= dumpdate
)
1374 /* We've read a header; don't drop it. */
1378 curfile
.mode
= header
->c_mode
;
1379 curfile
.uid
= header
->c_uid
;
1380 curfile
.gid
= header
->c_gid
;
1381 curfile
.file_flags
= header
->c_file_flags
;
1382 curfile
.rdev
= header
->c_rdev
;
1383 curfile
.atime_sec
= header
->c_atime
;
1384 curfile
.atime_nsec
= header
->c_atimensec
;
1385 curfile
.mtime_sec
= header
->c_mtime
;
1386 curfile
.mtime_nsec
= header
->c_mtimensec
;
1387 curfile
.birthtime_sec
= header
->c_birthtime
;
1388 curfile
.birthtime_nsec
= header
->c_birthtimensec
;
1389 curfile
.size
= header
->c_size
;
1390 curfile
.ino
= header
->c_inumber
;
1394 curfile
.ino
= maxino
;
1398 curfile
.name
= "<file removal list>";
1402 curfile
.name
= "<file dump list>";
1406 panic("unexpected tape header\n");
1410 panic("unknown tape header type %d\n", spcl
.c_type
);
1414 } while (header
->c_type
== TS_ADDR
);
1416 fprintf(stderr
, "resync restore, skipped %ld blocks\n",
1426 j
= sizeof(union u_spcl
) / sizeof(int);
1434 i
+= bswap32(*buf
++);
1438 if (i
!= CHECKSUM
) {
1439 fprintf(stderr
, "Checksum error %o, inode %llu file %s\n", i
,
1440 (unsigned long long)curfile
.ino
, curfile
.name
);
1450 msg(const char *fmt
, ...)
1455 (void)vfprintf(stderr
, fmt
, ap
);
1458 #endif /* RRESTORE */
1461 swap_header(struct s_spcl
*s
)
1463 s
->c_type
= bswap32(s
->c_type
);
1464 s
->c_old_date
= bswap32(s
->c_old_date
);
1465 s
->c_old_ddate
= bswap32(s
->c_old_ddate
);
1466 s
->c_volume
= bswap32(s
->c_volume
);
1467 s
->c_old_tapea
= bswap32(s
->c_old_tapea
);
1468 s
->c_inumber
= bswap32(s
->c_inumber
);
1469 s
->c_magic
= bswap32(s
->c_magic
);
1470 s
->c_checksum
= bswap32(s
->c_checksum
);
1472 s
->c_mode
= bswap16(s
->c_mode
);
1473 s
->c_size
= bswap64(s
->c_size
);
1474 s
->c_old_atime
= bswap32(s
->c_old_atime
);
1475 s
->c_atimensec
= bswap32(s
->c_atimensec
);
1476 s
->c_old_mtime
= bswap32(s
->c_old_mtime
);
1477 s
->c_mtimensec
= bswap32(s
->c_mtimensec
);
1478 s
->c_rdev
= bswap32(s
->c_rdev
);
1479 s
->c_birthtimensec
= bswap32(s
->c_birthtimensec
);
1480 s
->c_birthtime
= bswap64(s
->c_birthtime
);
1481 s
->c_atime
= bswap64(s
->c_atime
);
1482 s
->c_mtime
= bswap64(s
->c_mtime
);
1483 s
->c_file_flags
= bswap32(s
->c_file_flags
);
1484 s
->c_uid
= bswap32(s
->c_uid
);
1485 s
->c_gid
= bswap32(s
->c_gid
);
1487 s
->c_count
= bswap32(s
->c_count
);
1488 s
->c_level
= bswap32(s
->c_level
);
1489 s
->c_flags
= bswap32(s
->c_flags
);
1490 s
->c_old_firstrec
= bswap32(s
->c_old_firstrec
);
1492 s
->c_date
= bswap64(s
->c_date
);
1493 s
->c_ddate
= bswap64(s
->c_ddate
);
1494 s
->c_tapea
= bswap64(s
->c_tapea
);
1495 s
->c_firstrec
= bswap64(s
->c_firstrec
);
1498 * These are ouid and ogid.
1500 s
->c_spare1
[1] = bswap16(s
->c_spare1
[1]);
1501 s
->c_spare1
[2] = bswap16(s
->c_spare1
[2]);
1505 swap_old_header(struct s_ospcl
*os
)
1507 os
->c_type
= bswap32(os
->c_type
);
1508 os
->c_date
= bswap32(os
->c_date
);
1509 os
->c_ddate
= bswap32(os
->c_ddate
);
1510 os
->c_volume
= bswap32(os
->c_volume
);
1511 os
->c_tapea
= bswap32(os
->c_tapea
);
1512 os
->c_inumber
= bswap16(os
->c_inumber
);
1513 os
->c_magic
= bswap32(os
->c_magic
);
1514 os
->c_checksum
= bswap32(os
->c_checksum
);
1516 os
->c_odinode
.odi_mode
= bswap16(os
->c_odinode
.odi_mode
);
1517 os
->c_odinode
.odi_nlink
= bswap16(os
->c_odinode
.odi_nlink
);
1518 os
->c_odinode
.odi_uid
= bswap16(os
->c_odinode
.odi_uid
);
1519 os
->c_odinode
.odi_gid
= bswap16(os
->c_odinode
.odi_gid
);
1521 os
->c_odinode
.odi_size
= bswap32(os
->c_odinode
.odi_size
);
1522 os
->c_odinode
.odi_rdev
= bswap32(os
->c_odinode
.odi_rdev
);
1523 os
->c_odinode
.odi_atime
= bswap32(os
->c_odinode
.odi_atime
);
1524 os
->c_odinode
.odi_mtime
= bswap32(os
->c_odinode
.odi_mtime
);
1525 os
->c_odinode
.odi_ctime
= bswap32(os
->c_odinode
.odi_ctime
);
1527 os
->c_count
= bswap32(os
->c_count
);