2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
39 static const char rcsid[] =
43 #include <sys/param.h>
49 #include <ufs/ufs/dinode.h>
50 #include <protocols/dumprestore.h>
65 static long fssize = MAXBSIZE;
67 static int pipein = 0;
68 static int pipecmdin = 0;
69 static FILE *popenfp = NULL;
74 static union u_spcl endoftapemark;
75 static long blksread; /* blocks read since last header */
76 static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */
77 static long tapesread;
78 static jmp_buf restart;
79 static int gettingfile = 0; /* restart has a valid frame */
80 static char *host = NULL;
81 static int readmapflag;
85 static char lnkbuf[MAXPATHLEN + 1];
88 int Bcvt; /* Swap Bytes */
90 #define FLUSHTAPEBUF() blkcnt = ntrec + 1
92 static void accthdr(struct s_spcl *);
93 static int checksum(int *);
94 static void findinode(struct s_spcl *);
95 static void findtapeblksize(void);
96 static int gethead(struct s_spcl *);
97 static void readtape(char *);
98 static void setdumpnum(void);
99 static u_long swabl(u_long);
100 static u_char *swablong(u_char *, int);
101 static u_char *swabshort(u_char *, int);
102 static void terminateinput(void);
103 static void xtrfile(char *, long);
104 static void xtrlnkfile(char *, long);
105 static void xtrlnkskip(char *, long);
106 static void xtrmap(char *, long);
107 static void xtrmapskip(char *, long);
108 static void xtrskip(char *, long);
111 * Set up an input source
114 setinput(char *source, int ispipecommand)
120 newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC);
127 if (strchr(source, ':')) {
129 source = strchr(host, ':');
131 if (rmthost(host) == 0)
135 if (strcmp(source, "-") == 0) {
137 * Since input is coming from a pipe we must establish
138 * our own connection to the terminal.
140 terminal = fopen(_PATH_TTY, "r");
141 if (terminal == NULL) {
142 (void)fprintf(stderr, "cannot open %s: %s\n",
143 _PATH_TTY, strerror(errno));
144 terminal = fopen(_PATH_DEVNULL, "r");
145 if (terminal == NULL) {
146 (void)fprintf(stderr, "cannot open %s: %s\n",
147 _PATH_DEVNULL, strerror(errno));
153 setuid(getuid()); /* no longer need or want root privileges */
154 magtape = strdup(source);
155 if (magtape == NULL) {
156 fprintf(stderr, "Cannot allocate space for magtape buffer\n");
162 newtapebuf(long size)
164 static int tapebufsize = -1;
167 if (size <= tapebufsize)
171 tapebuf = malloc(size * TP_BSIZE);
172 if (tapebuf == NULL) {
173 fprintf(stderr, "Cannot allocate space for tape buffer\n");
180 * Verify that the tape drive can be accessed and
181 * that it actually is a dump tape.
189 vprintf(stdout, "Verify tape and initialize maps\n");
191 if (setenv("RESTORE_VOLUME", "1", 1) == -1) {
192 fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
196 popenfp = popen(magtape, "r");
197 mt = popenfp ? fileno(popenfp) : -1;
201 mt = rmtopen(magtape, 0);
207 mt = open(magtape, O_RDONLY, 0);
209 fprintf(stderr, "%s: %s\n", magtape, strerror(errno));
215 if (!pipein && !bflag)
217 if (gethead(&spcl) == FAIL) {
218 fprintf(stderr, "Tape is not a dump tape\n");
222 endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC;
223 endoftapemark.s_spcl.c_type = TS_END;
224 ip = (int *)&endoftapemark;
225 j = sizeof(union u_spcl) / sizeof(int);
230 endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
232 if (vflag || command == 't')
234 dumptime = _time64_to_time(spcl.c_ddate);
235 dumpdate = _time64_to_time(spcl.c_date);
236 if (stat(".", &stbuf) < 0) {
237 fprintf(stderr, "cannot stat .: %s\n", strerror(errno));
240 if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
242 if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE)
243 fssize = stbuf.st_blksize;
244 if (((fssize - 1) & fssize) != 0) {
245 fprintf(stderr, "bad block size %ld\n", fssize);
248 if (spcl.c_volume != 1) {
249 fprintf(stderr, "Tape is not volume 1 of the dump\n");
252 if (gethead(&spcl) == FAIL) {
253 dprintf(stdout, "header read failed at %ld blocks\n", blksread);
254 panic("no header after volume mark!\n");
257 if (spcl.c_type != TS_CLRI) {
258 fprintf(stderr, "Cannot find file removal list\n");
261 maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
262 dprintf(stdout, "maxino = %d\n", maxino);
263 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
265 panic("no memory for active inode map\n");
267 curfile.action = USING;
268 getfile(xtrmap, xtrmapskip);
269 if (spcl.c_type != TS_BITS) {
270 fprintf(stderr, "Cannot find file dump list\n");
273 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
274 if (map == (char *)NULL)
275 panic("no memory for file dump list\n");
277 curfile.action = USING;
278 getfile(xtrmap, xtrmapskip);
280 * If there may be whiteout entries on the tape, pretend that the
281 * whiteout inode exists, so that the whiteout entries can be
284 SETINO(WINO, dumpmap);
285 /* 'r' restores don't call getvol() for tape 1, so mark it as read. */
291 * Prompt user to load a new dump volume.
292 * "Nextvol" is the next suggested volume to use.
293 * This suggested volume is enforced when doing full
294 * or incremental restores, but can be overridden by
295 * the user when only extracting a subset of the files.
301 long i, newvol, savecnt;
302 union u_spcl tmpspcl;
303 # define tmpbuf tmpspcl.s_spcl
310 prevtapea = tapeaddr;
314 panic("Changing volumes on pipe input?\n");
315 /* Avoid looping if we couldn't ask the user. */
316 if (yflag || ferror(terminal) || feof(terminal))
329 done(1); /* pipes do not get a second chance */
330 if (command == 'R' || command == 'r' || curfile.action != SKIP)
334 while (newvol <= 0) {
335 if (tapesread == 0) {
336 fprintf(stderr, "%s%s%s%s%s%s%s",
337 "You have not read any tapes yet.\n",
338 "If you are extracting just a few files,",
339 " start with the last volume\n",
340 "and work towards the first; restore",
341 " can quickly skip tapes that\n",
342 "have no further files to extract.",
343 " Otherwise, begin with volume 1.\n");
345 fprintf(stderr, "You have read volumes");
347 for (i = 0; i < 32; i++)
348 if (tapesread & (1 << i)) {
349 fprintf(stderr, "%s%ld", buf, i + 1);
352 fprintf(stderr, "\n");
355 fprintf(stderr, "Specify next volume #: ");
356 (void) fflush(stderr);
357 if (fgets(buf, BUFSIZ, terminal) == NULL)
359 } while (buf[0] == '\n');
363 "Volume numbers are positive numerics\n");
366 if (newvol == volno) {
367 tapesread |= 1 << (volno - 1);
371 fprintf(stderr, "Mount tape volume %ld\n", newvol);
372 fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
373 fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape);
374 (void) fflush(stderr);
375 if (fgets(buf, BUFSIZ, terminal) == NULL)
377 if (!strcmp(buf, "none\n")) {
381 if (buf[0] != '\n') {
382 (void) strcpy(magtape, buf);
383 magtape[strlen(magtape) - 1] = '\0';
386 char volno[sizeof("2147483647")];
389 (void)sprintf(volno, "%d", newvol);
390 if (setenv("RESTORE_VOLUME", volno, 1) == -1) {
391 fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n",
395 popenfp = popen(magtape, "r");
396 mt = popenfp ? fileno(popenfp) : -1;
400 mt = rmtopen(magtape, 0);
403 mt = open(magtape, O_RDONLY, 0);
406 fprintf(stderr, "Cannot open %s\n", magtape);
414 if (gethead(&tmpbuf) == FAIL) {
415 dprintf(stdout, "header read failed at %ld blocks\n", blksread);
416 fprintf(stderr, "tape is not dump tape\n");
420 if (tmpbuf.c_volume != volno) {
421 fprintf(stderr, "Wrong volume (%ld)\n", tmpbuf.c_volume);
425 if (_time64_to_time(tmpbuf.c_date) != dumpdate ||
426 _time64_to_time(tmpbuf.c_ddate) != dumptime) {
427 time_t t = _time64_to_time(tmpbuf.c_date);
428 fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t));
429 fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
433 tapesread |= 1 << (volno - 1);
436 * If continuing from the previous volume, skip over any
437 * blocks read already at the end of the previous volume.
439 * If coming to this volume at random, skip to the beginning
440 * of the next record.
442 dprintf(stdout, "last rec %qd, tape starts with %qd\n", prevtapea,
444 if (tmpbuf.c_type == TS_TAPE) {
445 if (curfile.action != USING) {
447 * XXX Dump incorrectly sets c_count to 1 in the
448 * volume header of the first tape, so ignore
449 * c_count when volno == 1.
452 for (i = tmpbuf.c_count; i > 0; i--)
454 } else if (tmpbuf.c_tapea <= prevtapea) {
456 * Normally the value of c_tapea in the volume
457 * header is the record number of the header itself.
458 * However in the volume header following an EOT-
459 * terminated tape, it is the record number of the
460 * first continuation data block (dump bug?).
462 * The next record we want is `prevtapea + 1'.
464 i = prevtapea + 1 - tmpbuf.c_tapea;
465 dprintf(stderr, "Skipping %ld duplicate record%s.\n",
466 i, i > 1 ? "s" : "");
471 if (curfile.action == USING) {
473 panic("active file into volume 1\n");
476 (void) gethead(&spcl);
485 * Handle unexpected EOF.
491 if (gettingfile && curfile.action == USING) {
492 printf("Warning: %s %s\n",
493 "End-of-input encountered while extracting", curfile.name);
495 curfile.name = "<name unknown>";
496 curfile.action = UNKNOWN;
498 curfile.ino = maxino;
506 * handle multiple dumps per tape by skipping forward to the
514 if (dumpnum == 1 || volno != 1)
517 fprintf(stderr, "Cannot have multiple dumps on pipe input\n");
521 tcom.mt_count = dumpnum - 1;
524 rmtioctl(MTFSF, dumpnum - 1);
527 if (!pipecmdin && ioctl(mt, MTIOCTOP, (char *)&tcom) < 0)
528 fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno));
535 t = _time64_to_time(spcl.c_date);
536 fprintf(stdout, "Dump date: %s", ctime(&t));
537 t = _time64_to_time(spcl.c_ddate);
538 fprintf(stdout, "Dumped from: %s",
539 (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t));
540 if (spcl.c_host[0] == '\0')
542 fprintf(stderr, "Level %ld dump of %s on %s:%s\n",
543 spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
544 fprintf(stderr, "Label: %s\n", spcl.c_label);
548 extractfile(char *name)
552 struct timeval mtimep[2], ctimep[2];
556 curfile.action = USING;
557 mtimep[0].tv_sec = curfile.atime_sec;
558 mtimep[0].tv_usec = curfile.atime_nsec / 1000;
559 mtimep[1].tv_sec = curfile.mtime_sec;
560 mtimep[1].tv_usec = curfile.mtime_nsec / 1000;
561 ctimep[0].tv_sec = curfile.atime_sec;
562 ctimep[0].tv_usec = curfile.atime_nsec / 1000;
563 ctimep[1].tv_sec = curfile.birthtime_sec;
564 ctimep[1].tv_usec = curfile.birthtime_nsec / 1000;
566 flags = curfile.file_flags;
567 switch (mode & IFMT) {
570 fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
575 vprintf(stdout, "skipped socket %s\n", name);
581 ep = lookupname(name);
582 if (ep == NULL || ep->e_flags & EXTRACT)
583 panic("unextracted directory %s\n", name);
587 vprintf(stdout, "extract file %s\n", name);
588 return (genliteraldir(name, curfile.ino));
593 getfile(xtrlnkfile, xtrlnkskip);
596 "%s: zero length symbolic link (ignored)\n", name);
599 if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
600 (void) lchown(name, curfile.uid, curfile.gid);
601 (void) lchmod(name, mode);
602 (void) lutimes(name, ctimep);
603 (void) lutimes(name, mtimep);
609 vprintf(stdout, "extract fifo %s\n", name);
616 if (mkfifo(name, mode) < 0) {
617 fprintf(stderr, "%s: cannot create fifo: %s\n",
618 name, strerror(errno));
622 (void) chown(name, curfile.uid, curfile.gid);
623 (void) chmod(name, mode);
624 (void) utimes(name, ctimep);
625 (void) utimes(name, mtimep);
626 (void) chflags(name, flags);
632 vprintf(stdout, "extract special file %s\n", name);
639 if (mknod(name, mode, (int)curfile.rdev) < 0) {
640 fprintf(stderr, "%s: cannot create special file: %s\n",
641 name, strerror(errno));
645 (void) chown(name, curfile.uid, curfile.gid);
646 (void) chmod(name, mode);
647 (void) utimes(name, ctimep);
648 (void) utimes(name, mtimep);
649 (void) chflags(name, flags);
654 vprintf(stdout, "extract file %s\n", name);
661 if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
663 fprintf(stderr, "%s: cannot create file: %s\n",
664 name, strerror(errno));
668 (void) fchown(ofile, curfile.uid, curfile.gid);
669 (void) fchmod(ofile, mode);
670 getfile(xtrfile, xtrskip);
672 (void) utimes(name, ctimep);
673 (void) utimes(name, mtimep);
674 (void) chflags(name, flags);
681 * skip over bit maps on the tape
687 while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI)
692 * skip over a file on the tape
698 curfile.action = SKIP;
699 getfile(xtrnull, xtrnull);
703 * Extract a file from the tape.
704 * When an allocated block is found it is passed to the fill function;
705 * when an unallocated block (hole) is found, a zeroed buffer is passed
706 * to the skip function.
709 getfile(void (*fill)(char *, long), void (*skip)(char *, long))
713 quad_t size = spcl.c_size;
714 static char clearedbuf[MAXBSIZE];
715 char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
718 if (spcl.c_type == TS_END)
719 panic("ran off end of tape\n");
720 if (spcl.c_magic != FS_UFS2_MAGIC)
721 panic("not at beginning of a file\n");
722 if (!gettingfile && setjmp(restart) != 0)
726 for (i = 0; i < spcl.c_count; i++) {
727 if (readmapflag || spcl.c_addr[i]) {
728 readtape(&buf[curblk++][0]);
729 if (curblk == fssize / TP_BSIZE) {
730 (*fill)((char *)buf, (long)(size > TP_BSIZE ?
731 fssize : (curblk - 1) * TP_BSIZE + size));
736 (*fill)((char *)buf, (long)(size > TP_BSIZE ?
738 (curblk - 1) * TP_BSIZE + size));
741 (*skip)(clearedbuf, (long)(size > TP_BSIZE ?
744 if ((size -= TP_BSIZE) <= 0) {
745 for (i++; i < spcl.c_count; i++)
746 if (readmapflag || spcl.c_addr[i])
751 if (gethead(&spcl) == GOOD && size > 0) {
752 if (spcl.c_type == TS_ADDR)
755 "Missing address (header) block for %s at %ld blocks\n",
756 curfile.name, blksread);
759 (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size));
765 * Write out the next block of a file.
768 xtrfile(char *buf, long size)
773 if (write(ofile, buf, (int) size) == -1) {
775 "write error extracting inode %d, name %s\nwrite: %s\n",
776 curfile.ino, curfile.name, strerror(errno));
781 * Skip over a hole in a file.
785 xtrskip(char *buf, long size)
788 if (lseek(ofile, size, SEEK_CUR) == -1) {
790 "seek error extracting inode %d, name %s\nlseek: %s\n",
791 curfile.ino, curfile.name, strerror(errno));
797 * Collect the next block of a symbolic link.
800 xtrlnkfile(char *buf, long size)
804 if (pathlen > MAXPATHLEN) {
805 fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n",
806 curfile.name, lnkbuf, buf, pathlen);
809 (void) strcat(lnkbuf, buf);
813 * Skip over a hole in a symbolic link (should never happen).
817 xtrlnkskip(char *buf, long size)
820 fprintf(stderr, "unallocated block in symbolic link %s\n",
826 * Collect the next block of a bit map.
829 xtrmap(char *buf, long size)
832 memmove(map, buf, size);
837 * Skip over a hole in a bit map (should never happen).
841 xtrmapskip(char *buf, long size)
844 panic("hole in map\n");
849 * Noop, when an extraction function is not needed.
853 xtrnull(char *buf, long size)
860 * Read TP_BSIZE blocks from the input.
861 * Handle read errors, and end of media.
867 int cnt, seek_failed;
869 if (blkcnt < numtrec) {
870 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE);
875 for (i = 0; i < ntrec; i++)
876 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
879 cnt = ntrec * TP_BSIZE;
884 i = rmtread(&tapebuf[rd], cnt);
887 i = read(mt, &tapebuf[rd], cnt);
889 * Check for mid-tape short read error.
890 * If found, skip rest of buffer and start with the next.
892 if (!pipein && numtrec < ntrec && i > 0) {
893 dprintf(stdout, "mid-media short read error.\n");
897 * Handle partial block read.
899 if (pipein && i == 0 && rd > 0)
901 else if (i > 0 && i != ntrec * TP_BSIZE) {
910 * Short read. Process the blocks read.
912 if (i % TP_BSIZE != 0)
914 "partial block read: %ld should be %ld\n",
915 i, ntrec * TP_BSIZE);
916 numtrec = i / TP_BSIZE;
923 fprintf(stderr, "Tape read error while ");
924 switch (curfile.action) {
926 fprintf(stderr, "trying to set up tape\n");
929 fprintf(stderr, "trying to resynchronize\n");
932 fprintf(stderr, "restoring %s\n", curfile.name);
935 fprintf(stderr, "skipping over inode %d\n",
939 if (!yflag && !reply("continue"))
941 i = ntrec * TP_BSIZE;
942 memset(tapebuf, 0, i);
945 seek_failed = (rmtseek(i, 1) < 0);
948 seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1);
952 "continuation failed: %s\n", strerror(errno));
957 * Handle end of tape.
960 vprintf(stdout, "End-of-tape encountered\n");
969 if (rd % TP_BSIZE != 0)
970 panic("partial block read: %d should be %d\n",
971 rd, ntrec * TP_BSIZE);
973 memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE);
976 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE);
982 findtapeblksize(void)
986 for (i = 0; i < ntrec; i++)
987 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
991 i = rmtread(tapebuf, ntrec * TP_BSIZE);
994 i = read(mt, tapebuf, ntrec * TP_BSIZE);
997 fprintf(stderr, "tape read error: %s\n", strerror(errno));
1000 if (i % TP_BSIZE != 0) {
1001 fprintf(stderr, "Tape block size (%ld) %s (%d)\n",
1002 i, "is not a multiple of dump block size", TP_BSIZE);
1005 ntrec = i / TP_BSIZE;
1007 vprintf(stdout, "Tape block size is %ld\n", ntrec);
1029 * Read the next block from the tape.
1030 * If it is not any valid header, return an error.
1033 gethead(struct s_spcl *buf)
1037 readtape((char *)buf);
1038 if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) {
1039 if (buf->c_magic == OFS_MAGIC) {
1041 "Format of dump tape is too old. Must use\n");
1043 "a version of restore from before 2002.\n");
1046 if (swabl(buf->c_magic) != FS_UFS2_MAGIC &&
1047 buf->c_magic != NFS_MAGIC) {
1048 if (buf->c_magic == OFS_MAGIC) {
1050 "Format of dump tape is too old. Must use\n");
1052 "a version of restore from before 2002.\n");
1057 vprintf(stdout, "Note: Doing Byte swapping\n");
1061 if (checksum((int *)buf) == FAIL)
1064 swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf);
1065 swabst((u_char *)"l",(u_char *) &buf->c_level);
1066 swabst((u_char *)"2l4q",(u_char *) &buf->c_flags);
1070 switch (buf->c_type) {
1075 * Have to patch up missing information in bit map headers
1078 buf->c_size = buf->c_count * TP_BSIZE;
1079 if (buf->c_count > TP_NINDIR)
1082 for (i = 0; i < buf->c_count; i++)
1093 * For old dump tapes, have to copy up old fields to
1096 if (buf->c_magic == NFS_MAGIC) {
1097 buf->c_tapea = buf->c_old_tapea;
1098 buf->c_firstrec = buf->c_old_firstrec;
1099 buf->c_date = _time32_to_time(buf->c_old_date);
1100 buf->c_ddate = _time32_to_time(buf->c_old_ddate);
1101 buf->c_atime = _time32_to_time(buf->c_old_atime);
1102 buf->c_mtime = _time32_to_time(buf->c_old_mtime);
1110 panic("gethead: unknown inode type %d\n", buf->c_type);
1113 buf->c_magic = FS_UFS2_MAGIC;
1114 tapeaddr = buf->c_tapea;
1121 * Check that a header is where it belongs and predict the next header
1124 accthdr(struct s_spcl *header)
1126 static ino_t previno = 0x7fffffff;
1127 static int prevtype;
1128 static long predict;
1131 if (header->c_type == TS_TAPE) {
1132 fprintf(stderr, "Volume header ");
1133 if (header->c_firstrec)
1134 fprintf(stderr, "begins with record %qd",
1135 header->c_firstrec);
1136 fprintf(stderr, "\n");
1137 previno = 0x7fffffff;
1140 if (previno == 0x7fffffff)
1144 fprintf(stderr, "Dumped inodes map header");
1147 fprintf(stderr, "Used inodes map header");
1150 fprintf(stderr, "File header, ino %d", previno);
1153 fprintf(stderr, "File continuation header, ino %d", previno);
1156 fprintf(stderr, "End of tape header");
1159 if (predict != blksread - 1)
1160 fprintf(stderr, "; predicted %ld blocks, got %ld blocks",
1161 predict, blksread - 1);
1162 fprintf(stderr, "\n");
1165 if (header->c_type != TS_END)
1166 for (i = 0; i < header->c_count; i++)
1167 if (readmapflag || header->c_addr[i] != 0)
1171 prevtype = header->c_type;
1172 previno = header->c_inumber;
1176 * Find an inode header.
1177 * Complain if had to skip.
1180 findinode(struct s_spcl *header)
1182 static long skipcnt = 0;
1187 curfile.name = "<name unknown>";
1188 curfile.action = UNKNOWN;
1192 htype = header->c_type;
1197 * Skip up to the beginning of the next record
1199 for (i = 0; i < header->c_count; i++)
1200 if (header->c_addr[i])
1202 while (gethead(header) == FAIL ||
1203 _time64_to_time(header->c_date) != dumpdate)
1208 curfile.mode = header->c_mode;
1209 curfile.uid = header->c_uid;
1210 curfile.gid = header->c_gid;
1211 curfile.file_flags = header->c_file_flags;
1212 curfile.rdev = header->c_rdev;
1213 curfile.atime_sec = header->c_atime;
1214 curfile.atime_nsec = header->c_atimensec;
1215 curfile.mtime_sec = header->c_mtime;
1216 curfile.mtime_nsec = header->c_mtimensec;
1217 curfile.birthtime_sec = header->c_birthtime;
1218 curfile.birthtime_nsec = header->c_birthtimensec;
1219 curfile.size = header->c_size;
1220 curfile.ino = header->c_inumber;
1224 /* If we missed some tapes, get another volume. */
1225 if (tapesread & (tapesread + 1)) {
1229 curfile.ino = maxino;
1233 curfile.name = "<file removal list>";
1237 curfile.name = "<file dump list>";
1241 panic("unexpected tape header\n");
1245 panic("unknown tape header type %d\n", spcl.c_type);
1249 } while (htype == TS_ADDR);
1251 fprintf(stderr, "resync restore, skipped %ld blocks\n",
1261 j = sizeof(union u_spcl) / sizeof(int);
1268 /* What happens if we want to read restore tapes
1269 for a 16bit int machine??? */
1275 if (i != CHECKSUM) {
1276 fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
1277 curfile.ino, curfile.name);
1287 msg(const char *fmt, ...)
1291 (void)vfprintf(stderr, fmt, ap);
1294 #endif /* RRESTORE */
1297 swabshort(u_char *sp, int n)
1302 c = sp[0]; sp[0] = sp[1]; sp[1] = c;
1309 swablong(u_char *sp, int n)
1314 c = sp[0]; sp[0] = sp[3]; sp[3] = c;
1315 c = sp[2]; sp[2] = sp[1]; sp[1] = c;
1322 swabquad(u_char *sp, int n)
1327 c = sp[0]; sp[0] = sp[7]; sp[7] = c;
1328 c = sp[1]; sp[1] = sp[6]; sp[6] = c;
1329 c = sp[2]; sp[2] = sp[5]; sp[5] = c;
1330 c = sp[3]; sp[3] = sp[4]; sp[4] = c;
1337 swabst(u_char *cp, u_char *sp)
1343 case '0': case '1': case '2': case '3': case '4':
1344 case '5': case '6': case '7': case '8': case '9':
1345 n = (n * 10) + (*cp++ - '0');
1348 case 's': case 'w': case 'h':
1351 sp = swabshort(sp, n);
1357 sp = swablong(sp, n);
1363 sp = swabquad(sp, n);
1373 fprintf(stderr, "Unknown conversion character: %c\n",
1386 swabst((u_char *)"l", (u_char *)&x);