#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.36 2001/04/27 12:23:23 stelian Exp $";
+ "$Id: tape.c,v 1.45 2001/07/20 09:01:46 stelian Exp $";
#endif /* not lint */
#include <config.h>
+#include <compatlfs.h>
#include <errno.h>
#include <compaterr.h>
+#include <system.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __linux__
#include <sys/time.h>
#include <time.h>
+#ifdef HAVE_EXT2FS_EXT2_FS_H
+#include <ext2fs/ext2_fs.h>
+#else
#include <linux/ext2_fs.h>
+#endif
#include <ext2fs/ext2fs.h>
#include <bsdcompat.h>
#else /* __linux__ */
static void xtrmap __P((char *, size_t));
static void xtrmapskip __P((char *, size_t));
static void xtrskip __P((char *, size_t));
+static void setmagtapein __P((void));
#ifdef HAVE_ZLIB
-static void newcomprbuf __P((long));
+static void newcomprbuf __P((int));
static void readtape_set __P((char *));
static void readtape_uncompr __P((char *));
static void readtape_comprfile __P((char *));
#ifdef HAVE_ZLIB
static void
-newcomprbuf(long size)
+newcomprbuf(int size)
{
- if (size <= comprlen)
+ size_t buf_size = (size+1) * TP_BSIZE + sizeof(struct tapebuf);
+ if (buf_size <= comprlen)
return;
- comprlen = size + sizeof(struct tapebuf);
+ comprlen = buf_size;
if (comprbuf != NULL)
free(comprbuf);
comprbuf = malloc(comprlen);
void
setup(void)
{
- int i, j, *ip;
- struct stat stbuf;
- struct mtget mt_stat;
+ int i, j, *ip, bot_code;
+ struct STAT stbuf;
Vprintf(stdout, "Verify tape and initialize maps\n");
+ if (bot_script) {
+ msg("Launching %s\n", bot_script);
+ bot_code = system_command(bot_script, magtape, 1);
+ if (bot_code != 0 && bot_code != 1) {
+ msg("Restore aborted by the beginning of tape script\n");
+ exit(1);
+ }
+ }
#ifdef RRESTORE
if (host)
mt = rmtopen(magtape, 0);
if (pipein)
mt = 0;
else
- mt = open(magtape, O_RDONLY, 0);
+ mt = OPEN(magtape, O_RDONLY, 0);
if (mt < 0)
err(1, "%s", magtape);
volno = 1;
- if (!pipein) {
- /* need to know if input is really from a tape */
-#ifdef RRESTORE
- if (host)
- magtapein = rmtioctl(MTNOP, 1) != -1;
- else
-#endif
- if (ioctl(mt, MTIOCGET, (char *) &mt_stat) == 0) {
- if (mt_stat.mt_dsreg & 0xffff)
- magtapein = 1; /* fixed blocksize */
- else
- magtapein = 2; /* variable blocksize */
- }
- }
-
- Vprintf(stdout,"Input is from %s\n", magtapein? "tape": "file/pipe");
+ setmagtapein();
setdumpnum();
FLUSHTAPEBUF();
findtapeblksize();
if (zflag) {
fprintf(stderr, "Dump tape is compressed.\n");
#ifdef HAVE_ZLIB
- newcomprbuf(bufsize);
+ newcomprbuf(ntrec);
#else
errx(1,"This restore version doesn't support decompression");
#endif /* HAVE_ZLIB */
}
dumptime = spcl.c_ddate;
dumpdate = spcl.c_date;
- if (stat(".", &stbuf) < 0)
+ if (STAT(".", &stbuf) < 0)
err(1, "cannot stat .");
if (stbuf.st_blksize > 0 && stbuf.st_blksize < TP_BSIZE )
fssize = TP_BSIZE;
void
getvol(long nextvol)
{
- long newvol = 0, savecnt = 0, wantnext = 0, i;
+ long newvol = 0, wantnext = 0, i;
+ long saved_blksread = 0, saved_tpblksread = 0;
union u_spcl tmpspcl;
# define tmpbuf tmpspcl.s_spcl
char buf[TP_BSIZE];
- int haderror = 0;
+ int haderror = 0, bot_code = 1;
if (nextvol == 1) {
tapesread = 0;
return;
goto gethdr;
}
- savecnt = blksread;
+ saved_blksread = blksread;
+ saved_tpblksread = tpblksread;
again:
if (pipein)
exit(1); /* pipes do not get a second chance */
snprintf(magtape, MAXPATHLEN, "%s%03ld", magtapeprefix, newvol);
magtape[MAXPATHLEN - 1] = '\0';
}
- if (!Mflag || haderror) {
+ if (bot_script && !haderror) {
+ msg("Launching %s\n", bot_script);
+ bot_code = system_command(bot_script, magtape, newvol);
+ if (bot_code != 0 && bot_code != 1) {
+ msg("Restore aborted by the beginning of tape script\n");
+ exit(1);
+ }
+ }
+ if (haderror || (bot_code && !Mflag)) {
haderror = 0;
fprintf(stderr, "Mount tape volume %ld\n", (long)newvol);
fprintf(stderr, "Enter ``none'' if there are no more tapes\n");
return;
}
if (buf[0] != '\n') {
- (void) strcpy(magtape, buf);
- magtape[strlen(magtape) - 1] = '\0';
+ char *pos;
+ (void) strncpy(magtape, buf, sizeof(magtape));
+ magtape[sizeof(magtape) - 1] = '\0';
+ if ((pos = strchr(magtape, '\n')))
+ magtape[pos - magtape] = '\0';
}
}
#ifdef RRESTORE
mt = rmtopen(magtape, 0);
else
#endif
- mt = open(magtape, O_RDONLY, 0);
+ mt = OPEN(magtape, O_RDONLY, 0);
if (mt == -1) {
fprintf(stderr, "Cannot open %s\n", magtape);
goto again;
}
gethdr:
+ setmagtapein();
volno = newvol;
setdumpnum();
FLUSHTAPEBUF();
+ findtapeblksize();
if (gethead(&tmpbuf) == FAIL) {
Dprintf(stdout, "header read failed at %ld blocks\n", (long)blksread);
fprintf(stderr, "tape is not dump tape\n");
volno = 0;
haderror = 1;
+ blksread = saved_blksread;
+ tpblksread = saved_tpblksread;
goto again;
}
if (tmpbuf.c_volume != volno) {
fprintf(stderr, "Wrong volume (%d)\n", tmpbuf.c_volume);
volno = 0;
haderror = 1;
+ blksread = saved_blksread;
+ tpblksread = saved_tpblksread;
goto again;
}
if (tmpbuf.c_date != dumpdate || tmpbuf.c_ddate != dumptime) {
fprintf(stderr, "\twanted: %s", ctime(&dumpdate));
volno = 0;
haderror = 1;
+ blksread = saved_blksread;
+ tpblksread = saved_tpblksread;
goto again;
}
tapesread |= 1 << volno;
- blksread = savecnt;
+ blksread = saved_blksread;
+ tpblksread = saved_tpblksread;
/*
* If continuing from the previous volume, skip over any
* blocks read already at the end of the previous volume.
}
if (uflag)
(void)unlink(name);
- if ((ofile = open(name, O_WRONLY | O_CREAT | O_TRUNC,
+ if ((ofile = OPEN(name, O_WRONLY | O_CREAT | O_TRUNC,
0666)) < 0) {
warn("%s: cannot create file", name);
skipfile();
}
if (size > 0) {
fprintf(stderr, "Missing blocks at the end of %s, assuming hole\n", curfile.name);
- (*skip)(clearedbuf, size);
+ while (size > 0) {
+ size_t skp = size > TP_BSIZE ? TP_BSIZE : size;
+ (*skip)(clearedbuf, skp);
+ size -= skp;
+ }
last_write_was_hole = 1;
}
if (last_write_was_hole) {
- ftruncate(ofile, origsize);
+ FTRUNCATE(ofile, origsize);
}
findinode(&spcl);
gettingfile = 0;
xtrskip(char *buf, size_t size)
{
- if (lseek(ofile, (off_t)size, SEEK_CUR) == -1)
+ if (LSEEK(ofile, (off_t)size, SEEK_CUR) == -1)
err(1, "seek error extracting inode %lu, name %s\nlseek",
(unsigned long)curfile.ino, curfile.name);
}
#else
void
#endif
-cmpfiles(char *tapefile, char *diskfile, struct stat *sbuf_disk)
+cmpfiles(char *tapefile, char *diskfile, struct STAT *sbuf_disk)
{
- struct stat sbuf_tape;
+ struct STAT sbuf_tape;
int fd_tape, fd_disk;
- if (stat(tapefile, &sbuf_tape) != 0) {
+ if (STAT(tapefile, &sbuf_tape) != 0) {
panic("Can't lstat tmp file %s: %s\n", tapefile,
strerror(errno));
compare_errors = 1;
#endif
}
- if ((fd_tape = open(tapefile, O_RDONLY)) < 0) {
+ if ((fd_tape = OPEN(tapefile, O_RDONLY)) < 0) {
panic("Can't open %s: %s\n", tapefile, strerror(errno));
compare_errors = 1;
}
- if ((fd_disk = open(diskfile, O_RDONLY)) < 0) {
+ if ((fd_disk = OPEN(diskfile, O_RDONLY)) < 0) {
close(fd_tape);
panic("Can't open %s: %s\n", diskfile, strerror(errno));
compare_errors = 1;
comparefile(char *name)
{
int mode;
- struct stat sb;
+ struct STAT sb;
int r;
#if !COMPARE_ONTHEFLY
static char *tmpfile = NULL;
- struct stat stemp;
+ struct STAT stemp;
#endif
- if ((r = lstat(name, &sb)) != 0) {
+ if ((r = LSTAT(name, &sb)) != 0) {
warn("%s: does not exist (%d)", name, r);
compare_errors = 1;
skipfile();
case IFREG:
#if COMPARE_ONTHEFLY
- if ((ifile = open(name, O_RDONLY)) < 0) {
+ if ((ifile = OPEN(name, O_RDONLY)) < 0) {
panic("Can't open %s: %s\n", name, strerror(errno));
skipfile();
compare_errors = 1;
snprintf(tmpfilename, sizeof(tmpfilename), "%s/restoreCXXXXXX", tmpdir);
tmpfile = mktemp(&tmpfilename[0]);
}
- if ((stat(tmpfile, &stemp) == 0) && (unlink(tmpfile) != 0)) {
+ if ((STAT(tmpfile, &stemp) == 0) && (unlink(tmpfile) != 0)) {
panic("cannot delete tmp file %s: %s\n",
tmpfile, strerror(errno));
}
- if ((ofile = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
+ if ((ofile = OPEN(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
panic("cannot create file temp file %s: %s\n",
name, strerror(errno));
}
if (!zflag)
readtape_func = readtape_uncompr;
else {
+ newcomprbuf(ntrec);
if (magtapein)
readtape_func = readtape_comprtape;
else
seek_failed = (rmtseek(i, 1) < 0);
else
#endif
- seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1);
+ seek_failed = (LSEEK(mt, i, SEEK_CUR) == (off_t)-1);
if (seek_failed) {
warn("continuation failed");
#endif /* HAVE_ZLIB */
/*
- * Read the first block and set the blocksize from its length. Test
- * if the block looks like a compressed dump tape. setup() will make
- * the final determination by checking the compressed flag if gethead()
+ * Read the first block and get the blocksize from it. Test
+ * for a compressed dump tape/file. setup() will make the final
+ * determination by checking the compressed flag if gethead()
* finds a valid header. The test here is necessary to offset the buffer
* by the size of the compressed prefix. zflag is set here so that
* readtape_set can set the correct function pointer for readtape().
- * Note that the first block of each tape/file will not be compressed.
+ * Note that the first block of each tape/file is not compressed
+ * and does not have a prefix.
*/
static void
findtapeblksize(void)
long i;
size_t len;
struct tapebuf *tpb = (struct tapebuf *) tapebuf;
- struct s_spcl *spclpt = (struct s_spcl *) tpb->buf;
+ struct s_spcl *spclpt = (struct s_spcl *) tapebuf;
for (i = 0; i < ntrec; i++)
((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0;
* For a pipe or file, read in the first record. For a tape, read
* the first block.
*/
- if (magtapein == 1) /* fixed blocksize tape, not compressed */
- len = ntrec * TP_BSIZE;
- else if (magtapein == 2)/* variable blocksize tape */
- len = bufsize + PREFIXSIZE;
- else /* not mag tape */
- len = TP_BSIZE;
+ len = magtapein ? ntrec * TP_BSIZE : TP_BSIZE;
if (read_a_block(mt, tapebuf, len, &i) <= 0)
errx(1, "Tape read error on first record");
/*
* If the input is from a file or a pipe, we read TP_BSIZE
- * bytes looking for a compressed dump header, we then
- * need to read in the rest of the record, as determined by
- * tpb->length or bufsize. The first block of the dump is
- * guaranteed to not be compressed so we look at the header.
+ * bytes looking for a dump header. If the dump is compressed
+ * we need to read in the rest of the block, as determined
+ * by c_ntrec in the dump header. The first block of the
+ * dump is not compressed and does not have a prefix.
*/
if (!magtapein) {
- if (tpb->length % TP_BSIZE == 0
- && tpb->length <= bufsize
- && tpb->compressed == 0
- && spclpt->c_type == TS_TAPE
+ if (spclpt->c_type == TS_TAPE
&& spclpt->c_flags & DR_COMPRESSED) {
- /* Looks like it's a compressed dump block prefix, */
- /* read in the rest of the block based on tpb->length. */
- len = tpb->length - TP_BSIZE + PREFIXSIZE;
- if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) <= 0
- || i != len)
- errx(1,"Error reading dump file header");
- tbufptr = tpb->buf;
- numtrec = ntrec = tpb->length / TP_BSIZE;
+ /* It's a compressed dump file, read in the */
+ /* rest of the block based on spclpt->c_ntrec. */
+ if (spclpt->c_ntrec > ntrec)
+ errx(1, "Tape blocksize is too large, use "
+ "\'-b %d\' ", spclpt->c_ntrec);
+ ntrec = spclpt->c_ntrec;
+ len = (ntrec - 1) * TP_BSIZE;
zflag = 1;
}
else {
/* read in the rest of the block based on bufsize */
len = bufsize - TP_BSIZE;
- if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) < 0
- || (i != len && i % TP_BSIZE != 0))
- errx(1,"Error reading dump file header");
- tbufptr = tapebuf;
- numtrec = ntrec;
}
+ if (read_a_block(mt, tapebuf+TP_BSIZE, len, &i) < 0
+ || (i != len && i % TP_BSIZE != 0))
+ errx(1,"Error reading dump file header");
+ tbufptr = tapebuf;
+ numtrec = ntrec;
Vprintf(stdout, "Input block size is %ld\n", ntrec);
return;
- }
+ } /* if (!magtapein) */
/*
- * If the input is a variable block size tape, we tried to
- * read PREFIXSIZE + ntrec * TP_BSIZE bytes.
- * If it's not a compressed dump tape or the value of ntrec is
- * too large, we have read less than * what we asked for;
- * adjust the value of ntrec and test for * a compressed dump
- * tape prefix.
+ * If the input is a tape, we tried to read ntrec * TP_BSIZE bytes.
+ * If the value of ntrec is too large, we read less than
+ * what we asked for; adjust the value of ntrec and test for
+ * a compressed dump tape.
*/
if (i % TP_BSIZE != 0) {
+ /* may be old format compressed dump tape with a prefix */
+ spclpt = (struct s_spcl *) tpb->buf;
if (i % TP_BSIZE == PREFIXSIZE
&& tpb->compressed == 0
&& spclpt->c_type == TS_TAPE
&& spclpt->c_flags & DR_COMPRESSED) {
-
zflag = 1;
tbufptr = tpb->buf;
if (tpb->length > bufsize)
i, TP_BSIZE);
}
ntrec = i / TP_BSIZE;
+ if (spclpt->c_type == TS_TAPE) {
+ if (spclpt->c_flags & DR_COMPRESSED)
+ zflag = 1;
+ if (spclpt->c_ntrec > ntrec)
+ errx(1, "Tape blocksize is too large, use "
+ "\'-b %d\' ", spclpt->c_ntrec);
+ }
numtrec = ntrec;
Vprintf(stdout, "Tape block size is %ld\n", ntrec);
}
(void) close(mt);
}
+static void
+setmagtapein(void) {
+ struct mtget mt_stat;
+ static int done = 0;
+ if (done)
+ return;
+ done = 1;
+ if (!pipein) {
+ /* need to know if input is really from a tape */
+#ifdef RRESTORE
+ if (host)
+ magtapein = rmtioctl(MTNOP, 1) != -1;
+ else
+#endif
+ magtapein = ioctl(mt, MTIOCGET, (char *)&mt_stat) == 0;
+ }
+
+ Vprintf(stdout,"Input is from %s\n", magtapein? "tape": "file/pipe");
+}
+
/*
* Read the next block from the tape.
* Check to see if it is one of several vintage headers.