]> git.wh0rd.org - dump.git/blobdiff - dump/tape.c
The -F script is called now *only* at the end of a tape.
[dump.git] / dump / tape.c
index 1b28c41e6e6307a9a9f662d36fc243c0b28045c3..69715003e67bf772103bfad8d0b5d996a64c03ec 100644 (file)
@@ -2,7 +2,7 @@
  *     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 
+ *     Stelian Pop <pop@cybercable.fr>, 1999-2000
  */
 
 /*-
@@ -40,7 +40,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: tape.c,v 1.7 1999/11/02 09:35:56 tiniou Exp $";
+       "$Id: tape.c,v 1.19 2000/05/28 16:24:14 stelian Exp $";
 #endif /* not lint */
 
 #ifdef __linux__
@@ -73,6 +73,7 @@ static const char rcsid[] =
 #include <setjmp.h>
 #include <signal.h>
 #include <stdio.h>
+#include <compaterr.h>
 #ifdef __STDC__
 #include <stdlib.h>
 #include <string.h>
@@ -81,9 +82,10 @@ static const char rcsid[] =
 int    write(), read();
 #endif
 
-#ifdef __linux__
+#ifdef __linux__
 #include <ext2fs/ext2fs.h>
 #endif
+
 #include "dump.h"
 
 int    writesize;              /* size of malloc()ed buffer for tape */
@@ -96,6 +98,7 @@ extern        int cartridge;
 extern char *host;
 char   *nexttape;
 extern  pid_t rshpid;
+int    eot_code = 1;
 
 static ssize_t atomic_read __P((int, void *, size_t));
 static ssize_t atomic_write __P((int, const void *, size_t));
@@ -104,6 +107,7 @@ static      void enslave __P((void));
 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
@@ -310,6 +314,8 @@ statussig(int notused)
 #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),
@@ -399,7 +405,45 @@ flushtape(void)
        timeest();
 }
 
