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
This commit is contained in:
Brian Feldman 2004-04-13 02:58:06 +00:00
parent ae13acf259
commit c51d70c690
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128175
8 changed files with 178 additions and 41 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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);
}

View file

@ -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 @@ startnewtape(int top)
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 @@ startnewtape(int top)
nexttape = NULL;
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)
#else
while ((tapefd = (pipeout ? 1 :
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?"))
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) :
open(tape, O_WRONLY|O_CREAT, 0666))) < 0)
#else
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);
}
}
enslave(); /* Share open tape file descriptor with slaves */
if (popenout)
close(tapefd); /* Give up our copy of it. */
signal(SIGINFO, infosch);
asize = 0;

View file

@ -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);

View file

@ -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);
}

View file

@ -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.

View file

@ -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 @@ getvol(long nextvol)
(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();