18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 48fae3551SRodney W. Grimes * Copyright (c) 1983, 1993 58fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 68fae3551SRodney W. Grimes * (c) UNIX System Laboratories, Inc. 78fae3551SRodney W. Grimes * All or some portions of this file are derived from material licensed 88fae3551SRodney W. Grimes * to the University of California by American Telephone and Telegraph 98fae3551SRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 108fae3551SRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 118fae3551SRodney W. Grimes * 128fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 138fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 148fae3551SRodney W. Grimes * are met: 158fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 168fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 178fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 188fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 198fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 20fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #include <sys/param.h> 388fae3551SRodney W. Grimes #include <sys/file.h> 398fae3551SRodney W. Grimes #include <sys/mtio.h> 40*6bb132baSBrooks Davis #include <sys/queue.h> 418fae3551SRodney W. Grimes #include <sys/stat.h> 42eb2fc780SGarrett Wollman #include <sys/time.h> 43772ad651SKirk McKusick #include <sys/extattr.h> 44772ad651SKirk McKusick #include <sys/acl.h> 458fae3551SRodney W. Grimes 46a9093e84SKirk McKusick #include <ufs/ufs/extattr.h> 478fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h> 488fae3551SRodney W. Grimes #include <protocols/dumprestore.h> 498fae3551SRodney W. Grimes 508fae3551SRodney W. Grimes #include <errno.h> 5189fdc4e1SMike Barcroft #include <limits.h> 528454c72cSDavid E. O'Brien #include <paths.h> 538fae3551SRodney W. Grimes #include <setjmp.h> 54cbc8bb98SDavid Malone #include <stdint.h> 558fae3551SRodney W. Grimes #include <stdio.h> 568fae3551SRodney W. Grimes #include <stdlib.h> 578fae3551SRodney W. Grimes #include <string.h> 58eb2fc780SGarrett Wollman #include <time.h> 59e54fb3f2SStefan Farfeleder #include <timeconv.h> 608fae3551SRodney W. Grimes #include <unistd.h> 618fae3551SRodney W. Grimes 628fae3551SRodney W. Grimes #include "restore.h" 638fae3551SRodney W. Grimes #include "extern.h" 648fae3551SRodney W. Grimes 658fae3551SRodney W. Grimes static long fssize = MAXBSIZE; 668fae3551SRodney W. Grimes static int mt = -1; 678fae3551SRodney W. Grimes static int pipein = 0; 68c51d70c6SBrian Feldman static int pipecmdin = 0; 69c51d70c6SBrian Feldman static FILE *popenfp = NULL; 7064121840SGuido van Rooij static char *magtape; 718fae3551SRodney W. Grimes static int blkcnt; 728fae3551SRodney W. Grimes static int numtrec; 738fae3551SRodney W. Grimes static char *tapebuf; 748fae3551SRodney W. Grimes static union u_spcl endoftapemark; 75cbc8bb98SDavid Malone static long byteslide = 0; 768fae3551SRodney W. Grimes static long blksread; /* blocks read since last header */ 771c85e6a3SKirk McKusick static int64_t tapeaddr = 0; /* current TP_BSIZE tape record */ 788fae3551SRodney W. Grimes static long tapesread; 798fae3551SRodney W. Grimes static jmp_buf restart; 808fae3551SRodney W. Grimes static int gettingfile = 0; /* restart has a valid frame */ 818fae3551SRodney W. Grimes static char *host = NULL; 821c85e6a3SKirk McKusick static int readmapflag; 838fae3551SRodney W. Grimes 848fae3551SRodney W. Grimes static int ofile; 858fae3551SRodney W. Grimes static char *map; 868fae3551SRodney W. Grimes static char lnkbuf[MAXPATHLEN + 1]; 878fae3551SRodney W. Grimes static int pathlen; 888fae3551SRodney W. Grimes 8933ceb489SKirk McKusick struct context curfile; /* describes next file available on the tape */ 9033ceb489SKirk McKusick union u_spcl u_spcl; /* mapping of variables in a control block */ 911c85e6a3SKirk McKusick int Bcvt; /* Swap Bytes */ 9266b42171SWarner Losh int oldinofmt; /* FreeBSD 1 inode format needs cvt */ 938fae3551SRodney W. Grimes 948fae3551SRodney W. Grimes #define FLUSHTAPEBUF() blkcnt = ntrec + 1 958fae3551SRodney W. Grimes 96772ad651SKirk McKusick char *namespace_names[] = EXTATTR_NAMESPACE_NAMES; 97772ad651SKirk McKusick 982db673abSWarner Losh static void accthdr(struct s_spcl *); 992db673abSWarner Losh static int checksum(int *); 1002db673abSWarner Losh static void findinode(struct s_spcl *); 1012db673abSWarner Losh static void findtapeblksize(void); 102772ad651SKirk McKusick static char *setupextattr(int); 10371a53e69SPedro F. Giffuni static void xtrattr(char *, size_t); 10471a53e69SPedro F. Giffuni static void skiphole(void (*)(char *, size_t), size_t *); 1052db673abSWarner Losh static int gethead(struct s_spcl *); 1062db673abSWarner Losh static void readtape(char *); 1072db673abSWarner Losh static void setdumpnum(void); 1082db673abSWarner Losh static u_long swabl(u_long); 1092db673abSWarner Losh static u_char *swablong(u_char *, int); 1102db673abSWarner Losh static u_char *swabshort(u_char *, int); 1112db673abSWarner Losh static void terminateinput(void); 11271a53e69SPedro F. Giffuni static void xtrfile(char *, size_t); 11371a53e69SPedro F. Giffuni static void xtrlnkfile(char *, size_t); 11471a53e69SPedro F. Giffuni static void xtrlnkskip(char *, size_t); 11571a53e69SPedro F. Giffuni static void xtrmap(char *, size_t); 11671a53e69SPedro F. Giffuni static void xtrmapskip(char *, size_t); 11771a53e69SPedro F. Giffuni static void xtrskip(char *, size_t); 1188fae3551SRodney W. Grimes 1198fae3551SRodney W. Grimes /* 1208fae3551SRodney W. Grimes * Set up an input source 1218fae3551SRodney W. Grimes */ 1228fae3551SRodney W. Grimes void 123c51d70c6SBrian Feldman setinput(char *source, int ispipecommand) 1248fae3551SRodney W. Grimes { 1258fae3551SRodney W. Grimes FLUSHTAPEBUF(); 1268fae3551SRodney W. Grimes if (bflag) 1278fae3551SRodney W. Grimes newtapebuf(ntrec); 1288fae3551SRodney W. Grimes else 129f4b72a8dSMarcelo Araujo newtapebuf(MAX(NTREC, HIGHDENSITYTREC)); 1308fae3551SRodney W. Grimes terminal = stdin; 1318fae3551SRodney W. Grimes 132c51d70c6SBrian Feldman if (ispipecommand) 133c51d70c6SBrian Feldman pipecmdin++; 134c51d70c6SBrian Feldman else 1358fae3551SRodney W. Grimes #ifdef RRESTORE 136d87d79aeSPeter Wemm if (strchr(source, ':')) { 1378fae3551SRodney W. Grimes host = source; 138d87d79aeSPeter Wemm source = strchr(host, ':'); 1398fae3551SRodney W. Grimes *source++ = '\0'; 1408fae3551SRodney W. Grimes if (rmthost(host) == 0) 1418fae3551SRodney W. Grimes done(1); 1428fae3551SRodney W. Grimes } else 1438fae3551SRodney W. Grimes #endif 1448fae3551SRodney W. Grimes if (strcmp(source, "-") == 0) { 1458fae3551SRodney W. Grimes /* 1468fae3551SRodney W. Grimes * Since input is coming from a pipe we must establish 1478fae3551SRodney W. Grimes * our own connection to the terminal. 1488fae3551SRodney W. Grimes */ 1498fae3551SRodney W. Grimes terminal = fopen(_PATH_TTY, "r"); 1508fae3551SRodney W. Grimes if (terminal == NULL) { 1518fae3551SRodney W. Grimes (void)fprintf(stderr, "cannot open %s: %s\n", 1528fae3551SRodney W. Grimes _PATH_TTY, strerror(errno)); 1538fae3551SRodney W. Grimes terminal = fopen(_PATH_DEVNULL, "r"); 1548fae3551SRodney W. Grimes if (terminal == NULL) { 1558fae3551SRodney W. Grimes (void)fprintf(stderr, "cannot open %s: %s\n", 1568fae3551SRodney W. Grimes _PATH_DEVNULL, strerror(errno)); 1578fae3551SRodney W. Grimes done(1); 1588fae3551SRodney W. Grimes } 1598fae3551SRodney W. Grimes } 1608fae3551SRodney W. Grimes pipein++; 1618fae3551SRodney W. Grimes } 16250e04779SEitan Adler /* no longer need or want root privileges */ 16350e04779SEitan Adler if (setuid(getuid()) != 0) { 16450e04779SEitan Adler fprintf(stderr, "setuid failed\n"); 16550e04779SEitan Adler done(1); 16650e04779SEitan Adler } 16764121840SGuido van Rooij magtape = strdup(source); 16864121840SGuido van Rooij if (magtape == NULL) { 16964121840SGuido van Rooij fprintf(stderr, "Cannot allocate space for magtape buffer\n"); 17064121840SGuido van Rooij done(1); 17164121840SGuido van Rooij } 1728fae3551SRodney W. Grimes } 1738fae3551SRodney W. Grimes 1748fae3551SRodney W. Grimes void 1752db673abSWarner Losh newtapebuf(long size) 1768fae3551SRodney W. Grimes { 1772db673abSWarner Losh static int tapebufsize = -1; 1788fae3551SRodney W. Grimes 1798fae3551SRodney W. Grimes ntrec = size; 1808fae3551SRodney W. Grimes if (size <= tapebufsize) 1818fae3551SRodney W. Grimes return; 1828fae3551SRodney W. Grimes if (tapebuf != NULL) 183cbc8bb98SDavid Malone free(tapebuf - TP_BSIZE); 184cbc8bb98SDavid Malone tapebuf = malloc((size+1) * TP_BSIZE); 1858fae3551SRodney W. Grimes if (tapebuf == NULL) { 1868fae3551SRodney W. Grimes fprintf(stderr, "Cannot allocate space for tape buffer\n"); 1878fae3551SRodney W. Grimes done(1); 1888fae3551SRodney W. Grimes } 189cbc8bb98SDavid Malone tapebuf += TP_BSIZE; 1908fae3551SRodney W. Grimes tapebufsize = size; 1918fae3551SRodney W. Grimes } 1928fae3551SRodney W. Grimes 1938fae3551SRodney W. Grimes /* 1948fae3551SRodney W. Grimes * Verify that the tape drive can be accessed and 1958fae3551SRodney W. Grimes * that it actually is a dump tape. 1968fae3551SRodney W. Grimes */ 1978fae3551SRodney W. Grimes void 1982db673abSWarner Losh setup(void) 1998fae3551SRodney W. Grimes { 2008fae3551SRodney W. Grimes int i, j, *ip; 2018fae3551SRodney W. Grimes struct stat stbuf; 2028fae3551SRodney W. Grimes 2038fae3551SRodney W. Grimes vprintf(stdout, "Verify tape and initialize maps\n"); 204c51d70c6SBrian Feldman if (pipecmdin) { 205c51d70c6SBrian Feldman if (setenv("RESTORE_VOLUME", "1", 1) == -1) { 206c51d70c6SBrian Feldman fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n", 207c51d70c6SBrian Feldman strerror(errno)); 208c51d70c6SBrian Feldman done(1); 209c51d70c6SBrian Feldman } 210c51d70c6SBrian Feldman popenfp = popen(magtape, "r"); 211c51d70c6SBrian Feldman mt = popenfp ? fileno(popenfp) : -1; 212c51d70c6SBrian Feldman } else 2138fae3551SRodney W. Grimes #ifdef RRESTORE 2148fae3551SRodney W. Grimes if (host) 2158fae3551SRodney W. Grimes mt = rmtopen(magtape, 0); 2168fae3551SRodney W. Grimes else 2178fae3551SRodney W. Grimes #endif 2188fae3551SRodney W. Grimes if (pipein) 2198fae3551SRodney W. Grimes mt = 0; 2208fae3551SRodney W. Grimes else 2218fae3551SRodney W. Grimes mt = open(magtape, O_RDONLY, 0); 2228fae3551SRodney W. Grimes if (mt < 0) { 2238fae3551SRodney W. Grimes fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); 2248fae3551SRodney W. Grimes done(1); 2258fae3551SRodney W. Grimes } 2268fae3551SRodney W. Grimes volno = 1; 2278fae3551SRodney W. Grimes setdumpnum(); 2288fae3551SRodney W. Grimes FLUSHTAPEBUF(); 229384e3c00SJaakko Heinonen if (!pipein && !pipecmdin && !bflag) 2308fae3551SRodney W. Grimes findtapeblksize(); 2318fae3551SRodney W. Grimes if (gethead(&spcl) == FAIL) { 2328fae3551SRodney W. Grimes fprintf(stderr, "Tape is not a dump tape\n"); 2338fae3551SRodney W. Grimes done(1); 2348fae3551SRodney W. Grimes } 2358fae3551SRodney W. Grimes if (pipein) { 2361c85e6a3SKirk McKusick endoftapemark.s_spcl.c_magic = FS_UFS2_MAGIC; 2378fae3551SRodney W. Grimes endoftapemark.s_spcl.c_type = TS_END; 2388fae3551SRodney W. Grimes ip = (int *)&endoftapemark; 2398fae3551SRodney W. Grimes j = sizeof(union u_spcl) / sizeof(int); 2408fae3551SRodney W. Grimes i = 0; 2418fae3551SRodney W. Grimes do 2428fae3551SRodney W. Grimes i += *ip++; 2438fae3551SRodney W. Grimes while (--j); 2448fae3551SRodney W. Grimes endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 2458fae3551SRodney W. Grimes } 2468fae3551SRodney W. Grimes if (vflag || command == 't') 2478fae3551SRodney W. Grimes printdumpinfo(); 2481c85e6a3SKirk McKusick dumptime = _time64_to_time(spcl.c_ddate); 2491c85e6a3SKirk McKusick dumpdate = _time64_to_time(spcl.c_date); 2508fae3551SRodney W. Grimes if (stat(".", &stbuf) < 0) { 2518fae3551SRodney W. Grimes fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); 2528fae3551SRodney W. Grimes done(1); 2538fae3551SRodney W. Grimes } 254b535f1baSJordan K. Hubbard if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE ) 255b535f1baSJordan K. Hubbard fssize = TP_BSIZE; 256b535f1baSJordan K. Hubbard if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) 2578fae3551SRodney W. Grimes fssize = stbuf.st_blksize; 25873187559SKirk McKusick if (((TP_BSIZE - 1) & stbuf.st_blksize) != 0) { 25973187559SKirk McKusick fprintf(stderr, "Warning: filesystem with non-multiple-of-%d " 26073187559SKirk McKusick "blocksize (%d);\n", TP_BSIZE, stbuf.st_blksize); 26173187559SKirk McKusick fssize = roundup(fssize, TP_BSIZE); 26273187559SKirk McKusick fprintf(stderr, "\twriting using blocksize %ld\n", fssize); 2638fae3551SRodney W. Grimes } 2648fae3551SRodney W. Grimes if (spcl.c_volume != 1) { 2658fae3551SRodney W. Grimes fprintf(stderr, "Tape is not volume 1 of the dump\n"); 2668fae3551SRodney W. Grimes done(1); 2678fae3551SRodney W. Grimes } 2688fae3551SRodney W. Grimes if (gethead(&spcl) == FAIL) { 2697fafc6f6SBruce Evans dprintf(stdout, "header read failed at %ld blocks\n", blksread); 2708fae3551SRodney W. Grimes panic("no header after volume mark!\n"); 2718fae3551SRodney W. Grimes } 2728fae3551SRodney W. Grimes findinode(&spcl); 2738fae3551SRodney W. Grimes if (spcl.c_type != TS_CLRI) { 2748fae3551SRodney W. Grimes fprintf(stderr, "Cannot find file removal list\n"); 2758fae3551SRodney W. Grimes done(1); 2768fae3551SRodney W. Grimes } 2778fae3551SRodney W. Grimes maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; 278e25a029eSMatthew D Fleming dprintf(stdout, "maxino = %ju\n", (uintmax_t)maxino); 2798fae3551SRodney W. Grimes map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 2808fae3551SRodney W. Grimes if (map == NULL) 281d87d79aeSPeter Wemm panic("no memory for active inode map\n"); 282d87d79aeSPeter Wemm usedinomap = map; 2838fae3551SRodney W. Grimes curfile.action = USING; 284772ad651SKirk McKusick getfile(xtrmap, xtrmapskip, xtrmapskip); 2858fae3551SRodney W. Grimes if (spcl.c_type != TS_BITS) { 2868fae3551SRodney W. Grimes fprintf(stderr, "Cannot find file dump list\n"); 2878fae3551SRodney W. Grimes done(1); 2888fae3551SRodney W. Grimes } 2898fae3551SRodney W. Grimes map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 2908fae3551SRodney W. Grimes if (map == (char *)NULL) 2918fae3551SRodney W. Grimes panic("no memory for file dump list\n"); 2928fae3551SRodney W. Grimes dumpmap = map; 2938fae3551SRodney W. Grimes curfile.action = USING; 294772ad651SKirk McKusick getfile(xtrmap, xtrmapskip, xtrmapskip); 295d87d79aeSPeter Wemm /* 296d87d79aeSPeter Wemm * If there may be whiteout entries on the tape, pretend that the 297d87d79aeSPeter Wemm * whiteout inode exists, so that the whiteout entries can be 298d87d79aeSPeter Wemm * extracted. 299d87d79aeSPeter Wemm */ 3001dc349abSEd Maste SETINO(UFS_WINO, dumpmap); 301dea08b68SIan Dowse /* 'r' restores don't call getvol() for tape 1, so mark it as read. */ 302dea08b68SIan Dowse if (command == 'r') 303dea08b68SIan Dowse tapesread = 1; 3048fae3551SRodney W. Grimes } 3058fae3551SRodney W. Grimes 3068fae3551SRodney W. Grimes /* 3078fae3551SRodney W. Grimes * Prompt user to load a new dump volume. 3088fae3551SRodney W. Grimes * "Nextvol" is the next suggested volume to use. 3098fae3551SRodney W. Grimes * This suggested volume is enforced when doing full 31091ac32e4SPhilippe Charnier * or incremental restores, but can be overridden by 3118fae3551SRodney W. Grimes * the user when only extracting a subset of the files. 3128fae3551SRodney W. Grimes */ 3138fae3551SRodney W. Grimes void 3142db673abSWarner Losh getvol(long nextvol) 3158fae3551SRodney W. Grimes { 3161c85e6a3SKirk McKusick int64_t prevtapea; 3171c85e6a3SKirk McKusick long i, newvol, savecnt; 3188fae3551SRodney W. Grimes union u_spcl tmpspcl; 3198fae3551SRodney W. Grimes # define tmpbuf tmpspcl.s_spcl 3208fae3551SRodney W. Grimes char buf[TP_BSIZE]; 3218fae3551SRodney W. Grimes 3228fae3551SRodney W. Grimes if (nextvol == 1) { 3238fae3551SRodney W. Grimes tapesread = 0; 3248fae3551SRodney W. Grimes gettingfile = 0; 3258fae3551SRodney W. Grimes } 326ab3d6ee0SIan Dowse prevtapea = tapeaddr; 327ab3d6ee0SIan Dowse savecnt = blksread; 3288fae3551SRodney W. Grimes if (pipein) { 3295a59ccccSIan Dowse if (nextvol != 1) { 3308fae3551SRodney W. Grimes panic("Changing volumes on pipe input?\n"); 3315a59ccccSIan Dowse /* Avoid looping if we couldn't ask the user. */ 3325a59ccccSIan Dowse if (yflag || ferror(terminal) || feof(terminal)) 3335a59ccccSIan Dowse done(1); 3345a59ccccSIan Dowse } 3358fae3551SRodney W. Grimes if (volno == 1) 3368fae3551SRodney W. Grimes return; 3378f07cb00SPedro F. Giffuni newvol = 0; 3388fae3551SRodney W. Grimes goto gethdr; 3398fae3551SRodney W. Grimes } 3408fae3551SRodney W. Grimes again: 3418fae3551SRodney W. Grimes if (pipein) 3428fae3551SRodney W. Grimes done(1); /* pipes do not get a second chance */ 3431603684dSIan Dowse if (command == 'R' || command == 'r' || curfile.action != SKIP) 3448fae3551SRodney W. Grimes newvol = nextvol; 3451603684dSIan Dowse else 3468fae3551SRodney W. Grimes newvol = 0; 3478fae3551SRodney W. Grimes while (newvol <= 0) { 3488fae3551SRodney W. Grimes if (tapesread == 0) { 349dea08b68SIan Dowse fprintf(stderr, "%s%s%s%s%s%s%s", 3508fae3551SRodney W. Grimes "You have not read any tapes yet.\n", 351dea08b68SIan Dowse "If you are extracting just a few files,", 352dea08b68SIan Dowse " start with the last volume\n", 353dea08b68SIan Dowse "and work towards the first; restore", 354dea08b68SIan Dowse " can quickly skip tapes that\n", 355dea08b68SIan Dowse "have no further files to extract.", 356dea08b68SIan Dowse " Otherwise, begin with volume 1.\n"); 3578fae3551SRodney W. Grimes } else { 3588fae3551SRodney W. Grimes fprintf(stderr, "You have read volumes"); 3598fae3551SRodney W. Grimes strcpy(buf, ": "); 360dea08b68SIan Dowse for (i = 0; i < 32; i++) 3618fae3551SRodney W. Grimes if (tapesread & (1 << i)) { 362dea08b68SIan Dowse fprintf(stderr, "%s%ld", buf, i + 1); 3638fae3551SRodney W. Grimes strcpy(buf, ", "); 3648fae3551SRodney W. Grimes } 3658fae3551SRodney W. Grimes fprintf(stderr, "\n"); 3668fae3551SRodney W. Grimes } 3678fae3551SRodney W. Grimes do { 3688fae3551SRodney W. Grimes fprintf(stderr, "Specify next volume #: "); 3698fae3551SRodney W. Grimes (void) fflush(stderr); 3705a59ccccSIan Dowse if (fgets(buf, BUFSIZ, terminal) == NULL) 3718fae3551SRodney W. Grimes done(1); 3725a59ccccSIan Dowse } while (buf[0] == '\n'); 3738fae3551SRodney W. Grimes newvol = atoi(buf); 3748fae3551SRodney W. Grimes if (newvol <= 0) { 3758fae3551SRodney W. Grimes fprintf(stderr, 3768fae3551SRodney W. Grimes "Volume numbers are positive numerics\n"); 3778fae3551SRodney W. Grimes } 3788fae3551SRodney W. Grimes } 3798fae3551SRodney W. Grimes if (newvol == volno) { 380dea08b68SIan Dowse tapesread |= 1 << (volno - 1); 3818fae3551SRodney W. Grimes return; 3828fae3551SRodney W. Grimes } 3838fae3551SRodney W. Grimes closemt(); 3847fafc6f6SBruce Evans fprintf(stderr, "Mount tape volume %ld\n", newvol); 3858fae3551SRodney W. Grimes fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); 3868fae3551SRodney W. Grimes fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); 3878fae3551SRodney W. Grimes (void) fflush(stderr); 3885a59ccccSIan Dowse if (fgets(buf, BUFSIZ, terminal) == NULL) 3898fae3551SRodney W. Grimes done(1); 3908fae3551SRodney W. Grimes if (!strcmp(buf, "none\n")) { 3918fae3551SRodney W. Grimes terminateinput(); 3928fae3551SRodney W. Grimes return; 3938fae3551SRodney W. Grimes } 3948fae3551SRodney W. Grimes if (buf[0] != '\n') { 3958fae3551SRodney W. Grimes (void) strcpy(magtape, buf); 3968fae3551SRodney W. Grimes magtape[strlen(magtape) - 1] = '\0'; 3978fae3551SRodney W. Grimes } 398c51d70c6SBrian Feldman if (pipecmdin) { 399c51d70c6SBrian Feldman char volno[sizeof("2147483647")]; 400c51d70c6SBrian Feldman 401cca1b3aaSJaakko Heinonen (void)sprintf(volno, "%ld", newvol); 402c51d70c6SBrian Feldman if (setenv("RESTORE_VOLUME", volno, 1) == -1) { 403c51d70c6SBrian Feldman fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n", 404c51d70c6SBrian Feldman strerror(errno)); 405c51d70c6SBrian Feldman done(1); 406c51d70c6SBrian Feldman } 407c51d70c6SBrian Feldman popenfp = popen(magtape, "r"); 408c51d70c6SBrian Feldman mt = popenfp ? fileno(popenfp) : -1; 409c51d70c6SBrian Feldman } else 4108fae3551SRodney W. Grimes #ifdef RRESTORE 4118fae3551SRodney W. Grimes if (host) 4128fae3551SRodney W. Grimes mt = rmtopen(magtape, 0); 4138fae3551SRodney W. Grimes else 4148fae3551SRodney W. Grimes #endif 4158fae3551SRodney W. Grimes mt = open(magtape, O_RDONLY, 0); 4168fae3551SRodney W. Grimes 4178fae3551SRodney W. Grimes if (mt == -1) { 4188fae3551SRodney W. Grimes fprintf(stderr, "Cannot open %s\n", magtape); 4198fae3551SRodney W. Grimes volno = -1; 4208fae3551SRodney W. Grimes goto again; 4218fae3551SRodney W. Grimes } 4228fae3551SRodney W. Grimes gethdr: 4238fae3551SRodney W. Grimes volno = newvol; 4248fae3551SRodney W. Grimes setdumpnum(); 4258fae3551SRodney W. Grimes FLUSHTAPEBUF(); 4268fae3551SRodney W. Grimes if (gethead(&tmpbuf) == FAIL) { 4277fafc6f6SBruce Evans dprintf(stdout, "header read failed at %ld blocks\n", blksread); 4288fae3551SRodney W. Grimes fprintf(stderr, "tape is not dump tape\n"); 4298fae3551SRodney W. Grimes volno = 0; 4308fae3551SRodney W. Grimes goto again; 4318fae3551SRodney W. Grimes } 4328fae3551SRodney W. Grimes if (tmpbuf.c_volume != volno) { 433cca1b3aaSJaakko Heinonen fprintf(stderr, "Wrong volume (%jd)\n", 434cca1b3aaSJaakko Heinonen (intmax_t)tmpbuf.c_volume); 4358fae3551SRodney W. Grimes volno = 0; 4368fae3551SRodney W. Grimes goto again; 4378fae3551SRodney W. Grimes } 4381c85e6a3SKirk McKusick if (_time64_to_time(tmpbuf.c_date) != dumpdate || 4391c85e6a3SKirk McKusick _time64_to_time(tmpbuf.c_ddate) != dumptime) { 4401c85e6a3SKirk McKusick time_t t = _time64_to_time(tmpbuf.c_date); 4415b3817c6SMatthew Dillon fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t)); 4428fae3551SRodney W. Grimes fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); 4438fae3551SRodney W. Grimes volno = 0; 4448fae3551SRodney W. Grimes goto again; 4458fae3551SRodney W. Grimes } 446dea08b68SIan Dowse tapesread |= 1 << (volno - 1); 4478fae3551SRodney W. Grimes blksread = savecnt; 4488fae3551SRodney W. Grimes /* 4498fae3551SRodney W. Grimes * If continuing from the previous volume, skip over any 4508fae3551SRodney W. Grimes * blocks read already at the end of the previous volume. 4518fae3551SRodney W. Grimes * 4528fae3551SRodney W. Grimes * If coming to this volume at random, skip to the beginning 4538fae3551SRodney W. Grimes * of the next record. 4548fae3551SRodney W. Grimes */ 455cca1b3aaSJaakko Heinonen dprintf(stdout, "last rec %jd, tape starts with %jd\n", 456cca1b3aaSJaakko Heinonen (intmax_t)prevtapea, (intmax_t)tmpbuf.c_tapea); 4571c85e6a3SKirk McKusick if (tmpbuf.c_type == TS_TAPE) { 4581603684dSIan Dowse if (curfile.action != USING) { 4591603684dSIan Dowse /* 4601603684dSIan Dowse * XXX Dump incorrectly sets c_count to 1 in the 4611603684dSIan Dowse * volume header of the first tape, so ignore 4621603684dSIan Dowse * c_count when volno == 1. 4631603684dSIan Dowse */ 4641603684dSIan Dowse if (volno != 1) 4658fae3551SRodney W. Grimes for (i = tmpbuf.c_count; i > 0; i--) 4668fae3551SRodney W. Grimes readtape(buf); 467ab3d6ee0SIan Dowse } else if (tmpbuf.c_tapea <= prevtapea) { 4688fae3551SRodney W. Grimes /* 469ab3d6ee0SIan Dowse * Normally the value of c_tapea in the volume 470ab3d6ee0SIan Dowse * header is the record number of the header itself. 471ab3d6ee0SIan Dowse * However in the volume header following an EOT- 472ab3d6ee0SIan Dowse * terminated tape, it is the record number of the 473ab3d6ee0SIan Dowse * first continuation data block (dump bug?). 474ab3d6ee0SIan Dowse * 475ab3d6ee0SIan Dowse * The next record we want is `prevtapea + 1'. 4768fae3551SRodney W. Grimes */ 477ab3d6ee0SIan Dowse i = prevtapea + 1 - tmpbuf.c_tapea; 4787fafc6f6SBruce Evans dprintf(stderr, "Skipping %ld duplicate record%s.\n", 4798fae3551SRodney W. Grimes i, i > 1 ? "s" : ""); 4808fae3551SRodney W. Grimes while (--i >= 0) 4818fae3551SRodney W. Grimes readtape(buf); 4828fae3551SRodney W. Grimes } 4838fae3551SRodney W. Grimes } 4841603684dSIan Dowse if (curfile.action == USING) { 4858fae3551SRodney W. Grimes if (volno == 1) 4868fae3551SRodney W. Grimes panic("active file into volume 1\n"); 4878fae3551SRodney W. Grimes return; 4888fae3551SRodney W. Grimes } 4898fae3551SRodney W. Grimes (void) gethead(&spcl); 4908fae3551SRodney W. Grimes findinode(&spcl); 4918fae3551SRodney W. Grimes if (gettingfile) { 4928fae3551SRodney W. Grimes gettingfile = 0; 4938fae3551SRodney W. Grimes longjmp(restart, 1); 4948fae3551SRodney W. Grimes } 4958fae3551SRodney W. Grimes } 4968fae3551SRodney W. Grimes 4978fae3551SRodney W. Grimes /* 4988fae3551SRodney W. Grimes * Handle unexpected EOF. 4998fae3551SRodney W. Grimes */ 5008fae3551SRodney W. Grimes static void 5012db673abSWarner Losh terminateinput(void) 5028fae3551SRodney W. Grimes { 5038fae3551SRodney W. Grimes 5048fae3551SRodney W. Grimes if (gettingfile && curfile.action == USING) { 5058fae3551SRodney W. Grimes printf("Warning: %s %s\n", 5068fae3551SRodney W. Grimes "End-of-input encountered while extracting", curfile.name); 5078fae3551SRodney W. Grimes } 5088fae3551SRodney W. Grimes curfile.name = "<name unknown>"; 5098fae3551SRodney W. Grimes curfile.action = UNKNOWN; 5101c85e6a3SKirk McKusick curfile.mode = 0; 5118fae3551SRodney W. Grimes curfile.ino = maxino; 5128fae3551SRodney W. Grimes if (gettingfile) { 5138fae3551SRodney W. Grimes gettingfile = 0; 5148fae3551SRodney W. Grimes longjmp(restart, 1); 5158fae3551SRodney W. Grimes } 5168fae3551SRodney W. Grimes } 5178fae3551SRodney W. Grimes 5188fae3551SRodney W. Grimes /* 5198fae3551SRodney W. Grimes * handle multiple dumps per tape by skipping forward to the 5208fae3551SRodney W. Grimes * appropriate one. 5218fae3551SRodney W. Grimes */ 5228fae3551SRodney W. Grimes static void 5232db673abSWarner Losh setdumpnum(void) 5248fae3551SRodney W. Grimes { 5258fae3551SRodney W. Grimes struct mtop tcom; 5268fae3551SRodney W. Grimes 5278fae3551SRodney W. Grimes if (dumpnum == 1 || volno != 1) 5288fae3551SRodney W. Grimes return; 5298fae3551SRodney W. Grimes if (pipein) { 5308fae3551SRodney W. Grimes fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); 5318fae3551SRodney W. Grimes done(1); 5328fae3551SRodney W. Grimes } 5338fae3551SRodney W. Grimes tcom.mt_op = MTFSF; 5348fae3551SRodney W. Grimes tcom.mt_count = dumpnum - 1; 5358fae3551SRodney W. Grimes #ifdef RRESTORE 5368fae3551SRodney W. Grimes if (host) 5378fae3551SRodney W. Grimes rmtioctl(MTFSF, dumpnum - 1); 5388fae3551SRodney W. Grimes else 5398fae3551SRodney W. Grimes #endif 540c51d70c6SBrian Feldman if (!pipecmdin && ioctl(mt, MTIOCTOP, (char *)&tcom) < 0) 5418fae3551SRodney W. Grimes fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); 5428fae3551SRodney W. Grimes } 5438fae3551SRodney W. Grimes 5448fae3551SRodney W. Grimes void 5452db673abSWarner Losh printdumpinfo(void) 5468fae3551SRodney W. Grimes { 5475b3817c6SMatthew Dillon time_t t; 5481c85e6a3SKirk McKusick t = _time64_to_time(spcl.c_date); 5495b3817c6SMatthew Dillon fprintf(stdout, "Dump date: %s", ctime(&t)); 5501c85e6a3SKirk McKusick t = _time64_to_time(spcl.c_ddate); 5518fae3551SRodney W. Grimes fprintf(stdout, "Dumped from: %s", 5525b3817c6SMatthew Dillon (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t)); 5538fae3551SRodney W. Grimes if (spcl.c_host[0] == '\0') 5548fae3551SRodney W. Grimes return; 555cca1b3aaSJaakko Heinonen fprintf(stderr, "Level %jd dump of %s on %s:%s\n", 556cca1b3aaSJaakko Heinonen (intmax_t)spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); 5578fae3551SRodney W. Grimes fprintf(stderr, "Label: %s\n", spcl.c_label); 5588fae3551SRodney W. Grimes } 5598fae3551SRodney W. Grimes 5608fae3551SRodney W. Grimes int 5612db673abSWarner Losh extractfile(char *name) 5628fae3551SRodney W. Grimes { 56371a53e69SPedro F. Giffuni u_int flags; 564ac5cc9e9SMaxim Konovalov uid_t uid; 565ac5cc9e9SMaxim Konovalov gid_t gid; 566d87d79aeSPeter Wemm mode_t mode; 567772ad651SKirk McKusick int extsize; 56859966d51SJilles Tjoelker struct timespec mtimep[2], ctimep[2]; 5698fae3551SRodney W. Grimes struct entry *ep; 570772ad651SKirk McKusick char *buf; 5718fae3551SRodney W. Grimes 5728fae3551SRodney W. Grimes curfile.name = name; 5738fae3551SRodney W. Grimes curfile.action = USING; 574fb36a3d8SKirk McKusick mtimep[0].tv_sec = curfile.atime_sec; 57559966d51SJilles Tjoelker mtimep[0].tv_nsec = curfile.atime_nsec; 576fb36a3d8SKirk McKusick mtimep[1].tv_sec = curfile.mtime_sec; 57759966d51SJilles Tjoelker mtimep[1].tv_nsec = curfile.mtime_nsec; 578fb36a3d8SKirk McKusick ctimep[0].tv_sec = curfile.atime_sec; 57959966d51SJilles Tjoelker ctimep[0].tv_nsec = curfile.atime_nsec; 580fb36a3d8SKirk McKusick ctimep[1].tv_sec = curfile.birthtime_sec; 58159966d51SJilles Tjoelker ctimep[1].tv_nsec = curfile.birthtime_nsec; 582772ad651SKirk McKusick extsize = curfile.extsize; 583c028393dSKirk McKusick uid = getuid(); 584c028393dSKirk McKusick if (uid == 0) 585ac5cc9e9SMaxim Konovalov uid = curfile.uid; 586ac5cc9e9SMaxim Konovalov gid = curfile.gid; 5871c85e6a3SKirk McKusick mode = curfile.mode; 5881c85e6a3SKirk McKusick flags = curfile.file_flags; 589d8ba45e2SEd Maste switch (mode & IFMT) { 5908fae3551SRodney W. Grimes 5918fae3551SRodney W. Grimes default: 5928fae3551SRodney W. Grimes fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); 5938fae3551SRodney W. Grimes skipfile(); 5948fae3551SRodney W. Grimes return (FAIL); 5958fae3551SRodney W. Grimes 596d8ba45e2SEd Maste case IFSOCK: 5978fae3551SRodney W. Grimes vprintf(stdout, "skipped socket %s\n", name); 5988fae3551SRodney W. Grimes skipfile(); 5998fae3551SRodney W. Grimes return (GOOD); 6008fae3551SRodney W. Grimes 601d8ba45e2SEd Maste case IFDIR: 6028fae3551SRodney W. Grimes if (mflag) { 6038fae3551SRodney W. Grimes ep = lookupname(name); 6048fae3551SRodney W. Grimes if (ep == NULL || ep->e_flags & EXTRACT) 6058fae3551SRodney W. Grimes panic("unextracted directory %s\n", name); 6068fae3551SRodney W. Grimes skipfile(); 6078fae3551SRodney W. Grimes return (GOOD); 6088fae3551SRodney W. Grimes } 6098fae3551SRodney W. Grimes vprintf(stdout, "extract file %s\n", name); 6108fae3551SRodney W. Grimes return (genliteraldir(name, curfile.ino)); 6118fae3551SRodney W. Grimes 612d8ba45e2SEd Maste case IFLNK: 6138fae3551SRodney W. Grimes lnkbuf[0] = '\0'; 6148fae3551SRodney W. Grimes pathlen = 0; 615772ad651SKirk McKusick buf = setupextattr(extsize); 616772ad651SKirk McKusick getfile(xtrlnkfile, xtrattr, xtrlnkskip); 6178fae3551SRodney W. Grimes if (pathlen == 0) { 6188fae3551SRodney W. Grimes vprintf(stdout, 6198fae3551SRodney W. Grimes "%s: zero length symbolic link (ignored)\n", name); 6208fae3551SRodney W. Grimes return (GOOD); 6218fae3551SRodney W. Grimes } 622a255f2f8SIan Dowse if (linkit(lnkbuf, name, SYMLINK) == GOOD) { 623ac5cc9e9SMaxim Konovalov (void) lchown(name, uid, gid); 624a255f2f8SIan Dowse (void) lchmod(name, mode); 6259dda00dfSChuck Silvers if (extsize > 0) 6269dda00dfSChuck Silvers set_extattr(-1, name, buf, extsize, SXA_LINK); 62759966d51SJilles Tjoelker (void) utimensat(AT_FDCWD, name, ctimep, 62859966d51SJilles Tjoelker AT_SYMLINK_NOFOLLOW); 62959966d51SJilles Tjoelker (void) utimensat(AT_FDCWD, name, mtimep, 63059966d51SJilles Tjoelker AT_SYMLINK_NOFOLLOW); 631ac5cc9e9SMaxim Konovalov (void) lchflags(name, flags); 632a255f2f8SIan Dowse return (GOOD); 633915a1dabSIan Dowse } 634a255f2f8SIan Dowse return (FAIL); 6358fae3551SRodney W. Grimes 636d8ba45e2SEd Maste case IFIFO: 637d87d79aeSPeter Wemm vprintf(stdout, "extract fifo %s\n", name); 638d87d79aeSPeter Wemm if (Nflag) { 639d87d79aeSPeter Wemm skipfile(); 640d87d79aeSPeter Wemm return (GOOD); 641d87d79aeSPeter Wemm } 642ac5cc9e9SMaxim Konovalov if (uflag) 64326408404SJordan K. Hubbard (void) unlink(name); 644ac5cc9e9SMaxim Konovalov if (mkfifo(name, 0600) < 0) { 645d87d79aeSPeter Wemm fprintf(stderr, "%s: cannot create fifo: %s\n", 646d6516153SMartin Renters name, strerror(errno)); 647d6516153SMartin Renters skipfile(); 648d6516153SMartin Renters return (FAIL); 649d6516153SMartin Renters } 6509dda00dfSChuck Silvers (void) chown(name, uid, gid); 6519dda00dfSChuck Silvers (void) chmod(name, mode); 652772ad651SKirk McKusick if (extsize == 0) { 653ac5cc9e9SMaxim Konovalov skipfile(); 654772ad651SKirk McKusick } else { 655772ad651SKirk McKusick buf = setupextattr(extsize); 656772ad651SKirk McKusick getfile(xtrnull, xtrattr, xtrnull); 657c9bf8148SConrad Meyer set_extattr(-1, name, buf, extsize, SXA_FILE); 658772ad651SKirk McKusick } 65959966d51SJilles Tjoelker (void) utimensat(AT_FDCWD, name, ctimep, 0); 66059966d51SJilles Tjoelker (void) utimensat(AT_FDCWD, name, mtimep, 0); 661d87d79aeSPeter Wemm (void) chflags(name, flags); 662d6516153SMartin Renters return (GOOD); 663d6516153SMartin Renters 664d8ba45e2SEd Maste case IFCHR: 665d8ba45e2SEd Maste case IFBLK: 6668fae3551SRodney W. Grimes vprintf(stdout, "extract special file %s\n", name); 6678fae3551SRodney W. Grimes if (Nflag) { 6688fae3551SRodney W. Grimes skipfile(); 6698fae3551SRodney W. Grimes return (GOOD); 6708fae3551SRodney W. Grimes } 67126408404SJordan K. Hubbard if (uflag) 67226408404SJordan K. Hubbard (void) unlink(name); 673d8ba45e2SEd Maste if (mknod(name, (mode & (IFCHR | IFBLK)) | 0600, 674ac5cc9e9SMaxim Konovalov (int)curfile.rdev) < 0) { 6758fae3551SRodney W. Grimes fprintf(stderr, "%s: cannot create special file: %s\n", 6768fae3551SRodney W. Grimes name, strerror(errno)); 6778fae3551SRodney W. Grimes skipfile(); 6788fae3551SRodney W. Grimes return (FAIL); 6798fae3551SRodney W. Grimes } 6809dda00dfSChuck Silvers (void) chown(name, uid, gid); 6819dda00dfSChuck Silvers (void) chmod(name, mode); 682772ad651SKirk McKusick if (extsize == 0) { 683ac5cc9e9SMaxim Konovalov skipfile(); 684772ad651SKirk McKusick } else { 685772ad651SKirk McKusick buf = setupextattr(extsize); 686772ad651SKirk McKusick getfile(xtrnull, xtrattr, xtrnull); 687c9bf8148SConrad Meyer set_extattr(-1, name, buf, extsize, SXA_FILE); 688772ad651SKirk McKusick } 68959966d51SJilles Tjoelker (void) utimensat(AT_FDCWD, name, ctimep, 0); 69059966d51SJilles Tjoelker (void) utimensat(AT_FDCWD, name, mtimep, 0); 691d87d79aeSPeter Wemm (void) chflags(name, flags); 6928fae3551SRodney W. Grimes return (GOOD); 6938fae3551SRodney W. Grimes 694d8ba45e2SEd Maste case IFREG: 6958fae3551SRodney W. Grimes vprintf(stdout, "extract file %s\n", name); 6968fae3551SRodney W. Grimes if (Nflag) { 6978fae3551SRodney W. Grimes skipfile(); 6988fae3551SRodney W. Grimes return (GOOD); 6998fae3551SRodney W. Grimes } 70026408404SJordan K. Hubbard if (uflag) 70126408404SJordan K. Hubbard (void) unlink(name); 702335524b9SWarner Losh if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 703ac5cc9e9SMaxim Konovalov 0600)) < 0) { 7048fae3551SRodney W. Grimes fprintf(stderr, "%s: cannot create file: %s\n", 7058fae3551SRodney W. Grimes name, strerror(errno)); 7068fae3551SRodney W. Grimes skipfile(); 7078fae3551SRodney W. Grimes return (FAIL); 7088fae3551SRodney W. Grimes } 7099dda00dfSChuck Silvers (void) fchown(ofile, uid, gid); 7109dda00dfSChuck Silvers (void) fchmod(ofile, mode); 711772ad651SKirk McKusick buf = setupextattr(extsize); 712772ad651SKirk McKusick getfile(xtrfile, xtrattr, xtrskip); 713772ad651SKirk McKusick if (extsize > 0) 714c9bf8148SConrad Meyer set_extattr(ofile, name, buf, extsize, SXA_FD); 71559966d51SJilles Tjoelker (void) futimens(ofile, ctimep); 71659966d51SJilles Tjoelker (void) futimens(ofile, mtimep); 717ac5cc9e9SMaxim Konovalov (void) fchflags(ofile, flags); 7188fae3551SRodney W. Grimes (void) close(ofile); 7198fae3551SRodney W. Grimes return (GOOD); 7208fae3551SRodney W. Grimes } 7218fae3551SRodney W. Grimes /* NOTREACHED */ 7228fae3551SRodney W. Grimes } 7238fae3551SRodney W. Grimes 7248fae3551SRodney W. Grimes /* 725c9bf8148SConrad Meyer * Set attributes on a file descriptor, link, or file. 726772ad651SKirk McKusick */ 727772ad651SKirk McKusick void 728c9bf8148SConrad Meyer set_extattr(int fd, char *name, void *buf, int size, enum set_extattr_mode mode) 729772ad651SKirk McKusick { 730772ad651SKirk McKusick struct extattr *eap, *eaend; 731c9bf8148SConrad Meyer const char *method; 732c9bf8148SConrad Meyer ssize_t res; 733c9bf8148SConrad Meyer int error; 734c9bf8148SConrad Meyer char eaname[EXTATTR_MAXNAMELEN + 1]; 735772ad651SKirk McKusick 736772ad651SKirk McKusick vprintf(stdout, "Set attributes for %s:", name); 737772ad651SKirk McKusick eaend = buf + size; 738772ad651SKirk McKusick for (eap = buf; eap < eaend; eap = EXTATTR_NEXT(eap)) { 739772ad651SKirk McKusick /* 740772ad651SKirk McKusick * Make sure this entry is complete. 741772ad651SKirk McKusick */ 742772ad651SKirk McKusick if (EXTATTR_NEXT(eap) > eaend || eap->ea_length <= 0) { 743772ad651SKirk McKusick dprintf(stdout, "\n\t%scorrupted", 744772ad651SKirk McKusick eap == buf ? "" : "remainder "); 745772ad651SKirk McKusick break; 746772ad651SKirk McKusick } 747772ad651SKirk McKusick if (eap->ea_namespace == EXTATTR_NAMESPACE_EMPTY) 748772ad651SKirk McKusick continue; 749c9bf8148SConrad Meyer snprintf(eaname, sizeof(eaname), "%.*s", 750c9bf8148SConrad Meyer (int)eap->ea_namelength, eap->ea_name); 751c9bf8148SConrad Meyer vprintf(stdout, "\n\t%s, (%d bytes), %s", 752772ad651SKirk McKusick namespace_names[eap->ea_namespace], eap->ea_length, 753c9bf8148SConrad Meyer eaname); 754772ad651SKirk McKusick /* 755772ad651SKirk McKusick * First we try the general attribute setting interface. 756772ad651SKirk McKusick * However, some attributes can only be set by root or 757772ad651SKirk McKusick * by using special interfaces (for example, ACLs). 758772ad651SKirk McKusick */ 759c9bf8148SConrad Meyer if (mode == SXA_FD) { 760c9bf8148SConrad Meyer res = extattr_set_fd(fd, eap->ea_namespace, 761c9bf8148SConrad Meyer eaname, EXTATTR_CONTENT(eap), 762c9bf8148SConrad Meyer EXTATTR_CONTENT_SIZE(eap)); 763c9bf8148SConrad Meyer method = "extattr_set_fd"; 764c9bf8148SConrad Meyer } else if (mode == SXA_LINK) { 765c9bf8148SConrad Meyer res = extattr_set_link(name, eap->ea_namespace, 766c9bf8148SConrad Meyer eaname, EXTATTR_CONTENT(eap), 767c9bf8148SConrad Meyer EXTATTR_CONTENT_SIZE(eap)); 768c9bf8148SConrad Meyer method = "extattr_set_link"; 769c9bf8148SConrad Meyer } else if (mode == SXA_FILE) { 770c9bf8148SConrad Meyer res = extattr_set_file(name, eap->ea_namespace, 771c9bf8148SConrad Meyer eaname, EXTATTR_CONTENT(eap), 772c9bf8148SConrad Meyer EXTATTR_CONTENT_SIZE(eap)); 773c9bf8148SConrad Meyer method = "extattr_set_file"; 774c9bf8148SConrad Meyer } 775c9bf8148SConrad Meyer if (res != -1) { 776c9bf8148SConrad Meyer dprintf(stdout, " (set using %s)", method); 777772ad651SKirk McKusick continue; 778772ad651SKirk McKusick } 779772ad651SKirk McKusick /* 780772ad651SKirk McKusick * If the general interface refuses to set the attribute, 781772ad651SKirk McKusick * then we try all the specialized interfaces that we 782772ad651SKirk McKusick * know about. 783772ad651SKirk McKusick */ 784772ad651SKirk McKusick if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 785c9bf8148SConrad Meyer strcmp(eaname, POSIX1E_ACL_ACCESS_EXTATTR_NAME) == 0) { 786c9bf8148SConrad Meyer if (mode == SXA_FD) { 787c9bf8148SConrad Meyer error = acl_set_fd(fd, EXTATTR_CONTENT(eap)); 788c9bf8148SConrad Meyer method = "acl_set_fd"; 789c9bf8148SConrad Meyer } else if (mode == SXA_LINK) { 790c9bf8148SConrad Meyer error = acl_set_link_np(name, ACL_TYPE_ACCESS, 791c9bf8148SConrad Meyer EXTATTR_CONTENT(eap)); 792c9bf8148SConrad Meyer method = "acl_set_link_np"; 793c9bf8148SConrad Meyer } else if (mode == SXA_FILE) { 794c9bf8148SConrad Meyer error = acl_set_file(name, ACL_TYPE_ACCESS, 795c9bf8148SConrad Meyer EXTATTR_CONTENT(eap)); 796c9bf8148SConrad Meyer method = "acl_set_file"; 797c9bf8148SConrad Meyer } 798c9bf8148SConrad Meyer if (error != -1) { 799c9bf8148SConrad Meyer dprintf(stdout, " (set using %s)", method); 800772ad651SKirk McKusick continue; 801772ad651SKirk McKusick } 802772ad651SKirk McKusick } 803772ad651SKirk McKusick if (eap->ea_namespace == EXTATTR_NAMESPACE_SYSTEM && 804c9bf8148SConrad Meyer strcmp(eaname, POSIX1E_ACL_DEFAULT_EXTATTR_NAME) == 0) { 805c9bf8148SConrad Meyer if (mode == SXA_LINK) { 806c9bf8148SConrad Meyer error = acl_set_link_np(name, ACL_TYPE_DEFAULT, 807c9bf8148SConrad Meyer EXTATTR_CONTENT(eap)); 808c9bf8148SConrad Meyer method = "acl_set_link_np"; 809c9bf8148SConrad Meyer } else { 810c9bf8148SConrad Meyer error = acl_set_file(name, ACL_TYPE_DEFAULT, 811c9bf8148SConrad Meyer EXTATTR_CONTENT(eap)); 812c9bf8148SConrad Meyer method = "acl_set_file"; 813772ad651SKirk McKusick } 814c9bf8148SConrad Meyer if (error != -1) { 815c9bf8148SConrad Meyer dprintf(stdout, " (set using %s)", method); 816772ad651SKirk McKusick continue; 817772ad651SKirk McKusick } 818772ad651SKirk McKusick } 819772ad651SKirk McKusick vprintf(stdout, " (unable to set)"); 820772ad651SKirk McKusick } 821772ad651SKirk McKusick vprintf(stdout, "\n"); 822772ad651SKirk McKusick } 823772ad651SKirk McKusick 824772ad651SKirk McKusick /* 8258fae3551SRodney W. Grimes * skip over bit maps on the tape 8268fae3551SRodney W. Grimes */ 8278fae3551SRodney W. Grimes void 8282db673abSWarner Losh skipmaps(void) 8298fae3551SRodney W. Grimes { 8308fae3551SRodney W. Grimes 8318fae3551SRodney W. Grimes while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) 8328fae3551SRodney W. Grimes skipfile(); 8338fae3551SRodney W. Grimes } 8348fae3551SRodney W. Grimes 8358fae3551SRodney W. Grimes /* 8368fae3551SRodney W. Grimes * skip over a file on the tape 8378fae3551SRodney W. Grimes */ 8388fae3551SRodney W. Grimes void 8392db673abSWarner Losh skipfile(void) 8408fae3551SRodney W. Grimes { 8418fae3551SRodney W. Grimes 8428fae3551SRodney W. Grimes curfile.action = SKIP; 843772ad651SKirk McKusick getfile(xtrnull, xtrnull, xtrnull); 8448fae3551SRodney W. Grimes } 8458fae3551SRodney W. Grimes 8468fae3551SRodney W. Grimes /* 8479ed7fa55SJohn-Mark Gurney * Skip a hole in an output file 8489ed7fa55SJohn-Mark Gurney */ 8499ed7fa55SJohn-Mark Gurney static void 85071a53e69SPedro F. Giffuni skiphole(void (*skip)(char *, size_t), size_t *seekpos) 8519ed7fa55SJohn-Mark Gurney { 8529ed7fa55SJohn-Mark Gurney char buf[MAXBSIZE]; 8539ed7fa55SJohn-Mark Gurney 8549ed7fa55SJohn-Mark Gurney if (*seekpos > 0) { 8559ed7fa55SJohn-Mark Gurney (*skip)(buf, *seekpos); 8569ed7fa55SJohn-Mark Gurney *seekpos = 0; 8579ed7fa55SJohn-Mark Gurney } 8589ed7fa55SJohn-Mark Gurney } 8599ed7fa55SJohn-Mark Gurney 8609ed7fa55SJohn-Mark Gurney /* 8618fae3551SRodney W. Grimes * Extract a file from the tape. 8628fae3551SRodney W. Grimes * When an allocated block is found it is passed to the fill function; 8638fae3551SRodney W. Grimes * when an unallocated block (hole) is found, a zeroed buffer is passed 8648fae3551SRodney W. Grimes * to the skip function. 8658fae3551SRodney W. Grimes */ 8668fae3551SRodney W. Grimes void 86771a53e69SPedro F. Giffuni getfile(void (*datafill)(char *, size_t), void (*attrfill)(char *, size_t), 86871a53e69SPedro F. Giffuni void (*skip)(char *, size_t)) 8698fae3551SRodney W. Grimes { 8703d438ad6SDavid E. O'Brien int i; 87171a53e69SPedro F. Giffuni volatile off_t size; 87271a53e69SPedro F. Giffuni size_t seekpos; 873772ad651SKirk McKusick int curblk, attrsize; 87471a53e69SPedro F. Giffuni void (*fillit)(char *, size_t); 8758fae3551SRodney W. Grimes char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 8768fae3551SRodney W. Grimes char junk[TP_BSIZE]; 8778fae3551SRodney W. Grimes 878772ad651SKirk McKusick curblk = 0; 879772ad651SKirk McKusick size = spcl.c_size; 8809ed7fa55SJohn-Mark Gurney seekpos = 0; 881772ad651SKirk McKusick attrsize = spcl.c_extsize; 8828fae3551SRodney W. Grimes if (spcl.c_type == TS_END) 8838fae3551SRodney W. Grimes panic("ran off end of tape\n"); 8841c85e6a3SKirk McKusick if (spcl.c_magic != FS_UFS2_MAGIC) 8858fae3551SRodney W. Grimes panic("not at beginning of a file\n"); 8868fae3551SRodney W. Grimes if (!gettingfile && setjmp(restart) != 0) 8878fae3551SRodney W. Grimes return; 8888fae3551SRodney W. Grimes gettingfile++; 889772ad651SKirk McKusick fillit = datafill; 890772ad651SKirk McKusick if (size == 0 && attrsize > 0) { 891772ad651SKirk McKusick fillit = attrfill; 892772ad651SKirk McKusick size = attrsize; 893772ad651SKirk McKusick attrsize = 0; 894772ad651SKirk McKusick } 8958fae3551SRodney W. Grimes loop: 8968fae3551SRodney W. Grimes for (i = 0; i < spcl.c_count; i++) { 897cbc8bb98SDavid Malone if (!readmapflag && i > TP_NINDIR) { 898cbc8bb98SDavid Malone if (Dflag) { 899cbc8bb98SDavid Malone fprintf(stderr, "spcl.c_count = %jd\n", 900cbc8bb98SDavid Malone (intmax_t)spcl.c_count); 901cbc8bb98SDavid Malone break; 902cbc8bb98SDavid Malone } else 903cbc8bb98SDavid Malone panic("spcl.c_count = %jd\n", 904cbc8bb98SDavid Malone (intmax_t)spcl.c_count); 905cbc8bb98SDavid Malone } 90649a32155SWarner Losh if (readmapflag || spcl.c_addr[i]) { 9078fae3551SRodney W. Grimes readtape(&buf[curblk++][0]); 9088fae3551SRodney W. Grimes if (curblk == fssize / TP_BSIZE) { 9099ed7fa55SJohn-Mark Gurney skiphole(skip, &seekpos); 910772ad651SKirk McKusick (*fillit)((char *)buf, (long)(size > TP_BSIZE ? 911d87d79aeSPeter Wemm fssize : (curblk - 1) * TP_BSIZE + size)); 9128fae3551SRodney W. Grimes curblk = 0; 9138fae3551SRodney W. Grimes } 9148fae3551SRodney W. Grimes } else { 9158fae3551SRodney W. Grimes if (curblk > 0) { 9169ed7fa55SJohn-Mark Gurney skiphole(skip, &seekpos); 917772ad651SKirk McKusick (*fillit)((char *)buf, (long)(size > TP_BSIZE ? 918d87d79aeSPeter Wemm curblk * TP_BSIZE : 919d87d79aeSPeter Wemm (curblk - 1) * TP_BSIZE + size)); 9208fae3551SRodney W. Grimes curblk = 0; 9218fae3551SRodney W. Grimes } 9229ed7fa55SJohn-Mark Gurney /* 9239ed7fa55SJohn-Mark Gurney * We have a block of a hole. Don't skip it 9249ed7fa55SJohn-Mark Gurney * now, because there may be next adjacent 9259ed7fa55SJohn-Mark Gurney * block of the hole in the file. Postpone the 9269ed7fa55SJohn-Mark Gurney * seek until next file write. 9279ed7fa55SJohn-Mark Gurney */ 928f4b72a8dSMarcelo Araujo seekpos += (long)MIN(TP_BSIZE, size); 9298fae3551SRodney W. Grimes } 9308fae3551SRodney W. Grimes if ((size -= TP_BSIZE) <= 0) { 931772ad651SKirk McKusick if (size > -TP_BSIZE && curblk > 0) { 9329ed7fa55SJohn-Mark Gurney skiphole(skip, &seekpos); 933772ad651SKirk McKusick (*fillit)((char *)buf, 934772ad651SKirk McKusick (long)((curblk * TP_BSIZE) + size)); 935772ad651SKirk McKusick curblk = 0; 936772ad651SKirk McKusick } 937772ad651SKirk McKusick if (attrsize > 0) { 938772ad651SKirk McKusick fillit = attrfill; 939772ad651SKirk McKusick size = attrsize; 940772ad651SKirk McKusick attrsize = 0; 941772ad651SKirk McKusick continue; 942772ad651SKirk McKusick } 943772ad651SKirk McKusick if (spcl.c_count - i > 1) 944772ad651SKirk McKusick dprintf(stdout, "skipping %d junk block(s)\n", 945772ad651SKirk McKusick spcl.c_count - i - 1); 946cbc8bb98SDavid Malone for (i++; i < spcl.c_count; i++) { 947cbc8bb98SDavid Malone if (!readmapflag && i > TP_NINDIR) { 948cbc8bb98SDavid Malone if (Dflag) { 949cbc8bb98SDavid Malone fprintf(stderr, 950cbc8bb98SDavid Malone "spcl.c_count = %jd\n", 951cbc8bb98SDavid Malone (intmax_t)spcl.c_count); 952cbc8bb98SDavid Malone break; 953cbc8bb98SDavid Malone } else 954cbc8bb98SDavid Malone panic("spcl.c_count = %jd\n", 955cbc8bb98SDavid Malone (intmax_t)spcl.c_count); 956cbc8bb98SDavid Malone } 95749a32155SWarner Losh if (readmapflag || spcl.c_addr[i]) 9588fae3551SRodney W. Grimes readtape(junk); 959cbc8bb98SDavid Malone } 9608fae3551SRodney W. Grimes break; 9618fae3551SRodney W. Grimes } 9628fae3551SRodney W. Grimes } 9638fae3551SRodney W. Grimes if (gethead(&spcl) == GOOD && size > 0) { 9648fae3551SRodney W. Grimes if (spcl.c_type == TS_ADDR) 9658fae3551SRodney W. Grimes goto loop; 9668fae3551SRodney W. Grimes dprintf(stdout, 9677fafc6f6SBruce Evans "Missing address (header) block for %s at %ld blocks\n", 9688fae3551SRodney W. Grimes curfile.name, blksread); 9698fae3551SRodney W. Grimes } 9708fae3551SRodney W. Grimes if (curblk > 0) 971772ad651SKirk McKusick panic("getfile: lost data\n"); 9728fae3551SRodney W. Grimes findinode(&spcl); 9738fae3551SRodney W. Grimes gettingfile = 0; 9748fae3551SRodney W. Grimes } 9758fae3551SRodney W. Grimes 9768fae3551SRodney W. Grimes /* 977772ad651SKirk McKusick * These variables are shared between the next two functions. 978772ad651SKirk McKusick */ 979772ad651SKirk McKusick static int extbufsize = 0; 980772ad651SKirk McKusick static char *extbuf; 981772ad651SKirk McKusick static int extloc; 982772ad651SKirk McKusick 983772ad651SKirk McKusick /* 984772ad651SKirk McKusick * Allocate a buffer into which to extract extended attributes. 985772ad651SKirk McKusick */ 986772ad651SKirk McKusick static char * 987772ad651SKirk McKusick setupextattr(int extsize) 988772ad651SKirk McKusick { 989772ad651SKirk McKusick 990772ad651SKirk McKusick extloc = 0; 991772ad651SKirk McKusick if (extsize <= extbufsize) 992772ad651SKirk McKusick return (extbuf); 993772ad651SKirk McKusick if (extbufsize > 0) 994772ad651SKirk McKusick free(extbuf); 995772ad651SKirk McKusick if ((extbuf = malloc(extsize)) != NULL) { 996772ad651SKirk McKusick extbufsize = extsize; 997772ad651SKirk McKusick return (extbuf); 998772ad651SKirk McKusick } 999772ad651SKirk McKusick extbufsize = 0; 1000772ad651SKirk McKusick extbuf = NULL; 1001e25a029eSMatthew D Fleming fprintf(stderr, "Cannot extract %d bytes %s for inode %ju, name %s\n", 1002e25a029eSMatthew D Fleming extsize, "of extended attributes", (uintmax_t)curfile.ino, 1003e25a029eSMatthew D Fleming curfile.name); 1004772ad651SKirk McKusick return (NULL); 1005772ad651SKirk McKusick } 1006772ad651SKirk McKusick 1007772ad651SKirk McKusick /* 1008772ad651SKirk McKusick * Extract the next block of extended attributes. 1009772ad651SKirk McKusick */ 1010772ad651SKirk McKusick static void 101171a53e69SPedro F. Giffuni xtrattr(char *buf, size_t size) 1012772ad651SKirk McKusick { 1013772ad651SKirk McKusick 1014772ad651SKirk McKusick if (extloc + size > extbufsize) 1015772ad651SKirk McKusick panic("overrun attribute buffer\n"); 1016772ad651SKirk McKusick memmove(&extbuf[extloc], buf, size); 1017772ad651SKirk McKusick extloc += size; 1018772ad651SKirk McKusick } 1019772ad651SKirk McKusick 1020772ad651SKirk McKusick /* 10218fae3551SRodney W. Grimes * Write out the next block of a file. 10228fae3551SRodney W. Grimes */ 10238fae3551SRodney W. Grimes static void 102471a53e69SPedro F. Giffuni xtrfile(char *buf, size_t size) 10258fae3551SRodney W. Grimes { 10268fae3551SRodney W. Grimes 10278fae3551SRodney W. Grimes if (Nflag) 10288fae3551SRodney W. Grimes return; 10298fae3551SRodney W. Grimes if (write(ofile, buf, (int) size) == -1) { 10308fae3551SRodney W. Grimes fprintf(stderr, 1031e25a029eSMatthew D Fleming "write error extracting inode %ju, name %s\nwrite: %s\n", 1032e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name, strerror(errno)); 10338fae3551SRodney W. Grimes } 10348fae3551SRodney W. Grimes } 10358fae3551SRodney W. Grimes 10368fae3551SRodney W. Grimes /* 10378fae3551SRodney W. Grimes * Skip over a hole in a file. 10388fae3551SRodney W. Grimes */ 10398fae3551SRodney W. Grimes /* ARGSUSED */ 10408fae3551SRodney W. Grimes static void 104171a53e69SPedro F. Giffuni xtrskip(char *buf, size_t size) 10428fae3551SRodney W. Grimes { 10438fae3551SRodney W. Grimes 10448fae3551SRodney W. Grimes if (lseek(ofile, size, SEEK_CUR) == -1) { 10458fae3551SRodney W. Grimes fprintf(stderr, 1046e25a029eSMatthew D Fleming "seek error extracting inode %ju, name %s\nlseek: %s\n", 1047e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name, strerror(errno)); 10488fae3551SRodney W. Grimes done(1); 10498fae3551SRodney W. Grimes } 10508fae3551SRodney W. Grimes } 10518fae3551SRodney W. Grimes 10528fae3551SRodney W. Grimes /* 10538fae3551SRodney W. Grimes * Collect the next block of a symbolic link. 10548fae3551SRodney W. Grimes */ 10558fae3551SRodney W. Grimes static void 105671a53e69SPedro F. Giffuni xtrlnkfile(char *buf, size_t size) 10578fae3551SRodney W. Grimes { 10588fae3551SRodney W. Grimes 10598fae3551SRodney W. Grimes pathlen += size; 10608fae3551SRodney W. Grimes if (pathlen > MAXPATHLEN) { 10618fae3551SRodney W. Grimes fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", 10628fae3551SRodney W. Grimes curfile.name, lnkbuf, buf, pathlen); 10638fae3551SRodney W. Grimes done(1); 10648fae3551SRodney W. Grimes } 10658fae3551SRodney W. Grimes (void) strcat(lnkbuf, buf); 10668fae3551SRodney W. Grimes } 10678fae3551SRodney W. Grimes 10688fae3551SRodney W. Grimes /* 10698fae3551SRodney W. Grimes * Skip over a hole in a symbolic link (should never happen). 10708fae3551SRodney W. Grimes */ 10718fae3551SRodney W. Grimes /* ARGSUSED */ 10728fae3551SRodney W. Grimes static void 107371a53e69SPedro F. Giffuni xtrlnkskip(char *buf, size_t size) 10748fae3551SRodney W. Grimes { 10758fae3551SRodney W. Grimes 10768fae3551SRodney W. Grimes fprintf(stderr, "unallocated block in symbolic link %s\n", 10778fae3551SRodney W. Grimes curfile.name); 10788fae3551SRodney W. Grimes done(1); 10798fae3551SRodney W. Grimes } 10808fae3551SRodney W. Grimes 10818fae3551SRodney W. Grimes /* 10828fae3551SRodney W. Grimes * Collect the next block of a bit map. 10838fae3551SRodney W. Grimes */ 10848fae3551SRodney W. Grimes static void 108571a53e69SPedro F. Giffuni xtrmap(char *buf, size_t size) 10868fae3551SRodney W. Grimes { 10878fae3551SRodney W. Grimes 1088d87d79aeSPeter Wemm memmove(map, buf, size); 10898fae3551SRodney W. Grimes map += size; 10908fae3551SRodney W. Grimes } 10918fae3551SRodney W. Grimes 10928fae3551SRodney W. Grimes /* 10938fae3551SRodney W. Grimes * Skip over a hole in a bit map (should never happen). 10948fae3551SRodney W. Grimes */ 10958fae3551SRodney W. Grimes /* ARGSUSED */ 10968fae3551SRodney W. Grimes static void 109771a53e69SPedro F. Giffuni xtrmapskip(char *buf, size_t size) 10988fae3551SRodney W. Grimes { 10998fae3551SRodney W. Grimes 11008fae3551SRodney W. Grimes panic("hole in map\n"); 11018fae3551SRodney W. Grimes map += size; 11028fae3551SRodney W. Grimes } 11038fae3551SRodney W. Grimes 11048fae3551SRodney W. Grimes /* 11058fae3551SRodney W. Grimes * Noop, when an extraction function is not needed. 11068fae3551SRodney W. Grimes */ 11078fae3551SRodney W. Grimes /* ARGSUSED */ 11088fae3551SRodney W. Grimes void 110971a53e69SPedro F. Giffuni xtrnull(char *buf, size_t size) 11108fae3551SRodney W. Grimes { 11118fae3551SRodney W. Grimes 11128fae3551SRodney W. Grimes return; 11138fae3551SRodney W. Grimes } 11148fae3551SRodney W. Grimes 11158fae3551SRodney W. Grimes /* 11168fae3551SRodney W. Grimes * Read TP_BSIZE blocks from the input. 11178fae3551SRodney W. Grimes * Handle read errors, and end of media. 11188fae3551SRodney W. Grimes */ 11198fae3551SRodney W. Grimes static void 11202db673abSWarner Losh readtape(char *buf) 11218fae3551SRodney W. Grimes { 1122cbc8bb98SDavid Malone long rd, newvol, i, oldnumtrec; 11238fae3551SRodney W. Grimes int cnt, seek_failed; 11248fae3551SRodney W. Grimes 1125cbc8bb98SDavid Malone if (blkcnt + (byteslide > 0) < numtrec) { 1126cbc8bb98SDavid Malone memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); 11278fae3551SRodney W. Grimes blksread++; 1128ab3d6ee0SIan Dowse tapeaddr++; 11298fae3551SRodney W. Grimes return; 11308fae3551SRodney W. Grimes } 1131cbc8bb98SDavid Malone if (numtrec > 0) 1132cbc8bb98SDavid Malone memmove(&tapebuf[-TP_BSIZE], 1133cbc8bb98SDavid Malone &tapebuf[(numtrec-1) * TP_BSIZE], (long)TP_BSIZE); 1134cbc8bb98SDavid Malone oldnumtrec = numtrec; 11358fae3551SRodney W. Grimes for (i = 0; i < ntrec; i++) 11368fae3551SRodney W. Grimes ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 11378fae3551SRodney W. Grimes if (numtrec == 0) 11388fae3551SRodney W. Grimes numtrec = ntrec; 11398fae3551SRodney W. Grimes cnt = ntrec * TP_BSIZE; 11408fae3551SRodney W. Grimes rd = 0; 11418fae3551SRodney W. Grimes getmore: 11428fae3551SRodney W. Grimes #ifdef RRESTORE 11438fae3551SRodney W. Grimes if (host) 11448fae3551SRodney W. Grimes i = rmtread(&tapebuf[rd], cnt); 11458fae3551SRodney W. Grimes else 11468fae3551SRodney W. Grimes #endif 11478fae3551SRodney W. Grimes i = read(mt, &tapebuf[rd], cnt); 11488fae3551SRodney W. Grimes /* 11498fae3551SRodney W. Grimes * Check for mid-tape short read error. 11508fae3551SRodney W. Grimes * If found, skip rest of buffer and start with the next. 11518fae3551SRodney W. Grimes */ 11529312d906SJaakko Heinonen if (!pipein && !pipecmdin && numtrec < ntrec && i > 0) { 11538fae3551SRodney W. Grimes dprintf(stdout, "mid-media short read error.\n"); 11548fae3551SRodney W. Grimes numtrec = ntrec; 11558fae3551SRodney W. Grimes } 11568fae3551SRodney W. Grimes /* 11578fae3551SRodney W. Grimes * Handle partial block read. 11588fae3551SRodney W. Grimes */ 11599312d906SJaakko Heinonen if ((pipein || pipecmdin) && i == 0 && rd > 0) 11608fae3551SRodney W. Grimes i = rd; 11618fae3551SRodney W. Grimes else if (i > 0 && i != ntrec * TP_BSIZE) { 11629312d906SJaakko Heinonen if (pipein || pipecmdin) { 11638fae3551SRodney W. Grimes rd += i; 11648fae3551SRodney W. Grimes cnt -= i; 11658fae3551SRodney W. Grimes if (cnt > 0) 11668fae3551SRodney W. Grimes goto getmore; 11678fae3551SRodney W. Grimes i = rd; 11688fae3551SRodney W. Grimes } else { 11698fae3551SRodney W. Grimes /* 11708fae3551SRodney W. Grimes * Short read. Process the blocks read. 11718fae3551SRodney W. Grimes */ 11728fae3551SRodney W. Grimes if (i % TP_BSIZE != 0) 11738fae3551SRodney W. Grimes vprintf(stdout, 11747fafc6f6SBruce Evans "partial block read: %ld should be %ld\n", 11758fae3551SRodney W. Grimes i, ntrec * TP_BSIZE); 11768fae3551SRodney W. Grimes numtrec = i / TP_BSIZE; 11778fae3551SRodney W. Grimes } 11788fae3551SRodney W. Grimes } 11798fae3551SRodney W. Grimes /* 11808fae3551SRodney W. Grimes * Handle read error. 11818fae3551SRodney W. Grimes */ 11828fae3551SRodney W. Grimes if (i < 0) { 11838fae3551SRodney W. Grimes fprintf(stderr, "Tape read error while "); 11848fae3551SRodney W. Grimes switch (curfile.action) { 11858fae3551SRodney W. Grimes default: 11868fae3551SRodney W. Grimes fprintf(stderr, "trying to set up tape\n"); 11878fae3551SRodney W. Grimes break; 11888fae3551SRodney W. Grimes case UNKNOWN: 11898fae3551SRodney W. Grimes fprintf(stderr, "trying to resynchronize\n"); 11908fae3551SRodney W. Grimes break; 11918fae3551SRodney W. Grimes case USING: 11928fae3551SRodney W. Grimes fprintf(stderr, "restoring %s\n", curfile.name); 11938fae3551SRodney W. Grimes break; 11948fae3551SRodney W. Grimes case SKIP: 1195e25a029eSMatthew D Fleming fprintf(stderr, "skipping over inode %ju\n", 1196e25a029eSMatthew D Fleming (uintmax_t)curfile.ino); 11978fae3551SRodney W. Grimes break; 11988fae3551SRodney W. Grimes } 11998fae3551SRodney W. Grimes if (!yflag && !reply("continue")) 12008fae3551SRodney W. Grimes done(1); 12018fae3551SRodney W. Grimes i = ntrec * TP_BSIZE; 1202d87d79aeSPeter Wemm memset(tapebuf, 0, i); 12038fae3551SRodney W. Grimes #ifdef RRESTORE 12048fae3551SRodney W. Grimes if (host) 12058fae3551SRodney W. Grimes seek_failed = (rmtseek(i, 1) < 0); 12068fae3551SRodney W. Grimes else 12078fae3551SRodney W. Grimes #endif 12088fae3551SRodney W. Grimes seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); 12098fae3551SRodney W. Grimes 12108fae3551SRodney W. Grimes if (seek_failed) { 12118fae3551SRodney W. Grimes fprintf(stderr, 12128fae3551SRodney W. Grimes "continuation failed: %s\n", strerror(errno)); 12138fae3551SRodney W. Grimes done(1); 12148fae3551SRodney W. Grimes } 12158fae3551SRodney W. Grimes } 12168fae3551SRodney W. Grimes /* 12178fae3551SRodney W. Grimes * Handle end of tape. 12188fae3551SRodney W. Grimes */ 12198fae3551SRodney W. Grimes if (i == 0) { 12208fae3551SRodney W. Grimes vprintf(stdout, "End-of-tape encountered\n"); 12218fae3551SRodney W. Grimes if (!pipein) { 12228fae3551SRodney W. Grimes newvol = volno + 1; 12238fae3551SRodney W. Grimes volno = 0; 12248fae3551SRodney W. Grimes numtrec = 0; 12258fae3551SRodney W. Grimes getvol(newvol); 12268fae3551SRodney W. Grimes readtape(buf); 12278fae3551SRodney W. Grimes return; 12288fae3551SRodney W. Grimes } 12298fae3551SRodney W. Grimes if (rd % TP_BSIZE != 0) 1230cca1b3aaSJaakko Heinonen panic("partial block read: %ld should be %ld\n", 12318fae3551SRodney W. Grimes rd, ntrec * TP_BSIZE); 12328fae3551SRodney W. Grimes terminateinput(); 1233d87d79aeSPeter Wemm memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); 12348fae3551SRodney W. Grimes } 1235cbc8bb98SDavid Malone if (oldnumtrec == 0) 12368fae3551SRodney W. Grimes blkcnt = 0; 1237cbc8bb98SDavid Malone else 1238cbc8bb98SDavid Malone blkcnt -= oldnumtrec; 1239cbc8bb98SDavid Malone memmove(buf, 1240cbc8bb98SDavid Malone &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); 12418fae3551SRodney W. Grimes blksread++; 1242ab3d6ee0SIan Dowse tapeaddr++; 12438fae3551SRodney W. Grimes } 12448fae3551SRodney W. Grimes 12458fae3551SRodney W. Grimes static void 12462db673abSWarner Losh findtapeblksize(void) 12478fae3551SRodney W. Grimes { 12483d438ad6SDavid E. O'Brien long i; 12498fae3551SRodney W. Grimes 12508fae3551SRodney W. Grimes for (i = 0; i < ntrec; i++) 12518fae3551SRodney W. Grimes ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 12528fae3551SRodney W. Grimes blkcnt = 0; 12538fae3551SRodney W. Grimes #ifdef RRESTORE 12548fae3551SRodney W. Grimes if (host) 12558fae3551SRodney W. Grimes i = rmtread(tapebuf, ntrec * TP_BSIZE); 12568fae3551SRodney W. Grimes else 12578fae3551SRodney W. Grimes #endif 12588fae3551SRodney W. Grimes i = read(mt, tapebuf, ntrec * TP_BSIZE); 12598fae3551SRodney W. Grimes 12608fae3551SRodney W. Grimes if (i <= 0) { 12618fae3551SRodney W. Grimes fprintf(stderr, "tape read error: %s\n", strerror(errno)); 12628fae3551SRodney W. Grimes done(1); 12638fae3551SRodney W. Grimes } 12648fae3551SRodney W. Grimes if (i % TP_BSIZE != 0) { 12657fafc6f6SBruce Evans fprintf(stderr, "Tape block size (%ld) %s (%d)\n", 12668fae3551SRodney W. Grimes i, "is not a multiple of dump block size", TP_BSIZE); 12678fae3551SRodney W. Grimes done(1); 12688fae3551SRodney W. Grimes } 12698fae3551SRodney W. Grimes ntrec = i / TP_BSIZE; 12708fae3551SRodney W. Grimes numtrec = ntrec; 12717fafc6f6SBruce Evans vprintf(stdout, "Tape block size is %ld\n", ntrec); 12728fae3551SRodney W. Grimes } 12738fae3551SRodney W. Grimes 12748fae3551SRodney W. Grimes void 12752db673abSWarner Losh closemt(void) 12768fae3551SRodney W. Grimes { 12778fae3551SRodney W. Grimes 12788fae3551SRodney W. Grimes if (mt < 0) 12798fae3551SRodney W. Grimes return; 1280c51d70c6SBrian Feldman if (pipecmdin) { 1281c51d70c6SBrian Feldman pclose(popenfp); 1282c51d70c6SBrian Feldman popenfp = NULL; 1283c51d70c6SBrian Feldman } else 12848fae3551SRodney W. Grimes #ifdef RRESTORE 12858fae3551SRodney W. Grimes if (host) 12868fae3551SRodney W. Grimes rmtclose(); 12878fae3551SRodney W. Grimes else 12888fae3551SRodney W. Grimes #endif 12898fae3551SRodney W. Grimes (void) close(mt); 12908fae3551SRodney W. Grimes } 12918fae3551SRodney W. Grimes 12928fae3551SRodney W. Grimes /* 12938fae3551SRodney W. Grimes * Read the next block from the tape. 12948fae3551SRodney W. Grimes * If it is not any valid header, return an error. 12958fae3551SRodney W. Grimes */ 12968fae3551SRodney W. Grimes static int 12972db673abSWarner Losh gethead(struct s_spcl *buf) 12988fae3551SRodney W. Grimes { 12998fae3551SRodney W. Grimes long i; 13008fae3551SRodney W. Grimes 13018fae3551SRodney W. Grimes readtape((char *)buf); 13021c85e6a3SKirk McKusick if (buf->c_magic != FS_UFS2_MAGIC && buf->c_magic != NFS_MAGIC) { 13031c85e6a3SKirk McKusick if (buf->c_magic == OFS_MAGIC) { 13041c85e6a3SKirk McKusick fprintf(stderr, 13051c85e6a3SKirk McKusick "Format of dump tape is too old. Must use\n"); 13061c85e6a3SKirk McKusick fprintf(stderr, 13071c85e6a3SKirk McKusick "a version of restore from before 2002.\n"); 13088fae3551SRodney W. Grimes return (FAIL); 13091c85e6a3SKirk McKusick } 13101c85e6a3SKirk McKusick if (swabl(buf->c_magic) != FS_UFS2_MAGIC && 1311bce2f1d7SAlexander Leidinger swabl(buf->c_magic) != NFS_MAGIC) { 1312bce2f1d7SAlexander Leidinger if (swabl(buf->c_magic) == OFS_MAGIC) { 13131c85e6a3SKirk McKusick fprintf(stderr, 13141c85e6a3SKirk McKusick "Format of dump tape is too old. Must use\n"); 13151c85e6a3SKirk McKusick fprintf(stderr, 13161c85e6a3SKirk McKusick "a version of restore from before 2002.\n"); 13171c85e6a3SKirk McKusick } 13181c85e6a3SKirk McKusick return (FAIL); 13191c85e6a3SKirk McKusick } 13208fae3551SRodney W. Grimes if (!Bcvt) { 13218fae3551SRodney W. Grimes vprintf(stdout, "Note: Doing Byte swapping\n"); 13228fae3551SRodney W. Grimes Bcvt = 1; 13238fae3551SRodney W. Grimes } 13248fae3551SRodney W. Grimes } 13258fae3551SRodney W. Grimes if (checksum((int *)buf) == FAIL) 13268fae3551SRodney W. Grimes return (FAIL); 1327a1d72e7cSWarner Losh if (Bcvt) { 13281c85e6a3SKirk McKusick swabst((u_char *)"8l4s1q8l2q17l", (u_char *)buf); 1329a1d72e7cSWarner Losh swabst((u_char *)"l",(u_char *) &buf->c_level); 13301c85e6a3SKirk McKusick swabst((u_char *)"2l4q",(u_char *) &buf->c_flags); 13318fae3551SRodney W. Grimes } 133249a32155SWarner Losh readmapflag = 0; 13338fae3551SRodney W. Grimes 13348fae3551SRodney W. Grimes switch (buf->c_type) { 13358fae3551SRodney W. Grimes 13368fae3551SRodney W. Grimes case TS_CLRI: 13378fae3551SRodney W. Grimes case TS_BITS: 13388fae3551SRodney W. Grimes /* 13398fae3551SRodney W. Grimes * Have to patch up missing information in bit map headers 13408fae3551SRodney W. Grimes */ 13411c85e6a3SKirk McKusick buf->c_size = buf->c_count * TP_BSIZE; 134249a32155SWarner Losh if (buf->c_count > TP_NINDIR) 134349a32155SWarner Losh readmapflag = 1; 134449a32155SWarner Losh else 13458fae3551SRodney W. Grimes for (i = 0; i < buf->c_count; i++) 13468fae3551SRodney W. Grimes buf->c_addr[i]++; 134767dafe43SKirk McKusick /* FALL THROUGH */ 13488fae3551SRodney W. Grimes 13498fae3551SRodney W. Grimes case TS_TAPE: 135067dafe43SKirk McKusick if (buf->c_magic == NFS_MAGIC && 135167dafe43SKirk McKusick (buf->c_flags & NFS_DR_NEWINODEFMT) == 0) 135266b42171SWarner Losh oldinofmt = 1; 135367dafe43SKirk McKusick /* FALL THROUGH */ 135467dafe43SKirk McKusick 13558fae3551SRodney W. Grimes case TS_END: 13568fae3551SRodney W. Grimes buf->c_inumber = 0; 135767dafe43SKirk McKusick /* FALL THROUGH */ 13588fae3551SRodney W. Grimes 135967dafe43SKirk McKusick case TS_ADDR: 13608fae3551SRodney W. Grimes case TS_INODE: 13611c85e6a3SKirk McKusick /* 13621c85e6a3SKirk McKusick * For old dump tapes, have to copy up old fields to 13631c85e6a3SKirk McKusick * new locations. 13641c85e6a3SKirk McKusick */ 13651c85e6a3SKirk McKusick if (buf->c_magic == NFS_MAGIC) { 13661c85e6a3SKirk McKusick buf->c_tapea = buf->c_old_tapea; 13671c85e6a3SKirk McKusick buf->c_firstrec = buf->c_old_firstrec; 13681c85e6a3SKirk McKusick buf->c_date = _time32_to_time(buf->c_old_date); 13691c85e6a3SKirk McKusick buf->c_ddate = _time32_to_time(buf->c_old_ddate); 13701c85e6a3SKirk McKusick buf->c_atime = _time32_to_time(buf->c_old_atime); 13711c85e6a3SKirk McKusick buf->c_mtime = _time32_to_time(buf->c_old_mtime); 13724e5867d2SKirk McKusick buf->c_birthtime = 0; 13734e5867d2SKirk McKusick buf->c_birthtimensec = 0; 13744e5867d2SKirk McKusick buf->c_extsize = 0; 13751c85e6a3SKirk McKusick } 13761c85e6a3SKirk McKusick break; 13771c85e6a3SKirk McKusick 13788fae3551SRodney W. Grimes default: 13798fae3551SRodney W. Grimes panic("gethead: unknown inode type %d\n", buf->c_type); 13808fae3551SRodney W. Grimes break; 13818fae3551SRodney W. Grimes } 138267dafe43SKirk McKusick if (dumpdate != 0 && _time64_to_time(buf->c_date) != dumpdate) 138367dafe43SKirk McKusick fprintf(stderr, "Header with wrong dumpdate.\n"); 138466b42171SWarner Losh /* 138566b42171SWarner Losh * If we're restoring a filesystem with the old (FreeBSD 1) 138666b42171SWarner Losh * format inodes, copy the uid/gid to the new location 138766b42171SWarner Losh */ 138866b42171SWarner Losh if (oldinofmt) { 138966b42171SWarner Losh buf->c_uid = buf->c_spare1[1]; 139066b42171SWarner Losh buf->c_gid = buf->c_spare1[2]; 139166b42171SWarner Losh } 13921c85e6a3SKirk McKusick buf->c_magic = FS_UFS2_MAGIC; 1393ab3d6ee0SIan Dowse tapeaddr = buf->c_tapea; 13948fae3551SRodney W. Grimes if (dflag) 13958fae3551SRodney W. Grimes accthdr(buf); 13968fae3551SRodney W. Grimes return(GOOD); 13978fae3551SRodney W. Grimes } 13988fae3551SRodney W. Grimes 13998fae3551SRodney W. Grimes /* 14008fae3551SRodney W. Grimes * Check that a header is where it belongs and predict the next header 14018fae3551SRodney W. Grimes */ 14028fae3551SRodney W. Grimes static void 14032db673abSWarner Losh accthdr(struct s_spcl *header) 14048fae3551SRodney W. Grimes { 14058fae3551SRodney W. Grimes static ino_t previno = 0x7fffffff; 14068fae3551SRodney W. Grimes static int prevtype; 14078fae3551SRodney W. Grimes static long predict; 14088fae3551SRodney W. Grimes long blks, i; 14098fae3551SRodney W. Grimes 14108fae3551SRodney W. Grimes if (header->c_type == TS_TAPE) { 14111c85e6a3SKirk McKusick fprintf(stderr, "Volume header "); 14128fae3551SRodney W. Grimes if (header->c_firstrec) 1413cca1b3aaSJaakko Heinonen fprintf(stderr, "begins with record %jd", 1414cca1b3aaSJaakko Heinonen (intmax_t)header->c_firstrec); 14158fae3551SRodney W. Grimes fprintf(stderr, "\n"); 14168fae3551SRodney W. Grimes previno = 0x7fffffff; 14178fae3551SRodney W. Grimes return; 14188fae3551SRodney W. Grimes } 14198fae3551SRodney W. Grimes if (previno == 0x7fffffff) 14208fae3551SRodney W. Grimes goto newcalc; 14218fae3551SRodney W. Grimes switch (prevtype) { 14228fae3551SRodney W. Grimes case TS_BITS: 1423d87d79aeSPeter Wemm fprintf(stderr, "Dumped inodes map header"); 14248fae3551SRodney W. Grimes break; 14258fae3551SRodney W. Grimes case TS_CLRI: 1426d87d79aeSPeter Wemm fprintf(stderr, "Used inodes map header"); 14278fae3551SRodney W. Grimes break; 14288fae3551SRodney W. Grimes case TS_INODE: 1429e25a029eSMatthew D Fleming fprintf(stderr, "File header, ino %ju", (uintmax_t)previno); 14308fae3551SRodney W. Grimes break; 14318fae3551SRodney W. Grimes case TS_ADDR: 1432e25a029eSMatthew D Fleming fprintf(stderr, "File continuation header, ino %ju", 1433e25a029eSMatthew D Fleming (uintmax_t)previno); 14348fae3551SRodney W. Grimes break; 14358fae3551SRodney W. Grimes case TS_END: 14368fae3551SRodney W. Grimes fprintf(stderr, "End of tape header"); 14378fae3551SRodney W. Grimes break; 14388fae3551SRodney W. Grimes } 14398fae3551SRodney W. Grimes if (predict != blksread - 1) 14407fafc6f6SBruce Evans fprintf(stderr, "; predicted %ld blocks, got %ld blocks", 14418fae3551SRodney W. Grimes predict, blksread - 1); 14428fae3551SRodney W. Grimes fprintf(stderr, "\n"); 14438fae3551SRodney W. Grimes newcalc: 14448fae3551SRodney W. Grimes blks = 0; 14458fae3551SRodney W. Grimes if (header->c_type != TS_END) 14468fae3551SRodney W. Grimes for (i = 0; i < header->c_count; i++) 144749a32155SWarner Losh if (readmapflag || header->c_addr[i] != 0) 14488fae3551SRodney W. Grimes blks++; 14498fae3551SRodney W. Grimes predict = blks; 14508fae3551SRodney W. Grimes blksread = 0; 14518fae3551SRodney W. Grimes prevtype = header->c_type; 14528fae3551SRodney W. Grimes previno = header->c_inumber; 14538fae3551SRodney W. Grimes } 14548fae3551SRodney W. Grimes 14558fae3551SRodney W. Grimes /* 14568fae3551SRodney W. Grimes * Find an inode header. 1457b6024ea8SIan Dowse * Complain if had to skip. 14588fae3551SRodney W. Grimes */ 14598fae3551SRodney W. Grimes static void 14602db673abSWarner Losh findinode(struct s_spcl *header) 14618fae3551SRodney W. Grimes { 14628fae3551SRodney W. Grimes static long skipcnt = 0; 14638fae3551SRodney W. Grimes long i; 14648fae3551SRodney W. Grimes char buf[TP_BSIZE]; 14651603684dSIan Dowse int htype; 14668fae3551SRodney W. Grimes 14678fae3551SRodney W. Grimes curfile.name = "<name unknown>"; 14688fae3551SRodney W. Grimes curfile.action = UNKNOWN; 14691c85e6a3SKirk McKusick curfile.mode = 0; 14708fae3551SRodney W. Grimes curfile.ino = 0; 14718fae3551SRodney W. Grimes do { 14721603684dSIan Dowse htype = header->c_type; 14731603684dSIan Dowse switch (htype) { 14748fae3551SRodney W. Grimes 14758fae3551SRodney W. Grimes case TS_ADDR: 14768fae3551SRodney W. Grimes /* 14778fae3551SRodney W. Grimes * Skip up to the beginning of the next record 14788fae3551SRodney W. Grimes */ 14798fae3551SRodney W. Grimes for (i = 0; i < header->c_count; i++) 14808fae3551SRodney W. Grimes if (header->c_addr[i]) 14818fae3551SRodney W. Grimes readtape(buf); 14828fae3551SRodney W. Grimes while (gethead(header) == FAIL || 1483cbc8bb98SDavid Malone _time64_to_time(header->c_date) != dumpdate) { 14848fae3551SRodney W. Grimes skipcnt++; 1485cbc8bb98SDavid Malone if (Dflag) { 1486cbc8bb98SDavid Malone byteslide++; 1487cbc8bb98SDavid Malone if (byteslide < TP_BSIZE) { 1488cbc8bb98SDavid Malone blkcnt--; 1489cbc8bb98SDavid Malone blksread--; 1490cbc8bb98SDavid Malone } else 1491cbc8bb98SDavid Malone byteslide = 0; 1492cbc8bb98SDavid Malone } 1493cbc8bb98SDavid Malone } 14948fae3551SRodney W. Grimes break; 14958fae3551SRodney W. Grimes 14968fae3551SRodney W. Grimes case TS_INODE: 14971c85e6a3SKirk McKusick curfile.mode = header->c_mode; 14981c85e6a3SKirk McKusick curfile.uid = header->c_uid; 14991c85e6a3SKirk McKusick curfile.gid = header->c_gid; 15001c85e6a3SKirk McKusick curfile.file_flags = header->c_file_flags; 15011c85e6a3SKirk McKusick curfile.rdev = header->c_rdev; 15021c85e6a3SKirk McKusick curfile.atime_sec = header->c_atime; 15031c85e6a3SKirk McKusick curfile.atime_nsec = header->c_atimensec; 15041c85e6a3SKirk McKusick curfile.mtime_sec = header->c_mtime; 15051c85e6a3SKirk McKusick curfile.mtime_nsec = header->c_mtimensec; 1506fb36a3d8SKirk McKusick curfile.birthtime_sec = header->c_birthtime; 1507fb36a3d8SKirk McKusick curfile.birthtime_nsec = header->c_birthtimensec; 1508772ad651SKirk McKusick curfile.extsize = header->c_extsize; 15091c85e6a3SKirk McKusick curfile.size = header->c_size; 15108fae3551SRodney W. Grimes curfile.ino = header->c_inumber; 15118fae3551SRodney W. Grimes break; 15128fae3551SRodney W. Grimes 15138fae3551SRodney W. Grimes case TS_END: 1514dea08b68SIan Dowse /* If we missed some tapes, get another volume. */ 1515dea08b68SIan Dowse if (tapesread & (tapesread + 1)) { 1516dea08b68SIan Dowse getvol(0); 1517dea08b68SIan Dowse continue; 1518dea08b68SIan Dowse } 15198fae3551SRodney W. Grimes curfile.ino = maxino; 15208fae3551SRodney W. Grimes break; 15218fae3551SRodney W. Grimes 15228fae3551SRodney W. Grimes case TS_CLRI: 15238fae3551SRodney W. Grimes curfile.name = "<file removal list>"; 15248fae3551SRodney W. Grimes break; 15258fae3551SRodney W. Grimes 15268fae3551SRodney W. Grimes case TS_BITS: 15278fae3551SRodney W. Grimes curfile.name = "<file dump list>"; 15288fae3551SRodney W. Grimes break; 15298fae3551SRodney W. Grimes 15308fae3551SRodney W. Grimes case TS_TAPE: 1531cbc8bb98SDavid Malone if (Dflag) 1532cbc8bb98SDavid Malone fprintf(stderr, "unexpected tape header\n"); 1533cbc8bb98SDavid Malone else 15348fae3551SRodney W. Grimes panic("unexpected tape header\n"); 15358fae3551SRodney W. Grimes 15368fae3551SRodney W. Grimes default: 1537cbc8bb98SDavid Malone if (Dflag) 1538cbc8bb98SDavid Malone fprintf(stderr, "unknown tape header type %d\n", 1539cbc8bb98SDavid Malone spcl.c_type); 1540cbc8bb98SDavid Malone else 1541cbc8bb98SDavid Malone panic("unknown tape header type %d\n", 1542cbc8bb98SDavid Malone spcl.c_type); 1543cbc8bb98SDavid Malone while (gethead(header) == FAIL || 1544cbc8bb98SDavid Malone _time64_to_time(header->c_date) != dumpdate) { 1545cbc8bb98SDavid Malone skipcnt++; 1546cbc8bb98SDavid Malone if (Dflag) { 1547cbc8bb98SDavid Malone byteslide++; 1548cbc8bb98SDavid Malone if (byteslide < TP_BSIZE) { 1549cbc8bb98SDavid Malone blkcnt--; 1550cbc8bb98SDavid Malone blksread--; 1551cbc8bb98SDavid Malone } else 1552cbc8bb98SDavid Malone byteslide = 0; 1553cbc8bb98SDavid Malone } 1554cbc8bb98SDavid Malone } 15558fae3551SRodney W. Grimes 15568fae3551SRodney W. Grimes } 15571603684dSIan Dowse } while (htype == TS_ADDR); 15588fae3551SRodney W. Grimes if (skipcnt > 0) 1559cbc8bb98SDavid Malone fprintf(stderr, "resync restore, skipped %ld %s\n", 1560cbc8bb98SDavid Malone skipcnt, Dflag ? "bytes" : "blocks"); 15618fae3551SRodney W. Grimes skipcnt = 0; 15628fae3551SRodney W. Grimes } 15638fae3551SRodney W. Grimes 15648fae3551SRodney W. Grimes static int 15652db673abSWarner Losh checksum(int *buf) 15668fae3551SRodney W. Grimes { 15673d438ad6SDavid E. O'Brien int i, j; 15688fae3551SRodney W. Grimes 15698fae3551SRodney W. Grimes j = sizeof(union u_spcl) / sizeof(int); 15708fae3551SRodney W. Grimes i = 0; 15718fae3551SRodney W. Grimes if (!Bcvt) { 15728fae3551SRodney W. Grimes do 15738fae3551SRodney W. Grimes i += *buf++; 15748fae3551SRodney W. Grimes while (--j); 15758fae3551SRodney W. Grimes } else { 15768fae3551SRodney W. Grimes /* What happens if we want to read restore tapes 15778fae3551SRodney W. Grimes for a 16bit int machine??? */ 15788fae3551SRodney W. Grimes do 15798fae3551SRodney W. Grimes i += swabl(*buf++); 15808fae3551SRodney W. Grimes while (--j); 15818fae3551SRodney W. Grimes } 15828fae3551SRodney W. Grimes 15838fae3551SRodney W. Grimes if (i != CHECKSUM) { 1584e25a029eSMatthew D Fleming fprintf(stderr, "Checksum error %o, inode %ju file %s\n", i, 1585e25a029eSMatthew D Fleming (uintmax_t)curfile.ino, curfile.name); 15868fae3551SRodney W. Grimes return(FAIL); 15878fae3551SRodney W. Grimes } 15888fae3551SRodney W. Grimes return(GOOD); 15898fae3551SRodney W. Grimes } 15908fae3551SRodney W. Grimes 15918fae3551SRodney W. Grimes #ifdef RRESTORE 15928fae3551SRodney W. Grimes #include <stdarg.h> 15938fae3551SRodney W. Grimes 15948fae3551SRodney W. Grimes void 15958fae3551SRodney W. Grimes msg(const char *fmt, ...) 15968fae3551SRodney W. Grimes { 15978fae3551SRodney W. Grimes va_list ap; 15988fae3551SRodney W. Grimes va_start(ap, fmt); 15998fae3551SRodney W. Grimes (void)vfprintf(stderr, fmt, ap); 16008fae3551SRodney W. Grimes va_end(ap); 16018fae3551SRodney W. Grimes } 16028fae3551SRodney W. Grimes #endif /* RRESTORE */ 16038fae3551SRodney W. Grimes 16048fae3551SRodney W. Grimes static u_char * 16052db673abSWarner Losh swabshort(u_char *sp, int n) 16068fae3551SRodney W. Grimes { 16078fae3551SRodney W. Grimes char c; 16088fae3551SRodney W. Grimes 16098fae3551SRodney W. Grimes while (--n >= 0) { 16108fae3551SRodney W. Grimes c = sp[0]; sp[0] = sp[1]; sp[1] = c; 16118fae3551SRodney W. Grimes sp += 2; 16128fae3551SRodney W. Grimes } 16138fae3551SRodney W. Grimes return (sp); 16148fae3551SRodney W. Grimes } 16158fae3551SRodney W. Grimes 16168fae3551SRodney W. Grimes static u_char * 16172db673abSWarner Losh swablong(u_char *sp, int n) 16188fae3551SRodney W. Grimes { 16198fae3551SRodney W. Grimes char c; 16208fae3551SRodney W. Grimes 16218fae3551SRodney W. Grimes while (--n >= 0) { 16228fae3551SRodney W. Grimes c = sp[0]; sp[0] = sp[3]; sp[3] = c; 16238fae3551SRodney W. Grimes c = sp[2]; sp[2] = sp[1]; sp[1] = c; 16248fae3551SRodney W. Grimes sp += 4; 16258fae3551SRodney W. Grimes } 16268fae3551SRodney W. Grimes return (sp); 16278fae3551SRodney W. Grimes } 16288fae3551SRodney W. Grimes 16291c85e6a3SKirk McKusick static u_char * 16301c85e6a3SKirk McKusick swabquad(u_char *sp, int n) 16311c85e6a3SKirk McKusick { 16321c85e6a3SKirk McKusick char c; 16331c85e6a3SKirk McKusick 16341c85e6a3SKirk McKusick while (--n >= 0) { 16351c85e6a3SKirk McKusick c = sp[0]; sp[0] = sp[7]; sp[7] = c; 16361c85e6a3SKirk McKusick c = sp[1]; sp[1] = sp[6]; sp[6] = c; 16371c85e6a3SKirk McKusick c = sp[2]; sp[2] = sp[5]; sp[5] = c; 16381c85e6a3SKirk McKusick c = sp[3]; sp[3] = sp[4]; sp[4] = c; 16391c85e6a3SKirk McKusick sp += 8; 16401c85e6a3SKirk McKusick } 16411c85e6a3SKirk McKusick return (sp); 16421c85e6a3SKirk McKusick } 16431c85e6a3SKirk McKusick 16448fae3551SRodney W. Grimes void 16452db673abSWarner Losh swabst(u_char *cp, u_char *sp) 16468fae3551SRodney W. Grimes { 16478fae3551SRodney W. Grimes int n = 0; 16488fae3551SRodney W. Grimes 16498fae3551SRodney W. Grimes while (*cp) { 16508fae3551SRodney W. Grimes switch (*cp) { 16518fae3551SRodney W. Grimes case '0': case '1': case '2': case '3': case '4': 16528fae3551SRodney W. Grimes case '5': case '6': case '7': case '8': case '9': 16538fae3551SRodney W. Grimes n = (n * 10) + (*cp++ - '0'); 16548fae3551SRodney W. Grimes continue; 16558fae3551SRodney W. Grimes 16568fae3551SRodney W. Grimes case 's': case 'w': case 'h': 16578fae3551SRodney W. Grimes if (n == 0) 16588fae3551SRodney W. Grimes n = 1; 16598fae3551SRodney W. Grimes sp = swabshort(sp, n); 16608fae3551SRodney W. Grimes break; 16618fae3551SRodney W. Grimes 16628fae3551SRodney W. Grimes case 'l': 16638fae3551SRodney W. Grimes if (n == 0) 16648fae3551SRodney W. Grimes n = 1; 16658fae3551SRodney W. Grimes sp = swablong(sp, n); 16668fae3551SRodney W. Grimes break; 16678fae3551SRodney W. Grimes 16681c85e6a3SKirk McKusick case 'q': 16691c85e6a3SKirk McKusick if (n == 0) 16701c85e6a3SKirk McKusick n = 1; 16711c85e6a3SKirk McKusick sp = swabquad(sp, n); 16721c85e6a3SKirk McKusick break; 16731c85e6a3SKirk McKusick 16741c85e6a3SKirk McKusick case 'b': 16758fae3551SRodney W. Grimes if (n == 0) 16768fae3551SRodney W. Grimes n = 1; 16778fae3551SRodney W. Grimes sp += n; 16788fae3551SRodney W. Grimes break; 16791c85e6a3SKirk McKusick 16801c85e6a3SKirk McKusick default: 16811c85e6a3SKirk McKusick fprintf(stderr, "Unknown conversion character: %c\n", 16821c85e6a3SKirk McKusick *cp); 16831c85e6a3SKirk McKusick done(0); 16841c85e6a3SKirk McKusick break; 16858fae3551SRodney W. Grimes } 16868fae3551SRodney W. Grimes cp++; 16878fae3551SRodney W. Grimes n = 0; 16888fae3551SRodney W. Grimes } 16898fae3551SRodney W. Grimes } 16908fae3551SRodney W. Grimes 16918fae3551SRodney W. Grimes static u_long 16922db673abSWarner Losh swabl(u_long x) 16938fae3551SRodney W. Grimes { 16948fae3551SRodney W. Grimes swabst((u_char *)"l", (u_char *)&x); 16958fae3551SRodney W. Grimes return (x); 16968fae3551SRodney W. Grimes } 1697