1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39#ifndef lint 40#if 0 41static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; 42#endif 43static const char rcsid[] =
| 1/* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39#ifndef lint 40#if 0 41static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95"; 42#endif 43static const char rcsid[] =
|
44 "$FreeBSD: head/sbin/restore/tape.c 90573 2002-02-12 17:15:45Z iedowse $";
| 44 "$FreeBSD: head/sbin/restore/tape.c 90608 2002-02-13 12:06:58Z iedowse $";
|
45#endif /* not lint */ 46 47#include <sys/param.h> 48#include <sys/file.h> 49#include <sys/mtio.h> 50#include <sys/stat.h> 51#include <sys/time.h> 52 53#include <ufs/ufs/dinode.h> 54#include <protocols/dumprestore.h> 55 56#include <errno.h> 57#include <paths.h> 58#include <setjmp.h> 59#include <stdio.h> 60#include <stdlib.h> 61#include <string.h> 62#include <time.h> 63#include <unistd.h> 64 65#include "restore.h" 66#include "extern.h" 67 68static long fssize = MAXBSIZE; 69static int mt = -1; 70static int pipein = 0; 71static char *magtape; 72static int blkcnt; 73static int numtrec; 74static char *tapebuf; 75static union u_spcl endoftapemark; 76static long blksread; /* blocks read since last header */ 77static long tpblksread = 0; /* TP_BSIZE blocks read */ 78static long tapesread; 79static jmp_buf restart; 80static int gettingfile = 0; /* restart has a valid frame */ 81static char *host = NULL; 82 83static int ofile; 84static char *map; 85static char lnkbuf[MAXPATHLEN + 1]; 86static int pathlen; 87 88int oldinofmt; /* old inode format conversion required */ 89int Bcvt; /* Swap Bytes (for CCI or sun) */ 90static int Qcvt; /* Swap quads (for sun) */ 91 92#define FLUSHTAPEBUF() blkcnt = ntrec + 1 93 94static void accthdr __P((struct s_spcl *)); 95static int checksum __P((int *)); 96static void findinode __P((struct s_spcl *)); 97static void findtapeblksize __P((void)); 98static int gethead __P((struct s_spcl *)); 99static void readtape __P((char *)); 100static void setdumpnum __P((void)); 101static u_long swabl __P((u_long)); 102static u_char *swablong __P((u_char *, int)); 103static u_char *swabshort __P((u_char *, int)); 104static void terminateinput __P((void)); 105static void xtrfile __P((char *, long)); 106static void xtrlnkfile __P((char *, long)); 107static void xtrlnkskip __P((char *, long)); 108static void xtrmap __P((char *, long)); 109static void xtrmapskip __P((char *, long)); 110static void xtrskip __P((char *, long)); 111 112static int readmapflag; 113 114/* 115 * Set up an input source 116 */ 117void 118setinput(source) 119 char *source; 120{ 121 FLUSHTAPEBUF(); 122 if (bflag) 123 newtapebuf(ntrec); 124 else 125 newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); 126 terminal = stdin; 127 128#ifdef RRESTORE 129 if (strchr(source, ':')) { 130 host = source; 131 source = strchr(host, ':'); 132 *source++ = '\0'; 133 if (rmthost(host) == 0) 134 done(1); 135 } else 136#endif 137 if (strcmp(source, "-") == 0) { 138 /* 139 * Since input is coming from a pipe we must establish 140 * our own connection to the terminal. 141 */ 142 terminal = fopen(_PATH_TTY, "r"); 143 if (terminal == NULL) { 144 (void)fprintf(stderr, "cannot open %s: %s\n", 145 _PATH_TTY, strerror(errno)); 146 terminal = fopen(_PATH_DEVNULL, "r"); 147 if (terminal == NULL) { 148 (void)fprintf(stderr, "cannot open %s: %s\n", 149 _PATH_DEVNULL, strerror(errno)); 150 done(1); 151 } 152 } 153 pipein++; 154 } 155 setuid(getuid()); /* no longer need or want root privileges */ 156 magtape = strdup(source); 157 if (magtape == NULL) { 158 fprintf(stderr, "Cannot allocate space for magtape buffer\n"); 159 done(1); 160 } 161} 162 163void 164newtapebuf(size) 165 long size; 166{ 167 static tapebufsize = -1; 168 169 ntrec = size; 170 if (size <= tapebufsize) 171 return; 172 if (tapebuf != NULL) 173 free(tapebuf); 174 tapebuf = malloc(size * TP_BSIZE); 175 if (tapebuf == NULL) { 176 fprintf(stderr, "Cannot allocate space for tape buffer\n"); 177 done(1); 178 } 179 tapebufsize = size; 180} 181 182/* 183 * Verify that the tape drive can be accessed and 184 * that it actually is a dump tape. 185 */ 186void 187setup() 188{ 189 int i, j, *ip; 190 struct stat stbuf; 191 192 vprintf(stdout, "Verify tape and initialize maps\n"); 193#ifdef RRESTORE 194 if (host) 195 mt = rmtopen(magtape, 0); 196 else 197#endif 198 if (pipein) 199 mt = 0; 200 else 201 mt = open(magtape, O_RDONLY, 0); 202 if (mt < 0) { 203 fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); 204 done(1); 205 } 206 volno = 1; 207 setdumpnum(); 208 FLUSHTAPEBUF(); 209 if (!pipein && !bflag) 210 findtapeblksize(); 211 if (gethead(&spcl) == FAIL) { 212 blkcnt--; /* push back this block */ 213 blksread--; 214 tpblksread--; 215 cvtflag++; 216 if (gethead(&spcl) == FAIL) { 217 fprintf(stderr, "Tape is not a dump tape\n"); 218 done(1); 219 } 220 fprintf(stderr, "Converting to new file system format.\n"); 221 } 222 if (pipein) { 223 endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; 224 endoftapemark.s_spcl.c_type = TS_END; 225 ip = (int *)&endoftapemark; 226 j = sizeof(union u_spcl) / sizeof(int); 227 i = 0; 228 do 229 i += *ip++; 230 while (--j); 231 endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 232 } 233 if (vflag || command == 't') 234 printdumpinfo(); 235 dumptime = _time32_to_time(spcl.c_ddate); 236 dumpdate = _time32_to_time(spcl.c_date); 237 if (stat(".", &stbuf) < 0) { 238 fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); 239 done(1); 240 } 241 if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE ) 242 fssize = TP_BSIZE; 243 if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) 244 fssize = stbuf.st_blksize; 245 if (((fssize - 1) & fssize) != 0) { 246 fprintf(stderr, "bad block size %ld\n", fssize); 247 done(1); 248 } 249 if (spcl.c_volume != 1) { 250 fprintf(stderr, "Tape is not volume 1 of the dump\n"); 251 done(1); 252 } 253 if (gethead(&spcl) == FAIL) { 254 dprintf(stdout, "header read failed at %ld blocks\n", blksread); 255 panic("no header after volume mark!\n"); 256 } 257 findinode(&spcl); 258 if (spcl.c_type != TS_CLRI) { 259 fprintf(stderr, "Cannot find file removal list\n"); 260 done(1); 261 } 262 maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; 263 dprintf(stdout, "maxino = %d\n", maxino); 264 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 265 if (map == NULL) 266 panic("no memory for active inode map\n"); 267 usedinomap = map; 268 curfile.action = USING; 269 getfile(xtrmap, xtrmapskip); 270 if (spcl.c_type != TS_BITS) { 271 fprintf(stderr, "Cannot find file dump list\n"); 272 done(1); 273 } 274 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 275 if (map == (char *)NULL) 276 panic("no memory for file dump list\n"); 277 dumpmap = map; 278 curfile.action = USING; 279 getfile(xtrmap, xtrmapskip); 280 /* 281 * If there may be whiteout entries on the tape, pretend that the 282 * whiteout inode exists, so that the whiteout entries can be 283 * extracted. 284 */ 285 if (oldinofmt == 0) 286 SETINO(WINO, dumpmap); 287} 288 289/* 290 * Prompt user to load a new dump volume. 291 * "Nextvol" is the next suggested volume to use. 292 * This suggested volume is enforced when doing full 293 * or incremental restores, but can be overridden by 294 * the user when only extracting a subset of the files. 295 */ 296void 297getvol(nextvol) 298 long nextvol; 299{
| 45#endif /* not lint */ 46 47#include <sys/param.h> 48#include <sys/file.h> 49#include <sys/mtio.h> 50#include <sys/stat.h> 51#include <sys/time.h> 52 53#include <ufs/ufs/dinode.h> 54#include <protocols/dumprestore.h> 55 56#include <errno.h> 57#include <paths.h> 58#include <setjmp.h> 59#include <stdio.h> 60#include <stdlib.h> 61#include <string.h> 62#include <time.h> 63#include <unistd.h> 64 65#include "restore.h" 66#include "extern.h" 67 68static long fssize = MAXBSIZE; 69static int mt = -1; 70static int pipein = 0; 71static char *magtape; 72static int blkcnt; 73static int numtrec; 74static char *tapebuf; 75static union u_spcl endoftapemark; 76static long blksread; /* blocks read since last header */ 77static long tpblksread = 0; /* TP_BSIZE blocks read */ 78static long tapesread; 79static jmp_buf restart; 80static int gettingfile = 0; /* restart has a valid frame */ 81static char *host = NULL; 82 83static int ofile; 84static char *map; 85static char lnkbuf[MAXPATHLEN + 1]; 86static int pathlen; 87 88int oldinofmt; /* old inode format conversion required */ 89int Bcvt; /* Swap Bytes (for CCI or sun) */ 90static int Qcvt; /* Swap quads (for sun) */ 91 92#define FLUSHTAPEBUF() blkcnt = ntrec + 1 93 94static void accthdr __P((struct s_spcl *)); 95static int checksum __P((int *)); 96static void findinode __P((struct s_spcl *)); 97static void findtapeblksize __P((void)); 98static int gethead __P((struct s_spcl *)); 99static void readtape __P((char *)); 100static void setdumpnum __P((void)); 101static u_long swabl __P((u_long)); 102static u_char *swablong __P((u_char *, int)); 103static u_char *swabshort __P((u_char *, int)); 104static void terminateinput __P((void)); 105static void xtrfile __P((char *, long)); 106static void xtrlnkfile __P((char *, long)); 107static void xtrlnkskip __P((char *, long)); 108static void xtrmap __P((char *, long)); 109static void xtrmapskip __P((char *, long)); 110static void xtrskip __P((char *, long)); 111 112static int readmapflag; 113 114/* 115 * Set up an input source 116 */ 117void 118setinput(source) 119 char *source; 120{ 121 FLUSHTAPEBUF(); 122 if (bflag) 123 newtapebuf(ntrec); 124 else 125 newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); 126 terminal = stdin; 127 128#ifdef RRESTORE 129 if (strchr(source, ':')) { 130 host = source; 131 source = strchr(host, ':'); 132 *source++ = '\0'; 133 if (rmthost(host) == 0) 134 done(1); 135 } else 136#endif 137 if (strcmp(source, "-") == 0) { 138 /* 139 * Since input is coming from a pipe we must establish 140 * our own connection to the terminal. 141 */ 142 terminal = fopen(_PATH_TTY, "r"); 143 if (terminal == NULL) { 144 (void)fprintf(stderr, "cannot open %s: %s\n", 145 _PATH_TTY, strerror(errno)); 146 terminal = fopen(_PATH_DEVNULL, "r"); 147 if (terminal == NULL) { 148 (void)fprintf(stderr, "cannot open %s: %s\n", 149 _PATH_DEVNULL, strerror(errno)); 150 done(1); 151 } 152 } 153 pipein++; 154 } 155 setuid(getuid()); /* no longer need or want root privileges */ 156 magtape = strdup(source); 157 if (magtape == NULL) { 158 fprintf(stderr, "Cannot allocate space for magtape buffer\n"); 159 done(1); 160 } 161} 162 163void 164newtapebuf(size) 165 long size; 166{ 167 static tapebufsize = -1; 168 169 ntrec = size; 170 if (size <= tapebufsize) 171 return; 172 if (tapebuf != NULL) 173 free(tapebuf); 174 tapebuf = malloc(size * TP_BSIZE); 175 if (tapebuf == NULL) { 176 fprintf(stderr, "Cannot allocate space for tape buffer\n"); 177 done(1); 178 } 179 tapebufsize = size; 180} 181 182/* 183 * Verify that the tape drive can be accessed and 184 * that it actually is a dump tape. 185 */ 186void 187setup() 188{ 189 int i, j, *ip; 190 struct stat stbuf; 191 192 vprintf(stdout, "Verify tape and initialize maps\n"); 193#ifdef RRESTORE 194 if (host) 195 mt = rmtopen(magtape, 0); 196 else 197#endif 198 if (pipein) 199 mt = 0; 200 else 201 mt = open(magtape, O_RDONLY, 0); 202 if (mt < 0) { 203 fprintf(stderr, "%s: %s\n", magtape, strerror(errno)); 204 done(1); 205 } 206 volno = 1; 207 setdumpnum(); 208 FLUSHTAPEBUF(); 209 if (!pipein && !bflag) 210 findtapeblksize(); 211 if (gethead(&spcl) == FAIL) { 212 blkcnt--; /* push back this block */ 213 blksread--; 214 tpblksread--; 215 cvtflag++; 216 if (gethead(&spcl) == FAIL) { 217 fprintf(stderr, "Tape is not a dump tape\n"); 218 done(1); 219 } 220 fprintf(stderr, "Converting to new file system format.\n"); 221 } 222 if (pipein) { 223 endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC; 224 endoftapemark.s_spcl.c_type = TS_END; 225 ip = (int *)&endoftapemark; 226 j = sizeof(union u_spcl) / sizeof(int); 227 i = 0; 228 do 229 i += *ip++; 230 while (--j); 231 endoftapemark.s_spcl.c_checksum = CHECKSUM - i; 232 } 233 if (vflag || command == 't') 234 printdumpinfo(); 235 dumptime = _time32_to_time(spcl.c_ddate); 236 dumpdate = _time32_to_time(spcl.c_date); 237 if (stat(".", &stbuf) < 0) { 238 fprintf(stderr, "cannot stat .: %s\n", strerror(errno)); 239 done(1); 240 } 241 if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE ) 242 fssize = TP_BSIZE; 243 if (stbuf.st_blksize >= TP_BSIZE && stbuf.st_blksize <= MAXBSIZE) 244 fssize = stbuf.st_blksize; 245 if (((fssize - 1) & fssize) != 0) { 246 fprintf(stderr, "bad block size %ld\n", fssize); 247 done(1); 248 } 249 if (spcl.c_volume != 1) { 250 fprintf(stderr, "Tape is not volume 1 of the dump\n"); 251 done(1); 252 } 253 if (gethead(&spcl) == FAIL) { 254 dprintf(stdout, "header read failed at %ld blocks\n", blksread); 255 panic("no header after volume mark!\n"); 256 } 257 findinode(&spcl); 258 if (spcl.c_type != TS_CLRI) { 259 fprintf(stderr, "Cannot find file removal list\n"); 260 done(1); 261 } 262 maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1; 263 dprintf(stdout, "maxino = %d\n", maxino); 264 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 265 if (map == NULL) 266 panic("no memory for active inode map\n"); 267 usedinomap = map; 268 curfile.action = USING; 269 getfile(xtrmap, xtrmapskip); 270 if (spcl.c_type != TS_BITS) { 271 fprintf(stderr, "Cannot find file dump list\n"); 272 done(1); 273 } 274 map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY)); 275 if (map == (char *)NULL) 276 panic("no memory for file dump list\n"); 277 dumpmap = map; 278 curfile.action = USING; 279 getfile(xtrmap, xtrmapskip); 280 /* 281 * If there may be whiteout entries on the tape, pretend that the 282 * whiteout inode exists, so that the whiteout entries can be 283 * extracted. 284 */ 285 if (oldinofmt == 0) 286 SETINO(WINO, dumpmap); 287} 288 289/* 290 * Prompt user to load a new dump volume. 291 * "Nextvol" is the next suggested volume to use. 292 * This suggested volume is enforced when doing full 293 * or incremental restores, but can be overridden by 294 * the user when only extracting a subset of the files. 295 */ 296void 297getvol(nextvol) 298 long nextvol; 299{
|
300 long newvol, savecnt, wantnext, i;
| 300 long newvol, savecnt, savetpcnt, i;
|
301 union u_spcl tmpspcl; 302# define tmpbuf tmpspcl.s_spcl 303 char buf[TP_BSIZE]; 304 305 if (nextvol == 1) { 306 tapesread = 0; 307 gettingfile = 0; 308 } 309 if (pipein) { 310 if (nextvol != 1) { 311 panic("Changing volumes on pipe input?\n"); 312 /* Avoid looping if we couldn't ask the user. */ 313 if (yflag || ferror(terminal) || feof(terminal)) 314 done(1); 315 } 316 if (volno == 1) 317 return; 318 goto gethdr; 319 } 320 savecnt = blksread;
| 301 union u_spcl tmpspcl; 302# define tmpbuf tmpspcl.s_spcl 303 char buf[TP_BSIZE]; 304 305 if (nextvol == 1) { 306 tapesread = 0; 307 gettingfile = 0; 308 } 309 if (pipein) { 310 if (nextvol != 1) { 311 panic("Changing volumes on pipe input?\n"); 312 /* Avoid looping if we couldn't ask the user. */ 313 if (yflag || ferror(terminal) || feof(terminal)) 314 done(1); 315 } 316 if (volno == 1) 317 return; 318 goto gethdr; 319 } 320 savecnt = blksread;
|
| 321 savetpcnt = tpblksread;
|
321again:
| 322again:
|
| 323 tpblksread = savetpcnt;
|
322 if (pipein) 323 done(1); /* pipes do not get a second chance */
| 324 if (pipein) 325 done(1); /* pipes do not get a second chance */
|
324 if (command == 'R' || command == 'r' || curfile.action != SKIP) {
| 326 if (command == 'R' || command == 'r' || curfile.action != SKIP)
|
325 newvol = nextvol;
| 327 newvol = nextvol;
|
326 wantnext = 1; 327 } else {
| 328 else
|
328 newvol = 0;
| 329 newvol = 0;
|
329 wantnext = 0; 330 }
| |
331 while (newvol <= 0) { 332 if (tapesread == 0) { 333 fprintf(stderr, "%s%s%s%s%s", 334 "You have not read any tapes yet.\n", 335 "Unless you know which volume your", 336 " file(s) are on you should start\n", 337 "with the last volume and work", 338 " towards the first.\n"); 339 } else { 340 fprintf(stderr, "You have read volumes"); 341 strcpy(buf, ": "); 342 for (i = 1; i < 32; i++) 343 if (tapesread & (1 << i)) { 344 fprintf(stderr, "%s%ld", buf, i); 345 strcpy(buf, ", "); 346 } 347 fprintf(stderr, "\n"); 348 } 349 do { 350 fprintf(stderr, "Specify next volume #: "); 351 (void) fflush(stderr); 352 if (fgets(buf, BUFSIZ, terminal) == NULL) 353 done(1); 354 } while (buf[0] == '\n'); 355 newvol = atoi(buf); 356 if (newvol <= 0) { 357 fprintf(stderr, 358 "Volume numbers are positive numerics\n"); 359 } 360 } 361 if (newvol == volno) { 362 tapesread |= 1 << volno; 363 return; 364 } 365 closemt(); 366 fprintf(stderr, "Mount tape volume %ld\n", newvol); 367 fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); 368 fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); 369 (void) fflush(stderr); 370 if (fgets(buf, BUFSIZ, terminal) == NULL) 371 done(1); 372 if (!strcmp(buf, "none\n")) { 373 terminateinput(); 374 return; 375 } 376 if (buf[0] != '\n') { 377 (void) strcpy(magtape, buf); 378 magtape[strlen(magtape) - 1] = '\0'; 379 } 380#ifdef RRESTORE 381 if (host) 382 mt = rmtopen(magtape, 0); 383 else 384#endif 385 mt = open(magtape, O_RDONLY, 0); 386 387 if (mt == -1) { 388 fprintf(stderr, "Cannot open %s\n", magtape); 389 volno = -1; 390 goto again; 391 } 392gethdr: 393 volno = newvol; 394 setdumpnum(); 395 FLUSHTAPEBUF(); 396 if (gethead(&tmpbuf) == FAIL) { 397 dprintf(stdout, "header read failed at %ld blocks\n", blksread); 398 fprintf(stderr, "tape is not dump tape\n"); 399 volno = 0; 400 goto again; 401 } 402 if (tmpbuf.c_volume != volno) { 403 fprintf(stderr, "Wrong volume (%ld)\n", tmpbuf.c_volume); 404 volno = 0; 405 goto again; 406 } 407 if (_time32_to_time(tmpbuf.c_date) != dumpdate || 408 _time32_to_time(tmpbuf.c_ddate) != dumptime) { 409 time_t t = _time32_to_time(tmpbuf.c_date); 410 fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t)); 411 fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); 412 volno = 0; 413 goto again; 414 } 415 tapesread |= 1 << volno; 416 blksread = savecnt; 417 /* 418 * If continuing from the previous volume, skip over any 419 * blocks read already at the end of the previous volume. 420 * 421 * If coming to this volume at random, skip to the beginning 422 * of the next record. 423 */ 424 dprintf(stdout, "read %ld recs, tape starts with %ld\n", 425 tpblksread, tmpbuf.c_firstrec); 426 if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
| 330 while (newvol <= 0) { 331 if (tapesread == 0) { 332 fprintf(stderr, "%s%s%s%s%s", 333 "You have not read any tapes yet.\n", 334 "Unless you know which volume your", 335 " file(s) are on you should start\n", 336 "with the last volume and work", 337 " towards the first.\n"); 338 } else { 339 fprintf(stderr, "You have read volumes"); 340 strcpy(buf, ": "); 341 for (i = 1; i < 32; i++) 342 if (tapesread & (1 << i)) { 343 fprintf(stderr, "%s%ld", buf, i); 344 strcpy(buf, ", "); 345 } 346 fprintf(stderr, "\n"); 347 } 348 do { 349 fprintf(stderr, "Specify next volume #: "); 350 (void) fflush(stderr); 351 if (fgets(buf, BUFSIZ, terminal) == NULL) 352 done(1); 353 } while (buf[0] == '\n'); 354 newvol = atoi(buf); 355 if (newvol <= 0) { 356 fprintf(stderr, 357 "Volume numbers are positive numerics\n"); 358 } 359 } 360 if (newvol == volno) { 361 tapesread |= 1 << volno; 362 return; 363 } 364 closemt(); 365 fprintf(stderr, "Mount tape volume %ld\n", newvol); 366 fprintf(stderr, "Enter ``none'' if there are no more tapes\n"); 367 fprintf(stderr, "otherwise enter tape name (default: %s) ", magtape); 368 (void) fflush(stderr); 369 if (fgets(buf, BUFSIZ, terminal) == NULL) 370 done(1); 371 if (!strcmp(buf, "none\n")) { 372 terminateinput(); 373 return; 374 } 375 if (buf[0] != '\n') { 376 (void) strcpy(magtape, buf); 377 magtape[strlen(magtape) - 1] = '\0'; 378 } 379#ifdef RRESTORE 380 if (host) 381 mt = rmtopen(magtape, 0); 382 else 383#endif 384 mt = open(magtape, O_RDONLY, 0); 385 386 if (mt == -1) { 387 fprintf(stderr, "Cannot open %s\n", magtape); 388 volno = -1; 389 goto again; 390 } 391gethdr: 392 volno = newvol; 393 setdumpnum(); 394 FLUSHTAPEBUF(); 395 if (gethead(&tmpbuf) == FAIL) { 396 dprintf(stdout, "header read failed at %ld blocks\n", blksread); 397 fprintf(stderr, "tape is not dump tape\n"); 398 volno = 0; 399 goto again; 400 } 401 if (tmpbuf.c_volume != volno) { 402 fprintf(stderr, "Wrong volume (%ld)\n", tmpbuf.c_volume); 403 volno = 0; 404 goto again; 405 } 406 if (_time32_to_time(tmpbuf.c_date) != dumpdate || 407 _time32_to_time(tmpbuf.c_ddate) != dumptime) { 408 time_t t = _time32_to_time(tmpbuf.c_date); 409 fprintf(stderr, "Wrong dump date\n\tgot: %s", ctime(&t)); 410 fprintf(stderr, "\twanted: %s", ctime(&dumpdate)); 411 volno = 0; 412 goto again; 413 } 414 tapesread |= 1 << volno; 415 blksread = savecnt; 416 /* 417 * If continuing from the previous volume, skip over any 418 * blocks read already at the end of the previous volume. 419 * 420 * If coming to this volume at random, skip to the beginning 421 * of the next record. 422 */ 423 dprintf(stdout, "read %ld recs, tape starts with %ld\n", 424 tpblksread, tmpbuf.c_firstrec); 425 if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) {
|
427 if (!wantnext) {
| 426 if (curfile.action != USING) {
|
428 tpblksread = tmpbuf.c_firstrec;
| 427 tpblksread = tmpbuf.c_firstrec;
|
429 for (i = tmpbuf.c_count; i > 0; i--) 430 readtape(buf);
| 428 /* 429 * XXX Dump incorrectly sets c_count to 1 in the 430 * volume header of the first tape, so ignore 431 * c_count when volno == 1. 432 */ 433 if (volno != 1) 434 for (i = tmpbuf.c_count; i > 0; i--) 435 readtape(buf);
|
431 } else if (tmpbuf.c_firstrec > 0 && 432 tmpbuf.c_firstrec < tpblksread - 1) { 433 /* 434 * -1 since we've read the volume header 435 */ 436 i = tpblksread - tmpbuf.c_firstrec - 1; 437 dprintf(stderr, "Skipping %ld duplicate record%s.\n", 438 i, i > 1 ? "s" : ""); 439 while (--i >= 0) 440 readtape(buf); 441 } 442 }
| 436 } else if (tmpbuf.c_firstrec > 0 && 437 tmpbuf.c_firstrec < tpblksread - 1) { 438 /* 439 * -1 since we've read the volume header 440 */ 441 i = tpblksread - tmpbuf.c_firstrec - 1; 442 dprintf(stderr, "Skipping %ld duplicate record%s.\n", 443 i, i > 1 ? "s" : ""); 444 while (--i >= 0) 445 readtape(buf); 446 } 447 }
|
443 if (curfile.action == USING || curfile.action == SKIP) {
| 448 if (curfile.action == USING) {
|
444 if (volno == 1) 445 panic("active file into volume 1\n"); 446 return; 447 }
| 449 if (volno == 1) 450 panic("active file into volume 1\n"); 451 return; 452 }
|
448 /* 449 * Skip up to the beginning of the next record 450 */ 451 if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER)) 452 for (i = tmpbuf.c_count; i > 0; i--) 453 readtape(buf);
| |
454 (void) gethead(&spcl); 455 findinode(&spcl); 456 if (gettingfile) { 457 gettingfile = 0; 458 longjmp(restart, 1); 459 } 460} 461 462/* 463 * Handle unexpected EOF. 464 */ 465static void 466terminateinput() 467{ 468 469 if (gettingfile && curfile.action == USING) { 470 printf("Warning: %s %s\n", 471 "End-of-input encountered while extracting", curfile.name); 472 } 473 curfile.name = "<name unknown>"; 474 curfile.action = UNKNOWN; 475 curfile.dip = NULL; 476 curfile.ino = maxino; 477 if (gettingfile) { 478 gettingfile = 0; 479 longjmp(restart, 1); 480 } 481} 482 483/* 484 * handle multiple dumps per tape by skipping forward to the 485 * appropriate one. 486 */ 487static void 488setdumpnum() 489{ 490 struct mtop tcom; 491 492 if (dumpnum == 1 || volno != 1) 493 return; 494 if (pipein) { 495 fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); 496 done(1); 497 } 498 tcom.mt_op = MTFSF; 499 tcom.mt_count = dumpnum - 1; 500#ifdef RRESTORE 501 if (host) 502 rmtioctl(MTFSF, dumpnum - 1); 503 else 504#endif 505 if (ioctl(mt, MTIOCTOP, (char *)&tcom) < 0) 506 fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); 507} 508 509void 510printdumpinfo() 511{ 512 time_t t; 513 t = _time32_to_time(spcl.c_date); 514 fprintf(stdout, "Dump date: %s", ctime(&t)); 515 t = _time32_to_time(spcl.c_ddate); 516 fprintf(stdout, "Dumped from: %s", 517 (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t)); 518 if (spcl.c_host[0] == '\0') 519 return; 520 fprintf(stderr, "Level %ld dump of %s on %s:%s\n", 521 spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); 522 fprintf(stderr, "Label: %s\n", spcl.c_label); 523} 524 525int 526extractfile(name) 527 char *name; 528{ 529 int flags; 530 mode_t mode; 531 struct timeval timep[2]; 532 struct entry *ep; 533 534 curfile.name = name; 535 curfile.action = USING; 536 timep[0].tv_sec = curfile.dip->di_atime; 537 timep[0].tv_usec = curfile.dip->di_atimensec / 1000; 538 timep[1].tv_sec = curfile.dip->di_mtime; 539 timep[1].tv_usec = curfile.dip->di_mtimensec / 1000; 540 mode = curfile.dip->di_mode; 541 flags = curfile.dip->di_flags; 542 switch (mode & IFMT) { 543 544 default: 545 fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); 546 skipfile(); 547 return (FAIL); 548 549 case IFSOCK: 550 vprintf(stdout, "skipped socket %s\n", name); 551 skipfile(); 552 return (GOOD); 553 554 case IFDIR: 555 if (mflag) { 556 ep = lookupname(name); 557 if (ep == NULL || ep->e_flags & EXTRACT) 558 panic("unextracted directory %s\n", name); 559 skipfile(); 560 return (GOOD); 561 } 562 vprintf(stdout, "extract file %s\n", name); 563 return (genliteraldir(name, curfile.ino)); 564 565 case IFLNK: 566 lnkbuf[0] = '\0'; 567 pathlen = 0; 568 getfile(xtrlnkfile, xtrlnkskip); 569 if (pathlen == 0) { 570 vprintf(stdout, 571 "%s: zero length symbolic link (ignored)\n", name); 572 return (GOOD); 573 } 574 return (linkit(lnkbuf, name, SYMLINK)); 575 576 case IFIFO: 577 vprintf(stdout, "extract fifo %s\n", name); 578 if (Nflag) { 579 skipfile(); 580 return (GOOD); 581 } 582 if (uflag && !Nflag) 583 (void)unlink(name); 584 if (mkfifo(name, mode) < 0) { 585 fprintf(stderr, "%s: cannot create fifo: %s\n", 586 name, strerror(errno)); 587 skipfile(); 588 return (FAIL); 589 } 590 (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 591 (void) chmod(name, mode); 592 utimes(name, timep); 593 (void) chflags(name, flags); 594 skipfile(); 595 return (GOOD); 596 597 case IFCHR: 598 case IFBLK: 599 vprintf(stdout, "extract special file %s\n", name); 600 if (Nflag) { 601 skipfile(); 602 return (GOOD); 603 } 604 if (uflag) 605 (void)unlink(name); 606 if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { 607 fprintf(stderr, "%s: cannot create special file: %s\n", 608 name, strerror(errno)); 609 skipfile(); 610 return (FAIL); 611 } 612 (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 613 (void) chmod(name, mode); 614 utimes(name, timep); 615 (void) chflags(name, flags); 616 skipfile(); 617 return (GOOD); 618 619 case IFREG: 620 vprintf(stdout, "extract file %s\n", name); 621 if (Nflag) { 622 skipfile(); 623 return (GOOD); 624 } 625 if (uflag) 626 (void)unlink(name); 627 if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 628 0666)) < 0) { 629 fprintf(stderr, "%s: cannot create file: %s\n", 630 name, strerror(errno)); 631 skipfile(); 632 return (FAIL); 633 } 634 (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); 635 (void) fchmod(ofile, mode); 636 getfile(xtrfile, xtrskip); 637 (void) close(ofile); 638 utimes(name, timep); 639 (void) chflags(name, flags); 640 return (GOOD); 641 } 642 /* NOTREACHED */ 643} 644 645/* 646 * skip over bit maps on the tape 647 */ 648void 649skipmaps() 650{ 651 652 while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) 653 skipfile(); 654} 655 656/* 657 * skip over a file on the tape 658 */ 659void 660skipfile() 661{ 662 663 curfile.action = SKIP; 664 getfile(xtrnull, xtrnull); 665} 666 667/* 668 * Extract a file from the tape. 669 * When an allocated block is found it is passed to the fill function; 670 * when an unallocated block (hole) is found, a zeroed buffer is passed 671 * to the skip function. 672 */ 673void 674getfile(fill, skip) 675 void (*fill) __P((char *, long)); 676 void (*skip) __P((char *, long)); 677{ 678 register int i; 679 int curblk = 0; 680 quad_t size = spcl.c_dinode.di_size; 681 static char clearedbuf[MAXBSIZE]; 682 char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 683 char junk[TP_BSIZE]; 684 685 if (spcl.c_type == TS_END) 686 panic("ran off end of tape\n"); 687 if (spcl.c_magic != NFS_MAGIC) 688 panic("not at beginning of a file\n"); 689 if (!gettingfile && setjmp(restart) != 0) 690 return; 691 gettingfile++; 692loop: 693 for (i = 0; i < spcl.c_count; i++) { 694 if (readmapflag || spcl.c_addr[i]) { 695 readtape(&buf[curblk++][0]); 696 if (curblk == fssize / TP_BSIZE) { 697 (*fill)((char *)buf, (long)(size > TP_BSIZE ? 698 fssize : (curblk - 1) * TP_BSIZE + size)); 699 curblk = 0; 700 } 701 } else { 702 if (curblk > 0) { 703 (*fill)((char *)buf, (long)(size > TP_BSIZE ? 704 curblk * TP_BSIZE : 705 (curblk - 1) * TP_BSIZE + size)); 706 curblk = 0; 707 } 708 (*skip)(clearedbuf, (long)(size > TP_BSIZE ? 709 TP_BSIZE : size)); 710 } 711 if ((size -= TP_BSIZE) <= 0) { 712 for (i++; i < spcl.c_count; i++) 713 if (readmapflag || spcl.c_addr[i]) 714 readtape(junk); 715 break; 716 } 717 } 718 if (gethead(&spcl) == GOOD && size > 0) { 719 if (spcl.c_type == TS_ADDR) 720 goto loop; 721 dprintf(stdout, 722 "Missing address (header) block for %s at %ld blocks\n", 723 curfile.name, blksread); 724 } 725 if (curblk > 0) 726 (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size)); 727 findinode(&spcl); 728 gettingfile = 0; 729} 730 731/* 732 * Write out the next block of a file. 733 */ 734static void 735xtrfile(buf, size) 736 char *buf; 737 long size; 738{ 739 740 if (Nflag) 741 return; 742 if (write(ofile, buf, (int) size) == -1) { 743 fprintf(stderr, 744 "write error extracting inode %d, name %s\nwrite: %s\n", 745 curfile.ino, curfile.name, strerror(errno)); 746 } 747} 748 749/* 750 * Skip over a hole in a file. 751 */ 752/* ARGSUSED */ 753static void 754xtrskip(buf, size) 755 char *buf; 756 long size; 757{ 758 759 if (lseek(ofile, size, SEEK_CUR) == -1) { 760 fprintf(stderr, 761 "seek error extracting inode %d, name %s\nlseek: %s\n", 762 curfile.ino, curfile.name, strerror(errno)); 763 done(1); 764 } 765} 766 767/* 768 * Collect the next block of a symbolic link. 769 */ 770static void 771xtrlnkfile(buf, size) 772 char *buf; 773 long size; 774{ 775 776 pathlen += size; 777 if (pathlen > MAXPATHLEN) { 778 fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", 779 curfile.name, lnkbuf, buf, pathlen); 780 done(1); 781 } 782 (void) strcat(lnkbuf, buf); 783} 784 785/* 786 * Skip over a hole in a symbolic link (should never happen). 787 */ 788/* ARGSUSED */ 789static void 790xtrlnkskip(buf, size) 791 char *buf; 792 long size; 793{ 794 795 fprintf(stderr, "unallocated block in symbolic link %s\n", 796 curfile.name); 797 done(1); 798} 799 800/* 801 * Collect the next block of a bit map. 802 */ 803static void 804xtrmap(buf, size) 805 char *buf; 806 long size; 807{ 808 809 memmove(map, buf, size); 810 map += size; 811} 812 813/* 814 * Skip over a hole in a bit map (should never happen). 815 */ 816/* ARGSUSED */ 817static void 818xtrmapskip(buf, size) 819 char *buf; 820 long size; 821{ 822 823 panic("hole in map\n"); 824 map += size; 825} 826 827/* 828 * Noop, when an extraction function is not needed. 829 */ 830/* ARGSUSED */ 831void 832xtrnull(buf, size) 833 char *buf; 834 long size; 835{ 836 837 return; 838} 839 840/* 841 * Read TP_BSIZE blocks from the input. 842 * Handle read errors, and end of media. 843 */ 844static void 845readtape(buf) 846 char *buf; 847{ 848 long rd, newvol, i; 849 int cnt, seek_failed; 850 851 if (blkcnt < numtrec) { 852 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); 853 blksread++; 854 tpblksread++; 855 return; 856 } 857 for (i = 0; i < ntrec; i++) 858 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 859 if (numtrec == 0) 860 numtrec = ntrec; 861 cnt = ntrec * TP_BSIZE; 862 rd = 0; 863getmore: 864#ifdef RRESTORE 865 if (host) 866 i = rmtread(&tapebuf[rd], cnt); 867 else 868#endif 869 i = read(mt, &tapebuf[rd], cnt); 870 /* 871 * Check for mid-tape short read error. 872 * If found, skip rest of buffer and start with the next. 873 */ 874 if (!pipein && numtrec < ntrec && i > 0) { 875 dprintf(stdout, "mid-media short read error.\n"); 876 numtrec = ntrec; 877 } 878 /* 879 * Handle partial block read. 880 */ 881 if (pipein && i == 0 && rd > 0) 882 i = rd; 883 else if (i > 0 && i != ntrec * TP_BSIZE) { 884 if (pipein) { 885 rd += i; 886 cnt -= i; 887 if (cnt > 0) 888 goto getmore; 889 i = rd; 890 } else { 891 /* 892 * Short read. Process the blocks read. 893 */ 894 if (i % TP_BSIZE != 0) 895 vprintf(stdout, 896 "partial block read: %ld should be %ld\n", 897 i, ntrec * TP_BSIZE); 898 numtrec = i / TP_BSIZE; 899 } 900 } 901 /* 902 * Handle read error. 903 */ 904 if (i < 0) { 905 fprintf(stderr, "Tape read error while "); 906 switch (curfile.action) { 907 default: 908 fprintf(stderr, "trying to set up tape\n"); 909 break; 910 case UNKNOWN: 911 fprintf(stderr, "trying to resynchronize\n"); 912 break; 913 case USING: 914 fprintf(stderr, "restoring %s\n", curfile.name); 915 break; 916 case SKIP: 917 fprintf(stderr, "skipping over inode %d\n", 918 curfile.ino); 919 break; 920 } 921 if (!yflag && !reply("continue")) 922 done(1); 923 i = ntrec * TP_BSIZE; 924 memset(tapebuf, 0, i); 925#ifdef RRESTORE 926 if (host) 927 seek_failed = (rmtseek(i, 1) < 0); 928 else 929#endif 930 seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); 931 932 if (seek_failed) { 933 fprintf(stderr, 934 "continuation failed: %s\n", strerror(errno)); 935 done(1); 936 } 937 } 938 /* 939 * Handle end of tape. 940 */ 941 if (i == 0) { 942 vprintf(stdout, "End-of-tape encountered\n"); 943 if (!pipein) { 944 newvol = volno + 1; 945 volno = 0; 946 numtrec = 0; 947 getvol(newvol); 948 readtape(buf); 949 return; 950 } 951 if (rd % TP_BSIZE != 0) 952 panic("partial block read: %d should be %d\n", 953 rd, ntrec * TP_BSIZE); 954 terminateinput(); 955 memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); 956 } 957 blkcnt = 0; 958 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); 959 blksread++; 960 tpblksread++; 961} 962 963static void 964findtapeblksize() 965{ 966 register long i; 967 968 for (i = 0; i < ntrec; i++) 969 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 970 blkcnt = 0; 971#ifdef RRESTORE 972 if (host) 973 i = rmtread(tapebuf, ntrec * TP_BSIZE); 974 else 975#endif 976 i = read(mt, tapebuf, ntrec * TP_BSIZE); 977 978 if (i <= 0) { 979 fprintf(stderr, "tape read error: %s\n", strerror(errno)); 980 done(1); 981 } 982 if (i % TP_BSIZE != 0) { 983 fprintf(stderr, "Tape block size (%ld) %s (%d)\n", 984 i, "is not a multiple of dump block size", TP_BSIZE); 985 done(1); 986 } 987 ntrec = i / TP_BSIZE; 988 numtrec = ntrec; 989 vprintf(stdout, "Tape block size is %ld\n", ntrec); 990} 991 992void 993closemt() 994{ 995 996 if (mt < 0) 997 return; 998#ifdef RRESTORE 999 if (host) 1000 rmtclose(); 1001 else 1002#endif 1003 (void) close(mt); 1004} 1005 1006/* 1007 * Read the next block from the tape. 1008 * Check to see if it is one of several vintage headers. 1009 * If it is an old style header, convert it to a new style header. 1010 * If it is not any valid header, return an error. 1011 */ 1012static int 1013gethead(buf) 1014 struct s_spcl *buf; 1015{ 1016 long i; 1017 union { 1018 quad_t qval; 1019 int32_t val[2]; 1020 } qcvt; 1021 union u_ospcl { 1022 char dummy[TP_BSIZE]; 1023 struct s_ospcl { 1024 int32_t c_type; 1025 int32_t c_date; 1026 int32_t c_ddate; 1027 int32_t c_volume; 1028 int32_t c_tapea; 1029 u_short c_inumber; 1030 int32_t c_magic; 1031 int32_t c_checksum; 1032 struct odinode { 1033 unsigned short odi_mode; 1034 u_short odi_nlink; 1035 u_short odi_uid; 1036 u_short odi_gid; 1037 int32_t odi_size; 1038 int32_t odi_rdev; 1039 char odi_addr[36]; 1040 int32_t odi_atime; 1041 int32_t odi_mtime; 1042 int32_t odi_ctime; 1043 } c_dinode; 1044 int32_t c_count; 1045 char c_addr[256]; 1046 } s_ospcl; 1047 } u_ospcl; 1048 1049 if (!cvtflag) { 1050 readtape((char *)buf); 1051 if (buf->c_magic != NFS_MAGIC) { 1052 if (swabl(buf->c_magic) != NFS_MAGIC) 1053 return (FAIL); 1054 if (!Bcvt) { 1055 vprintf(stdout, "Note: Doing Byte swapping\n"); 1056 Bcvt = 1; 1057 } 1058 } 1059 if (checksum((int *)buf) == FAIL) 1060 return (FAIL); 1061 if (Bcvt) { 1062 swabst((u_char *)"8l4s31l", (u_char *)buf); 1063 swabst((u_char *)"l",(u_char *) &buf->c_level); 1064 swabst((u_char *)"2l",(u_char *) &buf->c_flags); 1065 } 1066 goto good; 1067 } 1068 readtape((char *)(&u_ospcl.s_ospcl)); 1069 memset(buf, 0, (long)TP_BSIZE); 1070 buf->c_type = u_ospcl.s_ospcl.c_type; 1071 buf->c_date = u_ospcl.s_ospcl.c_date; 1072 buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 1073 buf->c_volume = u_ospcl.s_ospcl.c_volume; 1074 buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 1075 buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 1076 buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 1077 buf->c_magic = u_ospcl.s_ospcl.c_magic; 1078 buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 1079 buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 1080 buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 1081 buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 1082 buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 1083 buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 1084 buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 1085 buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 1086 buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 1087 buf->c_count = u_ospcl.s_ospcl.c_count; 1088 memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); 1089 if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || 1090 checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) 1091 return(FAIL); 1092 buf->c_magic = NFS_MAGIC; 1093 1094good: 1095 if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) && 1096 (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { 1097 qcvt.qval = buf->c_dinode.di_size; 1098 if (qcvt.val[0] || qcvt.val[1]) { 1099 printf("Note: Doing Quad swapping\n"); 1100 Qcvt = 1; 1101 } 1102 } 1103 if (Qcvt) { 1104 qcvt.qval = buf->c_dinode.di_size; 1105 i = qcvt.val[1]; 1106 qcvt.val[1] = qcvt.val[0]; 1107 qcvt.val[0] = i; 1108 buf->c_dinode.di_size = qcvt.qval; 1109 } 1110 readmapflag = 0; 1111 1112 switch (buf->c_type) { 1113 1114 case TS_CLRI: 1115 case TS_BITS: 1116 /* 1117 * Have to patch up missing information in bit map headers 1118 */ 1119 buf->c_inumber = 0; 1120 buf->c_dinode.di_size = buf->c_count * TP_BSIZE; 1121 if (buf->c_count > TP_NINDIR) 1122 readmapflag = 1; 1123 else 1124 for (i = 0; i < buf->c_count; i++) 1125 buf->c_addr[i]++; 1126 break; 1127 1128 case TS_TAPE: 1129 if ((buf->c_flags & DR_NEWINODEFMT) == 0) 1130 oldinofmt = 1; 1131 /* fall through */ 1132 case TS_END: 1133 buf->c_inumber = 0; 1134 break; 1135 1136 case TS_INODE: 1137 case TS_ADDR: 1138 break; 1139 1140 default: 1141 panic("gethead: unknown inode type %d\n", buf->c_type); 1142 break; 1143 } 1144 /* 1145 * If we are restoring a filesystem with old format inodes, 1146 * copy the uid/gid to the new location. 1147 */ 1148 if (oldinofmt) { 1149 buf->c_dinode.di_uid = buf->c_dinode.di_ouid; 1150 buf->c_dinode.di_gid = buf->c_dinode.di_ogid; 1151 } 1152 if (dflag) 1153 accthdr(buf); 1154 return(GOOD); 1155} 1156 1157/* 1158 * Check that a header is where it belongs and predict the next header 1159 */ 1160static void 1161accthdr(header) 1162 struct s_spcl *header; 1163{ 1164 static ino_t previno = 0x7fffffff; 1165 static int prevtype; 1166 static long predict; 1167 long blks, i; 1168 1169 if (header->c_type == TS_TAPE) { 1170 fprintf(stderr, "Volume header (%s inode format) ", 1171 oldinofmt ? "old" : "new"); 1172 if (header->c_firstrec) 1173 fprintf(stderr, "begins with record %ld", 1174 header->c_firstrec); 1175 fprintf(stderr, "\n"); 1176 previno = 0x7fffffff; 1177 return; 1178 } 1179 if (previno == 0x7fffffff) 1180 goto newcalc; 1181 switch (prevtype) { 1182 case TS_BITS: 1183 fprintf(stderr, "Dumped inodes map header"); 1184 break; 1185 case TS_CLRI: 1186 fprintf(stderr, "Used inodes map header"); 1187 break; 1188 case TS_INODE: 1189 fprintf(stderr, "File header, ino %d", previno); 1190 break; 1191 case TS_ADDR: 1192 fprintf(stderr, "File continuation header, ino %d", previno); 1193 break; 1194 case TS_END: 1195 fprintf(stderr, "End of tape header"); 1196 break; 1197 } 1198 if (predict != blksread - 1) 1199 fprintf(stderr, "; predicted %ld blocks, got %ld blocks", 1200 predict, blksread - 1); 1201 fprintf(stderr, "\n"); 1202newcalc: 1203 blks = 0; 1204 if (header->c_type != TS_END) 1205 for (i = 0; i < header->c_count; i++) 1206 if (readmapflag || header->c_addr[i] != 0) 1207 blks++; 1208 predict = blks; 1209 blksread = 0; 1210 prevtype = header->c_type; 1211 previno = header->c_inumber; 1212} 1213 1214/* 1215 * Find an inode header. 1216 * Complain if had to skip. 1217 */ 1218static void 1219findinode(header) 1220 struct s_spcl *header; 1221{ 1222 static long skipcnt = 0; 1223 long i; 1224 char buf[TP_BSIZE];
| 453 (void) gethead(&spcl); 454 findinode(&spcl); 455 if (gettingfile) { 456 gettingfile = 0; 457 longjmp(restart, 1); 458 } 459} 460 461/* 462 * Handle unexpected EOF. 463 */ 464static void 465terminateinput() 466{ 467 468 if (gettingfile && curfile.action == USING) { 469 printf("Warning: %s %s\n", 470 "End-of-input encountered while extracting", curfile.name); 471 } 472 curfile.name = "<name unknown>"; 473 curfile.action = UNKNOWN; 474 curfile.dip = NULL; 475 curfile.ino = maxino; 476 if (gettingfile) { 477 gettingfile = 0; 478 longjmp(restart, 1); 479 } 480} 481 482/* 483 * handle multiple dumps per tape by skipping forward to the 484 * appropriate one. 485 */ 486static void 487setdumpnum() 488{ 489 struct mtop tcom; 490 491 if (dumpnum == 1 || volno != 1) 492 return; 493 if (pipein) { 494 fprintf(stderr, "Cannot have multiple dumps on pipe input\n"); 495 done(1); 496 } 497 tcom.mt_op = MTFSF; 498 tcom.mt_count = dumpnum - 1; 499#ifdef RRESTORE 500 if (host) 501 rmtioctl(MTFSF, dumpnum - 1); 502 else 503#endif 504 if (ioctl(mt, MTIOCTOP, (char *)&tcom) < 0) 505 fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); 506} 507 508void 509printdumpinfo() 510{ 511 time_t t; 512 t = _time32_to_time(spcl.c_date); 513 fprintf(stdout, "Dump date: %s", ctime(&t)); 514 t = _time32_to_time(spcl.c_ddate); 515 fprintf(stdout, "Dumped from: %s", 516 (spcl.c_ddate == 0) ? "the epoch\n" : ctime(&t)); 517 if (spcl.c_host[0] == '\0') 518 return; 519 fprintf(stderr, "Level %ld dump of %s on %s:%s\n", 520 spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev); 521 fprintf(stderr, "Label: %s\n", spcl.c_label); 522} 523 524int 525extractfile(name) 526 char *name; 527{ 528 int flags; 529 mode_t mode; 530 struct timeval timep[2]; 531 struct entry *ep; 532 533 curfile.name = name; 534 curfile.action = USING; 535 timep[0].tv_sec = curfile.dip->di_atime; 536 timep[0].tv_usec = curfile.dip->di_atimensec / 1000; 537 timep[1].tv_sec = curfile.dip->di_mtime; 538 timep[1].tv_usec = curfile.dip->di_mtimensec / 1000; 539 mode = curfile.dip->di_mode; 540 flags = curfile.dip->di_flags; 541 switch (mode & IFMT) { 542 543 default: 544 fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode); 545 skipfile(); 546 return (FAIL); 547 548 case IFSOCK: 549 vprintf(stdout, "skipped socket %s\n", name); 550 skipfile(); 551 return (GOOD); 552 553 case IFDIR: 554 if (mflag) { 555 ep = lookupname(name); 556 if (ep == NULL || ep->e_flags & EXTRACT) 557 panic("unextracted directory %s\n", name); 558 skipfile(); 559 return (GOOD); 560 } 561 vprintf(stdout, "extract file %s\n", name); 562 return (genliteraldir(name, curfile.ino)); 563 564 case IFLNK: 565 lnkbuf[0] = '\0'; 566 pathlen = 0; 567 getfile(xtrlnkfile, xtrlnkskip); 568 if (pathlen == 0) { 569 vprintf(stdout, 570 "%s: zero length symbolic link (ignored)\n", name); 571 return (GOOD); 572 } 573 return (linkit(lnkbuf, name, SYMLINK)); 574 575 case IFIFO: 576 vprintf(stdout, "extract fifo %s\n", name); 577 if (Nflag) { 578 skipfile(); 579 return (GOOD); 580 } 581 if (uflag && !Nflag) 582 (void)unlink(name); 583 if (mkfifo(name, mode) < 0) { 584 fprintf(stderr, "%s: cannot create fifo: %s\n", 585 name, strerror(errno)); 586 skipfile(); 587 return (FAIL); 588 } 589 (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 590 (void) chmod(name, mode); 591 utimes(name, timep); 592 (void) chflags(name, flags); 593 skipfile(); 594 return (GOOD); 595 596 case IFCHR: 597 case IFBLK: 598 vprintf(stdout, "extract special file %s\n", name); 599 if (Nflag) { 600 skipfile(); 601 return (GOOD); 602 } 603 if (uflag) 604 (void)unlink(name); 605 if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) { 606 fprintf(stderr, "%s: cannot create special file: %s\n", 607 name, strerror(errno)); 608 skipfile(); 609 return (FAIL); 610 } 611 (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid); 612 (void) chmod(name, mode); 613 utimes(name, timep); 614 (void) chflags(name, flags); 615 skipfile(); 616 return (GOOD); 617 618 case IFREG: 619 vprintf(stdout, "extract file %s\n", name); 620 if (Nflag) { 621 skipfile(); 622 return (GOOD); 623 } 624 if (uflag) 625 (void)unlink(name); 626 if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 627 0666)) < 0) { 628 fprintf(stderr, "%s: cannot create file: %s\n", 629 name, strerror(errno)); 630 skipfile(); 631 return (FAIL); 632 } 633 (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid); 634 (void) fchmod(ofile, mode); 635 getfile(xtrfile, xtrskip); 636 (void) close(ofile); 637 utimes(name, timep); 638 (void) chflags(name, flags); 639 return (GOOD); 640 } 641 /* NOTREACHED */ 642} 643 644/* 645 * skip over bit maps on the tape 646 */ 647void 648skipmaps() 649{ 650 651 while (spcl.c_type == TS_BITS || spcl.c_type == TS_CLRI) 652 skipfile(); 653} 654 655/* 656 * skip over a file on the tape 657 */ 658void 659skipfile() 660{ 661 662 curfile.action = SKIP; 663 getfile(xtrnull, xtrnull); 664} 665 666/* 667 * Extract a file from the tape. 668 * When an allocated block is found it is passed to the fill function; 669 * when an unallocated block (hole) is found, a zeroed buffer is passed 670 * to the skip function. 671 */ 672void 673getfile(fill, skip) 674 void (*fill) __P((char *, long)); 675 void (*skip) __P((char *, long)); 676{ 677 register int i; 678 int curblk = 0; 679 quad_t size = spcl.c_dinode.di_size; 680 static char clearedbuf[MAXBSIZE]; 681 char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE]; 682 char junk[TP_BSIZE]; 683 684 if (spcl.c_type == TS_END) 685 panic("ran off end of tape\n"); 686 if (spcl.c_magic != NFS_MAGIC) 687 panic("not at beginning of a file\n"); 688 if (!gettingfile && setjmp(restart) != 0) 689 return; 690 gettingfile++; 691loop: 692 for (i = 0; i < spcl.c_count; i++) { 693 if (readmapflag || spcl.c_addr[i]) { 694 readtape(&buf[curblk++][0]); 695 if (curblk == fssize / TP_BSIZE) { 696 (*fill)((char *)buf, (long)(size > TP_BSIZE ? 697 fssize : (curblk - 1) * TP_BSIZE + size)); 698 curblk = 0; 699 } 700 } else { 701 if (curblk > 0) { 702 (*fill)((char *)buf, (long)(size > TP_BSIZE ? 703 curblk * TP_BSIZE : 704 (curblk - 1) * TP_BSIZE + size)); 705 curblk = 0; 706 } 707 (*skip)(clearedbuf, (long)(size > TP_BSIZE ? 708 TP_BSIZE : size)); 709 } 710 if ((size -= TP_BSIZE) <= 0) { 711 for (i++; i < spcl.c_count; i++) 712 if (readmapflag || spcl.c_addr[i]) 713 readtape(junk); 714 break; 715 } 716 } 717 if (gethead(&spcl) == GOOD && size > 0) { 718 if (spcl.c_type == TS_ADDR) 719 goto loop; 720 dprintf(stdout, 721 "Missing address (header) block for %s at %ld blocks\n", 722 curfile.name, blksread); 723 } 724 if (curblk > 0) 725 (*fill)((char *)buf, (long)((curblk * TP_BSIZE) + size)); 726 findinode(&spcl); 727 gettingfile = 0; 728} 729 730/* 731 * Write out the next block of a file. 732 */ 733static void 734xtrfile(buf, size) 735 char *buf; 736 long size; 737{ 738 739 if (Nflag) 740 return; 741 if (write(ofile, buf, (int) size) == -1) { 742 fprintf(stderr, 743 "write error extracting inode %d, name %s\nwrite: %s\n", 744 curfile.ino, curfile.name, strerror(errno)); 745 } 746} 747 748/* 749 * Skip over a hole in a file. 750 */ 751/* ARGSUSED */ 752static void 753xtrskip(buf, size) 754 char *buf; 755 long size; 756{ 757 758 if (lseek(ofile, size, SEEK_CUR) == -1) { 759 fprintf(stderr, 760 "seek error extracting inode %d, name %s\nlseek: %s\n", 761 curfile.ino, curfile.name, strerror(errno)); 762 done(1); 763 } 764} 765 766/* 767 * Collect the next block of a symbolic link. 768 */ 769static void 770xtrlnkfile(buf, size) 771 char *buf; 772 long size; 773{ 774 775 pathlen += size; 776 if (pathlen > MAXPATHLEN) { 777 fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n", 778 curfile.name, lnkbuf, buf, pathlen); 779 done(1); 780 } 781 (void) strcat(lnkbuf, buf); 782} 783 784/* 785 * Skip over a hole in a symbolic link (should never happen). 786 */ 787/* ARGSUSED */ 788static void 789xtrlnkskip(buf, size) 790 char *buf; 791 long size; 792{ 793 794 fprintf(stderr, "unallocated block in symbolic link %s\n", 795 curfile.name); 796 done(1); 797} 798 799/* 800 * Collect the next block of a bit map. 801 */ 802static void 803xtrmap(buf, size) 804 char *buf; 805 long size; 806{ 807 808 memmove(map, buf, size); 809 map += size; 810} 811 812/* 813 * Skip over a hole in a bit map (should never happen). 814 */ 815/* ARGSUSED */ 816static void 817xtrmapskip(buf, size) 818 char *buf; 819 long size; 820{ 821 822 panic("hole in map\n"); 823 map += size; 824} 825 826/* 827 * Noop, when an extraction function is not needed. 828 */ 829/* ARGSUSED */ 830void 831xtrnull(buf, size) 832 char *buf; 833 long size; 834{ 835 836 return; 837} 838 839/* 840 * Read TP_BSIZE blocks from the input. 841 * Handle read errors, and end of media. 842 */ 843static void 844readtape(buf) 845 char *buf; 846{ 847 long rd, newvol, i; 848 int cnt, seek_failed; 849 850 if (blkcnt < numtrec) { 851 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); 852 blksread++; 853 tpblksread++; 854 return; 855 } 856 for (i = 0; i < ntrec; i++) 857 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 858 if (numtrec == 0) 859 numtrec = ntrec; 860 cnt = ntrec * TP_BSIZE; 861 rd = 0; 862getmore: 863#ifdef RRESTORE 864 if (host) 865 i = rmtread(&tapebuf[rd], cnt); 866 else 867#endif 868 i = read(mt, &tapebuf[rd], cnt); 869 /* 870 * Check for mid-tape short read error. 871 * If found, skip rest of buffer and start with the next. 872 */ 873 if (!pipein && numtrec < ntrec && i > 0) { 874 dprintf(stdout, "mid-media short read error.\n"); 875 numtrec = ntrec; 876 } 877 /* 878 * Handle partial block read. 879 */ 880 if (pipein && i == 0 && rd > 0) 881 i = rd; 882 else if (i > 0 && i != ntrec * TP_BSIZE) { 883 if (pipein) { 884 rd += i; 885 cnt -= i; 886 if (cnt > 0) 887 goto getmore; 888 i = rd; 889 } else { 890 /* 891 * Short read. Process the blocks read. 892 */ 893 if (i % TP_BSIZE != 0) 894 vprintf(stdout, 895 "partial block read: %ld should be %ld\n", 896 i, ntrec * TP_BSIZE); 897 numtrec = i / TP_BSIZE; 898 } 899 } 900 /* 901 * Handle read error. 902 */ 903 if (i < 0) { 904 fprintf(stderr, "Tape read error while "); 905 switch (curfile.action) { 906 default: 907 fprintf(stderr, "trying to set up tape\n"); 908 break; 909 case UNKNOWN: 910 fprintf(stderr, "trying to resynchronize\n"); 911 break; 912 case USING: 913 fprintf(stderr, "restoring %s\n", curfile.name); 914 break; 915 case SKIP: 916 fprintf(stderr, "skipping over inode %d\n", 917 curfile.ino); 918 break; 919 } 920 if (!yflag && !reply("continue")) 921 done(1); 922 i = ntrec * TP_BSIZE; 923 memset(tapebuf, 0, i); 924#ifdef RRESTORE 925 if (host) 926 seek_failed = (rmtseek(i, 1) < 0); 927 else 928#endif 929 seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); 930 931 if (seek_failed) { 932 fprintf(stderr, 933 "continuation failed: %s\n", strerror(errno)); 934 done(1); 935 } 936 } 937 /* 938 * Handle end of tape. 939 */ 940 if (i == 0) { 941 vprintf(stdout, "End-of-tape encountered\n"); 942 if (!pipein) { 943 newvol = volno + 1; 944 volno = 0; 945 numtrec = 0; 946 getvol(newvol); 947 readtape(buf); 948 return; 949 } 950 if (rd % TP_BSIZE != 0) 951 panic("partial block read: %d should be %d\n", 952 rd, ntrec * TP_BSIZE); 953 terminateinput(); 954 memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); 955 } 956 blkcnt = 0; 957 memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE)], (long)TP_BSIZE); 958 blksread++; 959 tpblksread++; 960} 961 962static void 963findtapeblksize() 964{ 965 register long i; 966 967 for (i = 0; i < ntrec; i++) 968 ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; 969 blkcnt = 0; 970#ifdef RRESTORE 971 if (host) 972 i = rmtread(tapebuf, ntrec * TP_BSIZE); 973 else 974#endif 975 i = read(mt, tapebuf, ntrec * TP_BSIZE); 976 977 if (i <= 0) { 978 fprintf(stderr, "tape read error: %s\n", strerror(errno)); 979 done(1); 980 } 981 if (i % TP_BSIZE != 0) { 982 fprintf(stderr, "Tape block size (%ld) %s (%d)\n", 983 i, "is not a multiple of dump block size", TP_BSIZE); 984 done(1); 985 } 986 ntrec = i / TP_BSIZE; 987 numtrec = ntrec; 988 vprintf(stdout, "Tape block size is %ld\n", ntrec); 989} 990 991void 992closemt() 993{ 994 995 if (mt < 0) 996 return; 997#ifdef RRESTORE 998 if (host) 999 rmtclose(); 1000 else 1001#endif 1002 (void) close(mt); 1003} 1004 1005/* 1006 * Read the next block from the tape. 1007 * Check to see if it is one of several vintage headers. 1008 * If it is an old style header, convert it to a new style header. 1009 * If it is not any valid header, return an error. 1010 */ 1011static int 1012gethead(buf) 1013 struct s_spcl *buf; 1014{ 1015 long i; 1016 union { 1017 quad_t qval; 1018 int32_t val[2]; 1019 } qcvt; 1020 union u_ospcl { 1021 char dummy[TP_BSIZE]; 1022 struct s_ospcl { 1023 int32_t c_type; 1024 int32_t c_date; 1025 int32_t c_ddate; 1026 int32_t c_volume; 1027 int32_t c_tapea; 1028 u_short c_inumber; 1029 int32_t c_magic; 1030 int32_t c_checksum; 1031 struct odinode { 1032 unsigned short odi_mode; 1033 u_short odi_nlink; 1034 u_short odi_uid; 1035 u_short odi_gid; 1036 int32_t odi_size; 1037 int32_t odi_rdev; 1038 char odi_addr[36]; 1039 int32_t odi_atime; 1040 int32_t odi_mtime; 1041 int32_t odi_ctime; 1042 } c_dinode; 1043 int32_t c_count; 1044 char c_addr[256]; 1045 } s_ospcl; 1046 } u_ospcl; 1047 1048 if (!cvtflag) { 1049 readtape((char *)buf); 1050 if (buf->c_magic != NFS_MAGIC) { 1051 if (swabl(buf->c_magic) != NFS_MAGIC) 1052 return (FAIL); 1053 if (!Bcvt) { 1054 vprintf(stdout, "Note: Doing Byte swapping\n"); 1055 Bcvt = 1; 1056 } 1057 } 1058 if (checksum((int *)buf) == FAIL) 1059 return (FAIL); 1060 if (Bcvt) { 1061 swabst((u_char *)"8l4s31l", (u_char *)buf); 1062 swabst((u_char *)"l",(u_char *) &buf->c_level); 1063 swabst((u_char *)"2l",(u_char *) &buf->c_flags); 1064 } 1065 goto good; 1066 } 1067 readtape((char *)(&u_ospcl.s_ospcl)); 1068 memset(buf, 0, (long)TP_BSIZE); 1069 buf->c_type = u_ospcl.s_ospcl.c_type; 1070 buf->c_date = u_ospcl.s_ospcl.c_date; 1071 buf->c_ddate = u_ospcl.s_ospcl.c_ddate; 1072 buf->c_volume = u_ospcl.s_ospcl.c_volume; 1073 buf->c_tapea = u_ospcl.s_ospcl.c_tapea; 1074 buf->c_inumber = u_ospcl.s_ospcl.c_inumber; 1075 buf->c_checksum = u_ospcl.s_ospcl.c_checksum; 1076 buf->c_magic = u_ospcl.s_ospcl.c_magic; 1077 buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode; 1078 buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink; 1079 buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid; 1080 buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid; 1081 buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size; 1082 buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev; 1083 buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime; 1084 buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime; 1085 buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime; 1086 buf->c_count = u_ospcl.s_ospcl.c_count; 1087 memmove(buf->c_addr, u_ospcl.s_ospcl.c_addr, (long)256); 1088 if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC || 1089 checksum((int *)(&u_ospcl.s_ospcl)) == FAIL) 1090 return(FAIL); 1091 buf->c_magic = NFS_MAGIC; 1092 1093good: 1094 if ((buf->c_dinode.di_size == 0 || buf->c_dinode.di_size > 0xfffffff) && 1095 (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt == 0) { 1096 qcvt.qval = buf->c_dinode.di_size; 1097 if (qcvt.val[0] || qcvt.val[1]) { 1098 printf("Note: Doing Quad swapping\n"); 1099 Qcvt = 1; 1100 } 1101 } 1102 if (Qcvt) { 1103 qcvt.qval = buf->c_dinode.di_size; 1104 i = qcvt.val[1]; 1105 qcvt.val[1] = qcvt.val[0]; 1106 qcvt.val[0] = i; 1107 buf->c_dinode.di_size = qcvt.qval; 1108 } 1109 readmapflag = 0; 1110 1111 switch (buf->c_type) { 1112 1113 case TS_CLRI: 1114 case TS_BITS: 1115 /* 1116 * Have to patch up missing information in bit map headers 1117 */ 1118 buf->c_inumber = 0; 1119 buf->c_dinode.di_size = buf->c_count * TP_BSIZE; 1120 if (buf->c_count > TP_NINDIR) 1121 readmapflag = 1; 1122 else 1123 for (i = 0; i < buf->c_count; i++) 1124 buf->c_addr[i]++; 1125 break; 1126 1127 case TS_TAPE: 1128 if ((buf->c_flags & DR_NEWINODEFMT) == 0) 1129 oldinofmt = 1; 1130 /* fall through */ 1131 case TS_END: 1132 buf->c_inumber = 0; 1133 break; 1134 1135 case TS_INODE: 1136 case TS_ADDR: 1137 break; 1138 1139 default: 1140 panic("gethead: unknown inode type %d\n", buf->c_type); 1141 break; 1142 } 1143 /* 1144 * If we are restoring a filesystem with old format inodes, 1145 * copy the uid/gid to the new location. 1146 */ 1147 if (oldinofmt) { 1148 buf->c_dinode.di_uid = buf->c_dinode.di_ouid; 1149 buf->c_dinode.di_gid = buf->c_dinode.di_ogid; 1150 } 1151 if (dflag) 1152 accthdr(buf); 1153 return(GOOD); 1154} 1155 1156/* 1157 * Check that a header is where it belongs and predict the next header 1158 */ 1159static void 1160accthdr(header) 1161 struct s_spcl *header; 1162{ 1163 static ino_t previno = 0x7fffffff; 1164 static int prevtype; 1165 static long predict; 1166 long blks, i; 1167 1168 if (header->c_type == TS_TAPE) { 1169 fprintf(stderr, "Volume header (%s inode format) ", 1170 oldinofmt ? "old" : "new"); 1171 if (header->c_firstrec) 1172 fprintf(stderr, "begins with record %ld", 1173 header->c_firstrec); 1174 fprintf(stderr, "\n"); 1175 previno = 0x7fffffff; 1176 return; 1177 } 1178 if (previno == 0x7fffffff) 1179 goto newcalc; 1180 switch (prevtype) { 1181 case TS_BITS: 1182 fprintf(stderr, "Dumped inodes map header"); 1183 break; 1184 case TS_CLRI: 1185 fprintf(stderr, "Used inodes map header"); 1186 break; 1187 case TS_INODE: 1188 fprintf(stderr, "File header, ino %d", previno); 1189 break; 1190 case TS_ADDR: 1191 fprintf(stderr, "File continuation header, ino %d", previno); 1192 break; 1193 case TS_END: 1194 fprintf(stderr, "End of tape header"); 1195 break; 1196 } 1197 if (predict != blksread - 1) 1198 fprintf(stderr, "; predicted %ld blocks, got %ld blocks", 1199 predict, blksread - 1); 1200 fprintf(stderr, "\n"); 1201newcalc: 1202 blks = 0; 1203 if (header->c_type != TS_END) 1204 for (i = 0; i < header->c_count; i++) 1205 if (readmapflag || header->c_addr[i] != 0) 1206 blks++; 1207 predict = blks; 1208 blksread = 0; 1209 prevtype = header->c_type; 1210 previno = header->c_inumber; 1211} 1212 1213/* 1214 * Find an inode header. 1215 * Complain if had to skip. 1216 */ 1217static void 1218findinode(header) 1219 struct s_spcl *header; 1220{ 1221 static long skipcnt = 0; 1222 long i; 1223 char buf[TP_BSIZE];
|
| 1224 int htype;
|
1225 1226 curfile.name = "<name unknown>"; 1227 curfile.action = UNKNOWN; 1228 curfile.dip = NULL; 1229 curfile.ino = 0; 1230 do { 1231 if (header->c_magic != NFS_MAGIC) { 1232 skipcnt++; 1233 while (gethead(header) == FAIL || 1234 _time32_to_time(header->c_date) != dumpdate) 1235 skipcnt++; 1236 }
| 1225 1226 curfile.name = "<name unknown>"; 1227 curfile.action = UNKNOWN; 1228 curfile.dip = NULL; 1229 curfile.ino = 0; 1230 do { 1231 if (header->c_magic != NFS_MAGIC) { 1232 skipcnt++; 1233 while (gethead(header) == FAIL || 1234 _time32_to_time(header->c_date) != dumpdate) 1235 skipcnt++; 1236 }
|
1237 switch (header->c_type) {
| 1237 htype = header->c_type; 1238 switch (htype) {
|
1238 1239 case TS_ADDR: 1240 /* 1241 * Skip up to the beginning of the next record 1242 */ 1243 for (i = 0; i < header->c_count; i++) 1244 if (header->c_addr[i]) 1245 readtape(buf); 1246 while (gethead(header) == FAIL || 1247 _time32_to_time(header->c_date) != dumpdate) 1248 skipcnt++; 1249 break; 1250 1251 case TS_INODE: 1252 curfile.dip = &header->c_dinode; 1253 curfile.ino = header->c_inumber; 1254 break; 1255 1256 case TS_END: 1257 curfile.ino = maxino; 1258 break; 1259 1260 case TS_CLRI: 1261 curfile.name = "<file removal list>"; 1262 break; 1263 1264 case TS_BITS: 1265 curfile.name = "<file dump list>"; 1266 break; 1267 1268 case TS_TAPE: 1269 panic("unexpected tape header\n"); 1270 /* NOTREACHED */ 1271 1272 default: 1273 panic("unknown tape header type %d\n", spcl.c_type); 1274 /* NOTREACHED */ 1275 1276 }
| 1239 1240 case TS_ADDR: 1241 /* 1242 * Skip up to the beginning of the next record 1243 */ 1244 for (i = 0; i < header->c_count; i++) 1245 if (header->c_addr[i]) 1246 readtape(buf); 1247 while (gethead(header) == FAIL || 1248 _time32_to_time(header->c_date) != dumpdate) 1249 skipcnt++; 1250 break; 1251 1252 case TS_INODE: 1253 curfile.dip = &header->c_dinode; 1254 curfile.ino = header->c_inumber; 1255 break; 1256 1257 case TS_END: 1258 curfile.ino = maxino; 1259 break; 1260 1261 case TS_CLRI: 1262 curfile.name = "<file removal list>"; 1263 break; 1264 1265 case TS_BITS: 1266 curfile.name = "<file dump list>"; 1267 break; 1268 1269 case TS_TAPE: 1270 panic("unexpected tape header\n"); 1271 /* NOTREACHED */ 1272 1273 default: 1274 panic("unknown tape header type %d\n", spcl.c_type); 1275 /* NOTREACHED */ 1276 1277 }
|
1277 } while (header->c_type == TS_ADDR);
| 1278 } while (htype == TS_ADDR);
|
1278 if (skipcnt > 0) 1279 fprintf(stderr, "resync restore, skipped %ld blocks\n", 1280 skipcnt); 1281 skipcnt = 0; 1282} 1283 1284static int 1285checksum(buf) 1286 register int *buf; 1287{ 1288 register int i, j; 1289 1290 j = sizeof(union u_spcl) / sizeof(int); 1291 i = 0; 1292 if(!Bcvt) { 1293 do 1294 i += *buf++; 1295 while (--j); 1296 } else { 1297 /* What happens if we want to read restore tapes 1298 for a 16bit int machine??? */ 1299 do 1300 i += swabl(*buf++); 1301 while (--j); 1302 } 1303 1304 if (i != CHECKSUM) { 1305 fprintf(stderr, "Checksum error %o, inode %d file %s\n", i, 1306 curfile.ino, curfile.name); 1307 return(FAIL); 1308 } 1309 return(GOOD); 1310} 1311 1312#ifdef RRESTORE 1313#if __STDC__ 1314#include <stdarg.h> 1315#else 1316#include <varargs.h> 1317#endif 1318 1319void 1320#if __STDC__ 1321msg(const char *fmt, ...) 1322#else 1323msg(fmt, va_alist) 1324 char *fmt; 1325 va_dcl 1326#endif 1327{ 1328 va_list ap; 1329#if __STDC__ 1330 va_start(ap, fmt); 1331#else 1332 va_start(ap); 1333#endif 1334 (void)vfprintf(stderr, fmt, ap); 1335 va_end(ap); 1336} 1337#endif /* RRESTORE */ 1338 1339static u_char * 1340swabshort(sp, n) 1341 register u_char *sp; 1342 register int n; 1343{ 1344 char c; 1345 1346 while (--n >= 0) { 1347 c = sp[0]; sp[0] = sp[1]; sp[1] = c; 1348 sp += 2; 1349 } 1350 return (sp); 1351} 1352 1353static u_char * 1354swablong(sp, n) 1355 register u_char *sp; 1356 register int n; 1357{ 1358 char c; 1359 1360 while (--n >= 0) { 1361 c = sp[0]; sp[0] = sp[3]; sp[3] = c; 1362 c = sp[2]; sp[2] = sp[1]; sp[1] = c; 1363 sp += 4; 1364 } 1365 return (sp); 1366} 1367 1368void 1369swabst(cp, sp) 1370 register u_char *cp, *sp; 1371{ 1372 int n = 0; 1373 1374 while (*cp) { 1375 switch (*cp) { 1376 case '0': case '1': case '2': case '3': case '4': 1377 case '5': case '6': case '7': case '8': case '9': 1378 n = (n * 10) + (*cp++ - '0'); 1379 continue; 1380 1381 case 's': case 'w': case 'h': 1382 if (n == 0) 1383 n = 1; 1384 sp = swabshort(sp, n); 1385 break; 1386 1387 case 'l': 1388 if (n == 0) 1389 n = 1; 1390 sp = swablong(sp, n); 1391 break; 1392 1393 default: /* Any other character, like 'b' counts as byte. */ 1394 if (n == 0) 1395 n = 1; 1396 sp += n; 1397 break; 1398 } 1399 cp++; 1400 n = 0; 1401 } 1402} 1403 1404static u_long 1405swabl(x) 1406 u_long x; 1407{ 1408 swabst((u_char *)"l", (u_char *)&x); 1409 return (x); 1410}
| 1279 if (skipcnt > 0) 1280 fprintf(stderr, "resync restore, skipped %ld blocks\n", 1281 skipcnt); 1282 skipcnt = 0; 1283} 1284 1285static int 1286checksum(buf) 1287 register int *buf; 1288{ 1289 register int i, j; 1290 1291 j = sizeof(union u_spcl) / sizeof(int); 1292 i = 0; 1293 if(!Bcvt) { 1294 do 1295 i += *buf++; 1296 while (--j); 1297 } else { 1298 /* What happens if we want to read restore tapes 1299 for a 16bit int machine??? */ 1300 do 1301 i += swabl(*buf++); 1302 while (--j); 1303 } 1304 1305 if (i != CHECKSUM) { 1306 fprintf(stderr, "Checksum error %o, inode %d file %s\n", i, 1307 curfile.ino, curfile.name); 1308 return(FAIL); 1309 } 1310 return(GOOD); 1311} 1312 1313#ifdef RRESTORE 1314#if __STDC__ 1315#include <stdarg.h> 1316#else 1317#include <varargs.h> 1318#endif 1319 1320void 1321#if __STDC__ 1322msg(const char *fmt, ...) 1323#else 1324msg(fmt, va_alist) 1325 char *fmt; 1326 va_dcl 1327#endif 1328{ 1329 va_list ap; 1330#if __STDC__ 1331 va_start(ap, fmt); 1332#else 1333 va_start(ap); 1334#endif 1335 (void)vfprintf(stderr, fmt, ap); 1336 va_end(ap); 1337} 1338#endif /* RRESTORE */ 1339 1340static u_char * 1341swabshort(sp, n) 1342 register u_char *sp; 1343 register int n; 1344{ 1345 char c; 1346 1347 while (--n >= 0) { 1348 c = sp[0]; sp[0] = sp[1]; sp[1] = c; 1349 sp += 2; 1350 } 1351 return (sp); 1352} 1353 1354static u_char * 1355swablong(sp, n) 1356 register u_char *sp; 1357 register int n; 1358{ 1359 char c; 1360 1361 while (--n >= 0) { 1362 c = sp[0]; sp[0] = sp[3]; sp[3] = c; 1363 c = sp[2]; sp[2] = sp[1]; sp[1] = c; 1364 sp += 4; 1365 } 1366 return (sp); 1367} 1368 1369void 1370swabst(cp, sp) 1371 register u_char *cp, *sp; 1372{ 1373 int n = 0; 1374 1375 while (*cp) { 1376 switch (*cp) { 1377 case '0': case '1': case '2': case '3': case '4': 1378 case '5': case '6': case '7': case '8': case '9': 1379 n = (n * 10) + (*cp++ - '0'); 1380 continue; 1381 1382 case 's': case 'w': case 'h': 1383 if (n == 0) 1384 n = 1; 1385 sp = swabshort(sp, n); 1386 break; 1387 1388 case 'l': 1389 if (n == 0) 1390 n = 1; 1391 sp = swablong(sp, n); 1392 break; 1393 1394 default: /* Any other character, like 'b' counts as byte. */ 1395 if (n == 0) 1396 n = 1; 1397 sp += n; 1398 break; 1399 } 1400 cp++; 1401 n = 0; 1402 } 1403} 1404 1405static u_long 1406swabl(x) 1407 u_long x; 1408{ 1409 swabst((u_char *)"l", (u_char *)&x); 1410 return (x); 1411}
|