132022Spc /*
232022Spc * Copyright (c) 1983 Regents of the University of California.
332022Spc * All rights reserved. The Berkeley software License Agreement
432022Spc * specifies the terms and conditions for redistribution.
532022Spc */
632022Spc
732022Spc #ifndef lint
832025Spc static char sccsid[] = "@(#)tape.c 5.10 (Berkeley) 1/28/87";
932022Spc #endif not lint
1032022Spc
1132022Spc #include "restore.h"
1232022Spc #include <protocols/dumprestore.h>
1332022Spc #include <sys/ioctl.h>
1432022Spc #include <sys/mtio.h>
1532022Spc #include <sys/file.h>
1632022Spc #include <setjmp.h>
1732022Spc #include <sys/stat.h>
1832022Spc
1932022Spc static long fssize = MAXBSIZE;
2032022Spc static int mt = -1;
2132022Spc static int pipein = 0;
2232022Spc static char magtape[BUFSIZ];
2332022Spc static int bct;
2432022Spc static char *tbf;
2532022Spc static union u_spcl endoftapemark;
2632022Spc static long blksread;
2732022Spc static long tapesread;
2832022Spc static jmp_buf restart;
2932022Spc static int gettingfile = 0; /* restart has a valid frame */
3032022Spc
3132022Spc static int ofile;
3232022Spc static char *map;
3332022Spc static char lnkbuf[MAXPATHLEN + 1];
3432022Spc static int pathlen;
3532022Spc
3632022Spc int Bcvt; /* Swap Bytes (for CCI or sun) */
3732022Spc static int Qcvt; /* Swap quads (for sun) */
3832022Spc /*
3932022Spc * Set up an input source
4032022Spc */
setinput(source)4132022Spc setinput(source)
4232022Spc char *source;
4332022Spc {
4432022Spc #ifdef RRESTORE
4532022Spc char *host, *tape;
4632022Spc #endif RRESTORE
4732022Spc
4832022Spc flsht();
4932022Spc if (bflag)
5032022Spc newtapebuf(ntrec);
5132022Spc else
5232022Spc newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC);
5332022Spc terminal = stdin;
5432022Spc #ifdef RRESTORE
5532022Spc host = source;
5632022Spc tape = index(host, ':');
5732022Spc if (tape == 0) {
5832022Spc nohost:
5932022Spc msg("need keyletter ``f'' and device ``host:tape''\n");
6032022Spc done(1);
6132022Spc }
6232022Spc *tape++ = '\0';
6332022Spc (void) strcpy(magtape, tape);
6432022Spc if (rmthost(host) == 0)
6532022Spc done(1);
6632022Spc setuid(getuid()); /* no longer need or want root privileges */
6732022Spc #else
6832022Spc if (strcmp(source, "-") == 0) {
6932022Spc /*
7032022Spc * Since input is coming from a pipe we must establish
7132022Spc * our own connection to the terminal.
7232022Spc */
7332022Spc terminal = fopen("/dev/tty", "r");
7432022Spc if (terminal == NULL) {
7532022Spc perror("Cannot open(\"/dev/tty\")");
7632022Spc terminal = fopen("/dev/null", "r");
7732022Spc if (terminal == NULL) {
7832022Spc perror("Cannot open(\"/dev/null\")");
7932022Spc done(1);
8032022Spc }
8132022Spc }
8232022Spc pipein++;
8332022Spc }
8432022Spc (void) strcpy(magtape, source);
8532022Spc #endif RRESTORE
8632022Spc }
8732022Spc
newtapebuf(size)8832022Spc newtapebuf(size)
8932022Spc long size;
9032022Spc {
9132022Spc static tbfsize = -1;
9232022Spc
9332022Spc ntrec = size;
9432022Spc if (size <= tbfsize)
9532022Spc return;
9632022Spc if (tbf != NULL)
9732022Spc free(tbf);
9832022Spc tbf = (char *)malloc(size * TP_BSIZE);
9932022Spc if (tbf == NULL) {
10032022Spc fprintf(stderr, "Cannot allocate space for tape buffer\n");
10132022Spc done(1);
10232022Spc }
10332022Spc tbfsize = size;
10432022Spc }
10532022Spc
10632022Spc /*
10732022Spc * Verify that the tape drive can be accessed and
10832022Spc * that it actually is a dump tape.
10932022Spc */
setup()11032022Spc setup()
11132022Spc {
11232022Spc int i, j, *ip;
11332022Spc struct stat stbuf;
11432022Spc extern char *ctime();
11532022Spc extern int xtrmap(), xtrmapskip();
11632022Spc
11732022Spc vprintf(stdout, "Verify tape and initialize maps\n");
11832022Spc #ifdef RRESTORE
11932022Spc if ((mt = rmtopen(magtape, 0)) < 0)
12032022Spc #else
12132022Spc if (pipein)
12232022Spc mt = 0;
12332022Spc else if ((mt = open(magtape, 0)) < 0)
12432022Spc #endif
12532022Spc {
12632022Spc perror(magtape);
12732022Spc done(1);
12832022Spc }
12932022Spc volno = 1;
13032022Spc setdumpnum();
13132022Spc flsht();
13232022Spc if (!pipein && !bflag)
13332022Spc findtapeblksize();
13432022Spc if (gethead(&spcl) == FAIL) {
13532022Spc bct--; /* push back this block */
13632022Spc cvtflag++;
13732022Spc if (gethead(&spcl) == FAIL) {
13832022Spc fprintf(stderr, "Tape is not a dump tape\n");
13932022Spc done(1);
14032022Spc }
14132022Spc fprintf(stderr, "Converting to new file system format.\n");
14232022Spc }
14332022Spc if (pipein) {
14432022Spc endoftapemark.s_spcl.c_magic = cvtflag ? OFS_MAGIC : NFS_MAGIC;
14532022Spc endoftapemark.s_spcl.c_type = TS_END;
14632022Spc ip = (int *)&endoftapemark;
14732022Spc j = sizeof(union u_spcl) / sizeof(int);
14832022Spc i = 0;
14932022Spc do
15032022Spc i += *ip++;
15132022Spc while (--j);
15232022Spc endoftapemark.s_spcl.c_checksum = CHECKSUM - i;
15332022Spc }
15432025Spc if (vflag || command == 't')
15532025Spc printdumpinfo();
15632022Spc dumptime = spcl.c_ddate;
15732022Spc dumpdate = spcl.c_date;
15832022Spc if (stat(".", &stbuf) < 0) {
15932022Spc perror("cannot stat .");
16032022Spc done(1);
16132022Spc }
16232022Spc if (stbuf.st_blksize > 0 && stbuf.st_blksize <= MAXBSIZE)
16332022Spc fssize = stbuf.st_blksize;
16432022Spc if (((fssize - 1) & fssize) != 0) {
16532022Spc fprintf(stderr, "bad block size %d\n", fssize);
16632022Spc done(1);
16732022Spc }
16832022Spc if (checkvol(&spcl, (long)1) == FAIL) {
16932022Spc fprintf(stderr, "Tape is not volume 1 of the dump\n");
17032022Spc done(1);
17132022Spc }
17232022Spc if (readhdr(&spcl) == FAIL)
17332022Spc panic("no header after volume mark!\n");
17432025Spc findinode(&spcl);
17532022Spc if (checktype(&spcl, TS_CLRI) == FAIL) {
17632022Spc fprintf(stderr, "Cannot find file removal list\n");
17732022Spc done(1);
17832022Spc }
17932022Spc maxino = (spcl.c_count * TP_BSIZE * NBBY) + 1;
18032022Spc dprintf(stdout, "maxino = %d\n", maxino);
18132022Spc map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
18232022Spc if (map == (char *)NIL)
18332022Spc panic("no memory for file removal list\n");
18432022Spc clrimap = map;
18532022Spc curfile.action = USING;
18632022Spc getfile(xtrmap, xtrmapskip);
18732022Spc if (checktype(&spcl, TS_BITS) == FAIL) {
18832022Spc fprintf(stderr, "Cannot find file dump list\n");
18932022Spc done(1);
19032022Spc }
19132022Spc map = calloc((unsigned)1, (unsigned)howmany(maxino, NBBY));
19232022Spc if (map == (char *)NULL)
19332022Spc panic("no memory for file dump list\n");
19432022Spc dumpmap = map;
19532022Spc curfile.action = USING;
19632022Spc getfile(xtrmap, xtrmapskip);
19732022Spc }
19832022Spc
19932022Spc /*
20032022Spc * Prompt user to load a new dump volume.
20132022Spc * "Nextvol" is the next suggested volume to use.
20232022Spc * This suggested volume is enforced when doing full
20332022Spc * or incremental restores, but can be overrridden by
20432022Spc * the user when only extracting a subset of the files.
20532022Spc */
getvol(nextvol)20632022Spc getvol(nextvol)
20732022Spc long nextvol;
20832022Spc {
20932022Spc long newvol;
21032022Spc long savecnt, i;
21132022Spc union u_spcl tmpspcl;
21232022Spc # define tmpbuf tmpspcl.s_spcl
21332025Spc char buf[TP_BSIZE];
21432022Spc
21532022Spc if (nextvol == 1) {
21632022Spc tapesread = 0;
21732022Spc gettingfile = 0;
21832022Spc }
21932022Spc if (pipein) {
22032022Spc if (nextvol != 1)
22132022Spc panic("Changing volumes on pipe input?\n");
22232022Spc if (volno == 1)
22332022Spc return;
22432022Spc goto gethdr;
22532022Spc }
22632022Spc savecnt = blksread;
22732022Spc again:
22832022Spc if (pipein)
22932022Spc done(1); /* pipes do not get a second chance */
23032022Spc if (command == 'R' || command == 'r' || curfile.action != SKIP)
23132022Spc newvol = nextvol;
23232022Spc else
23332022Spc newvol = 0;
23432022Spc while (newvol <= 0) {
23532022Spc if (tapesread == 0) {
23632022Spc fprintf(stderr, "%s%s%s%s%s",
23732022Spc "You have not read any tapes yet.\n",
23832022Spc "Unless you know which volume your",
23932022Spc " file(s) are on you should start\n",
24032022Spc "with the last volume and work",
24132022Spc " towards towards the first.\n");
24232022Spc } else {
24332022Spc fprintf(stderr, "You have read volumes");
24432022Spc strcpy(tbf, ": ");
24532022Spc for (i = 1; i < 32; i++)
24632022Spc if (tapesread & (1 << i)) {
24732022Spc fprintf(stderr, "%s%d", tbf, i);
24832022Spc strcpy(tbf, ", ");
24932022Spc }
25032022Spc fprintf(stderr, "\n");
25132022Spc }
25232022Spc do {
25332022Spc fprintf(stderr, "Specify next volume #: ");
25432022Spc (void) fflush(stderr);
25532022Spc (void) fgets(tbf, BUFSIZ, terminal);
25632022Spc } while (!feof(terminal) && tbf[0] == '\n');
25732022Spc if (feof(terminal))
25832022Spc done(1);
25932022Spc newvol = atoi(tbf);
26032022Spc if (newvol <= 0) {
26132022Spc fprintf(stderr,
26232022Spc "Volume numbers are positive numerics\n");
26332022Spc }
26432022Spc }
26532022Spc if (newvol == volno) {
26632022Spc tapesread |= 1 << volno;
26732022Spc return;
26832022Spc }
26932022Spc closemt();
27032022Spc fprintf(stderr, "Mount tape volume %d\n", newvol);
27132022Spc fprintf(stderr, "then enter tape name (default: %s) ", magtape);
27232022Spc (void) fflush(stderr);
27332022Spc (void) fgets(tbf, BUFSIZ, terminal);
27432022Spc if (feof(terminal))
27532022Spc done(1);
27632022Spc if (tbf[0] != '\n') {
27732022Spc (void) strcpy(magtape, tbf);
27832022Spc magtape[strlen(magtape) - 1] = '\0';
27932022Spc }
28032022Spc #ifdef RRESTORE
28132022Spc if ((mt = rmtopen(magtape, 0)) == -1)
28232022Spc #else
28332022Spc if ((mt = open(magtape, 0)) == -1)
28432022Spc #endif
28532022Spc {
28632022Spc fprintf(stderr, "Cannot open %s\n", magtape);
28732022Spc volno = -1;
28832022Spc goto again;
28932022Spc }
29032022Spc gethdr:
29132022Spc volno = newvol;
29232022Spc setdumpnum();
29332022Spc flsht();
29432022Spc if (readhdr(&tmpbuf) == FAIL) {
29532022Spc fprintf(stderr, "tape is not dump tape\n");
29632022Spc volno = 0;
29732022Spc goto again;
29832022Spc }
29932022Spc if (checkvol(&tmpbuf, volno) == FAIL) {
30032022Spc fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
30132022Spc volno = 0;
30232022Spc goto again;
30332022Spc }
30432022Spc if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
30532022Spc fprintf(stderr, "Wrong dump date\n\tgot: %s",
30632022Spc ctime(&tmpbuf.c_date));
30732022Spc fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
30832022Spc volno = 0;
30932022Spc goto again;
31032022Spc }
31132022Spc tapesread |= 1 << volno;
31232022Spc blksread = savecnt;
31332022Spc if (curfile.action == USING) {
31432022Spc if (volno == 1)
31532022Spc panic("active file into volume 1\n");
31632022Spc return;
31732022Spc }
31832025Spc /*
31932025Spc * Skip up to the beginning of the next record
32032025Spc */
32132025Spc if (tmpbuf.c_type == TS_TAPE && (tmpbuf.c_flags & DR_NEWHEADER))
32232025Spc for (i = tmpbuf.c_count; i > 0; i--)
32332025Spc readtape(buf);
32432022Spc (void) gethead(&spcl);
32532025Spc findinode(&spcl);
32632022Spc if (gettingfile) {
32732022Spc gettingfile = 0;
32832022Spc longjmp(restart, 1);
32932022Spc }
33032022Spc }
33132022Spc
33232022Spc /*
33332022Spc * handle multiple dumps per tape by skipping forward to the
33432022Spc * appropriate one.
33532022Spc */
setdumpnum()33632022Spc setdumpnum()
33732022Spc {
33832022Spc struct mtop tcom;
33932022Spc
34032022Spc if (dumpnum == 1 || volno != 1)
34132022Spc return;
34232022Spc if (pipein) {
34332022Spc fprintf(stderr, "Cannot have multiple dumps on pipe input\n");
34432022Spc done(1);
34532022Spc }
34632022Spc tcom.mt_op = MTFSF;
34732022Spc tcom.mt_count = dumpnum - 1;
34832022Spc #ifdef RRESTORE
34932022Spc rmtioctl(MTFSF, dumpnum - 1);
35032022Spc #else
35132022Spc if (ioctl(mt, (int)MTIOCTOP, (char *)&tcom) < 0)
35232022Spc perror("ioctl MTFSF");
35332022Spc #endif
35432022Spc }
35532022Spc
printdumpinfo()35632025Spc printdumpinfo()
35732025Spc {
35832025Spc
35932025Spc fprintf(stdout, "Dump date: %s", ctime(&spcl.c_date));
36032025Spc fprintf(stdout, "Dumped from: %s", ctime(&spcl.c_ddate));
36132025Spc if (spcl.c_host[0] == '\0')
36232025Spc return;
36332025Spc fprintf(stderr, "Level %d dump of %s on %s:%s\n",
36432025Spc spcl.c_level, spcl.c_filesys, spcl.c_host, spcl.c_dev);
365*32048Spc printf("Volume %d of the dump, starting at inode %d\n",
366*32048Spc spcl.c_volume, spcl.c_inumber);
36732025Spc fprintf(stderr, "Label: %s\n", spcl.c_label);
36832025Spc }
36932025Spc
extractfile(name)37032022Spc extractfile(name)
37132022Spc char *name;
37232022Spc {
37332022Spc int mode;
37432022Spc time_t timep[2];
37532022Spc struct entry *ep;
37632022Spc extern int xtrlnkfile(), xtrlnkskip();
37732022Spc extern int xtrfile(), xtrskip();
37832022Spc
37932022Spc curfile.name = name;
38032022Spc curfile.action = USING;
38132022Spc timep[0] = curfile.dip->di_atime;
38232022Spc timep[1] = curfile.dip->di_mtime;
38332022Spc mode = curfile.dip->di_mode;
38432022Spc switch (mode & IFMT) {
38532022Spc
38632022Spc default:
38732022Spc fprintf(stderr, "%s: unknown file mode 0%o\n", name, mode);
38832022Spc skipfile();
38932022Spc return (FAIL);
39032022Spc
39132022Spc case IFSOCK:
39232022Spc vprintf(stdout, "skipped socket %s\n", name);
39332022Spc skipfile();
39432022Spc return (GOOD);
39532022Spc
39632022Spc case IFDIR:
39732022Spc if (mflag) {
39832022Spc ep = lookupname(name);
39932022Spc if (ep == NIL || ep->e_flags & EXTRACT)
40032022Spc panic("unextracted directory %s\n", name);
40132022Spc skipfile();
40232022Spc return (GOOD);
40332022Spc }
40432022Spc vprintf(stdout, "extract file %s\n", name);
40532022Spc return (genliteraldir(name, curfile.ino));
40632022Spc
40732022Spc case IFLNK:
40832022Spc lnkbuf[0] = '\0';
40932022Spc pathlen = 0;
41032022Spc getfile(xtrlnkfile, xtrlnkskip);
41132022Spc if (pathlen == 0) {
41232022Spc vprintf(stdout,
41332022Spc "%s: zero length symbolic link (ignored)\n", name);
41432022Spc return (GOOD);
41532022Spc }
41632022Spc return (linkit(lnkbuf, name, SYMLINK));
41732022Spc
41832022Spc case IFCHR:
41932022Spc case IFBLK:
42032022Spc vprintf(stdout, "extract special file %s\n", name);
42132022Spc if (mknod(name, mode, (int)curfile.dip->di_rdev) < 0) {
42232022Spc fprintf(stderr, "%s: ", name);
42332022Spc (void) fflush(stderr);
42432022Spc perror("cannot create special file");
42532022Spc skipfile();
42632022Spc return (FAIL);
42732022Spc }
42832022Spc (void) chown(name, curfile.dip->di_uid, curfile.dip->di_gid);
42932022Spc (void) chmod(name, mode);
43032022Spc skipfile();
43132022Spc utime(name, timep);
43232022Spc return (GOOD);
43332022Spc
43432022Spc case IFREG:
43532022Spc vprintf(stdout, "extract file %s\n", name);
43632022Spc if ((ofile = creat(name, 0666)) < 0) {
43732022Spc fprintf(stderr, "%s: ", name);
43832022Spc (void) fflush(stderr);
43932022Spc perror("cannot create file");
44032022Spc skipfile();
44132022Spc return (FAIL);
44232022Spc }
44332022Spc (void) fchown(ofile, curfile.dip->di_uid, curfile.dip->di_gid);
44432022Spc (void) fchmod(ofile, mode);
44532022Spc getfile(xtrfile, xtrskip);
44632022Spc (void) close(ofile);
44732022Spc utime(name, timep);
44832022Spc return (GOOD);
44932022Spc }
45032022Spc /* NOTREACHED */
45132022Spc }
45232022Spc
45332022Spc /*
45432022Spc * skip over bit maps on the tape
45532022Spc */
skipmaps()45632022Spc skipmaps()
45732022Spc {
45832022Spc
45932022Spc while (checktype(&spcl, TS_CLRI) == GOOD ||
46032022Spc checktype(&spcl, TS_BITS) == GOOD)
46132022Spc skipfile();
46232022Spc }
46332022Spc
46432022Spc /*
46532022Spc * skip over a file on the tape
46632022Spc */
skipfile()46732022Spc skipfile()
46832022Spc {
46932022Spc extern int null();
47032022Spc
47132022Spc curfile.action = SKIP;
47232022Spc getfile(null, null);
47332022Spc }
47432022Spc
47532022Spc /*
47632022Spc * Do the file extraction, calling the supplied functions
47732022Spc * with the blocks
47832022Spc */
47932022Spc getfile(f1, f2)
48032022Spc int (*f2)(), (*f1)();
48132022Spc {
48232022Spc register int i;
48332022Spc int curblk = 0;
48432022Spc off_t size = spcl.c_dinode.di_size;
48532022Spc static char clearedbuf[MAXBSIZE];
48632022Spc char buf[MAXBSIZE / TP_BSIZE][TP_BSIZE];
48732022Spc char junk[TP_BSIZE];
48832022Spc
48932022Spc if (checktype(&spcl, TS_END) == GOOD)
49032022Spc panic("ran off end of tape\n");
49132022Spc if (ishead(&spcl) == FAIL)
49232022Spc panic("not at beginning of a file\n");
49332022Spc if (!gettingfile && setjmp(restart) != 0)
49432022Spc return;
49532022Spc gettingfile++;
49632022Spc loop:
49732022Spc for (i = 0; i < spcl.c_count; i++) {
49832022Spc if (spcl.c_addr[i]) {
49932022Spc readtape(&buf[curblk++][0]);
50032022Spc if (curblk == fssize / TP_BSIZE) {
50132022Spc (*f1)(buf, size > TP_BSIZE ?
50232022Spc (long) (fssize) :
50332022Spc (curblk - 1) * TP_BSIZE + size);
50432022Spc curblk = 0;
50532022Spc }
50632022Spc } else {
50732022Spc if (curblk > 0) {
50832022Spc (*f1)(buf, size > TP_BSIZE ?
50932022Spc (long) (curblk * TP_BSIZE) :
51032022Spc (curblk - 1) * TP_BSIZE + size);
51132022Spc curblk = 0;
51232022Spc }
51332022Spc (*f2)(clearedbuf, size > TP_BSIZE ?
51432022Spc (long) TP_BSIZE : size);
51532022Spc }
51632022Spc if ((size -= TP_BSIZE) <= 0) {
51732022Spc for (i++; i < spcl.c_count; i++)
51832022Spc if (spcl.c_addr[i])
51932022Spc readtape(junk);
52032022Spc break;
52132022Spc }
52232022Spc }
52332022Spc if (readhdr(&spcl) == GOOD && size > 0) {
52432022Spc if (checktype(&spcl, TS_ADDR) == GOOD)
52532022Spc goto loop;
52632022Spc dprintf(stdout, "Missing address (header) block for %s\n",
52732022Spc curfile.name);
52832022Spc }
52932022Spc if (curblk > 0)
53032022Spc (*f1)(buf, (curblk * TP_BSIZE) + size);
53132025Spc findinode(&spcl);
53232022Spc gettingfile = 0;
53332022Spc }
53432022Spc
53532022Spc /*
53632022Spc * The next routines are called during file extraction to
53732022Spc * put the data into the right form and place.
53832022Spc */
xtrfile(buf,size)53932022Spc xtrfile(buf, size)
54032022Spc char *buf;
54132022Spc long size;
54232022Spc {
54332022Spc
54432022Spc if (write(ofile, buf, (int) size) == -1) {
54532022Spc fprintf(stderr, "write error extracting inode %d, name %s\n",
54632022Spc curfile.ino, curfile.name);
54732022Spc perror("write");
54832022Spc done(1);
54932022Spc }
55032022Spc }
55132022Spc
xtrskip(buf,size)55232022Spc xtrskip(buf, size)
55332022Spc char *buf;
55432022Spc long size;
55532022Spc {
55632022Spc
55732022Spc #ifdef lint
55832022Spc buf = buf;
55932022Spc #endif
56032022Spc if (lseek(ofile, size, 1) == (long)-1) {
56132022Spc fprintf(stderr, "seek error extracting inode %d, name %s\n",
56232022Spc curfile.ino, curfile.name);
56332022Spc perror("lseek");
56432022Spc done(1);
56532022Spc }
56632022Spc }
56732022Spc
xtrlnkfile(buf,size)56832022Spc xtrlnkfile(buf, size)
56932022Spc char *buf;
57032022Spc long size;
57132022Spc {
57232022Spc
57332022Spc pathlen += size;
57432022Spc if (pathlen > MAXPATHLEN) {
57532022Spc fprintf(stderr, "symbolic link name: %s->%s%s; too long %d\n",
57632022Spc curfile.name, lnkbuf, buf, pathlen);
57732022Spc done(1);
57832022Spc }
57932022Spc (void) strcat(lnkbuf, buf);
58032022Spc }
58132022Spc
xtrlnkskip(buf,size)58232022Spc xtrlnkskip(buf, size)
58332022Spc char *buf;
58432022Spc long size;
58532022Spc {
58632022Spc
58732022Spc #ifdef lint
58832022Spc buf = buf, size = size;
58932022Spc #endif
59032022Spc fprintf(stderr, "unallocated block in symbolic link %s\n",
59132022Spc curfile.name);
59232022Spc done(1);
59332022Spc }
59432022Spc
xtrmap(buf,size)59532022Spc xtrmap(buf, size)
59632022Spc char *buf;
59732022Spc long size;
59832022Spc {
59932022Spc
60032022Spc bcopy(buf, map, size);
60132022Spc map += size;
60232022Spc }
60332022Spc
xtrmapskip(buf,size)60432022Spc xtrmapskip(buf, size)
60532022Spc char *buf;
60632022Spc long size;
60732022Spc {
60832022Spc
60932022Spc #ifdef lint
61032022Spc buf = buf;
61132022Spc #endif
61232022Spc panic("hole in map\n");
61332022Spc map += size;
61432022Spc }
61532022Spc
null()61632022Spc null() {;}
61732022Spc
61832022Spc /*
61932022Spc * Do the tape i/o, dealing with volume changes
62032022Spc * etc..
62132022Spc */
readtape(b)62232022Spc readtape(b)
62332022Spc char *b;
62432022Spc {
62532022Spc register long i;
62632022Spc long rd, newvol;
62732022Spc int cnt;
62832022Spc
62932022Spc if (bct < ntrec) {
63032022Spc bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
63132022Spc blksread++;
63232022Spc return;
63332022Spc }
63432022Spc for (i = 0; i < ntrec; i++)
63532022Spc ((struct s_spcl *)&tbf[i*TP_BSIZE])->c_magic = 0;
63632022Spc bct = 0;
63732022Spc cnt = ntrec*TP_BSIZE;
63832022Spc rd = 0;
63932022Spc getmore:
64032022Spc #ifdef RRESTORE
64132022Spc i = rmtread(&tbf[rd], cnt);
64232022Spc #else
64332022Spc i = read(mt, &tbf[rd], cnt);
64432022Spc #endif
64532022Spc if (i > 0 && i != ntrec*TP_BSIZE) {
64632022Spc if (pipein) {
64732022Spc rd += i;
64832022Spc cnt -= i;
64932022Spc if (cnt > 0)
65032022Spc goto getmore;
65132022Spc i = rd;
65232022Spc } else {
65332022Spc if (i % TP_BSIZE != 0)
65432022Spc panic("partial block read: %d should be %d\n",
65532022Spc i, ntrec * TP_BSIZE);
65632022Spc bcopy((char *)&endoftapemark, &tbf[i],
65732022Spc (long)TP_BSIZE);
65832022Spc }
65932022Spc }
66032022Spc if (i < 0) {
66132022Spc fprintf(stderr, "Tape read error while ");
66232022Spc switch (curfile.action) {
66332022Spc default:
66432022Spc fprintf(stderr, "trying to set up tape\n");
66532022Spc break;
66632022Spc case UNKNOWN:
66732022Spc fprintf(stderr, "trying to resyncronize\n");
66832022Spc break;
66932022Spc case USING:
67032022Spc fprintf(stderr, "restoring %s\n", curfile.name);
67132022Spc break;
67232022Spc case SKIP:
67332022Spc fprintf(stderr, "skipping over inode %d\n",
67432022Spc curfile.ino);
67532022Spc break;
67632022Spc }
67732022Spc if (!yflag && !reply("continue"))
67832022Spc done(1);
67932022Spc i = ntrec*TP_BSIZE;
68032022Spc bzero(tbf, i);
68132022Spc #ifdef RRESTORE
68232022Spc if (rmtseek(i, 1) < 0)
68332022Spc #else
68432022Spc if (lseek(mt, i, 1) == (long)-1)
68532022Spc #endif
68632022Spc {
68732022Spc perror("continuation failed");
68832022Spc done(1);
68932022Spc }
69032022Spc }
69132022Spc if (i == 0) {
69232022Spc if (!pipein) {
69332022Spc newvol = volno + 1;
69432022Spc volno = 0;
69532022Spc getvol(newvol);
69632022Spc readtape(b);
69732022Spc return;
69832022Spc }
69932022Spc if (rd % TP_BSIZE != 0)
70032022Spc panic("partial block read: %d should be %d\n",
70132022Spc rd, ntrec * TP_BSIZE);
70232022Spc bcopy((char *)&endoftapemark, &tbf[rd], (long)TP_BSIZE);
70332022Spc }
70432022Spc bcopy(&tbf[(bct++*TP_BSIZE)], b, (long)TP_BSIZE);
70532022Spc blksread++;
70632022Spc }
70732022Spc
findtapeblksize()70832022Spc findtapeblksize()
70932022Spc {
71032022Spc register long i;
71132022Spc
71232022Spc for (i = 0; i < ntrec; i++)
71332022Spc ((struct s_spcl *)&tbf[i * TP_BSIZE])->c_magic = 0;
71432022Spc bct = 0;
71532022Spc #ifdef RRESTORE
71632022Spc i = rmtread(tbf, ntrec * TP_BSIZE);
71732022Spc #else
71832022Spc i = read(mt, tbf, ntrec * TP_BSIZE);
71932022Spc #endif
72032022Spc if (i <= 0) {
72132022Spc perror("Tape read error");
72232022Spc done(1);
72332022Spc }
72432022Spc if (i % TP_BSIZE != 0) {
72532022Spc fprintf(stderr, "Tape block size (%d) %s (%d)\n",
72632022Spc i, "is not a multiple of dump block size", TP_BSIZE);
72732022Spc done(1);
72832022Spc }
72932022Spc ntrec = i / TP_BSIZE;
73032022Spc vprintf(stdout, "Tape block size is %d\n", ntrec);
73132022Spc }
73232022Spc
flsht()73332022Spc flsht()
73432022Spc {
73532022Spc
73632022Spc bct = ntrec+1;
73732022Spc }
73832022Spc
closemt()73932022Spc closemt()
74032022Spc {
74132022Spc if (mt < 0)
74232022Spc return;
74332022Spc #ifdef RRESTORE
74432022Spc rmtclose();
74532022Spc #else
74632022Spc (void) close(mt);
74732022Spc #endif
74832022Spc }
74932022Spc
75032022Spc checkvol(b, t)
75132022Spc struct s_spcl *b;
75232022Spc long t;
75332022Spc {
75432022Spc
75532022Spc if (b->c_volume != t)
75632022Spc return(FAIL);
75732022Spc return(GOOD);
75832022Spc }
75932022Spc
76032022Spc readhdr(b)
76132022Spc struct s_spcl *b;
76232022Spc {
76332022Spc
76432022Spc if (gethead(b) == FAIL) {
76532022Spc dprintf(stdout, "readhdr fails at %d blocks\n", blksread);
76632022Spc return(FAIL);
76732022Spc }
76832022Spc return(GOOD);
76932022Spc }
77032022Spc
77132022Spc /*
77232022Spc * read the tape into buf, then return whether or
77332022Spc * or not it is a header block.
77432022Spc */
77532022Spc gethead(buf)
77632022Spc struct s_spcl *buf;
77732022Spc {
77832022Spc long i, *j;
77932022Spc union u_ospcl {
78032022Spc char dummy[TP_BSIZE];
78132022Spc struct s_ospcl {
78232022Spc long c_type;
78332022Spc long c_date;
78432022Spc long c_ddate;
78532022Spc long c_volume;
78632022Spc long c_tapea;
78732022Spc u_short c_inumber;
78832022Spc long c_magic;
78932022Spc long c_checksum;
79032022Spc struct odinode {
79132022Spc unsigned short odi_mode;
79232022Spc u_short odi_nlink;
79332022Spc u_short odi_uid;
79432022Spc u_short odi_gid;
79532022Spc long odi_size;
79632022Spc long odi_rdev;
79732022Spc char odi_addr[36];
79832022Spc long odi_atime;
79932022Spc long odi_mtime;
80032022Spc long odi_ctime;
80132022Spc } c_dinode;
80232022Spc long c_count;
80332022Spc char c_addr[256];
80432022Spc } s_ospcl;
80532022Spc } u_ospcl;
80632022Spc
80732022Spc if (!cvtflag) {
80832022Spc readtape((char *)buf);
80932022Spc if (buf->c_magic != NFS_MAGIC) {
81032022Spc if (swabl(buf->c_magic) != NFS_MAGIC)
81132022Spc return (FAIL);
81232022Spc if (!Bcvt) {
81332022Spc vprintf(stdout, "Note: Doing Byte swapping\n");
81432022Spc Bcvt = 1;
81532022Spc }
81632022Spc }
81732022Spc if (checksum((int *)buf) == FAIL)
81832022Spc return (FAIL);
81932022Spc if (Bcvt)
82032022Spc swabst("8l4s31l", (char *)buf);
82132022Spc goto good;
82232022Spc }
82332022Spc readtape((char *)(&u_ospcl.s_ospcl));
82432022Spc bzero((char *)buf, (long)TP_BSIZE);
82532022Spc buf->c_type = u_ospcl.s_ospcl.c_type;
82632022Spc buf->c_date = u_ospcl.s_ospcl.c_date;
82732022Spc buf->c_ddate = u_ospcl.s_ospcl.c_ddate;
82832022Spc buf->c_volume = u_ospcl.s_ospcl.c_volume;
82932022Spc buf->c_tapea = u_ospcl.s_ospcl.c_tapea;
83032022Spc buf->c_inumber = u_ospcl.s_ospcl.c_inumber;
83132022Spc buf->c_checksum = u_ospcl.s_ospcl.c_checksum;
83232022Spc buf->c_magic = u_ospcl.s_ospcl.c_magic;
83332022Spc buf->c_dinode.di_mode = u_ospcl.s_ospcl.c_dinode.odi_mode;
83432022Spc buf->c_dinode.di_nlink = u_ospcl.s_ospcl.c_dinode.odi_nlink;
83532022Spc buf->c_dinode.di_uid = u_ospcl.s_ospcl.c_dinode.odi_uid;
83632022Spc buf->c_dinode.di_gid = u_ospcl.s_ospcl.c_dinode.odi_gid;
83732022Spc buf->c_dinode.di_size = u_ospcl.s_ospcl.c_dinode.odi_size;
83832022Spc buf->c_dinode.di_rdev = u_ospcl.s_ospcl.c_dinode.odi_rdev;
83932022Spc buf->c_dinode.di_atime = u_ospcl.s_ospcl.c_dinode.odi_atime;
84032022Spc buf->c_dinode.di_mtime = u_ospcl.s_ospcl.c_dinode.odi_mtime;
84132022Spc buf->c_dinode.di_ctime = u_ospcl.s_ospcl.c_dinode.odi_ctime;
84232022Spc buf->c_count = u_ospcl.s_ospcl.c_count;
84332022Spc bcopy(u_ospcl.s_ospcl.c_addr, buf->c_addr, (long)256);
84432022Spc if (u_ospcl.s_ospcl.c_magic != OFS_MAGIC ||
84532022Spc checksum((int *)(&u_ospcl.s_ospcl)) == FAIL)
84632022Spc return(FAIL);
84732022Spc buf->c_magic = NFS_MAGIC;
84832022Spc
84932022Spc good:
85032022Spc j = buf->c_dinode.di_ic.ic_size.val;
85132022Spc i = j[1];
85232022Spc if (buf->c_dinode.di_size == 0 &&
85332022Spc (buf->c_dinode.di_mode & IFMT) == IFDIR && Qcvt==0) {
85432022Spc if (*j || i) {
85532022Spc printf("Note: Doing Quad swapping\n");
85632022Spc Qcvt = 1;
85732022Spc }
85832022Spc }
85932022Spc if (Qcvt) {
86032022Spc j[1] = *j; *j = i;
86132022Spc }
86232022Spc switch (buf->c_type) {
86332022Spc
86432022Spc case TS_CLRI:
86532022Spc case TS_BITS:
86632022Spc /*
86732022Spc * Have to patch up missing information in bit map headers
86832022Spc */
86932022Spc buf->c_inumber = 0;
87032022Spc buf->c_dinode.di_size = buf->c_count * TP_BSIZE;
87132022Spc for (i = 0; i < buf->c_count; i++)
87232022Spc buf->c_addr[i]++;
87332022Spc break;
87432022Spc
87532022Spc case TS_TAPE:
87632022Spc case TS_END:
87732022Spc buf->c_inumber = 0;
87832022Spc break;
87932022Spc
88032022Spc case TS_INODE:
88132022Spc case TS_ADDR:
88232022Spc break;
88332022Spc
88432022Spc default:
88532022Spc panic("gethead: unknown inode type %d\n", buf->c_type);
88632022Spc break;
88732022Spc }
88832022Spc if (dflag)
88932022Spc accthdr(buf);
89032022Spc return(GOOD);
89132022Spc }
89232022Spc
89332022Spc /*
89432022Spc * Check that a header is where it belongs and predict the next header
89532022Spc */
89632022Spc accthdr(header)
89732022Spc struct s_spcl *header;
89832022Spc {
89932022Spc static ino_t previno = 0x7fffffff;
90032022Spc static int prevtype;
90132022Spc static long predict;
90232022Spc long blks, i;
90332022Spc
90432022Spc if (header->c_type == TS_TAPE) {
90532022Spc fprintf(stderr, "Volume header\n");
90632025Spc previno = 0x7fffffff;
90732022Spc return;
90832022Spc }
90932022Spc if (previno == 0x7fffffff)
91032022Spc goto newcalc;
91132022Spc switch (prevtype) {
91232022Spc case TS_BITS:
91332022Spc fprintf(stderr, "Dump mask header");
91432022Spc break;
91532022Spc case TS_CLRI:
91632022Spc fprintf(stderr, "Remove mask header");
91732022Spc break;
91832022Spc case TS_INODE:
91932022Spc fprintf(stderr, "File header, ino %d", previno);
92032022Spc break;
92132022Spc case TS_ADDR:
92232022Spc fprintf(stderr, "File continuation header, ino %d", previno);
92332022Spc break;
92432022Spc case TS_END:
92532022Spc fprintf(stderr, "End of tape header");
92632022Spc break;
92732022Spc }
92832022Spc if (predict != blksread - 1)
92932022Spc fprintf(stderr, "; predicted %d blocks, got %d blocks",
93032022Spc predict, blksread - 1);
93132022Spc fprintf(stderr, "\n");
93232022Spc newcalc:
93332022Spc blks = 0;
93432022Spc if (header->c_type != TS_END)
93532022Spc for (i = 0; i < header->c_count; i++)
93632022Spc if (header->c_addr[i] != 0)
93732022Spc blks++;
93832022Spc predict = blks;
93932022Spc blksread = 0;
94032022Spc prevtype = header->c_type;
94132022Spc previno = header->c_inumber;
94232022Spc }
94332022Spc
94432022Spc /*
94532022Spc * Find an inode header.
94632022Spc * Complain if had to skip, and complain is set.
94732022Spc */
94832025Spc findinode(header)
94932022Spc struct s_spcl *header;
95032022Spc {
95132022Spc static long skipcnt = 0;
95232025Spc long i;
95332025Spc char buf[TP_BSIZE];
95432022Spc
95532022Spc curfile.name = "<name unknown>";
95632022Spc curfile.action = UNKNOWN;
95732022Spc curfile.dip = (struct dinode *)NIL;
95832022Spc curfile.ino = 0;
95932022Spc if (ishead(header) == FAIL) {
96032022Spc skipcnt++;
96132025Spc while (gethead(header) == FAIL || header->c_date != dumpdate)
96232022Spc skipcnt++;
96332022Spc }
96432022Spc for (;;) {
96532025Spc if (checktype(header, TS_ADDR) == GOOD) {
96632025Spc /*
96732025Spc * Skip up to the beginning of the next record
96832025Spc */
96932025Spc for (i = 0; i < header->c_count; i++)
97032025Spc if (header->c_addr[i])
97132025Spc readtape(buf);
97232025Spc (void) gethead(header);
97332025Spc continue;
97432025Spc }
97532022Spc if (checktype(header, TS_INODE) == GOOD) {
97632022Spc curfile.dip = &header->c_dinode;
97732022Spc curfile.ino = header->c_inumber;
97832022Spc break;
97932022Spc }
98032022Spc if (checktype(header, TS_END) == GOOD) {
98132022Spc curfile.ino = maxino;
98232022Spc break;
98332022Spc }
98432022Spc if (checktype(header, TS_CLRI) == GOOD) {
98532022Spc curfile.name = "<file removal list>";
98632022Spc break;
98732022Spc }
98832022Spc if (checktype(header, TS_BITS) == GOOD) {
98932022Spc curfile.name = "<file dump list>";
99032022Spc break;
99132022Spc }
99232022Spc while (gethead(header) == FAIL)
99332022Spc skipcnt++;
99432022Spc }
99532025Spc if (skipcnt > 0)
99632022Spc fprintf(stderr, "resync restore, skipped %d blocks\n", skipcnt);
99732022Spc skipcnt = 0;
99832022Spc }
99932022Spc
100032022Spc /*
100132022Spc * return whether or not the buffer contains a header block
100232022Spc */
100332022Spc ishead(buf)
100432022Spc struct s_spcl *buf;
100532022Spc {
100632022Spc
100732022Spc if (buf->c_magic != NFS_MAGIC)
100832022Spc return(FAIL);
100932022Spc return(GOOD);
101032022Spc }
101132022Spc
101232022Spc checktype(b, t)
101332022Spc struct s_spcl *b;
101432022Spc int t;
101532022Spc {
101632022Spc
101732022Spc if (b->c_type != t)
101832022Spc return(FAIL);
101932022Spc return(GOOD);
102032022Spc }
102132022Spc
checksum(b)102232022Spc checksum(b)
102332022Spc register int *b;
102432022Spc {
102532022Spc register int i, j;
102632022Spc
102732022Spc j = sizeof(union u_spcl) / sizeof(int);
102832022Spc i = 0;
102932022Spc if(!Bcvt) {
103032022Spc do
103132022Spc i += *b++;
103232022Spc while (--j);
103332022Spc } else {
103432022Spc /* What happens if we want to read restore tapes
103532022Spc for a 16bit int machine??? */
103632022Spc do
103732022Spc i += swabl(*b++);
103832022Spc while (--j);
103932022Spc }
104032022Spc
104132022Spc if (i != CHECKSUM) {
104232022Spc fprintf(stderr, "Checksum error %o, inode %d file %s\n", i,
104332022Spc curfile.ino, curfile.name);
104432022Spc return(FAIL);
104532022Spc }
104632022Spc return(GOOD);
104732022Spc }
104832022Spc
104932022Spc #ifdef RRESTORE
105032022Spc /* VARARGS1 */
msg(cp,a1,a2,a3)105132022Spc msg(cp, a1, a2, a3)
105232022Spc char *cp;
105332022Spc {
105432022Spc
105532022Spc fprintf(stderr, cp, a1, a2, a3);
105632022Spc }
105732022Spc #endif RRESTORE
105832022Spc
swabst(cp,sp)105932022Spc swabst(cp, sp)
106032022Spc register char *cp, *sp;
106132022Spc {
106232022Spc int n = 0;
106332022Spc char c;
106432022Spc while(*cp) {
106532022Spc switch (*cp) {
106632022Spc case '0': case '1': case '2': case '3': case '4':
106732022Spc case '5': case '6': case '7': case '8': case '9':
106832022Spc n = (n * 10) + (*cp++ - '0');
106932022Spc continue;
107032022Spc
107132022Spc case 's': case 'w': case 'h':
107232022Spc c = sp[0]; sp[0] = sp[1]; sp[1] = c;
107332022Spc sp++;
107432022Spc break;
107532022Spc
107632022Spc case 'l':
107732022Spc c = sp[0]; sp[0] = sp[3]; sp[3] = c;
107832022Spc c = sp[2]; sp[2] = sp[1]; sp[1] = c;
107932022Spc sp += 3;
108032022Spc }
108132022Spc sp++; /* Any other character, like 'b' counts as byte. */
108232022Spc if (n <= 1) {
108332022Spc n = 0; cp++;
108432022Spc } else
108532022Spc n--;
108632022Spc }
108732022Spc }
swabl(x)108832022Spc swabl(x) { unsigned long l = x; swabst("l", (char *)&l); return l; }
1089