* dump and restore backup suit
* Remy Card <card@Linux.EU.Org>, 1994-1997
* Stelian Pop <pop@cybercable.fr>, 1999-2000
+ * Stelian Pop <pop@cybercable.fr> - Alcôve <www.alcove.fr>, 2000
*/
/*-
#ifndef lint
static const char rcsid[] =
- "$Id: tape.c,v 1.12 2000/02/10 09:42:32 stelian Exp $";
+ "$Id: tape.c,v 1.24 2000/11/10 14:42:25 stelian Exp $";
#endif /* not lint */
#ifdef __linux__
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
+#include <compaterr.h>
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
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));
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
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());
+#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);
+ }
+ 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;
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 || Mflag)
+ (void)trewind();
+ if (nexttape || Mflag || (eot_code == 0) )
return;
if (!nogripe) {
msg("Change Volumes: Mount volume #%d\n", tapeno+1);
}
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;
/*
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);
*/
tapeno++; /* current tape sequence */
if (Mflag) {
- snprintf(tape, NAME_MAX, "%s%03d", tapeprefix, tapeno);
- tape[NAME_MAX - 1] = '\0';
+ 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, ',')) {
nexttape = p + 1;
} else
nexttape = NULL;
- strncpy(tape, tapeprefix, NAME_MAX);
- tape[NAME_MAX - 1] = '\0';
+ 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
{
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 = 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]) {
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)
quit("master/slave protocol botched.\n");
}
}
- if (setjmp(jmpbuf) == 0) {
+ if (sigsetjmp(jmpbuf, 1) == 0) {
ready = 1;
if (!caught)
(void) pause();
if (wrote < 0) {
(void) kill(master, SIGUSR1);
sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
for (;;)
sigsuspend(&sigset);
} else {