* Ported to Linux's Second Extended File System as part of the
* dump and restore backup suit
* Remy Card <card@Linux.EU.Org>, 1994-1997
- * Stelian Pop <pop@cybercable.fr>, 1999-2000
+ * Stelian Pop <pop@noos.fr>, 1999-2000
+ * Stelian Pop <pop@noos.fr> - AlcĂ´ve <www.alcove.fr>, 2000
*/
/*-
#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.15 2000/03/02 11:34:51 stelian Exp $";
+ "$Id: tape.c,v 1.30 2001/02/16 13:38:47 stelian Exp $";
#endif /* not lint */
+#include <config.h>
#ifdef __linux__
#include <sys/types.h>
#include <linux/types.h>
static void flushtape __P((void));
static void killall __P((void));
static void rollforward __P((void));
+static int system_command __P((const char *, const char *, int));
/*
* Concurrent dump mods (Caltech) - disk block reading and tape writing
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
#else
ctime(&tnow));
#endif
+ msg("Volume %d: %ld tape blocks (%.2fMB)\n", tapeno,
+ blocks, ((double)blocks * TP_BSIZE / 1048576));
if (ttaken > 0) {
msg("Volume %d took %d:%02d:%02d\n", tapeno,
ttaken / 3600, (ttaken % 3600) / 60, ttaken % 60);
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;
+ if (tnow > tstart_volume)
+ (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));
+ else
+ (void)snprintf(msgbuf, sizeof(msgbuf),
+ "%3.2f%% done, finished in %d:%02d\n",
+ (blockswritten * 100.0) / tapesize,
+ (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
}
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");
* Returns -1 if an error occured, the exit status of
* the command on success.
*/
-int system_command(const char *command) {
+int system_command(const char *command, const char *device, int volnum) {
int pid, status;
+ char commandstr[4096];
pid = fork();
if (pid == -1) {
if (pid == 0) {
setuid(getuid());
setgid(getgid());
- execl("/bin/sh", "sh", "-c", command, NULL);
+#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");
exit(-1);
}
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");
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);
+ eot_code = system_command(eot_script, tape, tapeno);
}
if (eot_code != 0 && eot_code != 1) {
msg("Dump aborted by the end of tape script\n");
}
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;
/*
}
slp->sent = 0;
+ if (got < 0)
+ tperror(-got);
+
if (got != writesize) {
quit("EOT detected at start of the tape!\n");
}
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__
#endif
restore_check_point:
+#ifdef __linux__
+ sigprocmask(SIG_UNBLOCK, &sigs, NULL);
+#else
(void)signal(SIGINT, interrupt_save);
+#endif
/*
* All signals are inherited...
*/
* 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);
static void
proceed(int signo)
{
-
if (ready)
siglongjmp(jmpbuf, 1);
caught++;
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]) {
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)
register int nread;
int nextslave, size, eot_count;
volatile int wrote = 0;
- sigset_t sigset;
#ifdef __linux__
errcode_t retval;
#endif
quit("master/slave protocol botched.\n");
}
}
- if (setjmp(jmpbuf) == 0) {
+ if (sigsetjmp(jmpbuf, 1) == 0) {
ready = 1;
if (!caught)
(void) pause();
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.