18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1983, 1993 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * (c) UNIX System Laboratories, Inc. 58fae3551SRodney W. Grimes * All or some portions of this file are derived from material licensed 68fae3551SRodney W. Grimes * to the University of California by American Telephone and Telegraph 78fae3551SRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 88fae3551SRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 98fae3551SRodney W. Grimes * 108fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 118fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 128fae3551SRodney W. Grimes * are met: 138fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 158fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 168fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 178fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 188fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 198fae3551SRodney W. Grimes * must display the following acknowledgement: 208fae3551SRodney W. Grimes * This product includes software developed by the University of 218fae3551SRodney W. Grimes * California, Berkeley and its contributors. 228fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 238fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 248fae3551SRodney W. Grimes * without specific prior written permission. 258fae3551SRodney W. Grimes * 268fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 278fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 288fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 298fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 308fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 318fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 328fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 338fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 348fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 358fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 368fae3551SRodney W. Grimes * SUCH DAMAGE. 378fae3551SRodney W. Grimes */ 388fae3551SRodney W. Grimes 398fae3551SRodney W. Grimes #ifndef lint 40d87d79aeSPeter Wemm static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; 418fae3551SRodney W. Grimes #endif /* not lint */ 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #include <sys/param.h> 448fae3551SRodney W. Grimes #include <sys/file.h> 458fae3551SRodney W. Grimes #include <sys/ioctl.h> 468fae3551SRodney W. Grimes #include <sys/mtio.h> 478fae3551SRodney W. Grimes #include <sys/stat.h> 488fae3551SRodney W. Grimes 498fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h> 508fae3551SRodney W. Grimes #include <protocols/dumprestore.h> 518fae3551SRodney W. Grimes 528fae3551SRodney W. Grimes #include <errno.h> 538fae3551SRodney W. Grimes #include <setjmp.h> 548fae3551SRodney W. Grimes #include <stdio.h> 558fae3551SRodney W. Grimes #include <stdlib.h> 568fae3551SRodney W. Grimes #include <string.h> 578fae3551SRodney W. Grimes #include <unistd.h> 588fae3551SRodney W. Grimes 598fae3551SRodney W. Grimes #include "restore.h" 608fae3551SRodney W. Grimes #include "extern.h" 618fae3551SRodney W. Grimes #include "pathnames.h" 628fae3551SRodney W. Grimes 638fae3551SRodney W. Grimes static long fssize = MAXBSIZE; 648fae3551SRodney W. Grimes static int mt = -1; 658fae3551SRodney W. Grimes static int pipein = 0; 6664121840SGuido van Rooij static char *magtape; 678fae3551SRodney W. Grimes static int blkcnt; 688fae3551SRodney W. Grimes static int numtrec; 698fae3551SRodney W. Grimes static char *tapebuf; 708fae3551SRodney W. Grimes static union u_spcl endoftapemark; 718fae3551SRodney W. Grimes static long blksread; /* blocks read since last header */ 728fae3551SRodney W. Grimes static long tpblksread = 0; /* TP_BSIZE blocks read */ 738fae3551SRodney W. Grimes static long tapesread; 748fae3551SRodney W. Grimes static jmp_buf restart; 758fae3551SRodney W. Grimes static int gettingfile = 0; /* restart has a valid frame */ 768fae3551SRodney W. Grimes static char *host = NULL; 778fae3551SRodney W. Grimes 788fae3551SRodney W. Grimes static int ofile; 798fae3551SRodney W. Grimes static char *map; 808fae3551SRodney W. Grimes static char lnkbuf[MAXPATHLEN + 1]; 818fae3551SRodney W. Grimes static int pathlen; 828fae3551SRodney W. Grimes 838fae3551SRodney W. Grimes int oldinofmt; /* old inode format conversion required */ 848fae3551SRodney W. Grimes int Bcvt; /* Swap Bytes (for CCI or sun) */ 858fae3551SRodney W. Grimes static int Qcvt; /* Swap quads (for sun) */ 868fae3551SRodney W. Grimes 878fae3551SRodney W. Grimes #define FLUSHTAPEBUF() blkcnt = ntrec + 1 888fae3551SRodney W. Grimes 898fae3551SRodney W. Grimes static void accthdr __P((struct s_spcl *)); 908fae3551SRodney W. Grimes static int checksum __P((int *)); 918fae3551SRodney W. Grimes static void findinode __P((struct s_spcl *)); 928fae3551SRodney W. Grimes static void findtapeblksize __P((void)); 938fae3551SRodney W. Grimes static int gethead __P((struct s_spcl *)); 948fae3551SRodney W. Grimes static void readtape __P((char *)); 958fae3551SRodney W. Grimes static void setdumpnum __P((void)); 968fae3551SRodney W. Grimes static u_long swabl __P((u_long)); 978fae3551SRodney W. Grimes static u_char *swablong __P((u_char *, int)); 988fae3551SRodney W. Grimes static u_char *swabshort __P((u_char *, int)); 998fae3551SRodney W. Grimes static void terminateinput __P((void)); 1008fae3551SRodney W. Grimes static void xtrfile __P((char *, long)); 1018fae3551SRodney W. Grimes static void xtrlnkfile __P((char *, long)); 1028fae3551SRodney W. Grimes static void xtrlnkskip __P((char *, long)); 1038fae3551SRodney W. Grimes static void xtrmap __P((char *, long)); 1048fae3551SRodney W. Grimes static void xtrmapskip __P((char *, long)); 1058fae3551SRodney W. Grimes static void xtrskip __P((char *, long)); 1068fae3551SRodney W. Grimes 1078fae3551SRodney W. Grimes /* 1088fae3551SRodney W. Grimes * Set up an input source 1098fae3551SRodney W. Grimes */ 1108fae3551SRodney W. Grimes void 1118fae3551SRodney W. Grimes setinput(source) 1128fae3551SRodney W. Grimes char *source; 1138fae3551SRodney W. Grimes { 1148fae3551SRodney W. Grimes FLUSHTAPEBUF(); 1158fae3551SRodney W. Grimes if (bflag) 1168fae3551SRodney W. Grimes newtapebuf(ntrec); 1178fae3551SRodney W. Grimes else 1188fae3551SRodney W. Grimes newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); 1198fae3551SRodney W. Grimes terminal = stdin; 1208fae3551SRodney W. Grimes 1218fae3551SRodney W. Grimes #ifdef RRESTORE 122d87d79aeSPeter Wemm if (strchr(source, ':')) { 1238fae3551SRodney W. Grimes host = source; 124d87d79aeSPeter Wemm source = strchr(host, ':'); 1258fae3551SRodney W. Grimes *source++ = '\0'; 1268fae3551SRodney W. Grimes if (rmthost(host) == 0) 1278fae3551SRodney W. Grimes done(1); 1288fae3551SRodney W. Grimes } else 1298fae3551SRodney W. Grimes #endif 1308fae3551SRodney W. Grimes if (strcmp(source, "-") == 0) { 1318fae3551SRodney W. Grimes /* 1328fae3551SRodney W. Grimes * Since input is coming from a pipe we must establish 1338fae3551SRodney W. Grimes * our own connection to the terminal. 1348fae3551SRodney W. Grimes */ 1358fae3551SRodney W. Grimes terminal = fopen(_PATH_TTY, "r"); 1368fae3551SRodney W. Grimes if (terminal == NULL) { 1378fae3551SRodney W. Grimes (void)fprintf(stderr, "cannot open %s: %s\n", 1388fae3551SRodney W. Grimes _PATH_TTY, strerror(errno)); 1398fae3551SRodney W. Grimes terminal = fopen(_PATH_DEVNULL, "r"); 1408fae3551SRodney W. Grimes if (terminal == NULL) { 1418fae3551SRodney W. Grimes (void)fprintf(stderr, "cannot open %s: %s\n", 1428fae3551SRodney W. Grimes _PATH_DEVNULL, strerror(errno)); 1438fae3551SRodney W. Grimes done(1); 1448fae3551SRodney W. Grimes } 1458fae3551SRodney W. Grimes } 1468fae3551SRodney W. Grimes pipein++; 1478fae3551SRodney W. Grimes } 1488fae3551SRodney W. Grimes setuid(getuid()); /* no longer need or want root privileges */ 14964121840SGuido van Rooij magtape = strdup(source); 15064121840SGuido van Rooij if (magtape == NULL) { 15164121840SGuido van Rooij fprintf(stderr, "Cannot allocate space for magtape buffer\n"); 15264121840SGuido van Rooij done(1); 15364121840SGuido van Rooij } 1548fae3551SRodney W. Grimes } 1558fae3551SRodney W. Grimes 1568fae3551SRodney W. Grimes void 1578fae3551SRodney W. Grimes newtapebuf(size) 1588fae3551SRodney W. Grimes long size; 1598fae3551SRodney W. Grimes { 1608fae3551SRodney W. Grimes static tapebufsize = -1; 1618fae3551SRodney W. Grimes 1628fae3551SRodney W. Grimes ntrec = size; 1638fae3551SRodney W. Grimes if (size <= tapebufsize) 1648fae3551SRodney W. Grimes return; 1658fae3551SRodney W. Grimes if (tapebuf != NULL) 1668fae3551SRodney W. Grimes free(tapebuf); 1678fae3551SRodney W. Grimes tapebuf = malloc(size * TP_BSIZE); 1688fae3551SRodney W. Grimes if (tapebuf == NULL) { 1698fae3551SRodney W. Grimes fprintf(stderr, "Cannot allocate space for tape buffer\n"); 1708fae3551SRodney W. Grimes done(1); 1718fae3551SRodney W. Grimes } 1728fae3551SRodney W. Grimes tapebufsize = size; 1738fae3551SRodney W. Grimes } 1748fae3551SRodney W. Grimes 1758fae3551SRodney W. Grimes /* 1768fae3551SRodney W. Grimes * Verify that the tape drive can be accessed and 1778fae3551SRodney W. Grimes * that it actually is a dump tape. 1788fae3551SRodney W. Grimes */ 1798fae3551SRodney W. Grimes void 1808fae3551SRodney W. Grimes setup() 1818fae3551SRodney W. Grimes { 1828fae3551SRodney W. Grimes int i, j, *ip; 1838fae3551SRodney W. Grimes struct stat stbuf; 1848fae3551SRodney W. Grimes 1858fae3551SRodney W. Grimes vprintf(stdout, "Verify tape and initialize maps\n"); 1868fae3551SRodney W. Grimes #ifdef RRESTORE 1878fae3551SRodney W. Grimes if (host) 1888fae3551SRodney W. Grimes mt = rmtopen(magtape, 0); 1898fae3551SRodney W. Grimes else 1908fae3551SRodney W. Grimes #endif 1918fae3551SRodney W. Grimes if (pipein) 1928fae3551SRodney W. Grimes mt = 0; 1938fae3551SRodney W. Grimes else 1948fae3551SRodney W. Grimes mt = open(magtape, O_RDONLY, 0); 1958fae3551SRodney W. Grimes if (mt < 0) { 1968fae3551SRodney W. Grimes fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); 1978fae3551SRodney W. Grimes done(1); 1988fae3551SRodney W. Grimes } 1998fae3551SRodney W. Grimes volno = 1; 2008fae3551SRodney W. Grimes setdumpnum(); 2018fae3551SRodney W. Grimes FLUSHTAPEBUF(); 2028fae3551SRodney W. Grimes if (!pipein && !bflag) 2038fae3551SRodney W. Grimes findtapeblksize(); 2048fae3551SRodney W. Grimes if (gethead(&spcl) == FAIL) { 2058fae3551SRodney W. Grimes blkcnt--; /* push back this block */ 2068fae3551SRodney W. Grimes blksread--; 2078fae3551SRodney W. Grimes tpblksread--; 2088fae3551SRodney W. Grimes cvtflag++; 2098fae3551SRodney W. Grimes if (gethead(&spcl) == FAIL) { 2108fae3551SRodney W. Grimes fprintf(stderr, "Tape is not a dump tape\n"); 2118fae3551SRodney W. Grimes done(1); 2128fae3551SRodney W. Grimes } 2138fae3551SRodney W. Grimes fprintf(stderr, "Converting to new file system format.\n"); 2148fae3551SRodney W. Grimes } 2158fae3551SRodney W. Grimes if (pipein) { 2168fae3551SRodney W. Grimes endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; 2178fae3551SRodney W. Grimes endoftapemark.s_spcl.c_type = TS_END; 2188fae3551SRodney W. Grimes ip = (int *)&endoftapemark; 2198fae3551SRodney W. Grimes j = sizeof(union u_spcl) / sizeof(int); 2208fae3551SRodney W. Grimes i = 0; 2218fae3551SRodney W. Grimes do 2228fae3551SRodney W. Grimes i += *ip++; 2238fae3551SRodney W. Grimes while (--j); 2248fae3551SRodney W. Grimes endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 2258fae3551SRodney W. Grimes } 2268fae3551SRodney W. Grimes if (vflag || command == 't') 2278fae3551SRodney W. Grimes printdumpinfo(); 2288fae3551SRodney W. Grimes dumptime = spcl.c_ddate; 2298fae3551SRodney W. Grimes dumpdate = spcl.c_date; 2308fae3551SRodney W. Grimes if (stat(".", &stbuf) < 0) { 2318fae3551SRodney W. Grimes fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); 2328fae3551SRodney W. Grimes done(1); 2338fae3551SRodney W. Grimes } 2348fae3551SRodney W. Grimes if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE) 2358fae3551SRodney W. Grimes fssize = stbuf.st_blksize; 2368fae3551SRodney W. Grimes if (((fssize - 1) & fssize) != 0) { 2378fae3551SRodney W. Grimes fprintf(stderr, "bad block size %d\n", fssize); 2388fae3551SRodney W. Grimes done(1); 2398fae3551SRodney W. Grimes } 2408fae3551SRodney W. Grimes if (spcl.c_volume != 1) { 2418fae3551SRodney W. Grimes fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2428fae3551SRodney W. Grimes done(1); 2438fae3551SRodney W. Grimes } 2448fae3551SRodney W. Grimes if (gethead(&spcl) == FAIL) { 2458fae3551SRodney W. Grimes dprintf(stdout, "header read failed at %d blocks\n", blksread); 2468fae3551SRodney W. Grimes panic("no header after volume mark!\n"); 2478fae3551SRodney W. Grimes } 2488fae3551SRodney W. Grimes findinode(&spcl); 2498fae3551SRodney W. Grimes if (spcl.c_type != TS_CLRI) { 2508fae3551SRodney W. Grimes fprintf(stderr, "Cannot find file removal list\n"); 2518fae3551SRodney W. Grimes done(1); 2528fae3551SRodney W. Grimes } 2538fae3551SRodney W. Grimes maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; 2548fae3551SRodney W. Grimes dprintf(stdout, "maxino = %d\n", maxino); 2558fae3551SRodney W. Grimes map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 2568fae3551SRodney W. Grimes if (map == NULL) 257d87d79aeSPeter Wemm panic("no memory for active inode map\n"); 258d87d79aeSPeter Wemm usedinomap = map; 2598fae3551SRodney W. Grimes curfile.action = USING; 2608fae3551SRodney W. Grimes getfile(xtrmap, xtrmapskip); 2618fae3551SRodney W. Grimes if (spcl.c_type != TS_BITS) { 2628fae3551SRodney W. Grimes fprintf(stderr, "Cannot find file dump list\n"); 2638fae3551SRodney W. Grimes done(1); 2648fae3551SRodney W. Grimes } 2658fae3551SRodney W. Grimes map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 2668fae3551SRodney W. Grimes if (map == (char *)NULL) 2678fae3551SRodney W. Grimes panic("no memory for file dump list\n"); 2688fae3551SRodney W. Grimes dumpmap = map; 2698fae3551SRodney W. Grimes curfile.action = USING; 2708fae3551SRodney W. Grimes getfile(xtrmap, xtrmapskip); 271d87d79aeSPeter Wemm /* 272d87d79aeSPeter Wemm * If there may be whiteout entries on the tape, pretend that the 273d87d79aeSPeter Wemm * whiteout inode exists, so that the whiteout entries can be 274d87d79aeSPeter Wemm * extracted. 275d87d79aeSPeter Wemm */ 276d87d79aeSPeter Wemm if (oldinofmt == 0) 277d87d79aeSPeter Wemm SETINO(WINO, dumpmap); 2788fae3551SRodney W. Grimes } 2798fae3551SRodney W. Grimes 2808fae3551SRodney W. Grimes /* 2818fae3551SRodney W. Grimes * Prompt user to load a new dump volume. 2828fae3551SRodney W. Grimes * "Nextvol" is the next suggested volume to use. 2838fae3551SRodney W. Grimes * This suggested volume is enforced when doing full 2848fae3551SRodney W. Grimes * or incremental restores, but can be overrridden by 2858fae3551SRodney W. Grimes * the user when only extracting a subset of the files. 2868fae3551SRodney W. Grimes */ 2878fae3551SRodney W. Grimes void 2888fae3551SRodney W. Grimes getvol(nextvol) 2898fae3551SRodney W. Grimes long nextvol; 2908fae3551SRodney W. Grimes { 2918fae3551SRodney W. Grimes long newvol, savecnt, wantnext, i; 2928fae3551SRodney W. Grimes union u_spcl tmpspcl; 2938fae3551SRodney W. Grimes # define tmpbuf tmpspcl.s_spcl 2948fae3551SRodney W. Grimes char buf[TP_BSIZE]; 2958fae3551SRodney W. Grimes 2968fae3551SRodney W. Grimes if (nextvol == 1) { 2978fae3551SRodney W. Grimes tapesread = 0; 2988fae3551SRodney W. Grimes gettingfile = 0; 2998fae3551SRodney W. Grimes } 3008fae3551SRodney W. Grimes if (pipein) { 3018fae3551SRodney W. Grimes if (nextvol != 1) 3028fae3551SRodney W. Grimes panic("Changing volumes on pipe input?\n"); 3038fae3551SRodney W. Grimes if (volno == 1) 3048fae3551SRodney W. Grimes return; 3058fae3551SRodney W. Grimes goto gethdr; 3068fae3551SRodney W. Grimes } 3078fae3551SRodney W. Grimes savecnt = blksread; 3088fae3551SRodney W. Grimes again: 3098fae3551SRodney W. Grimes if (pipein) 3108fae3551SRodney W. Grimes done(1); /* pipes do not get a second chance */ 3118fae3551SRodney W. Grimes if (command == 'R' || command == 'r' || curfile.action != SKIP) { 3128fae3551SRodney W. Grimes newvol = nextvol; 3138fae3551SRodney W. Grimes wantnext = 1; 3148fae3551SRodney W. Grimes } else { 3158fae3551SRodney W. Grimes newvol = 0; 3168fae3551SRodney W. Grimes wantnext = 0; 3178fae3551SRodney W. Grimes } 3188fae3551SRodney W. Grimes while (newvol <= 0) { 3198fae3551SRodney W. Grimes if (tapesread == 0) { 3208fae3551SRodney W. Grimes fprintf(stderr, "%s%s%s%s%s", 3218fae3551SRodney W. Grimes "You have not read any tapes yet.\n", 3228fae3551SRodney W. Grimes "Unless you know which volume your", 3238fae3551SRodney W. Grimes " file(s) are on you should start\n", 3248fae3551SRodney W. Grimes "with the last volume and work", 3258fae3551SRodney W. Grimes " towards towards the first.\n"); 3268fae3551SRodney W. Grimes } else { 3278fae3551SRodney W. Grimes fprintf(stderr, "You have read volumes"); 3288fae3551SRodney W. Grimes strcpy(buf, ": "); 3298fae3551SRodney W. Grimes for (i = 1; i < 32; i++) 3308fae3551SRodney W. Grimes if (tapesread & (1 << i)) { 3318fae3551SRodney W. Grimes fprintf(stderr, "%s%d", buf, i); 3328fae3551SRodney W. Grimes strcpy(buf, ", "); 3338fae3551SRodney W. Grimes } 3348fae3551SRodney W. Grimes fprintf(stderr, "\n"); 3358fae3551SRodney W. Grimes } 3368fae3551SRodney W. Grimes do { 3378fae3551SRodney W. Grimes fprintf(stderr, "Specify next volume #: "); 3388fae3551SRodney W. Grimes (void) fflush(stderr); 3398fae3551SRodney W. Grimes (void) fgets(buf, BUFSIZ, terminal); 3408fae3551SRodney W. Grimes } while (!feof(terminal) && buf[0] == '\n'); 3418fae3551SRodney W. Grimes if (feof(terminal)) 3428fae3551SRodney W. Grimes done(1); 3438fae3551SRodney W. Grimes newvol = atoi(buf); 3448fae3551SRodney W. Grimes if (newvol <= 0) { 3458fae3551SRodney W. Grimes fprintf(stderr, 3468fae3551SRodney W. Grimes "Volume numbers are positive numerics\n"); 3478fae3551SRodney W. Grimes } 3488fae3551SRodney W. Grimes } 3498fae3551SRodney W. Grimes if (newvol == volno) { 3508fae3551SRodney W. Grimes tapesread |= 1 << volno; 3518fae3551SRodney W. Grimes return; 3528fae3551SRodney W. Grimes } 3538fae3551SRodney W. Grimes closemt(); 3548fae3551SRodney W. Grimes fprintf(stderr, "Mount tape volume %d\n", newvol); 3558fae3551SRodney W. Grimes fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); 3568fae3551SRodney W. Grimes fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); 3578fae3551SRodney W. Grimes (void) fflush(stderr); 3588fae3551SRodney W. Grimes (void) fgets(buf, BUFSIZ, terminal); 3598fae3551SRodney W. Grimes if (feof(terminal)) 3608fae3551SRodney W. Grimes done(1); 3618fae3551SRodney W. Grimes if (!strcmp(buf, "none\n")) { 3628fae3551SRodney W. Grimes terminateinput(); 3638fae3551SRodney W. Grimes return; 3648fae3551SRodney W. Grimes } 3658fae3551SRodney W. Grimes if (buf[0] != '\n') { 3668fae3551SRodney W. Grimes (void) strcpy(magtape, buf); 3678fae3551SRodney W. Grimes magtape[strlen(magtape) - 1] = '\0'; 3688fae3551SRodney W. Grimes } 3698fae3551SRodney W. Grimes #ifdef RRESTORE 3708fae3551SRodney W. Grimes if (host) 3718fae3551SRodney W. Grimes mt = rmtopen(magtape, 0); 3728fae3551SRodney W. Grimes else 3738fae3551SRodney W. Grimes #endif 3748fae3551SRodney W. Grimes mt = open(magtape, O_RDONLY, 0); 3758fae3551SRodney W. Grimes 3768fae3551SRodney W. Grimes if (mt == -1) { 3778fae3551SRodney W. Grimes fprintf(stderr, "Cannot open %s\n", magtape); 3788fae3551SRodney W. Grimes volno = -1; 3798fae3551SRodney W. Grimes goto again; 3808fae3551SRodney W. Grimes } 3818fae3551SRodney W. Grimes gethdr: 3828fae3551SRodney W. Grimes volno = newvol; 3838fae3551SRodney W. Grimes setdumpnum(); 3848fae3551SRodney W. Grimes FLUSHTAPEBUF(); 3858fae3551SRodney W. Grimes if (gethead(&tmpbuf) == FAIL) { 3868fae3551SRodney W. Grimes dprintf(stdout, "header read failed at %d blocks\n", blksread); 3878fae3551SRodney W. Grimes fprintf(stderr, "tape is not dump tape\n"); 3888fae3551SRodney W. Grimes volno = 0; 3898fae3551SRodney W. Grimes goto again; 3908fae3551SRodney W. Grimes } 3918fae3551SRodney W. Grimes if (tmpbuf.c_volume != volno) { 3928fae3551SRodney W. Grimes fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume); 3938fae3551SRodney W. Grimes volno = 0; 3948fae3551SRodney W. Grimes goto again; 3958fae3551SRodney W. Grimes } 3968fae3551SRodney W. Grimes if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) { 3978fae3551SRodney W. Grimes fprintf(stderr, "Wrong dump date\n\tgot: %s", 3988fae3551SRodney W. Grimes ctime(&tmpbuf.c_date)); 3998fae3551SRodney W. Grimes fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); 4008fae3551SRodney W. Grimes volno = 0; 4018fae3551SRodney W. Grimes goto again; 4028fae3551SRodney W. Grimes } 4038fae3551SRodney W. Grimes tapesread |= 1 << volno; 4048fae3551SRodney W. Grimes blksread = savecnt; 4058fae3551SRodney W. Grimes /* 4068fae3551SRodney W. Grimes * If continuing from the previous volume, skip over any 4078fae3551SRodney W. Grimes * blocks read already at the end of the previous volume. 4088fae3551SRodney W. Grimes * 4098fae3551SRodney W. Grimes * If coming to this volume at random, skip to the beginning 4108fae3551SRodney W. Grimes * of the next record. 4118fae3551SRodney W. Grimes */ 4128fae3551SRodney W. Grimes dprintf(stdout, "read %ld recs, tape starts with %ld\n", 4138fae3551SRodney W. Grimes tpblksread, tmpbuf.c_firstrec); 4148fae3551SRodney W. Grimes if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) { 4158fae3551SRodney W. Grimes if (!wantnext) { 4168fae3551SRodney W. Grimes tpblksread = tmpbuf.c_firstrec; 4178fae3551SRodney W. Grimes for (i = tmpbuf.c_count; i > 0; i--) 4188fae3551SRodney W. Grimes readtape(buf); 4198fae3551SRodney W. Grimes } else if (tmpbuf.c_firstrec > 0 && 4208fae3551SRodney W. Grimes tmpbuf.c_firstrec < tpblksread - 1) { 4218fae3551SRodney W. Grimes /* 4228fae3551SRodney W. Grimes * -1 since we've read the volume header 4238fae3551SRodney W. Grimes */ 4248fae3551SRodney W. Grimes i = tpblksread - tmpbuf.c_firstrec - 1; 4258fae3551SRodney W. Grimes dprintf(stderr, "Skipping %d duplicate record%s.\n", 4268fae3551SRodney W. Grimes i, i > 1 ? "s" : ""); 4278fae3551SRodney W. Grimes while (--i >= 0) 4288fae3551SRodney W. Grimes readtape(buf); 4298fae3551SRodney W. Grimes } 4308fae3551SRodney W. Grimes } 4318fae3551SRodney W. Grimes if (curfile.action == USING) { 4328fae3551SRodney W. Grimes if (volno == 1) 4338fae3551SRodney W. Grimes panic("active file into volume 1\n"); 4348fae3551SRodney W. Grimes return; 4358fae3551SRodney W. Grimes } 4368fae3551SRodney W. Grimes /* 4378fae3551SRodney W. Grimes * Skip up to the beginning of the next record 4388fae3551SRodney W. Grimes */ 4398fae3551SRodney W. Grimes if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) 4408fae3551SRodney W. Grimes for (i = tmpbuf.c_count; i > 0; i--) 4418fae3551SRodney W. Grimes readtape(buf); 4428fae3551SRodney W. Grimes (void) gethead(&spcl); 4438fae3551SRodney W. Grimes findinode(&spcl); 4448fae3551SRodney W. Grimes if (gettingfile) { 4458fae3551SRodney W. Grimes gettingfile = 0; 4468fae3551SRodney W. Grimes longjmp(restart, 1); 4478fae3551SRodney W. Grimes } 4488fae3551SRodney W. Grimes } 4498fae3551SRodney W. Grimes 4508fae3551SRodney W. Grimes /* 4518fae3551SRodney W. Grimes * Handle unexpected EOF. 4528fae3551SRodney W. Grimes */ 4538fae3551SRodney W. Grimes static void 4548fae3551SRodney W. Grimes terminateinput() 4558fae3551SRodney W. Grimes { 4568fae3551SRodney W. Grimes 4578fae3551SRodney W. Grimes if (gettingfile && curfile.action == USING) { 4588fae3551SRodney W. Grimes printf("Warning: %s %s\n", 4598fae3551SRodney W. Grimes "End-of-input encountered while extracting", curfile.name); 4608fae3551SRodney W. Grimes } 4618fae3551SRodney W. Grimes curfile.name = "<name unknown>"; 4628fae3551SRodney W. Grimes curfile.action = UNKNOWN; 4638fae3551SRodney W. Grimes curfile.dip = NULL; 4648fae3551SRodney W. Grimes curfile.ino = maxino; 4658fae3551SRodney W. Grimes if (gettingfile) { 4668fae3551SRodney W. Grimes gettingfile = 0; 4678fae3551SRodney W. Grimes longjmp(restart, 1); 4688fae3551SRodney W. Grimes } 4698fae3551SRodney W. Grimes } 4708fae3551SRodney W. Grimes 4718fae3551SRodney W. Grimes /* 4728fae3551SRodney W. Grimes * handle multiple dumps per tape by skipping forward to the 4738fae3551SRodney W. Grimes * appropriate one. 4748fae3551SRodney W. Grimes */ 4758fae3551SRodney W. Grimes static void 4768fae3551SRodney W. Grimes setdumpnum() 4778fae3551SRodney W. Grimes { 4788fae3551SRodney W. Grimes struct mtop tcom; 4798fae3551SRodney W. Grimes 4808fae3551SRodney W. Grimes if (dumpnum == 1 || volno != 1) 4818fae3551SRodney W. Grimes return; 4828fae3551SRodney W. Grimes if (pipein) { 4838fae3551SRodney W. Grimes fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); 4848fae3551SRodney W. Grimes done(1); 4858fae3551SRodney W. Grimes } 4868fae3551SRodney W. Grimes tcom.mt_op = MTFSF; 4878fae3551SRodney W. Grimes tcom.mt_count = dumpnum - 1; 4888fae3551SRodney W. Grimes #ifdef RRESTORE 4898fae3551SRodney W. Grimes if (host) 4908fae3551SRodney W. Grimes rmtioctl(MTFSF, dumpnum - 1); 4918fae3551SRodney W. Grimes else 4928fae3551SRodney W. Grimes #endif 4938fae3551SRodney W. Grimes if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0) 4948fae3551SRodney W. Grimes fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); 4958fae3551SRodney W. Grimes } 4968fae3551SRodney W. Grimes 4978fae3551SRodney W. Grimes void 4988fae3551SRodney W. Grimes printdumpinfo() 4998fae3551SRodney W. Grimes { 5008fae3551SRodney W. Grimes fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date)); 5018fae3551SRodney W. Grimes fprintf(stdout, "Dumped from: %s", 5028fae3551SRodney W. Grimes (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&spcl.c_ddate)); 5038fae3551SRodney W. Grimes if (spcl.c_host[0] == '\0') 5048fae3551SRodney W. Grimes return; 5058fae3551SRodney W. Grimes fprintf(stderr, "Level %d dump of %s on %s:%s\n", 5068fae3551SRodney W. Grimes spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); 5078fae3551SRodney W. Grimes fprintf(stderr, "Label: %s\n", spcl.c_label); 5088fae3551SRodney W. Grimes } 5098fae3551SRodney W. Grimes 5108fae3551SRodney W. Grimes int 5118fae3551SRodney W. Grimes extractfile(name) 5128fae3551SRodney W. Grimes char *name; 5138fae3551SRodney W. Grimes { 514d87d79aeSPeter Wemm int flags; 515d87d79aeSPeter Wemm mode_t mode; 5168fae3551SRodney W. Grimes struct timeval timep[2]; 5178fae3551SRodney W. Grimes struct entry *ep; 5188fae3551SRodney W. Grimes 5198fae3551SRodney W. Grimes curfile.name = name; 5208fae3551SRodney W. Grimes curfile.action = USING; 521d87d79aeSPeter Wemm timep[0].tv_sec = curfile.dip->di_atime; 522d87d79aeSPeter Wemm timep[0].tv_usec = curfile.dip->di_atimensec / 1000; 523d87d79aeSPeter Wemm timep[1].tv_sec = curfile.dip->di_mtime; 524d87d79aeSPeter Wemm timep[1].tv_usec = curfile.dip->di_mtimensec / 1000; 5258fae3551SRodney W. Grimes mode = curfile.dip->di_mode; 526d87d79aeSPeter Wemm flags = curfile.dip->di_flags; 5278fae3551SRodney W. Grimes switch (mode & IFMT) { 5288fae3551SRodney W. Grimes 5298fae3551SRodney W. Grimes default: 5308fae3551SRodney W. Grimes fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); 5318fae3551SRodney W. Grimes skipfile(); 5328fae3551SRodney W. Grimes return (FAIL); 5338fae3551SRodney W. Grimes 5348fae3551SRodney W. Grimes case IFSOCK: 5358fae3551SRodney W. Grimes vprintf(stdout, "skipped socket %s\n", name); 5368fae3551SRodney W. Grimes skipfile(); 5378fae3551SRodney W. Grimes return (GOOD); 5388fae3551SRodney W. Grimes 5398fae3551SRodney W. Grimes case IFDIR: 5408fae3551SRodney W. Grimes if (mflag) { 5418fae3551SRodney W. Grimes ep = lookupname(name); 5428fae3551SRodney W. Grimes if (ep == NULL || ep->e_flags & EXTRACT) 5438fae3551SRodney W. Grimes panic("unextracted directory %s\n", name); 5448fae3551SRodney W. Grimes skipfile(); 5458fae3551SRodney W. Grimes return (GOOD); 5468fae3551SRodney W. Grimes } 5478fae3551SRodney W. Grimes vprintf(stdout, "extract file %s\n", name); 5488fae3551SRodney W. Grimes return (genliteraldir(name, curfile.ino)); 5498fae3551SRodney W. Grimes 5508fae3551SRodney W. Grimes case IFLNK: 5518fae3551SRodney W. Grimes lnkbuf[0] = '\0'; 5528fae3551SRodney W. Grimes pathlen = 0; 5538fae3551SRodney W. Grimes getfile(xtrlnkfile, xtrlnkskip); 5548fae3551SRodney W. Grimes if (pathlen == 0) { 5558fae3551SRodney W. Grimes vprintf(stdout, 5568fae3551SRodney W. Grimes "%s: zero length symbolic link (ignored)\n", name); 5578fae3551SRodney W. Grimes return (GOOD); 5588fae3551SRodney W. Grimes } 5598fae3551SRodney W. Grimes return (linkit(lnkbuf, name, SYMLINK)); 5608fae3551SRodney W. Grimes 561d6516153SMartin Renters case IFIFO: 562d87d79aeSPeter Wemm vprintf(stdout, "extract fifo %s\n", name); 563d87d79aeSPeter Wemm if (Nflag) { 564d87d79aeSPeter Wemm skipfile(); 565d87d79aeSPeter Wemm return (GOOD); 566d87d79aeSPeter Wemm } 567d6516153SMartin Renters if (mkfifo(name, mode) < 0) { 568d87d79aeSPeter Wemm fprintf(stderr, "%s: cannot create fifo: %s\n", 569d6516153SMartin Renters name, strerror(errno)); 570d6516153SMartin Renters skipfile(); 571d6516153SMartin Renters return (FAIL); 572d6516153SMartin Renters } 573d6516153SMartin Renters (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 574d6516153SMartin Renters (void) chmod(name, mode); 575d87d79aeSPeter Wemm (void) chflags(name, flags); 576d6516153SMartin Renters skipfile(); 577d6516153SMartin Renters utimes(name, timep); 578d6516153SMartin Renters return (GOOD); 579d6516153SMartin Renters 5808fae3551SRodney W. Grimes case IFCHR: 5818fae3551SRodney W. Grimes case IFBLK: 5828fae3551SRodney W. Grimes vprintf(stdout, "extract special file %s\n", name); 5838fae3551SRodney W. Grimes if (Nflag) { 5848fae3551SRodney W. Grimes skipfile(); 5858fae3551SRodney W. Grimes return (GOOD); 5868fae3551SRodney W. Grimes } 5878fae3551SRodney W. Grimes if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { 5888fae3551SRodney W. Grimes fprintf(stderr, "%s: cannot create special file: %s\n", 5898fae3551SRodney W. Grimes name, strerror(errno)); 5908fae3551SRodney W. Grimes skipfile(); 5918fae3551SRodney W. Grimes return (FAIL); 5928fae3551SRodney W. Grimes } 5938fae3551SRodney W. Grimes (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 5948fae3551SRodney W. Grimes (void) chmod(name, mode); 595d87d79aeSPeter Wemm (void) chflags(name, flags); 5968fae3551SRodney W. Grimes skipfile(); 5978fae3551SRodney W. Grimes utimes(name, timep); 5988fae3551SRodney W. Grimes return (GOOD); 5998fae3551SRodney W. Grimes 6008fae3551SRodney W. Grimes case IFREG: 6018fae3551SRodney W. Grimes vprintf(stdout, "extract file %s\n", name); 6028fae3551SRodney W. Grimes if (Nflag) { 6038fae3551SRodney W. Grimes skipfile(); 6048fae3551SRodney W. Grimes return (GOOD); 6058fae3551SRodney W. Grimes } 606335524b9SWarner Losh if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 607335524b9SWarner Losh 0666)) < 0) { 6088fae3551SRodney W. Grimes fprintf(stderr, "%s: cannot create file: %s\n", 6098fae3551SRodney W. Grimes name, strerror(errno)); 6108fae3551SRodney W. Grimes skipfile(); 6118fae3551SRodney W. Grimes return (FAIL); 6128fae3551SRodney W. Grimes } 6138fae3551SRodney W. Grimes (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); 6148fae3551SRodney W. Grimes (void) fchmod(ofile, mode); 615d87d79aeSPeter Wemm (void) fchflags(ofile, flags); 6168fae3551SRodney W. Grimes getfile(xtrfile, xtrskip); 6178fae3551SRodney W. Grimes (void) close(ofile); 6188fae3551SRodney W. Grimes utimes(name, timep); 6198fae3551SRodney W. Grimes return (GOOD); 6208fae3551SRodney W. Grimes } 6218fae3551SRodney W. Grimes /* NOTREACHED */ 6228fae3551SRodney W. Grimes } 6238fae3551SRodney W. Grimes 6248fae3551SRodney W. Grimes /* 6258fae3551SRodney W. Grimes * skip over bit maps on the tape 6268fae3551SRodney W. Grimes */ 6278fae3551SRodney W. Grimes void 6288fae3551SRodney W. Grimes skipmaps() 6298fae3551SRodney W. Grimes { 6308fae3551SRodney W. Grimes 6318fae3551SRodney W. Grimes while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) 6328fae3551SRodney W. Grimes skipfile(); 6338fae3551SRodney W. Grimes } 6348fae3551SRodney W. Grimes 6358fae3551SRodney W. Grimes /* 6368fae3551SRodney W. Grimes * skip over a file on the tape 6378fae3551SRodney W. Grimes */ 6388fae3551SRodney W. Grimes void 6398fae3551SRodney W. Grimes skipfile() 6408fae3551SRodney W. Grimes { 6418fae3551SRodney W. Grimes 6428fae3551SRodney W. Grimes curfile.action = SKIP; 6438fae3551SRodney W. Grimes getfile(xtrnull, xtrnull); 6448fae3551SRodney W. Grimes } 6458fae3551SRodney W. Grimes 6468fae3551SRodney W. Grimes /* 6478fae3551SRodney W. Grimes * Extract a file from the tape. 6488fae3551SRodney W. Grimes * When an allocated block is found it is passed to the fill function; 6498fae3551SRodney W. Grimes * when an unallocated block (hole) is found, a zeroed buffer is passed 6508fae3551SRodney W. Grimes * to the skip function. 6518fae3551SRodney W. Grimes */ 6528fae3551SRodney W. Grimes void 6538fae3551SRodney W. Grimes getfile(fill, skip) 6548fae3551SRodney W. Grimes void (*fill) __P((char *, long)); 6558fae3551SRodney W. Grimes void (*skip) __P((char *, long)); 6568fae3551SRodney W. Grimes { 6578fae3551SRodney W. Grimes register int i; 6588fae3551SRodney W. Grimes int curblk = 0; 659d87d79aeSPeter Wemm quad_t size = spcl.c_dinode.di_size; 6608fae3551SRodney W. Grimes static char clearedbuf[MAXBSIZE]; 6618fae3551SRodney W. Grimes char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 6628fae3551SRodney W. Grimes char junk[TP_BSIZE]; 6638fae3551SRodney W. Grimes 6648fae3551SRodney W. Grimes if (spcl.c_type == TS_END) 6658fae3551SRodney W. Grimes panic("ran off end of tape\n"); 6668fae3551SRodney W. Grimes if (spcl.c_magic != NFS_MAGIC) 6678fae3551SRodney W. Grimes panic("not at beginning of a file\n"); 6688fae3551SRodney W. Grimes if (!gettingfile && setjmp(restart) != 0) 6698fae3551SRodney W. Grimes return; 6708fae3551SRodney W. Grimes gettingfile++; 6718fae3551SRodney W. Grimes loop: 6728fae3551SRodney W. Grimes for (i = 0; i < spcl.c_count; i++) { 6738fae3551SRodney W. Grimes if (spcl.c_addr[i]) { 6748fae3551SRodney W. Grimes readtape(&buf[curblk++][0]); 6758fae3551SRodney W. Grimes if (curblk == fssize / TP_BSIZE) { 676d87d79aeSPeter Wemm (*fill)((char *)buf, (long)(size > TP_BSIZE ? 677d87d79aeSPeter Wemm fssize : (curblk - 1) * TP_BSIZE + size)); 6788fae3551SRodney W. Grimes curblk = 0; 6798fae3551SRodney W. Grimes } 6808fae3551SRodney W. Grimes } else { 6818fae3551SRodney W. Grimes if (curblk > 0) { 682d87d79aeSPeter Wemm (*fill)((char *)buf, (long)(size > TP_BSIZE ? 683d87d79aeSPeter Wemm curblk * TP_BSIZE : 684d87d79aeSPeter Wemm (curblk - 1) * TP_BSIZE + size)); 6858fae3551SRodney W. Grimes curblk = 0; 6868fae3551SRodney W. Grimes } 687d87d79aeSPeter Wemm (*skip)(clearedbuf, (long)(size > TP_BSIZE ? 688d87d79aeSPeter Wemm TP_BSIZE : size)); 6898fae3551SRodney W. Grimes } 6908fae3551SRodney W. Grimes if ((size -= TP_BSIZE) <= 0) { 6918fae3551SRodney W. Grimes for (i++; i < spcl.c_count; i++) 6928fae3551SRodney W. Grimes if (spcl.c_addr[i]) 6938fae3551SRodney W. Grimes readtape(junk); 6948fae3551SRodney W. Grimes break; 6958fae3551SRodney W. Grimes } 6968fae3551SRodney W. Grimes } 6978fae3551SRodney W. Grimes if (gethead(&spcl) == GOOD && size > 0) { 6988fae3551SRodney W. Grimes if (spcl.c_type == TS_ADDR) 6998fae3551SRodney W. Grimes goto loop; 7008fae3551SRodney W. Grimes dprintf(stdout, 7018fae3551SRodney W. Grimes "Missing address (header) block for %s at %d blocks\n", 7028fae3551SRodney W. Grimes curfile.name, blksread); 7038fae3551SRodney W. Grimes } 7048fae3551SRodney W. Grimes if (curblk > 0) 705d87d79aeSPeter Wemm (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size)); 7068fae3551SRodney W. Grimes findinode(&spcl); 7078fae3551SRodney W. Grimes gettingfile = 0; 7088fae3551SRodney W. Grimes } 7098fae3551SRodney W. Grimes 7108fae3551SRodney W. Grimes /* 7118fae3551SRodney W. Grimes * Write out the next block of a file. 7128fae3551SRodney W. Grimes */ 7138fae3551SRodney W. Grimes static void 7148fae3551SRodney W. Grimes xtrfile(buf, size) 7158fae3551SRodney W. Grimes char *buf; 7168fae3551SRodney W. Grimes long size; 7178fae3551SRodney W. Grimes { 7188fae3551SRodney W. Grimes 7198fae3551SRodney W. Grimes if (Nflag) 7208fae3551SRodney W. Grimes return; 7218fae3551SRodney W. Grimes if (write(ofile, buf, (int) size) == -1) { 7228fae3551SRodney W. Grimes fprintf(stderr, 7238fae3551SRodney W. Grimes "write error extracting inode %d, name %s\nwrite: %s\n", 7248fae3551SRodney W. Grimes curfile.ino, curfile.name, strerror(errno)); 7258fae3551SRodney W. Grimes done(1); 7268fae3551SRodney W. Grimes } 7278fae3551SRodney W. Grimes } 7288fae3551SRodney W. Grimes 7298fae3551SRodney W. Grimes /* 7308fae3551SRodney W. Grimes * Skip over a hole in a file. 7318fae3551SRodney W. Grimes */ 7328fae3551SRodney W. Grimes /* ARGSUSED */ 7338fae3551SRodney W. Grimes static void 7348fae3551SRodney W. Grimes xtrskip(buf, size) 7358fae3551SRodney W. Grimes char *buf; 7368fae3551SRodney W. Grimes long size; 7378fae3551SRodney W. Grimes { 7388fae3551SRodney W. Grimes 7398fae3551SRodney W. Grimes if (lseek(ofile, size, SEEK_CUR) == -1) { 7408fae3551SRodney W. Grimes fprintf(stderr, 7418fae3551SRodney W. Grimes "seek error extracting inode %d, name %s\nlseek: %s\n", 7428fae3551SRodney W. Grimes curfile.ino, curfile.name, strerror(errno)); 7438fae3551SRodney W. Grimes done(1); 7448fae3551SRodney W. Grimes } 7458fae3551SRodney W. Grimes } 7468fae3551SRodney W. Grimes 7478fae3551SRodney W. Grimes /* 7488fae3551SRodney W. Grimes * Collect the next block of a symbolic link. 7498fae3551SRodney W. Grimes */ 7508fae3551SRodney W. Grimes static void 7518fae3551SRodney W. Grimes xtrlnkfile(buf, size) 7528fae3551SRodney W. Grimes char *buf; 7538fae3551SRodney W. Grimes long size; 7548fae3551SRodney W. Grimes { 7558fae3551SRodney W. Grimes 7568fae3551SRodney W. Grimes pathlen += size; 7578fae3551SRodney W. Grimes if (pathlen > MAXPATHLEN) { 7588fae3551SRodney W. Grimes fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", 7598fae3551SRodney W. Grimes curfile.name, lnkbuf, buf, pathlen); 7608fae3551SRodney W. Grimes done(1); 7618fae3551SRodney W. Grimes } 7628fae3551SRodney W. Grimes (void) strcat(lnkbuf, buf); 7638fae3551SRodney W. Grimes } 7648fae3551SRodney W. Grimes 7658fae3551SRodney W. Grimes /* 7668fae3551SRodney W. Grimes * Skip over a hole in a symbolic link (should never happen). 7678fae3551SRodney W. Grimes */ 7688fae3551SRodney W. Grimes /* ARGSUSED */ 7698fae3551SRodney W. Grimes static void 7708fae3551SRodney W. Grimes xtrlnkskip(buf, size) 7718fae3551SRodney W. Grimes char *buf; 7728fae3551SRodney W. Grimes long size; 7738fae3551SRodney W. Grimes { 7748fae3551SRodney W. Grimes 7758fae3551SRodney W. Grimes fprintf(stderr, "unallocated block in symbolic link %s\n", 7768fae3551SRodney W. Grimes curfile.name); 7778fae3551SRodney W. Grimes done(1); 7788fae3551SRodney W. Grimes } 7798fae3551SRodney W. Grimes 7808fae3551SRodney W. Grimes /* 7818fae3551SRodney W. Grimes * Collect the next block of a bit map. 7828fae3551SRodney W. Grimes */ 7838fae3551SRodney W. Grimes static void 7848fae3551SRodney W. Grimes xtrmap(buf, size) 7858fae3551SRodney W. Grimes char *buf; 7868fae3551SRodney W. Grimes long size; 7878fae3551SRodney W. Grimes { 7888fae3551SRodney W. Grimes 789d87d79aeSPeter Wemm memmove(map, buf, size); 7908fae3551SRodney W. Grimes map += size; 7918fae3551SRodney W. Grimes } 7928fae3551SRodney W. Grimes 7938fae3551SRodney W. Grimes /* 7948fae3551SRodney W. Grimes * Skip over a hole in a bit map (should never happen). 7958fae3551SRodney W. Grimes */ 7968fae3551SRodney W. Grimes /* ARGSUSED */ 7978fae3551SRodney W. Grimes static void 7988fae3551SRodney W. Grimes xtrmapskip(buf, size) 7998fae3551SRodney W. Grimes char *buf; 8008fae3551SRodney W. Grimes long size; 8018fae3551SRodney W. Grimes { 8028fae3551SRodney W. Grimes 8038fae3551SRodney W. Grimes panic("hole in map\n"); 8048fae3551SRodney W. Grimes map += size; 8058fae3551SRodney W. Grimes } 8068fae3551SRodney W. Grimes 8078fae3551SRodney W. Grimes /* 8088fae3551SRodney W. Grimes * Noop, when an extraction function is not needed. 8098fae3551SRodney W. Grimes */ 8108fae3551SRodney W. Grimes /* ARGSUSED */ 8118fae3551SRodney W. Grimes void 8128fae3551SRodney W. Grimes xtrnull(buf, size) 8138fae3551SRodney W. Grimes char *buf; 8148fae3551SRodney W. Grimes long size; 8158fae3551SRodney W. Grimes { 8168fae3551SRodney W. Grimes 8178fae3551SRodney W. Grimes return; 8188fae3551SRodney W. Grimes } 8198fae3551SRodney W. Grimes 8208fae3551SRodney W. Grimes /* 8218fae3551SRodney W. Grimes * Read TP_BSIZE blocks from the input. 8228fae3551SRodney W. Grimes * Handle read errors, and end of media. 8238fae3551SRodney W. Grimes */ 8248fae3551SRodney W. Grimes static void 8258fae3551SRodney W. Grimes readtape(buf) 8268fae3551SRodney W. Grimes char *buf; 8278fae3551SRodney W. Grimes { 8288fae3551SRodney W. Grimes long rd, newvol, i; 8298fae3551SRodney W. Grimes int cnt, seek_failed; 8308fae3551SRodney W. Grimes 8318fae3551SRodney W. Grimes if (blkcnt < numtrec) { 832d87d79aeSPeter Wemm memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); 8338fae3551SRodney W. Grimes blksread++; 8348fae3551SRodney W. Grimes tpblksread++; 8358fae3551SRodney W. Grimes return; 8368fae3551SRodney W. Grimes } 8378fae3551SRodney W. Grimes for (i = 0; i < ntrec; i++) 8388fae3551SRodney W. Grimes ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 8398fae3551SRodney W. Grimes if (numtrec == 0) 8408fae3551SRodney W. Grimes numtrec = ntrec; 8418fae3551SRodney W. Grimes cnt = ntrec * TP_BSIZE; 8428fae3551SRodney W. Grimes rd = 0; 8438fae3551SRodney W. Grimes getmore: 8448fae3551SRodney W. Grimes #ifdef RRESTORE 8458fae3551SRodney W. Grimes if (host) 8468fae3551SRodney W. Grimes i = rmtread(&tapebuf[rd], cnt); 8478fae3551SRodney W. Grimes else 8488fae3551SRodney W. Grimes #endif 8498fae3551SRodney W. Grimes i = read(mt, &tapebuf[rd], cnt); 8508fae3551SRodney W. Grimes /* 8518fae3551SRodney W. Grimes * Check for mid-tape short read error. 8528fae3551SRodney W. Grimes * If found, skip rest of buffer and start with the next. 8538fae3551SRodney W. Grimes */ 8548fae3551SRodney W. Grimes if (!pipein && numtrec < ntrec && i > 0) { 8558fae3551SRodney W. Grimes dprintf(stdout, "mid-media short read error.\n"); 8568fae3551SRodney W. Grimes numtrec = ntrec; 8578fae3551SRodney W. Grimes } 8588fae3551SRodney W. Grimes /* 8598fae3551SRodney W. Grimes * Handle partial block read. 8608fae3551SRodney W. Grimes */ 8618fae3551SRodney W. Grimes if (pipein && i == 0 && rd > 0) 8628fae3551SRodney W. Grimes i = rd; 8638fae3551SRodney W. Grimes else if (i > 0 && i != ntrec * TP_BSIZE) { 8648fae3551SRodney W. Grimes if (pipein) { 8658fae3551SRodney W. Grimes rd += i; 8668fae3551SRodney W. Grimes cnt -= i; 8678fae3551SRodney W. Grimes if (cnt > 0) 8688fae3551SRodney W. Grimes goto getmore; 8698fae3551SRodney W. Grimes i = rd; 8708fae3551SRodney W. Grimes } else { 8718fae3551SRodney W. Grimes /* 8728fae3551SRodney W. Grimes * Short read. Process the blocks read. 8738fae3551SRodney W. Grimes */ 8748fae3551SRodney W. Grimes if (i % TP_BSIZE != 0) 8758fae3551SRodney W. Grimes vprintf(stdout, 8768fae3551SRodney W. Grimes "partial block read: %d should be %d\n", 8778fae3551SRodney W. Grimes i, ntrec * TP_BSIZE); 8788fae3551SRodney W. Grimes numtrec = i / TP_BSIZE; 8798fae3551SRodney W. Grimes } 8808fae3551SRodney W. Grimes } 8818fae3551SRodney W. Grimes /* 8828fae3551SRodney W. Grimes * Handle read error. 8838fae3551SRodney W. Grimes */ 8848fae3551SRodney W. Grimes if (i < 0) { 8858fae3551SRodney W. Grimes fprintf(stderr, "Tape read error while "); 8868fae3551SRodney W. Grimes switch (curfile.action) { 8878fae3551SRodney W. Grimes default: 8888fae3551SRodney W. Grimes fprintf(stderr, "trying to set up tape\n"); 8898fae3551SRodney W. Grimes break; 8908fae3551SRodney W. Grimes case UNKNOWN: 8918fae3551SRodney W. Grimes fprintf(stderr, "trying to resynchronize\n"); 8928fae3551SRodney W. Grimes break; 8938fae3551SRodney W. Grimes case USING: 8948fae3551SRodney W. Grimes fprintf(stderr, "restoring %s\n", curfile.name); 8958fae3551SRodney W. Grimes break; 8968fae3551SRodney W. Grimes case SKIP: 8978fae3551SRodney W. Grimes fprintf(stderr, "skipping over inode %d\n", 8988fae3551SRodney W. Grimes curfile.ino); 8998fae3551SRodney W. Grimes break; 9008fae3551SRodney W. Grimes } 9018fae3551SRodney W. Grimes if (!yflag && !reply("continue")) 9028fae3551SRodney W. Grimes done(1); 9038fae3551SRodney W. Grimes i = ntrec * TP_BSIZE; 904d87d79aeSPeter Wemm memset(tapebuf, 0, i); 9058fae3551SRodney W. Grimes #ifdef RRESTORE 9068fae3551SRodney W. Grimes if (host) 9078fae3551SRodney W. Grimes seek_failed = (rmtseek(i, 1) < 0); 9088fae3551SRodney W. Grimes else 9098fae3551SRodney W. Grimes #endif 9108fae3551SRodney W. Grimes seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); 9118fae3551SRodney W. Grimes 9128fae3551SRodney W. Grimes if (seek_failed) { 9138fae3551SRodney W. Grimes fprintf(stderr, 9148fae3551SRodney W. Grimes "continuation failed: %s\n", strerror(errno)); 9158fae3551SRodney W. Grimes done(1); 9168fae3551SRodney W. Grimes } 9178fae3551SRodney W. Grimes } 9188fae3551SRodney W. Grimes /* 9198fae3551SRodney W. Grimes * Handle end of tape. 9208fae3551SRodney W. Grimes */ 9218fae3551SRodney W. Grimes if (i == 0) { 9228fae3551SRodney W. Grimes vprintf(stdout, "End-of-tape encountered\n"); 9238fae3551SRodney W. Grimes if (!pipein) { 9248fae3551SRodney W. Grimes newvol = volno + 1; 9258fae3551SRodney W. Grimes volno = 0; 9268fae3551SRodney W. Grimes numtrec = 0; 9278fae3551SRodney W. Grimes getvol(newvol); 9288fae3551SRodney W. Grimes readtape(buf); 9298fae3551SRodney W. Grimes return; 9308fae3551SRodney W. Grimes } 9318fae3551SRodney W. Grimes if (rd % TP_BSIZE != 0) 9328fae3551SRodney W. Grimes panic("partial block read: %d should be %d\n", 9338fae3551SRodney W. Grimes rd, ntrec * TP_BSIZE); 9348fae3551SRodney W. Grimes terminateinput(); 935d87d79aeSPeter Wemm memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); 9368fae3551SRodney W. Grimes } 9378fae3551SRodney W. Grimes blkcnt = 0; 938d87d79aeSPeter Wemm memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); 9398fae3551SRodney W. Grimes blksread++; 9408fae3551SRodney W. Grimes tpblksread++; 9418fae3551SRodney W. Grimes } 9428fae3551SRodney W. Grimes 9438fae3551SRodney W. Grimes static void 9448fae3551SRodney W. Grimes findtapeblksize() 9458fae3551SRodney W. Grimes { 9468fae3551SRodney W. Grimes register long i; 9478fae3551SRodney W. Grimes 9488fae3551SRodney W. Grimes for (i = 0; i < ntrec; i++) 9498fae3551SRodney W. Grimes ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 9508fae3551SRodney W. Grimes blkcnt = 0; 9518fae3551SRodney W. Grimes #ifdef RRESTORE 9528fae3551SRodney W. Grimes if (host) 9538fae3551SRodney W. Grimes i = rmtread(tapebuf, ntrec * TP_BSIZE); 9548fae3551SRodney W. Grimes else 9558fae3551SRodney W. Grimes #endif 9568fae3551SRodney W. Grimes i = read(mt, tapebuf, ntrec * TP_BSIZE); 9578fae3551SRodney W. Grimes 9588fae3551SRodney W. Grimes if (i <= 0) { 9598fae3551SRodney W. Grimes fprintf(stderr, "tape read error: %s\n", strerror(errno)); 9608fae3551SRodney W. Grimes done(1); 9618fae3551SRodney W. Grimes } 9628fae3551SRodney W. Grimes if (i % TP_BSIZE != 0) { 9638fae3551SRodney W. Grimes fprintf(stderr, "Tape block size (%d) %s (%d)\n", 9648fae3551SRodney W. Grimes i, "is not a multiple of dump block size", TP_BSIZE); 9658fae3551SRodney W. Grimes done(1); 9668fae3551SRodney W. Grimes } 9678fae3551SRodney W. Grimes ntrec = i / TP_BSIZE; 9688fae3551SRodney W. Grimes numtrec = ntrec; 9698fae3551SRodney W. Grimes vprintf(stdout, "Tape block size is %d\n", ntrec); 9708fae3551SRodney W. Grimes } 9718fae3551SRodney W. Grimes 9728fae3551SRodney W. Grimes void 9738fae3551SRodney W. Grimes closemt() 9748fae3551SRodney W. Grimes { 9758fae3551SRodney W. Grimes 9768fae3551SRodney W. Grimes if (mt < 0) 9778fae3551SRodney W. Grimes return; 9788fae3551SRodney W. Grimes #ifdef RRESTORE 9798fae3551SRodney W. Grimes if (host) 9808fae3551SRodney W. Grimes rmtclose(); 9818fae3551SRodney W. Grimes else 9828fae3551SRodney W. Grimes #endif 9838fae3551SRodney W. Grimes (void) close(mt); 9848fae3551SRodney W. Grimes } 9858fae3551SRodney W. Grimes 9868fae3551SRodney W. Grimes /* 9878fae3551SRodney W. Grimes * Read the next block from the tape. 9888fae3551SRodney W. Grimes * Check to see if it is one of several vintage headers. 9898fae3551SRodney W. Grimes * If it is an old style header, convert it to a new style header. 9908fae3551SRodney W. Grimes * If it is not any valid header, return an error. 9918fae3551SRodney W. Grimes */ 9928fae3551SRodney W. Grimes static int 9938fae3551SRodney W. Grimes gethead(buf) 9948fae3551SRodney W. Grimes struct s_spcl *buf; 9958fae3551SRodney W. Grimes { 9968fae3551SRodney W. Grimes long i; 9978fae3551SRodney W. Grimes union { 9988fae3551SRodney W. Grimes quad_t qval; 9998fae3551SRodney W. Grimes long val[2]; 10008fae3551SRodney W. Grimes } qcvt; 10018fae3551SRodney W. Grimes union u_ospcl { 10028fae3551SRodney W. Grimes char dummy[TP_BSIZE]; 10038fae3551SRodney W. Grimes struct s_ospcl { 10048fae3551SRodney W. Grimes long c_type; 10058fae3551SRodney W. Grimes long c_date; 10068fae3551SRodney W. Grimes long c_ddate; 10078fae3551SRodney W. Grimes long c_volume; 10088fae3551SRodney W. Grimes long c_tapea; 10098fae3551SRodney W. Grimes u_short c_inumber; 10108fae3551SRodney W. Grimes long c_magic; 10118fae3551SRodney W. Grimes long c_checksum; 10128fae3551SRodney W. Grimes struct odinode { 10138fae3551SRodney W. Grimes unsigned short odi_mode; 10148fae3551SRodney W. Grimes u_short odi_nlink; 10158fae3551SRodney W. Grimes u_short odi_uid; 10168fae3551SRodney W. Grimes u_short odi_gid; 10178fae3551SRodney W. Grimes long odi_size; 10188fae3551SRodney W. Grimes long odi_rdev; 10198fae3551SRodney W. Grimes char odi_addr[36]; 10208fae3551SRodney W. Grimes long odi_atime; 10218fae3551SRodney W. Grimes long odi_mtime; 10228fae3551SRodney W. Grimes long odi_ctime; 10238fae3551SRodney W. Grimes } c_dinode; 10248fae3551SRodney W. Grimes long c_count; 10258fae3551SRodney W. Grimes char c_addr[256]; 10268fae3551SRodney W. Grimes } s_ospcl; 10278fae3551SRodney W. Grimes } u_ospcl; 10288fae3551SRodney W. Grimes 10298fae3551SRodney W. Grimes if (!cvtflag) { 10308fae3551SRodney W. Grimes readtape((char *)buf); 10318fae3551SRodney W. Grimes if (buf->c_magic != NFS_MAGIC) { 10328fae3551SRodney W. Grimes if (swabl(buf->c_magic) != NFS_MAGIC) 10338fae3551SRodney W. Grimes return (FAIL); 10348fae3551SRodney W. Grimes if (!Bcvt) { 10358fae3551SRodney W. Grimes vprintf(stdout, "Note: Doing Byte swapping\n"); 10368fae3551SRodney W. Grimes Bcvt = 1; 10378fae3551SRodney W. Grimes } 10388fae3551SRodney W. Grimes } 10398fae3551SRodney W. Grimes if (checksum((int *)buf) == FAIL) 10408fae3551SRodney W. Grimes return (FAIL); 1041a1d72e7cSWarner Losh if (Bcvt) { 10428fae3551SRodney W. Grimes swabst((u_char *)"8l4s31l", (u_char *)buf); 1043a1d72e7cSWarner Losh swabst((u_char *)"l",(u_char *) &buf->c_level); 1044a1d72e7cSWarner Losh swabst((u_char *)"2l",(u_char *) &buf->c_flags); 1045a1d72e7cSWarner Losh } 10468fae3551SRodney W. Grimes goto good; 10478fae3551SRodney W. Grimes } 10488fae3551SRodney W. Grimes readtape((char *)(&u_ospcl.s_ospcl)); 1049d87d79aeSPeter Wemm memset(buf, 0, (long)TP_BSIZE); 10508fae3551SRodney W. Grimes buf->c_type = u_ospcl.s_ospcl.c_type; 10518fae3551SRodney W. Grimes buf->c_date = u_ospcl.s_ospcl.c_date; 10528fae3551SRodney W. Grimes buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 10538fae3551SRodney W. Grimes buf->c_volume = u_ospcl.s_ospcl.c_volume; 10548fae3551SRodney W. Grimes buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 10558fae3551SRodney W. Grimes buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 10568fae3551SRodney W. Grimes buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 10578fae3551SRodney W. Grimes buf->c_magic = u_ospcl.s_ospcl.c_magic; 10588fae3551SRodney W. Grimes buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 10598fae3551SRodney W. Grimes buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 10608fae3551SRodney W. Grimes buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 10618fae3551SRodney W. Grimes buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 10628fae3551SRodney W. Grimes buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 10638fae3551SRodney W. Grimes buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 1064d87d79aeSPeter Wemm buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 1065d87d79aeSPeter Wemm buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 1066d87d79aeSPeter Wemm buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 10678fae3551SRodney W. Grimes buf->c_count = u_ospcl.s_ospcl.c_count; 1068d87d79aeSPeter Wemm memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); 10698fae3551SRodney W. Grimes if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || 10708fae3551SRodney W. Grimes checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) 10718fae3551SRodney W. Grimes return(FAIL); 10728fae3551SRodney W. Grimes buf->c_magic = NFS_MAGIC; 10738fae3551SRodney W. Grimes 10748fae3551SRodney W. Grimes good: 10758fae3551SRodney W. Grimes if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) && 10768fae3551SRodney W. Grimes (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { 10778fae3551SRodney W. Grimes qcvt.qval = buf->c_dinode.di_size; 10788fae3551SRodney W. Grimes if (qcvt.val[0] || qcvt.val[1]) { 10798fae3551SRodney W. Grimes printf("Note: Doing Quad swapping\n"); 10808fae3551SRodney W. Grimes Qcvt = 1; 10818fae3551SRodney W. Grimes } 10828fae3551SRodney W. Grimes } 10838fae3551SRodney W. Grimes if (Qcvt) { 10848fae3551SRodney W. Grimes qcvt.qval = buf->c_dinode.di_size; 10858fae3551SRodney W. Grimes i = qcvt.val[1]; 10868fae3551SRodney W. Grimes qcvt.val[1] = qcvt.val[0]; 10878fae3551SRodney W. Grimes qcvt.val[0] = i; 10888fae3551SRodney W. Grimes buf->c_dinode.di_size = qcvt.qval; 10898fae3551SRodney W. Grimes } 10908fae3551SRodney W. Grimes 10918fae3551SRodney W. Grimes switch (buf->c_type) { 10928fae3551SRodney W. Grimes 10938fae3551SRodney W. Grimes case TS_CLRI: 10948fae3551SRodney W. Grimes case TS_BITS: 10958fae3551SRodney W. Grimes /* 10968fae3551SRodney W. Grimes * Have to patch up missing information in bit map headers 10978fae3551SRodney W. Grimes */ 10988fae3551SRodney W. Grimes buf->c_inumber = 0; 10998fae3551SRodney W. Grimes buf->c_dinode.di_size = buf->c_count * TP_BSIZE; 11008fae3551SRodney W. Grimes for (i = 0; i < buf->c_count; i++) 11018fae3551SRodney W. Grimes buf->c_addr[i]++; 11028fae3551SRodney W. Grimes break; 11038fae3551SRodney W. Grimes 11048fae3551SRodney W. Grimes case TS_TAPE: 11058fae3551SRodney W. Grimes if ((buf->c_flags & DR_NEWINODEFMT) == 0) 11068fae3551SRodney W. Grimes oldinofmt = 1; 11078fae3551SRodney W. Grimes /* fall through */ 11088fae3551SRodney W. Grimes case TS_END: 11098fae3551SRodney W. Grimes buf->c_inumber = 0; 11108fae3551SRodney W. Grimes break; 11118fae3551SRodney W. Grimes 11128fae3551SRodney W. Grimes case TS_INODE: 11138fae3551SRodney W. Grimes case TS_ADDR: 11148fae3551SRodney W. Grimes break; 11158fae3551SRodney W. Grimes 11168fae3551SRodney W. Grimes default: 11178fae3551SRodney W. Grimes panic("gethead: unknown inode type %d\n", buf->c_type); 11188fae3551SRodney W. Grimes break; 11198fae3551SRodney W. Grimes } 11208fae3551SRodney W. Grimes /* 11218fae3551SRodney W. Grimes * If we are restoring a filesystem with old format inodes, 11228fae3551SRodney W. Grimes * copy the uid/gid to the new location. 11238fae3551SRodney W. Grimes */ 11248fae3551SRodney W. Grimes if (oldinofmt) { 11258fae3551SRodney W. Grimes buf->c_dinode.di_uid = buf->c_dinode.di_ouid; 11268fae3551SRodney W. Grimes buf->c_dinode.di_gid = buf->c_dinode.di_ogid; 11278fae3551SRodney W. Grimes } 11288fae3551SRodney W. Grimes if (dflag) 11298fae3551SRodney W. Grimes accthdr(buf); 11308fae3551SRodney W. Grimes return(GOOD); 11318fae3551SRodney W. Grimes } 11328fae3551SRodney W. Grimes 11338fae3551SRodney W. Grimes /* 11348fae3551SRodney W. Grimes * Check that a header is where it belongs and predict the next header 11358fae3551SRodney W. Grimes */ 11368fae3551SRodney W. Grimes static void 11378fae3551SRodney W. Grimes accthdr(header) 11388fae3551SRodney W. Grimes struct s_spcl *header; 11398fae3551SRodney W. Grimes { 11408fae3551SRodney W. Grimes static ino_t previno = 0x7fffffff; 11418fae3551SRodney W. Grimes static int prevtype; 11428fae3551SRodney W. Grimes static long predict; 11438fae3551SRodney W. Grimes long blks, i; 11448fae3551SRodney W. Grimes 11458fae3551SRodney W. Grimes if (header->c_type == TS_TAPE) { 11468fae3551SRodney W. Grimes fprintf(stderr, "Volume header (%s inode format) ", 11478fae3551SRodney W. Grimes oldinofmt ? "old" : "new"); 11488fae3551SRodney W. Grimes if (header->c_firstrec) 11498fae3551SRodney W. Grimes fprintf(stderr, "begins with record %d", 11508fae3551SRodney W. Grimes header->c_firstrec); 11518fae3551SRodney W. Grimes fprintf(stderr, "\n"); 11528fae3551SRodney W. Grimes previno = 0x7fffffff; 11538fae3551SRodney W. Grimes return; 11548fae3551SRodney W. Grimes } 11558fae3551SRodney W. Grimes if (previno == 0x7fffffff) 11568fae3551SRodney W. Grimes goto newcalc; 11578fae3551SRodney W. Grimes switch (prevtype) { 11588fae3551SRodney W. Grimes case TS_BITS: 1159d87d79aeSPeter Wemm fprintf(stderr, "Dumped inodes map header"); 11608fae3551SRodney W. Grimes break; 11618fae3551SRodney W. Grimes case TS_CLRI: 1162d87d79aeSPeter Wemm fprintf(stderr, "Used inodes map header"); 11638fae3551SRodney W. Grimes break; 11648fae3551SRodney W. Grimes case TS_INODE: 11658fae3551SRodney W. Grimes fprintf(stderr, "File header, ino %d", previno); 11668fae3551SRodney W. Grimes break; 11678fae3551SRodney W. Grimes case TS_ADDR: 11688fae3551SRodney W. Grimes fprintf(stderr, "File continuation header, ino %d", previno); 11698fae3551SRodney W. Grimes break; 11708fae3551SRodney W. Grimes case TS_END: 11718fae3551SRodney W. Grimes fprintf(stderr, "End of tape header"); 11728fae3551SRodney W. Grimes break; 11738fae3551SRodney W. Grimes } 11748fae3551SRodney W. Grimes if (predict != blksread - 1) 11758fae3551SRodney W. Grimes fprintf(stderr, "; predicted %d blocks, got %d blocks", 11768fae3551SRodney W. Grimes predict, blksread - 1); 11778fae3551SRodney W. Grimes fprintf(stderr, "\n"); 11788fae3551SRodney W. Grimes newcalc: 11798fae3551SRodney W. Grimes blks = 0; 11808fae3551SRodney W. Grimes if (header->c_type != TS_END) 11818fae3551SRodney W. Grimes for (i = 0; i < header->c_count; i++) 11828fae3551SRodney W. Grimes if (header->c_addr[i] != 0) 11838fae3551SRodney W. Grimes blks++; 11848fae3551SRodney W. Grimes predict = blks; 11858fae3551SRodney W. Grimes blksread = 0; 11868fae3551SRodney W. Grimes prevtype = header->c_type; 11878fae3551SRodney W. Grimes previno = header->c_inumber; 11888fae3551SRodney W. Grimes } 11898fae3551SRodney W. Grimes 11908fae3551SRodney W. Grimes /* 11918fae3551SRodney W. Grimes * Find an inode header. 11928fae3551SRodney W. Grimes * Complain if had to skip, and complain is set. 11938fae3551SRodney W. Grimes */ 11948fae3551SRodney W. Grimes static void 11958fae3551SRodney W. Grimes findinode(header) 11968fae3551SRodney W. Grimes struct s_spcl *header; 11978fae3551SRodney W. Grimes { 11988fae3551SRodney W. Grimes static long skipcnt = 0; 11998fae3551SRodney W. Grimes long i; 12008fae3551SRodney W. Grimes char buf[TP_BSIZE]; 12018fae3551SRodney W. Grimes 12028fae3551SRodney W. Grimes curfile.name = "<name unknown>"; 12038fae3551SRodney W. Grimes curfile.action = UNKNOWN; 12048fae3551SRodney W. Grimes curfile.dip = NULL; 12058fae3551SRodney W. Grimes curfile.ino = 0; 12068fae3551SRodney W. Grimes do { 12078fae3551SRodney W. Grimes if (header->c_magic != NFS_MAGIC) { 12088fae3551SRodney W. Grimes skipcnt++; 12098fae3551SRodney W. Grimes while (gethead(header) == FAIL || 12108fae3551SRodney W. Grimes header->c_date != dumpdate) 12118fae3551SRodney W. Grimes skipcnt++; 12128fae3551SRodney W. Grimes } 12138fae3551SRodney W. Grimes switch (header->c_type) { 12148fae3551SRodney W. Grimes 12158fae3551SRodney W. Grimes case TS_ADDR: 12168fae3551SRodney W. Grimes /* 12178fae3551SRodney W. Grimes * Skip up to the beginning of the next record 12188fae3551SRodney W. Grimes */ 12198fae3551SRodney W. Grimes for (i = 0; i < header->c_count; i++) 12208fae3551SRodney W. Grimes if (header->c_addr[i]) 12218fae3551SRodney W. Grimes readtape(buf); 12228fae3551SRodney W. Grimes while (gethead(header) == FAIL || 12238fae3551SRodney W. Grimes header->c_date != dumpdate) 12248fae3551SRodney W. Grimes skipcnt++; 12258fae3551SRodney W. Grimes break; 12268fae3551SRodney W. Grimes 12278fae3551SRodney W. Grimes case TS_INODE: 12288fae3551SRodney W. Grimes curfile.dip = &header->c_dinode; 12298fae3551SRodney W. Grimes curfile.ino = header->c_inumber; 12308fae3551SRodney W. Grimes break; 12318fae3551SRodney W. Grimes 12328fae3551SRodney W. Grimes case TS_END: 12338fae3551SRodney W. Grimes curfile.ino = maxino; 12348fae3551SRodney W. Grimes break; 12358fae3551SRodney W. Grimes 12368fae3551SRodney W. Grimes case TS_CLRI: 12378fae3551SRodney W. Grimes curfile.name = "<file removal list>"; 12388fae3551SRodney W. Grimes break; 12398fae3551SRodney W. Grimes 12408fae3551SRodney W. Grimes case TS_BITS: 12418fae3551SRodney W. Grimes curfile.name = "<file dump list>"; 12428fae3551SRodney W. Grimes break; 12438fae3551SRodney W. Grimes 12448fae3551SRodney W. Grimes case TS_TAPE: 12458fae3551SRodney W. Grimes panic("unexpected tape header\n"); 12468fae3551SRodney W. Grimes /* NOTREACHED */ 12478fae3551SRodney W. Grimes 12488fae3551SRodney W. Grimes default: 12498fae3551SRodney W. Grimes panic("unknown tape header type %d\n", spcl.c_type); 12508fae3551SRodney W. Grimes /* NOTREACHED */ 12518fae3551SRodney W. Grimes 12528fae3551SRodney W. Grimes } 12538fae3551SRodney W. Grimes } while (header->c_type == TS_ADDR); 12548fae3551SRodney W. Grimes if (skipcnt > 0) 12558fae3551SRodney W. Grimes fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt); 12568fae3551SRodney W. Grimes skipcnt = 0; 12578fae3551SRodney W. Grimes } 12588fae3551SRodney W. Grimes 12598fae3551SRodney W. Grimes static int 12608fae3551SRodney W. Grimes checksum(buf) 12618fae3551SRodney W. Grimes register int *buf; 12628fae3551SRodney W. Grimes { 12638fae3551SRodney W. Grimes register int i, j; 12648fae3551SRodney W. Grimes 12658fae3551SRodney W. Grimes j = sizeof(union u_spcl) / sizeof(int); 12668fae3551SRodney W. Grimes i = 0; 12678fae3551SRodney W. Grimes if(!Bcvt) { 12688fae3551SRodney W. Grimes do 12698fae3551SRodney W. Grimes i += *buf++; 12708fae3551SRodney W. Grimes while (--j); 12718fae3551SRodney W. Grimes } else { 12728fae3551SRodney W. Grimes /* What happens if we want to read restore tapes 12738fae3551SRodney W. Grimes for a 16bit int machine??? */ 12748fae3551SRodney W. Grimes do 12758fae3551SRodney W. Grimes i += swabl(*buf++); 12768fae3551SRodney W. Grimes while (--j); 12778fae3551SRodney W. Grimes } 12788fae3551SRodney W. Grimes 12798fae3551SRodney W. Grimes if (i != CHECKSUM) { 12808fae3551SRodney W. Grimes fprintf(stderr, "Checksum error %o, inode %d file %s\n", i, 12818fae3551SRodney W. Grimes curfile.ino, curfile.name); 12828fae3551SRodney W. Grimes return(FAIL); 12838fae3551SRodney W. Grimes } 12848fae3551SRodney W. Grimes return(GOOD); 12858fae3551SRodney W. Grimes } 12868fae3551SRodney W. Grimes 12878fae3551SRodney W. Grimes #ifdef RRESTORE 12888fae3551SRodney W. Grimes #if __STDC__ 12898fae3551SRodney W. Grimes #include <stdarg.h> 12908fae3551SRodney W. Grimes #else 12918fae3551SRodney W. Grimes #include <varargs.h> 12928fae3551SRodney W. Grimes #endif 12938fae3551SRodney W. Grimes 12948fae3551SRodney W. Grimes void 12958fae3551SRodney W. Grimes #if __STDC__ 12968fae3551SRodney W. Grimes msg(const char *fmt, ...) 12978fae3551SRodney W. Grimes #else 12988fae3551SRodney W. Grimes msg(fmt, va_alist) 12998fae3551SRodney W. Grimes char *fmt; 13008fae3551SRodney W. Grimes va_dcl 13018fae3551SRodney W. Grimes #endif 13028fae3551SRodney W. Grimes { 13038fae3551SRodney W. Grimes va_list ap; 13048fae3551SRodney W. Grimes #if __STDC__ 13058fae3551SRodney W. Grimes va_start(ap, fmt); 13068fae3551SRodney W. Grimes #else 13078fae3551SRodney W. Grimes va_start(ap); 13088fae3551SRodney W. Grimes #endif 13098fae3551SRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 13108fae3551SRodney W. Grimes va_end(ap); 13118fae3551SRodney W. Grimes } 13128fae3551SRodney W. Grimes #endif /* RRESTORE */ 13138fae3551SRodney W. Grimes 13148fae3551SRodney W. Grimes static u_char * 13158fae3551SRodney W. Grimes swabshort(sp, n) 13168fae3551SRodney W. Grimes register u_char *sp; 13178fae3551SRodney W. Grimes register int n; 13188fae3551SRodney W. Grimes { 13198fae3551SRodney W. Grimes char c; 13208fae3551SRodney W. Grimes 13218fae3551SRodney W. Grimes while (--n >= 0) { 13228fae3551SRodney W. Grimes c = sp[0]; sp[0] = sp[1]; sp[1] = c; 13238fae3551SRodney W. Grimes sp += 2; 13248fae3551SRodney W. Grimes } 13258fae3551SRodney W. Grimes return (sp); 13268fae3551SRodney W. Grimes } 13278fae3551SRodney W. Grimes 13288fae3551SRodney W. Grimes static u_char * 13298fae3551SRodney W. Grimes swablong(sp, n) 13308fae3551SRodney W. Grimes register u_char *sp; 13318fae3551SRodney W. Grimes register int n; 13328fae3551SRodney W. Grimes { 13338fae3551SRodney W. Grimes char c; 13348fae3551SRodney W. Grimes 13358fae3551SRodney W. Grimes while (--n >= 0) { 13368fae3551SRodney W. Grimes c = sp[0]; sp[0] = sp[3]; sp[3] = c; 13378fae3551SRodney W. Grimes c = sp[2]; sp[2] = sp[1]; sp[1] = c; 13388fae3551SRodney W. Grimes sp += 4; 13398fae3551SRodney W. Grimes } 13408fae3551SRodney W. Grimes return (sp); 13418fae3551SRodney W. Grimes } 13428fae3551SRodney W. Grimes 13438fae3551SRodney W. Grimes void 13448fae3551SRodney W. Grimes swabst(cp, sp) 13458fae3551SRodney W. Grimes register u_char *cp, *sp; 13468fae3551SRodney W. Grimes { 13478fae3551SRodney W. Grimes int n = 0; 13488fae3551SRodney W. Grimes 13498fae3551SRodney W. Grimes while (*cp) { 13508fae3551SRodney W. Grimes switch (*cp) { 13518fae3551SRodney W. Grimes case '0': case '1': case '2': case '3': case '4': 13528fae3551SRodney W. Grimes case '5': case '6': case '7': case '8': case '9': 13538fae3551SRodney W. Grimes n = (n * 10) + (*cp++ - '0'); 13548fae3551SRodney W. Grimes continue; 13558fae3551SRodney W. Grimes 13568fae3551SRodney W. Grimes case 's': case 'w': case 'h': 13578fae3551SRodney W. Grimes if (n == 0) 13588fae3551SRodney W. Grimes n = 1; 13598fae3551SRodney W. Grimes sp = swabshort(sp, n); 13608fae3551SRodney W. Grimes break; 13618fae3551SRodney W. Grimes 13628fae3551SRodney W. Grimes case 'l': 13638fae3551SRodney W. Grimes if (n == 0) 13648fae3551SRodney W. Grimes n = 1; 13658fae3551SRodney W. Grimes sp = swablong(sp, n); 13668fae3551SRodney W. Grimes break; 13678fae3551SRodney W. Grimes 13688fae3551SRodney W. Grimes default: /* Any other character, like 'b' counts as byte. */ 13698fae3551SRodney W. Grimes if (n == 0) 13708fae3551SRodney W. Grimes n = 1; 13718fae3551SRodney W. Grimes sp += n; 13728fae3551SRodney W. Grimes break; 13738fae3551SRodney W. Grimes } 13748fae3551SRodney W. Grimes cp++; 13758fae3551SRodney W. Grimes n = 0; 13768fae3551SRodney W. Grimes } 13778fae3551SRodney W. Grimes } 13788fae3551SRodney W. Grimes 13798fae3551SRodney W. Grimes static u_long 13808fae3551SRodney W. Grimes swabl(x) 13818fae3551SRodney W. Grimes u_long x; 13828fae3551SRodney W. Grimes { 13838fae3551SRodney W. Grimes swabst((u_char *)"l", (u_char *)&x); 13848fae3551SRodney W. Grimes return (x); 13858fae3551SRodney W. Grimes } 1386