diff options
author | Tom Erickson <Tom.Erickson@Sun.COM> | 2010-01-08 16:55:38 -0800 |
---|---|---|
committer | Tom Erickson <Tom.Erickson@Sun.COM> | 2010-01-08 16:55:38 -0800 |
commit | f64930f5a99dc5cadc013502deedef5a6ef3971f (patch) | |
tree | 5d0ca0f906e6ea9474bde4fc01b1c7d869ffa03d /usr/src | |
parent | b72c368a02e0464faeef362bc5a1cf0fc69981da (diff) | |
download | illumos-gate-f64930f5a99dc5cadc013502deedef5a6ef3971f.tar.gz |
PSARC 2009/663 zfs receive -e
6885138 Would like ability to specify exact receive path when receiving "zfs send -R" stream
6644648 want "zfs send -R a/b/c@snap|zfs recv d/e" to create d/e/c[/...]
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/zfs/zfs_main.c | 8 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 6 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_sendrecv.c | 32 |
3 files changed, 24 insertions, 22 deletions
diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c index a0d0a59118..9c800d2861 100644 --- a/usr/src/cmd/zfs/zfs_main.c +++ b/usr/src/cmd/zfs/zfs_main.c @@ -2684,7 +2684,7 @@ zfs_do_send(int argc, char **argv) } /* - * zfs receive [-dnvF] <fs@snap> + * zfs receive [-denvF] <fs@snap> * * Restore a backup stream from stdin. */ @@ -2695,11 +2695,15 @@ zfs_do_receive(int argc, char **argv) recvflags_t flags = { 0 }; /* check options */ - while ((c = getopt(argc, argv, ":dnuvF")) != -1) { + while ((c = getopt(argc, argv, ":denuvF")) != -1) { switch (c) { case 'd': flags.isprefix = B_TRUE; break; + case 'e': + flags.isprefix = B_TRUE; + flags.istail = B_TRUE; + break; case 'n': flags.dryrun = B_TRUE; break; diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index e6bd268291..4d0aef344f 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -544,6 +544,12 @@ typedef struct recvflags { /* the destination is a prefix, not the exact fs (ie, -d) */ int isprefix : 1; + /* + * Only the tail of the sent snapshot path is appended to the + * destination to determine the received snapshot name (ie, -e). + */ + int istail : 1; + /* do not actually do the recv, just check if it would work (ie, -n) */ int dryrun : 1; diff --git a/usr/src/lib/libzfs/common/libzfs_sendrecv.c b/usr/src/lib/libzfs/common/libzfs_sendrecv.c index 4d507aaf58..65f9b66b60 100644 --- a/usr/src/lib/libzfs/common/libzfs_sendrecv.c +++ b/usr/src/lib/libzfs/common/libzfs_sendrecv.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1921,24 +1921,12 @@ zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname, * Read in the nvlist from the stream. */ if (drr->drr_payloadlen != 0) { - boolean_t recursive; - error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen, &stream_nv, flags.byteswap, zc); if (error) { error = zfs_error(hdl, EZFS_BADSTREAM, errbuf); goto out; } - - recursive = (nvlist_lookup_boolean(stream_nv, - "not_recursive") == ENOENT); - - if (recursive && !flags.isprefix) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "must use -d to receive replication " - "(send -R) stream")); - return (zfs_error(hdl, EZFS_BADSTREAM, errbuf)); - } } /* @@ -2189,23 +2177,27 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap, (void) strcpy(chopprefix, drrb->drr_toname); if (flags.isprefix) { /* - * They specified a fs with -d, we want to tack on - * everything but the pool name stored in the stream + * They specified a fs with -d or -e. We want to tack on + * everything but the first element of the sent snapshot path + * (all but the pool name) in the case of -d, or only the tail + * of the sent snapshot path in the case of -e. */ if (strchr(tosnap, '@')) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid " - "argument - snapshot not allowed with -d")); + "argument - snapshot not allowed with %s"), + (flags.istail ? "-e" : "-d")); return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); } - cp = strchr(chopprefix, '/'); + cp = (flags.istail ? strrchr(chopprefix, '/') : + strchr(chopprefix, '/')); if (cp == NULL) cp = strchr(chopprefix, '@'); *cp = '\0'; } else if (strchr(tosnap, '@') == NULL) { /* - * If they specified a filesystem without -d, we want to - * tack on everything after the fs specified in the - * first name from the stream. + * If they specified a filesystem without -d or -e, we want to + * tack on everything after the fs specified in the first name + * from the stream. */ cp = strchr(chopprefix, '@'); *cp = '\0'; |