diff options
-rw-r--r-- | sbin/dump/dump.8 | 24 | ||||
-rw-r--r-- | sbin/dump/dump.h | 1 | ||||
-rw-r--r-- | sbin/dump/main.c | 28 | ||||
-rw-r--r-- | sbin/dump/tape.c | 51 | ||||
-rw-r--r-- | sbin/restore/extern.h | 2 | ||||
-rw-r--r-- | sbin/restore/main.c | 37 | ||||
-rw-r--r-- | sbin/restore/restore.8 | 33 | ||||
-rw-r--r-- | sbin/restore/tape.c | 39 |
8 files changed, 176 insertions, 39 deletions
diff --git a/sbin/dump/dump.8 b/sbin/dump/dump.8 index 0e86ebe..fedf9a6 100644 --- a/sbin/dump/dump.8 +++ b/sbin/dump/dump.8 @@ -44,7 +44,7 @@ .Op Fl C Ar cachesize .Op Fl D Ar dumpdates .Op Fl d Ar density -.Op Fl f Ar file +.Op Fl f Ar file | Fl P Ar pipecommand .Op Fl h Ar level .Op Fl s Ar feet .Op Fl T Ar date @@ -190,6 +190,28 @@ program is .Pa /etc/rmt ; this can be overridden by the environment variable .Ev RMT . +.It Fl P Ar pipecommand +Use +.Xr popen 3 +to execute the +.Xr sh 1 +script string defined by +.Ar pipecommand +for the output device of each volume. +This child pipeline's +.Dv stdin +.Pa ( /dev/fd/0 ) +is redirected from the +.Nm +output stream, and the environment variable +.Ev DUMP_VOLUME +is set to the current volume number being written. +After every volume, the writer side of the pipe is closed and +.Ar pipecommand +is executed again. +Subject to the media size specified by +.Fl B , +each volume is written in this manner as if the output were a tape drive. .It Fl h Ar level Honor the user .Dq nodump diff --git a/sbin/dump/dump.h b/sbin/dump/dump.h index 08acb9e..75b33d5 100644 --- a/sbin/dump/dump.h +++ b/sbin/dump/dump.h @@ -56,6 +56,7 @@ char *dumpinomap; /* map of files to be dumped */ */ char *disk; /* name of the disk file */ char *tape; /* name of the tape file */ +char *popenout; /* popen(3) per-"tape" command */ char *dumpdates; /* name of the file containing dump date information*/ char *temp; /* name of the file for doing rewrite of dumpdates */ char lastlevel; /* dump level of previous dump */ diff --git a/sbin/dump/main.c b/sbin/dump/main.c index baf8a25..09c27ab 100644 --- a/sbin/dump/main.c +++ b/sbin/dump/main.c @@ -110,9 +110,9 @@ main(int argc, char *argv[]) spcl.c_date = _time_to_time64(time(NULL)); tsize = 0; /* Default later, based on 'c' option for cart tapes */ - if ((tape = getenv("TAPE")) == NULL) - tape = _PATH_DEFTAPE; dumpdates = _PATH_DUMPDATES; + popenout = NULL; + tape = NULL; temp = _PATH_DTMP; if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0) quit("TP_BSIZE must be a multiple of DEV_BSIZE\n"); @@ -123,7 +123,7 @@ main(int argc, char *argv[]) obsolete(&argc, &argv); while ((ch = getopt(argc, argv, - "0123456789aB:b:C:cD:d:f:h:LnSs:T:uWw")) != -1) + "0123456789aB:b:C:cD:d:f:h:LnP:Ss:T:uWw")) != -1) switch (ch) { /* dump level */ case '0': case '1': case '2': case '3': case '4': @@ -164,6 +164,9 @@ main(int argc, char *argv[]) break; case 'f': /* output file */ + if (popenout != NULL) + errx(X_STARTUP, "You cannot use the P and f " + "flags together.\n"); tape = optarg; break; @@ -179,6 +182,13 @@ main(int argc, char *argv[]) notify = 1; break; + case 'P': + if (tape != NULL) + errx(X_STARTUP, "You cannot use the P and f " + "flags together.\n"); + popenout = optarg; + break; + case 'S': /* exit after estimating # of tapes */ just_estimate = 1; break; @@ -231,6 +241,10 @@ main(int argc, char *argv[]) "You cannot use the T and u flags together.\n"); exit(X_STARTUP); } + if (popenout) { + tape = "child pipeline process"; + } else if (tape == NULL && (tape = getenv("TAPE")) == NULL) + tape = _PATH_DEFTAPE; if (strcmp(tape, "-") == 0) { pipeout++; tape = "standard output"; @@ -316,8 +330,8 @@ main(int argc, char *argv[]) snapdump = 0; } } else if (snapdump == 0) { - msg("WARNING: %s%s\n", - "should use -L when dumping live read-write ", + msg("WARNING: %s\n", + "should use -L when dumping live read-write " "filesystems!"); } else { char snapname[BUFSIZ], snapcmd[BUFSIZ]; @@ -562,8 +576,8 @@ usage(void) { fprintf(stderr, "usage: dump [-0123456789acLnSu] [-B records] [-b blocksize] [-C cachesize]\n" - " [-D dumpdates] [-d density] [-f file] [-h level] [-s feet]\n" - " [-T date] filesystem\n" + " [-D dumpdates] [-d density] [-h level] [-s feet] [-T date]\n" + " [-f file | -P pipecommand] filesystem\n" " dump -W | -w\n"); exit(X_STARTUP); } diff --git a/sbin/dump/tape.c b/sbin/dump/tape.c index 5437e05..490d3d9 100644 --- a/sbin/dump/tape.c +++ b/sbin/dump/tape.c @@ -67,6 +67,7 @@ extern int ntrec; /* blocking factor on tape */ extern int cartridge; extern char *host; char *nexttape; +FILE *popenfp = NULL; static int atomic(ssize_t (*)(), int, char *, int); static void doslave(int, int); @@ -336,6 +337,12 @@ trewind(void) msg("Closing %s\n", tape); + if (popenout) { + tapefd = -1; + (void)pclose(popenfp); + popenfp = NULL; + return; + } #ifdef RDUMP if (host) { rmtclose(); @@ -500,7 +507,6 @@ startnewtape(int top) int parentpid; int childpid; int status; - int waitpid; char *p; sig_t interrupt_save; @@ -530,9 +536,9 @@ restore_check_point: msg("Tape: %d; parent process: %d child process %d\n", tapeno+1, parentpid, childpid); #endif /* TDEBUG */ - while ((waitpid = wait(&status)) != childpid) - msg("Parent %d waiting for child %d has another child %d return\n", - parentpid, childpid, waitpid); + if (waitpid(childpid, &status, 0) == -1) + msg("Waiting for child %d: %s\n", childpid, + strerror(errno)); if (status & 0xFF) { msg("Child %d returns LOB status %o\n", childpid, status&0xFF); @@ -589,20 +595,41 @@ restore_check_point: nexttape = NULL; msg("Dumping volume %d on %s\n", tapeno, tape); } + if (pipeout) { + tapefd = STDOUT_FILENO; + } else if (popenout) { + char volno[sizeof("2147483647")]; + + (void)sprintf(volno, "%d", spcl.c_volume + 1); + if (setenv("DUMP_VOLUME", volno, 1) == -1) { + msg("Cannot set $DUMP_VOLUME.\n"); + dumpabort(0); + } + popenfp = popen(popenout, "w"); + if (popenfp == NULL) { + msg("Cannot open output pipeline \"%s\".\n", + popenout); + dumpabort(0); + } + tapefd = fileno(popenfp); + } else { #ifdef RDUMP - while ((tapefd = (host ? rmtopen(tape, 2) : - pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0) + while ((tapefd = (host ? rmtopen(tape, 2) : + open(tape, O_WRONLY|O_CREAT, 0666))) < 0) #else - while ((tapefd = (pipeout ? 1 : - open(tape, O_WRONLY|O_CREAT, 0666))) < 0) + while ((tapefd = + open(tape, O_WRONLY|O_CREAT, 0666)) < 0) #endif - { - msg("Cannot open output \"%s\".\n", tape); - if (!query("Do you want to retry the open?")) - dumpabort(0); + { + msg("Cannot open output \"%s\".\n", tape); + if (!query("Do you want to retry the open?")) + dumpabort(0); + } } enslave(); /* Share open tape file descriptor with slaves */ + if (popenout) + close(tapefd); /* Give up our copy of it. */ signal(SIGINFO, infosch); asize = 0; diff --git a/sbin/restore/extern.h b/sbin/restore/extern.h index 2d1f464..9edf6f9 100644 --- a/sbin/restore/extern.h +++ b/sbin/restore/extern.h @@ -87,7 +87,7 @@ void rst_closedir(RST_DIR *dirp); void runcmdshell(void); char *savename(char *); void setdirmodes(int); -void setinput(char *); +void setinput(char *, int); void setup(void); void skipdirs(void); void skipfile(void); diff --git a/sbin/restore/main.c b/sbin/restore/main.c index 9006ea5..b2ace5d 100644 --- a/sbin/restore/main.c +++ b/sbin/restore/main.c @@ -62,6 +62,7 @@ static const char rcsid[] = int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0; int hflag = 1, mflag = 1, Nflag = 0; int uflag = 0; +int pipecmd = 0; char command = '\0'; long dumpnum = 1; long volno = 0; @@ -93,10 +94,9 @@ main(int argc, char *argv[]) (void)setlocale(LC_ALL, ""); - if ((inputdev = getenv("TAPE")) == NULL) - inputdev = _PATH_DEFTAPE; + inputdev = NULL; obsolete(&argc, &argv); - while ((ch = getopt(argc, argv, "b:df:himNRrs:tuvxy")) != -1) + while ((ch = getopt(argc, argv, "b:df:himNP:Rrs:tuvxy")) != -1) switch(ch) { case 'b': /* Change default tape blocksize. */ @@ -111,8 +111,18 @@ main(int argc, char *argv[]) dflag = 1; break; case 'f': + if (pipecmd) + errx(1, + "-P and -f options are mutually exclusive"); inputdev = optarg; break; + case 'P': + if (!pipecmd && inputdev) + errx(1, + "-P and -f options are mutually exclusive"); + inputdev = optarg; + pipecmd = 1; + break; case 'h': hflag = 0; break; @@ -165,7 +175,9 @@ main(int argc, char *argv[]) (void) signal(SIGTERM, SIG_IGN); setlinebuf(stderr); - setinput(inputdev); + if (inputdev == NULL && (inputdev = getenv("TAPE")) == NULL) + inputdev = _PATH_DEFTAPE; + setinput(inputdev, pipecmd); if (argc == 0) { argc = 1; @@ -277,12 +289,17 @@ main(int argc, char *argv[]) static void usage() { - (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n", - "restore -i [-cdhmNuvy] [-b blocksize] [-f file] [-s fileno]", - "restore -r [-cdNuvy] [-b blocksize] [-f file] [-s fileno]", - "restore -R [-cdNuvy] [-b blocksize] [-f file] [-s fileno]", - "restore -x [-cdhmNuvy] [-b blocksize] [-f file] [-s fileno] [file ...]", - "restore -t [-cdhNuvy] [-b blocksize] [-f file] [-s fileno] [file ...]"); + const char *const common = + "[-b blocksize] [-P pipecmd | -f file] [-s fileno]"; + const char *const fileell = "[file ...]"; + + (void)fprintf(stderr, "usage:\t%s %s\n\t%s %s\n\t%s %s\n" + "\t%s %s %s\n\t%s %s %s\n", + "restore -i [-cdhmNuvy]", common, + "restore -r [-cdNuvy]", common, + "restore -R [-cdNuvy]", common, + "restore -x [-cdhmNuvy]", common, fileell, + "restore -t [-cdhNuvy]", common, fileell); done(1); } diff --git a/sbin/restore/restore.8 b/sbin/restore/restore.8 index 4d970a7..8b1514a 100644 --- a/sbin/restore/restore.8 +++ b/sbin/restore/restore.8 @@ -40,32 +40,32 @@ .Fl i .Op Fl cdhmNuvy .Op Fl b Ar blocksize -.Op Fl f Ar file +.Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Nm .Fl R .Op Fl cdNuvy .Op Fl b Ar blocksize -.Op Fl f Ar file +.Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Nm .Fl r .Op Fl cdNuvy .Op Fl b Ar blocksize -.Op Fl f Ar file +.Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Nm .Fl t .Op Fl cdhNuvy .Op Fl b Ar blocksize -.Op Fl f Ar file +.Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Op Ar .Nm .Fl x .Op Fl cdhmNuvy .Op Fl b Ar blocksize -.Op Fl f Ar file +.Op Fl f Ar file | Fl P Ar pipecommand .Op Fl s Ar fileno .Op Ar .Pp @@ -93,7 +93,9 @@ The utility works across a network; to do this see the .Fl f -flag described below. +and +.Fl P +flags described below. Other arguments to the command are file or directory names specifying the files that are to be restored. Unless the @@ -304,6 +306,25 @@ or .Nm reads from the named file on the remote host using .Xr rmt 8 . +.It Fl P Ar pipecommand +Use +.Xr popen 3 +to execute the +.Xr sh 1 +script string defined by +.Ar pipecommand +as the input for every volume in the backup. +This child pipeline's +.Dv stdout +.Pa ( /dev/fd/1 ) +is redirected to the +.Nm +input stream, and the environment variable +.Ev RESTORE_VOLUME +is set to the current volume number being read. +The +.Ar pipecommand +script is started each time a volume is loaded, as if it were a tape drive. .It Fl h Extract the actual directory, rather than the files that it references. diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c index 0b59364..6a2163b 100644 --- a/sbin/restore/tape.c +++ b/sbin/restore/tape.c @@ -65,6 +65,8 @@ static const char rcsid[] = static long fssize = MAXBSIZE; static int mt = -1; static int pipein = 0; +static int pipecmdin = 0; +static FILE *popenfp = NULL; static char *magtape; static int blkcnt; static int numtrec; @@ -109,7 +111,7 @@ static void xtrskip(char *, long); * Set up an input source */ void -setinput(char *source) +setinput(char *source, int ispipecommand) { FLUSHTAPEBUF(); if (bflag) @@ -118,6 +120,9 @@ setinput(char *source) newtapebuf(NTREC > HIGHDENSITYTREC ? NTREC : HIGHDENSITYTREC); terminal = stdin; + if (ispipecommand) + pipecmdin++; + else #ifdef RRESTORE if (strchr(source, ':')) { host = source; @@ -182,6 +187,15 @@ setup(void) struct stat stbuf; vprintf(stdout, "Verify tape and initialize maps\n"); + if (pipecmdin) { + if (setenv("RESTORE_VOLUME", "1", 1) == -1) { + fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n", + strerror(errno)); + done(1); + } + popenfp = popen(magtape, "r"); + mt = popenfp ? fileno(popenfp) : -1; + } else #ifdef RRESTORE if (host) mt = rmtopen(magtape, 0); @@ -304,6 +318,10 @@ getvol(long nextvol) } if (volno == 1) return; + if (pipecmdin) { + closemt(); + goto getpipecmdhdr; + } goto gethdr; } again: @@ -364,6 +382,19 @@ again: (void) strcpy(magtape, buf); magtape[strlen(magtape) - 1] = '\0'; } + if (pipecmdin) { + char volno[sizeof("2147483647")]; + +getpipecmdhdr: + (void)sprintf(volno, "%d", newvol); + if (setenv("RESTORE_VOLUME", volno, 1) == -1) { + fprintf(stderr, "Cannot set $RESTORE_VOLUME: %s\n", + strerror(errno)); + done(1); + } + popenfp = popen(magtape, "r"); + mt = popenfp ? fileno(popenfp) : -1; + } else #ifdef RRESTORE if (host) mt = rmtopen(magtape, 0); @@ -493,7 +524,7 @@ setdumpnum(void) rmtioctl(MTFSF, dumpnum - 1); else #endif - if (ioctl(mt, MTIOCTOP, (char *)&tcom) < 0) + if (!pipecmdin && ioctl(mt, MTIOCTOP, (char *)&tcom) < 0) fprintf(stderr, "ioctl MTFSF: %s\n", strerror(errno)); } @@ -982,6 +1013,10 @@ closemt(void) if (mt < 0) return; + if (pipecmdin) { + pclose(popenfp); + popenfp = NULL; + } else #ifdef RRESTORE if (host) rmtclose(); |