summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgreen <green@FreeBSD.org>2004-04-13 02:58:06 +0000
committergreen <green@FreeBSD.org>2004-04-13 02:58:06 +0000
commit581462d4656a457daa431e77d6ec725f56cba982 (patch)
treea1d674955b8c95633685662ea70b1c1e05573efd
parenta98a06d2276b300662ee818529a9a455454f506c (diff)
downloadFreeBSD-src-581462d4656a457daa431e77d6ec725f56cba982.zip
FreeBSD-src-581462d4656a457daa431e77d6ec725f56cba982.tar.gz
Add -P arguments for dump(8) and restore(8) which allow the user to
use backup methods other than files and tapes. The -P argument is a normal sh(1) pipeline with either $DUMP_VOLUME or $RESTORE_VOLUME defined in the environment, respectively. For example, I can back up my home to three DVD+R[W]s as so: Filesystem 1K-blocks Used Avail Capacity Mounted on /dev/ad0s2e 40028550 10093140 26733126 27% /home green# dump -0 -L -C16 -B4589840 -P 'growisofs -Z /dev/cd0=/dev/fd/0' /home
-rw-r--r--sbin/dump/dump.824
-rw-r--r--sbin/dump/dump.h1
-rw-r--r--sbin/dump/main.c28
-rw-r--r--sbin/dump/tape.c51
-rw-r--r--sbin/restore/extern.h2
-rw-r--r--sbin/restore/main.c37
-rw-r--r--sbin/restore/restore.833
-rw-r--r--sbin/restore/tape.c39
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();
OpenPOWER on IntegriCloud