-void
+/*
+ * Executes the command in a shell.
+ * Returns -1 if an error occured, the exit status of
+ * the command on success.
+ */
+int system_command(const char *command, const char *device, int volnum) {
+       int pid, status;
+       char commandstr[4096];
+
+       pid = fork();
+       if (pid == -1) {
+               perror("  DUMP: unable to fork");
+               return -1;
+       }
+       if (pid == 0) {
+               setuid(getuid());
+               setgid(getgid());
+               snprintf(commandstr, sizeof(commandstr), "%s %s %d", command, device, volnum);
+               commandstr[sizeof(commandstr) - 1] = '\0';
+               execl("/bin/sh", "sh", "-c", commandstr, NULL);
+               perror("  DUMP: unable to execute shell");
+               exit(-1);
+       }
+       do {
+               if (waitpid(pid, &status, 0) == -1) {
+                       if (errno != EINTR) {
+                               perror("  DUMP: waitpid error");
+                               return -1;
+                       }
+               } else {
+                       if (WIFEXITED(status))
+                               return WEXITSTATUS(status);
+                       else
+                               return -1;
+               }
+       } while(1);
+}
+
+time_t
 trewind(void)
 {
        int f;
@@ -432,32 +476,44 @@ trewind(void)
        while (wait((int *)NULL) >= 0)  /* wait for any signals from slaves */
                /* void */;
 
-       if (pipeout)
-               return;
+       if (!pipeout) {
 
-       msg("Closing %s\n", tape);
+               msg("Closing %s\n", tape);
 
 #ifdef RDUMP
-       if (host) {
-               rmtclose();
-               while (rmtopen(tape, 0) < 0)
-                       sleep(10);
-               rmtclose();
-               return;
-       }
+               if (host) {
+                       rmtclose();
+                       while (rmtopen(tape, 0) < 0)
+                               sleep(10);
+                       rmtclose();
+               }
+               else 
 #endif
-       (void) close(tapefd);
-       while ((f = open(tape, 0)) < 0)
-               sleep (10);
-       (void) close(f);
+               {
+                       (void) close(tapefd);
+                       while ((f = open(tape, 0)) < 0)
+                               sleep (10);
+                       (void) close(f);
+               }
+               eot_code = 1;
+               if (eot_script && spcl.c_type != TS_END) {
+                       msg("Launching %s\n", 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");
+                       dumpabort(0);
+               }
+       }
+       return do_stats();
 }
 
+               
 void
 close_rewind(void)
 {
-       trewind();
-       (void)do_stats();
-       if (nexttape)
+       (void)trewind();
+       if (nexttape || Mflag || (eot_code == 0) )
                return;
        if (!nogripe) {
                msg("Change Volumes: Mount volume #%d\n", tapeno+1);
@@ -561,12 +617,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;
 
        /*
@@ -620,17 +677,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__
@@ -640,7 +701,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...
         */
@@ -656,7 +721,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);
@@ -711,21 +780,29 @@ restore_check_point:
                 * the remaining names for subsequent volumes.
                 */
                tapeno++;               /* current tape sequence */
-               if (nexttape || strchr(tape, ',')) {
+               if (Mflag) {
+                       snprintf(tape, MAXPATHLEN, "%s%03d", tapeprefix, tapeno);
+                       tape[MAXPATHLEN - 1] = '\0';
+                       msg("Dumping volume %d on %s\n", tapeno, tape);
+               }
+               else if (nexttape || strchr(tapeprefix, ',')) {
                        if (nexttape && *nexttape)
-                               tape = nexttape;
-                       if ((p = strchr(tape, ',')) != NULL) {
+                               tapeprefix = nexttape;
+                       if ((p = strchr(tapeprefix, ',')) != NULL) {
                                *p = '\0';
                                nexttape = p + 1;
                        } else
                                nexttape = NULL;
+                       strncpy(tape, tapeprefix, MAXPATHLEN);
+                       tape[MAXPATHLEN - 1] = '\0';
                        msg("Dumping volume %d on %s\n", tapeno, tape);
                }
 #ifdef RDUMP
-               while ((tapefd = (host ? rmtopen(tape, 2) :
-                       pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
+               while ((tapefd = (host ? rmtopen(tape, 2) : pipeout ? 
+                       fileno(stdout) : 
+                       open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
 #else
-               while ((tapefd = (pipeout ? 1 :
+               while ((tapefd = (pipeout ? fileno(stdout) :
                                  open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
 #endif
                    {
@@ -796,10 +873,9 @@ Exit(int status)
 static void
 proceed(int signo)
 {
-
+       caught++;
        if (ready)
                siglongjmp(jmpbuf, 1);
-       caught++;
 }
 
 void
@@ -814,10 +890,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;
+       sa.sa_handler = dumpabort;
+       sigaction(SIGTERM, &sa, NULL); /* Slave sends SIGTERM on dumpabort() */
+       sa.sa_handler = sigpipe;
+       sigaction(SIGPIPE, &sa, NULL);
+       sa.sa_handler = tperror;
+       sigaction(SIGUSR1, &sa, NULL); /* Slave sends SIGUSR1 on tape errors */
+       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]) {
@@ -834,12 +917,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)
@@ -908,9 +994,9 @@ doslave(int cmd, int slave_number)
                quit("slave couldn't reopen disk: %s\n", strerror(errno));
 #ifdef __linux__
        ext2fs_close(fs);
-       retval = ext2fs_open(disk, 0, 0, 0, unix_io_manager, &fs);
+       retval = dump_fs_open(disk, &fs);
        if (retval)
-               quit("slave couldn't reopen disk: %s\n", strerror(errno));
+               quit("slave couldn't reopen disk: %s\n", error_message(retval));
 #endif /* __linux__ */
 
        /*
@@ -939,7 +1025,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();
@@ -1021,8 +1107,10 @@ atomic_read(int fd, void *buf, size_t count)
 {
        int got, need = count;
 
-       while ((got = read(fd, buf, need)) > 0 && (need -= got) > 0)
-               (char *)buf += got;
+       do {
+               while ((got = read(fd, buf, need)) > 0 && (need -= got) > 0)
+                       (char *)buf += got;
+       } while (got == -1 && errno == EINTR);
        return (got < 0 ? got : count - need);
 }
 
@@ -1036,7 +1124,9 @@ atomic_write(int fd, const void *buf, size_t count)
 {
        int got, need = count;
 
-       while ((got = write(fd, buf, need)) > 0 && (need -= got) > 0)
-               (char *)buf += got;
+       do {
+               while ((got = write(fd, buf, need)) > 0 && (need -= got) > 0)
+                       (char *)buf += got;
+       } while (got == -1 && errno == EINTR);
        return (got < 0 ? got : count - need);
 }