X-Git-Url: https://git.wh0rd.org/?p=dump.git;a=blobdiff_plain;f=dump%2Ftape.c;h=0dffa3a7cba384772f087967cf0356e4236412a8;hp=f61fc879ee395b2228fe61d4e510d0348ea96210;hb=b0b1d9d02b199eddbd62589d01c664ca13262f2d;hpb=103245b6fea8e7d77722e85ccb404ac1d928987d diff --git a/dump/tape.c b/dump/tape.c index f61fc87..0dffa3a 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -2,8 +2,8 @@ * Ported to Linux's Second Extended File System as part of the * dump and restore backup suit * Remy Card , 1994-1997 - * Stelian Pop , 1999-2000 - * Stelian Pop - Alcôve , 2000 + * Stelian Pop , 1999-2000 + * Stelian Pop - Alcôve , 2000-2002 */ /*- @@ -41,7 +41,7 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.55 2001/09/06 09:00:32 stelian Exp $"; + "$Id: tape.c,v 1.67 2002/04/11 14:51:09 stelian Exp $"; #endif /* not lint */ #include @@ -68,19 +68,16 @@ int write(), read(); #endif #include #include -#include #include #include #ifdef __linux__ -#include -#undef atomic_read /* this get wrongly defined in kernel */ - /* headers and we don't want it */ #ifdef HAVE_EXT2FS_EXT2_FS_H #include #else #include #endif #include +#include #include #elif defined sunos #include @@ -111,19 +108,23 @@ extern long blocksperfile; /* number of blocks per output file */ long blocksthisvol; /* number of blocks on current output file */ extern int ntrec; /* blocking factor on tape */ extern int cartridge; -extern char *host; char *nexttape; extern pid_t rshpid; int eot_code = 1; long long tapea_bytes = 0; /* bytes_written at start of current volume */ +static int magtapeout; /* output is really a tape */ -static ssize_t atomic_read __P((int, void *, size_t)); -static ssize_t atomic_write __P((int, const void *, size_t)); +static ssize_t dump_atomic_read __P((int, void *, size_t)); +static ssize_t dump_atomic_write __P((int, const void *, size_t)); static void doslave __P((int, int, int)); static void enslave __P((void)); static void flushtape __P((void)); static void killall __P((void)); static void rollforward __P((void)); +#ifdef USE_QFA +static int GetTapePos __P((long long *)); +static void MkTapeString __P((struct s_spcl *, long long)); +#endif /* * Concurrent dump mods (Caltech) - disk block reading and tape writing @@ -230,6 +231,30 @@ writerec(const void *dp, int isspcl) slp->req[trecno].count = 1; /* XXX post increment triggers an egcs-1.1.2-12 bug on alpha/sparc */ *(union u_spcl *)(*(nextblock)) = *(union u_spcl *)dp; + + /* Need to write it to the archive file */ + if (Afile < 0 && isspcl && (spcl.c_type == TS_END)) + Afile = -Afile; + if (Afile > 0) { + /* When we dump an inode which is not a directory, + * it means we ended the archive contents */ + if (isspcl && (spcl.c_type == TS_INODE) && + ((spcl.c_dinode.di_mode & S_IFMT) != IFDIR)) + Afile = -Afile; + else { + union u_spcl tmp; + tmp = *(union u_spcl *)dp; + /* Write the record, _uncompressed_ */ + if (isspcl) { + tmp.s_spcl.c_flags &= ~DR_COMPRESSED; + mkchecksum(&tmp); + } + if (write(Afile, &tmp, TP_BSIZE) != TP_BSIZE) + msg("error writing archive file: %s\n", + strerror(errno)); + } + } + nextblock++; if (isspcl) lastspclrec = spcl.c_tapea; @@ -385,7 +410,7 @@ flushtape(void) slp->req[trecno].count = 0; /* Sentinel */ - if (atomic_write( slp->fd, (char *)slp->req, siz) != siz) + if (dump_atomic_write( slp->fd, (char *)slp->req, siz) != siz) quit("error writing command pipe: %s\n", strerror(errno)); slp->sent = 1; /* we sent a request, read the response later */ @@ -396,7 +421,7 @@ flushtape(void) /* Read results back from next slave */ if (slp->sent) { - if (atomic_read( slp->fd, (char *)&returned, sizeof returned) + if (dump_atomic_read( slp->fd, (char *)&returned, sizeof returned) != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); @@ -421,7 +446,7 @@ flushtape(void) */ for (i = 0; i < SLAVES; i++) { if (slaves[i].sent) { - if (atomic_read( slaves[i].fd, + if (dump_atomic_read( slaves[i].fd, (char *)&returned, sizeof returned) != sizeof returned) { perror(" DUMP: error reading command pipe in master"); @@ -485,7 +510,7 @@ trewind(void) * fixme: punt for now. */ if (slaves[f].sent) { - if (atomic_read( slaves[f].fd, (char *)&returned, sizeof returned) + if (dump_atomic_read( slaves[f].fd, (char *)&returned, sizeof returned) != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); @@ -565,8 +590,8 @@ close_rewind(void) void rollforward(void) { - register struct req *p, *q = NULL, *prev; - register struct slave *tslp; + struct req *p, *q = NULL, *prev; + struct slave *tslp; int i, size, savedtapea, got; union u_spcl *ntb, *otb; struct slave_results returned; @@ -620,7 +645,7 @@ rollforward(void) lastspclrec = savedtapea - 1; } size = (char *)ntb - (char *)q; - if (atomic_write( slp->fd, (char *)q, size) != size) { + if (dump_atomic_write( slp->fd, (char *)q, size) != size) { perror(" DUMP: error writing command pipe"); dumpabort(0); } @@ -668,7 +693,7 @@ rollforward(void) * worked ok, otherwise the tape is much too short! */ if (slp->sent) { - if (atomic_read( slp->fd, (char *)&returned, sizeof returned) + if (dump_atomic_read( slp->fd, (char *)&returned, sizeof returned) != sizeof returned) { perror(" DUMP: error reading command pipe in master"); dumpabort(0); @@ -847,10 +872,22 @@ restore_check_point: OPEN(tape, O_RDWR|O_CREAT, 0666))) < 0) #endif { - msg("Cannot open output \"%s\".\n", tape); + msg("Cannot open output \"%s\": %s\n", tape, + strerror(errno)); if (!query("Do you want to retry the open?")) dumpabort(0); } +#ifdef RDUMP + if (!host) +#endif + { + struct mtget mt_stat; + magtapeout = ioctl(tapefd, MTIOCGET, (char *)&mt_stat) == 0; + /* + msg("Output is to %s\n", + magtapeout ? "tape" : "file/pipe"); + */ + } enslave(); /* Share open tape file descriptor with slaves */ @@ -877,6 +914,8 @@ restore_check_point: if (tapeno > 1) msg("Volume %d begins with blocks from inode %d\n", tapeno, slp->inode); + if (tapeno < TP_NINOS) + volinfo[tapeno] = slp->inode; } } @@ -925,7 +964,7 @@ enslave(void) #ifdef LINUX_FORK_BUG int i, j; #else - register int i, j; + int i, j; #endif master = getpid(); @@ -968,7 +1007,7 @@ enslave(void) sigprocmask(SIG_BLOCK, &sigs, NULL); #ifdef LINUX_FORK_BUG - if (atomic_write( cmd[0], (char *) &i, sizeof i) + if (dump_atomic_write( cmd[0], (char *) &i, sizeof i) != sizeof i) quit("master/slave protocol botched 3\n"); #endif @@ -986,12 +1025,12 @@ enslave(void) * returned from fork() causes a SEGV in the child process */ for (i = 0; i < SLAVES; i++) - if (atomic_read( slaves[i].fd, (char *) &j, sizeof j) != sizeof j) + if (dump_atomic_read( slaves[i].fd, (char *) &j, sizeof j) != sizeof j) quit("master/slave protocol botched 4\n"); #endif for (i = 0; i < SLAVES; i++) - (void) atomic_write( slaves[i].fd, + (void) dump_atomic_write( slaves[i].fd, (char *) &slaves[(i + 1) % SLAVES].pid, sizeof slaves[0].pid); @@ -1001,7 +1040,7 @@ enslave(void) void killall(void) { - register int i; + int i; for (i = 0; i < SLAVES; i++) if (slaves[i].pid > 0) { @@ -1020,7 +1059,7 @@ killall(void) static void doslave(int cmd, int slave_number, int first) { - register int nread; + int nread; int nextslave, size, eot_count, bufsize; volatile int wrote = 0; char *buffer; @@ -1037,10 +1076,16 @@ doslave(int cmd, int slave_number, int first) errcode_t retval; #endif #ifdef USE_QFA - long curtapepos; + long long curtapepos; union u_spcl *uspclptr; struct s_spcl *spclptr; #endif /* USE_QFA */ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGUSR2); + sigprocmask(SIG_BLOCK, &set, NULL); + sigemptyset(&set); /* * Need our own seek pointer. @@ -1061,7 +1106,7 @@ doslave(int cmd, int slave_number, int first) /* * Need the pid of the next slave in the loop... */ - if ((nread = atomic_read( cmd, (char *)&nextslave, sizeof nextslave)) + if ((nread = dump_atomic_read( cmd, (char *)&nextslave, sizeof nextslave)) != sizeof nextslave) { quit("master/slave protocol botched - didn't get pid of next slave.\n"); } @@ -1082,8 +1127,8 @@ doslave(int cmd, int slave_number, int first) /* * Get list of blocks to dump, read the blocks into tape buffer */ - while ((nread = atomic_read( cmd, (char *)slp->req, reqsiz)) == reqsiz) { - register struct req *p = slp->req; + while ((nread = dump_atomic_read( cmd, (char *)slp->req, reqsiz)) == reqsiz) { + struct req *p = slp->req; for (trecno = 0; trecno < ntrec; trecno += p->count, p += p->count) { @@ -1091,7 +1136,7 @@ doslave(int cmd, int slave_number, int first) bread(p->dblk, slp->tblock[trecno], p->count * TP_BSIZE); } else { /* read record from pipe */ - if (p->count != 1 || atomic_read( cmd, + if (p->count != 1 || dump_atomic_read( cmd, (char *)slp->tblock[trecno], TP_BSIZE) != TP_BSIZE) quit("master/slave protocol botched.\n"); @@ -1123,6 +1168,7 @@ doslave(int cmd, int slave_number, int first) if (compressed && do_compress) { comp_buf->length = bufsize; worklen = TP_BSIZE + writesize; + compresult = 1; #ifdef HAVE_ZLIB if (!bzipflag) { compresult = compress2(comp_buf->buf, @@ -1178,30 +1224,31 @@ doslave(int cmd, int slave_number, int first) if (sigsetjmp(jmpbuf, 1) == 0) { ready = 1; if (!caught) - (void) pause(); + sigsuspend(&set); } ready = 0; caught = 0; #ifdef USE_QFA if (gTapeposfd >= 0) { - uspclptr = (union u_spcl *)&slp->tblock[0]; - spclptr = &uspclptr->s_spcl; - if ((spclptr->c_magic == NFS_MAGIC) && - (spclptr->c_type == TS_INODE) && - (spclptr->c_date == gThisDumpDate)) { - /* if an error occured previously don't - * try again */ - if (gtperr == 0) { - if ((gtperr = GetTapePos(&curtapepos)) == 0) { -#ifdef DEBUG_QFA - msg("inode %ld at tapepos %ld\n", spclptr->c_inumber, curtapepos); -#endif - sprintf(gTps, "%ld\t%d\t%ld\n", (unsigned long)spclptr->c_inumber, tapeno, curtapepos); - if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) { - warn("error writing tapepos file.\n"); - } + int i; + int firstpass = 1; + for (i = 0; i < ntrec; ++i) { + uspclptr = (union u_spcl *)&slp->tblock[i]; + spclptr = &uspclptr->s_spcl; + if ((spclptr->c_magic == NFS_MAGIC) && + (spclptr->c_type == TS_INODE) && + ((spclptr->c_dinode.di_mode & S_IFMT) != IFDIR) && + (spclptr->c_date == gThisDumpDate)) { + /* if an error occured previously don't + * try again */ + if (firstpass) { + firstpass = 0; + if (gtperr == 0) + gtperr = GetTapePos(&curtapepos); } + if (gtperr == 0) + MkTapeString(spclptr, curtapepos); } } } @@ -1251,7 +1298,7 @@ doslave(int cmd, int slave_number, int first) * pass size of data and size of write back to master * (for EOT handling) */ - (void) atomic_write( cmd, (char *)&returns, sizeof returns); + (void) dump_atomic_write( cmd, (char *)&returns, sizeof returns); /* * Signal the next slave to go. @@ -1268,7 +1315,7 @@ doslave(int cmd, int slave_number, int first) * loop until the count is satisfied (or error). */ static ssize_t -atomic_read(int fd, void *buf, size_t count) +dump_atomic_read(int fd, void *buf, size_t count) { int got, need = count; @@ -1285,7 +1332,7 @@ atomic_read(int fd, void *buf, size_t count) * loop until the count is satisfied (or error). */ static ssize_t -atomic_write(int fd, const void *buf, size_t count) +dump_atomic_write(int fd, const void *buf, size_t count) { int got, need = count; @@ -1301,18 +1348,53 @@ atomic_write(int fd, const void *buf, size_t count) /* * read the current tape position */ -int -GetTapePos(long *pos) +static int +GetTapePos(long long *pos) { int err = 0; - *pos = 0; - if (ioctl(tapefd, MTIOCPOS, pos) == -1) { +#ifdef RDUMP + if (host) { + *pos = (long long) rmtseek(0, SEEK_CUR); + err = *pos < 0; + } + else +#endif + { + if (magtapeout) { + long mtpos; + *pos = 0; + err = (ioctl(tapefd, MTIOCPOS, &mtpos) < 0); + *pos = (long long)mtpos; + } + else { + *pos = LSEEK(tapefd, 0, SEEK_CUR); + err = (*pos < 0); + } + } + if (err) { err = errno; - msg("[%ld] error: %d (getting tapepos: %ld)\n", getpid(), + msg("[%ld] error: %d (getting tapepos: %lld)\n", getpid(), err, *pos); return err; } return err; } + +static void +MkTapeString(struct s_spcl *spclptr, long long curtapepos) { + +#ifdef DEBUG_QFA + msg("inode %ld at tapepos %lld\n", spclptr->c_inumber, curtapepos); +#endif + + snprintf(gTps, sizeof(gTps), "%ld\t%d\t%lld\n", + (unsigned long)spclptr->c_inumber, + tapeno, + curtapepos); + gTps[sizeof(gTps) - 1] = '\0'; + if (write(gTapeposfd, gTps, strlen(gTps)) != strlen(gTps)) { + warn("error writing tapepos file.\n"); + } +} #endif /* USE_QFA */