mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
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:
parent
ae13acf259
commit
c51d70c690
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=128175
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue