X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=dump%2Ftape.c;h=b0eed5b1beb672cfac4ddbfffe32a18bfc860d11;hb=7ae7e2fd107494c21ad619d1bd824ff7e72603f1;hp=45828a52f742e782b48582be691317487a9e8070;hpb=365a7c7c86abbe2b0a1e76e4e9fc8523bd73a8a1;p=dump.git diff --git a/dump/tape.c b/dump/tape.c index 45828a5..b0eed5b 100644 --- a/dump/tape.c +++ b/dump/tape.c @@ -2,7 +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 , 1999-2000 + * Stelian Pop - AlcĂ´ve , 2000 */ /*- @@ -40,9 +41,10 @@ #ifndef lint static const char rcsid[] = - "$Id: tape.c,v 1.17 2000/03/10 10:03:09 stelian Exp $"; + "$Id: tape.c,v 1.28 2000/12/21 15:01:54 stelian Exp $"; #endif /* not lint */ +#include #ifdef __linux__ #include #include @@ -234,24 +236,27 @@ dumpblock(daddr_t blkno, int size) int nogripe = 0; static void -tperror(int signo) +tperror(int errnum) { if (pipeout) { - msg("write error on %s\n", tape); + msg("write error on %s: %s\n", tape, strerror(errnum)); quit("Cannot recover\n"); /* NOTREACHED */ } - msg("write error %d blocks into volume %d\n", blocksthisvol, tapeno); + msg("write error %d blocks into volume %d: %s\n", blocksthisvol, tapeno, strerror(errnum)); broadcast("DUMP WRITE ERROR!\n"); - if (!query("Do you want to restart?")) - dumpabort(0); - msg("Closing this volume. Prepare to restart with new media;\n"); - msg("this dump volume will be rewritten.\n"); - killall(); - nogripe = 1; - close_rewind(); - Exit(X_REWRITE); + if (query("Do you want to rewrite this volume?")) { + msg("Closing this volume. Prepare to restart with new media;\n"); + msg("this dump volume will be rewritten.\n"); + killall(); + nogripe = 1; + close_rewind(); + Exit(X_REWRITE); + } + if (query("Do you want to start the next tape?")) + return; + dumpabort(0); } static void @@ -294,36 +299,49 @@ do_stats(void) return(tnow); } +char * +mktimeest(time_t tnow) +{ + static char msgbuf[128]; + time_t deltat; + + msgbuf[0] = '\0'; + + if (blockswritten < 500) + return NULL; + if (blockswritten > tapesize) + tapesize = blockswritten; + deltat = tstart_writing - tnow + (1.0 * (tnow - tstart_writing)) + / blockswritten * tapesize; + (void)snprintf(msgbuf, sizeof(msgbuf), + "%3.2f%% done at %ld KB/s, finished in %d:%02d\n", + (blockswritten * 100.0) / tapesize, + (spcl.c_tapea - tapea_volume) / (tnow - tstart_volume), + (int)(deltat / 3600), (int)((deltat % 3600) / 60)); + + return msgbuf; +} + #if defined(SIGINFO) /* * statussig -- * information message upon receipt of SIGINFO - * (derived from optr.c::timeest()) */ void statussig(int notused) { - time_t tnow, deltat; - char msgbuf[128]; + time_t tnow; int save_errno = errno; + char *buf; - if (blockswritten < 500) - return; #ifdef __linux__ (void) time4(&tnow); #else (void) time((time_t *) &tnow); #endif - if (blockswritten > tapesize) - tapesize = blockswritten; - deltat = tstart_writing - tnow + (1.0 * (tnow - tstart_writing)) - / blockswritten * tapesize; - (void)snprintf(msgbuf, sizeof(msgbuf), - "%3.2f%% done at %ld KB/s, finished in %d:%02d\n", - (blockswritten * 100.0) / tapesize, - (spcl.c_tapea - tapea_volume) / (tnow - tstart_volume), - (int)(deltat / 3600), (int)((deltat % 3600) / 60)); - write(STDERR_FILENO, msgbuf, strlen(msgbuf)); + buf = mktimeest(tnow); + if (buf) + write(STDERR_FILENO, buf, strlen(buf)); errno = save_errno; } #endif @@ -356,6 +374,10 @@ flushtape(void) } slp->sent = 0; + /* Check for errors */ + if (got < 0) + tperror(-got); + /* Check for end of tape */ if (got < writesize) { msg("End of tape detected\n"); @@ -422,7 +444,11 @@ int system_command(const char *command, const char *device, int volnum) { if (pid == 0) { setuid(getuid()); setgid(getgid()); +#if OLD_STYLE_FSCRIPT + snprintf(commandstr, sizeof(commandstr), "%s", command); +#else snprintf(commandstr, sizeof(commandstr), "%s %s %d", command, device, volnum); +#endif commandstr[sizeof(commandstr) - 1] = '\0'; execl("/bin/sh", "sh", "-c", commandstr, NULL); perror(" DUMP: unable to execute shell"); @@ -465,6 +491,10 @@ trewind(void) dumpabort(0); } slaves[f].sent = 0; + + if (got < 0) + tperror(-got); + if (got != writesize) { msg("EOT detected in last 2 tape records!\n"); msg("Use a longer tape, decrease the size estimate\n"); @@ -488,16 +518,15 @@ trewind(void) rmtclose(); } else -#else +#endif { (void) close(tapefd); while ((f = open(tape, 0)) < 0) sleep (10); (void) close(f); } -#endif eot_code = 1; - if (eot_script) { + if (eot_script && spcl.c_type != TS_END) { msg("Launching %s\n", eot_script); eot_code = system_command(eot_script, tape, tapeno); } @@ -618,12 +647,13 @@ rollforward(void) } slp->req[0] = *q; nextblock = slp->tblock; - if (q->dblk == 0) + if (q->dblk == 0) { #ifdef __linux__ - *(union u_spcl *)(*(nextblock)++) = *(union u_spcl *)tslp->tblock; -#else - nextblock++; + /* XXX post increment triggers an egcs-1.1.2-12 bug on alpha/sparc */ + *(union u_spcl *)(*nextblock) = *(union u_spcl *)tslp->tblock; #endif + nextblock++; + } trecno = 1; /* @@ -638,6 +668,9 @@ rollforward(void) } slp->sent = 0; + if (got < 0) + tperror(-got); + if (got != writesize) { quit("EOT detected at start of the tape!\n"); } @@ -677,17 +710,21 @@ startnewtape(int top) int status; int waitpid; char *p; + #ifdef __linux__ - void (*interrupt_save) __P((int signo)); + sigset_t sigs; + sigemptyset(&sigs); + sigaddset(&sigs, SIGINT); + sigprocmask(SIG_BLOCK, &sigs, NULL); #else /* __linux__ */ #ifdef sunos void (*interrupt_save)(); #else sig_t interrupt_save; #endif + interrupt_save = signal(SIGINT, SIG_IGN); #endif /* __linux__ */ - interrupt_save = signal(SIGINT, SIG_IGN); parentpid = getpid(); tapea_volume = spcl.c_tapea; #ifdef __linux__ @@ -697,7 +734,11 @@ startnewtape(int top) #endif restore_check_point: +#ifdef __linux__ + sigprocmask(SIG_UNBLOCK, &sigs, NULL); +#else (void)signal(SIGINT, interrupt_save); +#endif /* * All signals are inherited... */ @@ -713,7 +754,11 @@ restore_check_point: * until the child doing all of the work returns. * don't catch the interrupt */ +#ifdef __linux__ + sigprocmask(SIG_BLOCK, &sigs, NULL); +#else signal(SIGINT, SIG_IGN); +#endif #ifdef TDEBUG msg("Tape: %d; parent process: %d child process %d\n", tapeno+1, parentpid, childpid); @@ -861,7 +906,6 @@ Exit(int status) static void proceed(int signo) { - if (ready) siglongjmp(jmpbuf, 1); caught++; @@ -879,10 +923,17 @@ enslave(void) master = getpid(); - signal(SIGTERM, dumpabort); /* Slave sends SIGTERM on dumpabort() */ - signal(SIGPIPE, sigpipe); - signal(SIGUSR1, tperror); /* Slave sends SIGUSR1 on tape errors */ - signal(SIGUSR2, proceed); /* Slave sends SIGUSR2 to next slave */ + { struct sigaction sa; + memset(&sa, 0, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_handler = dumpabort; + sigaction(SIGTERM, &sa, NULL); /* Slave sends SIGTERM on dumpabort() */ + sa.sa_handler = sigpipe; + sigaction(SIGPIPE, &sa, NULL); + sa.sa_handler = proceed; + sa.sa_flags = SA_RESTART; + sigaction(SIGUSR2, &sa, NULL); /* Slave sends SIGUSR2 to next slave */ + } for (i = 0; i < SLAVES; i++) { if (i == slp - &slaves[0]) { @@ -899,12 +950,15 @@ enslave(void) slaves[i].fd = cmd[1]; slaves[i].sent = 0; if (slaves[i].pid == 0) { /* Slave starts up here */ + sigset_t sigs; for (j = 0; j <= i; j++) (void) close(slaves[j].fd); - signal(SIGINT, SIG_IGN); /* Master handles this */ + sigemptyset(&sigs); + sigaddset(&sigs, SIGINT); /* Master handles this */ #if defined(SIGINFO) - signal(SIGINFO, SIG_IGN); + sigaddset(&sigs, SIGINFO); #endif + sigprocmask(SIG_BLOCK, &sigs, NULL); #ifdef LINUX_FORK_BUG if (atomic_write( cmd[0], (char *) &i, sizeof i) @@ -960,7 +1014,6 @@ doslave(int cmd, int slave_number) register int nread; int nextslave, size, eot_count; volatile int wrote = 0; - sigset_t sigset; #ifdef __linux__ errcode_t retval; #endif @@ -1004,7 +1057,7 @@ doslave(int cmd, int slave_number) quit("master/slave protocol botched.\n"); } } - if (setjmp(jmpbuf) == 0) { + if (sigsetjmp(jmpbuf, 1) == 0) { ready = 1; if (!caught) (void) pause(); @@ -1053,18 +1106,17 @@ doslave(int cmd, int slave_number) if (eot_count > 0) size = 0; - if (wrote < 0) { - (void) kill(master, SIGUSR1); - sigemptyset(&sigset); - for (;;) - sigsuspend(&sigset); - } else { - /* - * pass size of write back to master - * (for EOT handling) - */ - (void) atomic_write( cmd, (char *)&size, sizeof size); - } + /* + * pass errno back to master for special handling + */ + if (wrote < 0) + size = -errno; + + /* + * pass size of write back to master + * (for EOT handling) + */ + (void) atomic_write( cmd, (char *)&size, sizeof size); /* * If partial write, don't want next slave to go.