7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  25  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  26  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  27  */
  28 
  29 #include <assert.h>
  30 #include <ctype.h>
  31 #include <errno.h>
  32 #include <libintl.h>
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 #include <strings.h>
  36 #include <unistd.h>
  37 #include <stddef.h>
  38 #include <fcntl.h>
  39 #include <sys/mount.h>
  40 #include <pthread.h>
  41 #include <umem.h>
  42 #include <time.h>
  43 
  44 #include <libzfs.h>
  45 #include <libzfs_core.h>
  46 
  47 #include "zfs_namecheck.h"
  48 #include "zfs_prop.h"
  49 #include "zfs_fletcher.h"
  50 #include "libzfs_impl.h"
  51 #include <zlib.h>
  52 #include <sha2.h>
  53 #include <sys/zio_checksum.h>
  54 #include <sys/ddt.h>
  55 
  56 /* in libzfs_dataset.c */
  57 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
  58 
  59 static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
  60     recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
  61     uint64_t *);
  62 static int guid_to_name(libzfs_handle_t *, const char *,
  63     uint64_t, boolean_t, char *);
  64 
  65 static const zio_cksum_t zero_cksum = { 0 };
  66 
  67 typedef struct dedup_arg {
  68         int     inputfd;
  69         int     outputfd;
  70         libzfs_handle_t  *dedup_hdl;
  71 } dedup_arg_t;
  72 
  73 typedef struct progress_arg {
  74         zfs_handle_t *pa_zhp;
  75         int pa_fd;
  76         boolean_t pa_parsable;
  77 } progress_arg_t;
  78 
  79 typedef struct dataref {
  80         uint64_t ref_guid;
  81         uint64_t ref_object;
 
2544         nvlist_free(local_nv);
2545 
2546         if (needagain && progress) {
2547                 /* do another pass to fix up temporary names */
2548                 if (flags->verbose)
2549                         (void) printf("another pass:\n");
2550                 goto again;
2551         }
2552 
2553         return (needagain);
2554 }
2555 
2556 static int
2557 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2558     recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2559     char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2560 {
2561         nvlist_t *stream_nv = NULL;
2562         avl_tree_t *stream_avl = NULL;
2563         char *fromsnap = NULL;
2564         char *cp;
2565         char tofs[ZFS_MAXNAMELEN];
2566         char sendfs[ZFS_MAXNAMELEN];
2567         char errbuf[1024];
2568         dmu_replay_record_t drre;
2569         int error;
2570         boolean_t anyerr = B_FALSE;
2571         boolean_t softerr = B_FALSE;
2572         boolean_t recursive;
2573 
2574         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2575             "cannot receive"));
2576 
2577         assert(drr->drr_type == DRR_BEGIN);
2578         assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2579         assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2580             DMU_COMPOUNDSTREAM);
2581 
2582         /*
2583          * Read in the nvlist from the stream.
 
2692                                         zfs_close(zhp);
2693                                         if (clp != NULL) {
2694                                                 softerr |=
2695                                                     changelist_prefix(clp);
2696                                                 changelist_free(clp);
2697                                         }
2698                                 }
2699                         }
2700 
2701                         nvlist_free(renamed);
2702                 }
2703         }
2704 
2705         /*
2706          * Get the fs specified by the first path in the stream (the top level
2707          * specified by 'zfs send') and pass it to each invocation of
2708          * zfs_receive_one().
2709          */
2710         (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2711             ZFS_MAXNAMELEN);
2712         if ((cp = strchr(sendfs, '@')) != NULL)
2713                 *cp = '\0';
2714 
2715         /* Finally, receive each contained stream */
2716         do {
2717                 /*
2718                  * we should figure out if it has a recoverable
2719                  * error, in which case do a recv_skip() and drive on.
2720                  * Note, if we fail due to already having this guid,
2721                  * zfs_receive_one() will take care of it (ie,
2722                  * recv_skip() and return 0).
2723                  */
2724                 error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
2725                     sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2726                     action_handlep);
2727                 if (error == ENODATA) {
2728                         error = 0;
2729                         break;
2730                 }
2731                 anyerr |= error;
2732         } while (error == 0);
2733 
2734         if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2735                 /*
2736                  * Now that we have the fs's they sent us, try the
2737                  * renames again.
2738                  */
2739                 softerr = recv_incremental_replication(hdl, tofs, flags,
2740                     stream_nv, stream_avl, NULL);
2741         }
2742 
2743 out:
2744         fsavl_destroy(stream_avl);
2745         if (stream_nv)
2746                 nvlist_free(stream_nv);
 
2870             token_buf, sizeof (token_buf),
2871             NULL, NULL, 0, B_TRUE);
2872         if (error == 0) {
2873                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2874                     "checksum mismatch or incomplete stream.\n"
2875                     "Partially received snapshot is saved.\n"
2876                     "A resuming stream can be generated on the sending "
2877                     "system by running:\n"
2878                     "    zfs send -t %s"),
2879                     token_buf);
2880         }
2881         zfs_close(zhp);
2882 }
2883 
2884 /*
2885  * Restores a backup of tosnap from the file descriptor specified by infd.
2886  */
2887 static int
2888 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2889     const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
2890     dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
2891     avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2892     uint64_t *action_handlep)
2893 {
2894         zfs_cmd_t zc = { 0 };
2895         time_t begin_time;
2896         int ioctl_err, ioctl_errno, err;
2897         char *cp;
2898         struct drr_begin *drrb = &drr->drr_u.drr_begin;
2899         char errbuf[1024];
2900         char prop_errbuf[1024];
2901         const char *chopprefix;
2902         boolean_t newfs = B_FALSE;
2903         boolean_t stream_wantsnewfs;
2904         uint64_t parent_snapguid = 0;
2905         prop_changelist_t *clp = NULL;
2906         nvlist_t *snapprops_nvlist = NULL;
2907         zprop_errflags_t prop_errflags;
2908         boolean_t recursive;
2909 
2910         begin_time = time(NULL);
2911 
2912         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2913             "cannot receive"));
2914 
2915         recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
2916             ENOENT);
2917 
2918         if (stream_avl != NULL) {
2919                 char *snapname;
2920                 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2921                     &snapname);
2922                 nvlist_t *props;
2923                 int ret;
2924 
2925                 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2926                     &parent_snapguid);
2927                 err = nvlist_lookup_nvlist(fs, "props", &props);
2928                 if (err)
2929                         VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2930 
2931                 if (flags->canmountoff) {
2932                         VERIFY(0 == nvlist_add_uint64(props,
2933                             zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2934                 }
2935                 ret = zcmd_write_src_nvlist(hdl, &zc, props);
2936                 if (err)
2937                         nvlist_free(props);
2938 
2939                 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
2940                         VERIFY(0 == nvlist_lookup_nvlist(props,
2941                             snapname, &snapprops_nvlist));
2942                 }
2943 
2944                 if (ret != 0)
2945                         return (-1);
2946         }
2947 
2948         cp = NULL;
2949 
2950         /*
2951          * Determine how much of the snapshot name stored in the stream
2952          * we are going to tack on to the name they specified on the
2953          * command line, and how much we are going to chop off.
2954          *
2955          * If they specified a snapshot, chop the entire name stored in
2956          * the stream.
 
2987                  * everything but the first element of the sent snapshot path
2988                  * (all but the pool name).
2989                  */
2990                 if (strchr(tosnap, '@')) {
2991                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2992                             "argument - snapshot not allowed with -d"));
2993                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2994                 }
2995 
2996                 chopprefix = strchr(drrb->drr_toname, '/');
2997                 if (chopprefix == NULL)
2998                         chopprefix = strchr(drrb->drr_toname, '@');
2999         } else if (strchr(tosnap, '@') == NULL) {
3000                 /*
3001                  * If a filesystem was specified without -d or -e, we want to
3002                  * tack on everything after the fs specified by 'zfs send'.
3003                  */
3004                 chopprefix = drrb->drr_toname + strlen(sendfs);
3005         } else {
3006                 /* A snapshot was specified as an exact path (no -d or -e). */
3007                 if (recursive) {
3008                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3009                             "cannot specify snapshot name for multi-snapshot "
3010                             "stream"));
3011                         return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3012                 }
3013                 chopprefix = drrb->drr_toname + strlen(drrb->drr_toname);
3014         }
3015 
3016         ASSERT(strstr(drrb->drr_toname, sendfs) == drrb->drr_toname);
3017         ASSERT(chopprefix > drrb->drr_toname);
3018         ASSERT(chopprefix <= drrb->drr_toname + strlen(drrb->drr_toname));
3019         ASSERT(chopprefix[0] == '/' || chopprefix[0] == '@' ||
3020             chopprefix[0] == '\0');
3021 
3022         /*
3023          * Determine name of destination snapshot, store in zc_value.
3024          */
3025         (void) strcpy(zc.zc_value, tosnap);
3026         (void) strncat(zc.zc_value, chopprefix, sizeof (zc.zc_value));
3027         free(cp);
 
3431                 char buf1[64];
3432                 char buf2[64];
3433                 uint64_t bytes = zc.zc_cookie;
3434                 time_t delta = time(NULL) - begin_time;
3435                 if (delta == 0)
3436                         delta = 1;
3437                 zfs_nicenum(bytes, buf1, sizeof (buf1));
3438                 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3439 
3440                 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3441                     buf1, delta, buf2);
3442         }
3443 
3444         return (0);
3445 }
3446 
3447 static int
3448 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
3449     const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
3450     nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
3451     uint64_t *action_handlep)
3452 {
3453         int err;
3454         dmu_replay_record_t drr, drr_noswap;
3455         struct drr_begin *drrb = &drr.drr_u.drr_begin;
3456         char errbuf[1024];
3457         zio_cksum_t zcksum = { 0 };
3458         uint64_t featureflags;
3459         int hdrtype;
3460 
3461         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3462             "cannot receive"));
3463 
3464         if (flags->isprefix &&
3465             !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3466                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3467                     "(%s) does not exist"), tosnap);
3468                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3469         }
3470         if (originsnap &&
3471             !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
 
3527 
3528         if (strchr(drrb->drr_toname, '@') == NULL) {
3529                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3530                     "stream (bad snapshot name)"));
3531                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3532         }
3533 
3534         if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3535                 char nonpackage_sendfs[ZFS_MAXNAMELEN];
3536                 if (sendfs == NULL) {
3537                         /*
3538                          * We were not called from zfs_receive_package(). Get
3539                          * the fs specified by 'zfs send'.
3540                          */
3541                         char *cp;
3542                         (void) strlcpy(nonpackage_sendfs,
3543                             drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3544                         if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3545                                 *cp = '\0';
3546                         sendfs = nonpackage_sendfs;
3547                 }
3548                 return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
3549                     &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
3550                     cleanup_fd, action_handlep));
3551         } else {
3552                 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3553                     DMU_COMPOUNDSTREAM);
3554                 return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
3555                     &zcksum, top_zfs, cleanup_fd, action_handlep));
3556         }
3557 }
3558 
3559 /*
3560  * Restores a backup of tosnap from the file descriptor specified by infd.
3561  * Return 0 on total success, -2 if some things couldn't be
3562  * destroyed/renamed/promoted, -1 if some things couldn't be received.
3563  * (-1 will override -2, if -1 and the resumable flag was specified the
3564  * transfer can be resumed if the sending side supports it).
3565  */
3566 int
3567 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
3568     recvflags_t *flags, int infd, avl_tree_t *stream_avl)
3569 {
3570         char *top_zfs = NULL;
3571         int err;
3572         int cleanup_fd;
3573         uint64_t action_handle = 0;
3574         char *originsnap = NULL;
3575         if (props) {
3576                 err = nvlist_lookup_string(props, "origin", &originsnap);
3577                 if (err && err != ENOENT)
3578                         return (err);
3579         }
3580 
3581         cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3582         VERIFY(cleanup_fd >= 0);
3583 
3584         err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
3585             stream_avl, &top_zfs, cleanup_fd, &action_handle);
3586 
3587         VERIFY(0 == close(cleanup_fd));
3588 
3589         if (err == 0 && !flags->nomount && top_zfs) {
3590                 zfs_handle_t *zhp;
3591                 prop_changelist_t *clp;
3592 
3593                 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3594                 if (zhp != NULL) {
3595                         clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3596                             CL_GATHER_MOUNT_ALWAYS, 0);
3597                         zfs_close(zhp);
3598                         if (clp != NULL) {
3599                                 /* mount and share received datasets */
3600                                 err = changelist_postfix(clp);
3601                                 changelist_free(clp);
3602                         }
3603                 }
3604                 if (zhp == NULL || clp == NULL || err)
3605                         err = -1;
 | 
 
 
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  25  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  26  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  27  * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
  28  */
  29 
  30 #include <assert.h>
  31 #include <ctype.h>
  32 #include <errno.h>
  33 #include <libintl.h>
  34 #include <stdio.h>
  35 #include <stdlib.h>
  36 #include <strings.h>
  37 #include <unistd.h>
  38 #include <stddef.h>
  39 #include <fcntl.h>
  40 #include <sys/mount.h>
  41 #include <pthread.h>
  42 #include <umem.h>
  43 #include <time.h>
  44 
  45 #include <libzfs.h>
  46 #include <libzfs_core.h>
  47 
  48 #include "zfs_namecheck.h"
  49 #include "zfs_prop.h"
  50 #include "zfs_fletcher.h"
  51 #include "libzfs_impl.h"
  52 #include <zlib.h>
  53 #include <sha2.h>
  54 #include <sys/zio_checksum.h>
  55 #include <sys/ddt.h>
  56 
  57 /* in libzfs_dataset.c */
  58 extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
  59 
  60 static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
  61     recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
  62     uint64_t *, const char *);
  63 static int guid_to_name(libzfs_handle_t *, const char *,
  64     uint64_t, boolean_t, char *);
  65 
  66 static const zio_cksum_t zero_cksum = { 0 };
  67 
  68 typedef struct dedup_arg {
  69         int     inputfd;
  70         int     outputfd;
  71         libzfs_handle_t  *dedup_hdl;
  72 } dedup_arg_t;
  73 
  74 typedef struct progress_arg {
  75         zfs_handle_t *pa_zhp;
  76         int pa_fd;
  77         boolean_t pa_parsable;
  78 } progress_arg_t;
  79 
  80 typedef struct dataref {
  81         uint64_t ref_guid;
  82         uint64_t ref_object;
 
2545         nvlist_free(local_nv);
2546 
2547         if (needagain && progress) {
2548                 /* do another pass to fix up temporary names */
2549                 if (flags->verbose)
2550                         (void) printf("another pass:\n");
2551                 goto again;
2552         }
2553 
2554         return (needagain);
2555 }
2556 
2557 static int
2558 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
2559     recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
2560     char **top_zfs, int cleanup_fd, uint64_t *action_handlep)
2561 {
2562         nvlist_t *stream_nv = NULL;
2563         avl_tree_t *stream_avl = NULL;
2564         char *fromsnap = NULL;
2565         char *sendsnap = NULL;
2566         char *cp;
2567         char tofs[ZFS_MAXNAMELEN];
2568         char sendfs[ZFS_MAXNAMELEN];
2569         char errbuf[1024];
2570         dmu_replay_record_t drre;
2571         int error;
2572         boolean_t anyerr = B_FALSE;
2573         boolean_t softerr = B_FALSE;
2574         boolean_t recursive;
2575 
2576         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2577             "cannot receive"));
2578 
2579         assert(drr->drr_type == DRR_BEGIN);
2580         assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
2581         assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
2582             DMU_COMPOUNDSTREAM);
2583 
2584         /*
2585          * Read in the nvlist from the stream.
 
2694                                         zfs_close(zhp);
2695                                         if (clp != NULL) {
2696                                                 softerr |=
2697                                                     changelist_prefix(clp);
2698                                                 changelist_free(clp);
2699                                         }
2700                                 }
2701                         }
2702 
2703                         nvlist_free(renamed);
2704                 }
2705         }
2706 
2707         /*
2708          * Get the fs specified by the first path in the stream (the top level
2709          * specified by 'zfs send') and pass it to each invocation of
2710          * zfs_receive_one().
2711          */
2712         (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
2713             ZFS_MAXNAMELEN);
2714         if ((cp = strchr(sendfs, '@')) != NULL) {
2715                 *cp = '\0';
2716                 /*
2717                  * Find the "sendsnap", the final snapshot in a replication
2718                  * stream, so zfs_receive_one() can set filesystem properties
2719                  * ONLY when receiving that final snapshot.
2720                  */
2721                 sendsnap = (cp + 1);
2722         }
2723 
2724         /* Finally, receive each contained stream */
2725         do {
2726                 /*
2727                  * we should figure out if it has a recoverable
2728                  * error, in which case do a recv_skip() and drive on.
2729                  * Note, if we fail due to already having this guid,
2730                  * zfs_receive_one() will take care of it (ie,
2731                  * recv_skip() and return 0).
2732                  */
2733                 error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
2734                     sendfs, stream_nv, stream_avl, top_zfs, cleanup_fd,
2735                     action_handlep, sendsnap);
2736                 if (error == ENODATA) {
2737                         error = 0;
2738                         break;
2739                 }
2740                 anyerr |= error;
2741         } while (error == 0);
2742 
2743         if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
2744                 /*
2745                  * Now that we have the fs's they sent us, try the
2746                  * renames again.
2747                  */
2748                 softerr = recv_incremental_replication(hdl, tofs, flags,
2749                     stream_nv, stream_avl, NULL);
2750         }
2751 
2752 out:
2753         fsavl_destroy(stream_avl);
2754         if (stream_nv)
2755                 nvlist_free(stream_nv);
 
2879             token_buf, sizeof (token_buf),
2880             NULL, NULL, 0, B_TRUE);
2881         if (error == 0) {
2882                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2883                     "checksum mismatch or incomplete stream.\n"
2884                     "Partially received snapshot is saved.\n"
2885                     "A resuming stream can be generated on the sending "
2886                     "system by running:\n"
2887                     "    zfs send -t %s"),
2888                     token_buf);
2889         }
2890         zfs_close(zhp);
2891 }
2892 
2893 /*
2894  * Restores a backup of tosnap from the file descriptor specified by infd.
2895  */
2896 static int
2897 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
2898     const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
2899     dmu_replay_record_t *drr_noswap, const char *sendfs,
2900     avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
2901     uint64_t *action_handlep, const char *finalsnap)
2902 {
2903         zfs_cmd_t zc = { 0 };
2904         time_t begin_time;
2905         int ioctl_err, ioctl_errno, err;
2906         char *cp;
2907         struct drr_begin *drrb = &drr->drr_u.drr_begin;
2908         char errbuf[1024];
2909         char prop_errbuf[1024];
2910         const char *chopprefix;
2911         boolean_t newfs = B_FALSE;
2912         boolean_t stream_wantsnewfs;
2913         uint64_t parent_snapguid = 0;
2914         prop_changelist_t *clp = NULL;
2915         nvlist_t *snapprops_nvlist = NULL;
2916         zprop_errflags_t prop_errflags;
2917 
2918         begin_time = time(NULL);
2919 
2920         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2921             "cannot receive"));
2922 
2923         if (stream_avl != NULL) {
2924                 char *snapname;
2925                 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
2926                     &snapname);
2927                 nvlist_t *props;
2928                 int ret;
2929                 boolean_t is_finalsnap;
2930 
2931                 VERIFY(fs != NULL);
2932                 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
2933                     &parent_snapguid);
2934                 /*
2935                  * Can safely use strcmp because at least "snapname" has been
2936                  * verified.
2937                  */
2938                 is_finalsnap = (strcmp(snapname, finalsnap) == 0);
2939 
2940                 if (is_finalsnap)
2941                         err = nvlist_lookup_nvlist(fs, "props", &props);
2942                 if (!is_finalsnap || err)
2943                         VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
2944 
2945                 if (flags->canmountoff) {
2946                         VERIFY(0 == nvlist_add_uint64(props,
2947                             zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
2948                 }
2949                 ret = zcmd_write_src_nvlist(hdl, &zc, props);
2950                 if (!is_finalsnap || err)
2951                         nvlist_free(props);
2952 
2953                 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
2954                         VERIFY(0 == nvlist_lookup_nvlist(props,
2955                             snapname, &snapprops_nvlist));
2956                 }
2957 
2958                 if (ret != 0)
2959                         return (-1);
2960         }
2961 
2962         cp = NULL;
2963 
2964         /*
2965          * Determine how much of the snapshot name stored in the stream
2966          * we are going to tack on to the name they specified on the
2967          * command line, and how much we are going to chop off.
2968          *
2969          * If they specified a snapshot, chop the entire name stored in
2970          * the stream.
 
3001                  * everything but the first element of the sent snapshot path
3002                  * (all but the pool name).
3003                  */
3004                 if (strchr(tosnap, '@')) {
3005                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3006                             "argument - snapshot not allowed with -d"));
3007                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3008                 }
3009 
3010                 chopprefix = strchr(drrb->drr_toname, '/');
3011                 if (chopprefix == NULL)
3012                         chopprefix = strchr(drrb->drr_toname, '@');
3013         } else if (strchr(tosnap, '@') == NULL) {
3014                 /*
3015                  * If a filesystem was specified without -d or -e, we want to
3016                  * tack on everything after the fs specified by 'zfs send'.
3017                  */
3018                 chopprefix = drrb->drr_toname + strlen(sendfs);
3019         } else {
3020                 /* A snapshot was specified as an exact path (no -d or -e). */
3021                 if (flags->recursive) {
3022                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3023                             "cannot specify snapshot name for multi-snapshot "
3024                             "stream"));
3025                         return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3026                 }
3027                 chopprefix = drrb->drr_toname + strlen(drrb->drr_toname);
3028         }
3029 
3030         ASSERT(strstr(drrb->drr_toname, sendfs) == drrb->drr_toname);
3031         ASSERT(chopprefix > drrb->drr_toname);
3032         ASSERT(chopprefix <= drrb->drr_toname + strlen(drrb->drr_toname));
3033         ASSERT(chopprefix[0] == '/' || chopprefix[0] == '@' ||
3034             chopprefix[0] == '\0');
3035 
3036         /*
3037          * Determine name of destination snapshot, store in zc_value.
3038          */
3039         (void) strcpy(zc.zc_value, tosnap);
3040         (void) strncat(zc.zc_value, chopprefix, sizeof (zc.zc_value));
3041         free(cp);
 
3445                 char buf1[64];
3446                 char buf2[64];
3447                 uint64_t bytes = zc.zc_cookie;
3448                 time_t delta = time(NULL) - begin_time;
3449                 if (delta == 0)
3450                         delta = 1;
3451                 zfs_nicenum(bytes, buf1, sizeof (buf1));
3452                 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
3453 
3454                 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
3455                     buf1, delta, buf2);
3456         }
3457 
3458         return (0);
3459 }
3460 
3461 static int
3462 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
3463     const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
3464     nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs, int cleanup_fd,
3465     uint64_t *action_handlep, const char *finalsnap)
3466 {
3467         int err;
3468         dmu_replay_record_t drr, drr_noswap;
3469         struct drr_begin *drrb = &drr.drr_u.drr_begin;
3470         char errbuf[1024];
3471         zio_cksum_t zcksum = { 0 };
3472         uint64_t featureflags;
3473         int hdrtype;
3474 
3475         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3476             "cannot receive"));
3477 
3478         if (flags->isprefix &&
3479             !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
3480                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
3481                     "(%s) does not exist"), tosnap);
3482                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
3483         }
3484         if (originsnap &&
3485             !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
 
3541 
3542         if (strchr(drrb->drr_toname, '@') == NULL) {
3543                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
3544                     "stream (bad snapshot name)"));
3545                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
3546         }
3547 
3548         if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
3549                 char nonpackage_sendfs[ZFS_MAXNAMELEN];
3550                 if (sendfs == NULL) {
3551                         /*
3552                          * We were not called from zfs_receive_package(). Get
3553                          * the fs specified by 'zfs send'.
3554                          */
3555                         char *cp;
3556                         (void) strlcpy(nonpackage_sendfs,
3557                             drr.drr_u.drr_begin.drr_toname, ZFS_MAXNAMELEN);
3558                         if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
3559                                 *cp = '\0';
3560                         sendfs = nonpackage_sendfs;
3561                         VERIFY(finalsnap == NULL);
3562                 }
3563                 flags->recursive =
3564                     (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
3565                     ENOENT);
3566                 err = zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
3567                     &drr, &drr_noswap, sendfs, stream_avl, top_zfs,
3568                     cleanup_fd, action_handlep, finalsnap);
3569                 /* Clear out internal-only flags. */
3570                 flags->recursive = B_FALSE;
3571                 return (err);
3572         } else {
3573                 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
3574                     DMU_COMPOUNDSTREAM);
3575                 return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
3576                     &zcksum, top_zfs, cleanup_fd, action_handlep));
3577         }
3578 }
3579 
3580 /*
3581  * Restores a backup of tosnap from the file descriptor specified by infd.
3582  * Return 0 on total success, -2 if some things couldn't be
3583  * destroyed/renamed/promoted, -1 if some things couldn't be received.
3584  * (-1 will override -2, if -1 and the resumable flag was specified the
3585  * transfer can be resumed if the sending side supports it).
3586  */
3587 int
3588 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
3589     recvflags_t *flags, int infd, avl_tree_t *stream_avl)
3590 {
3591         char *top_zfs = NULL;
3592         int err;
3593         int cleanup_fd;
3594         uint64_t action_handle = 0;
3595         char *originsnap = NULL;
3596         if (props) {
3597                 err = nvlist_lookup_string(props, "origin", &originsnap);
3598                 if (err && err != ENOENT)
3599                         return (err);
3600         }
3601 
3602         cleanup_fd = open(ZFS_DEV, O_RDWR|O_EXCL);
3603         VERIFY(cleanup_fd >= 0);
3604 
3605         err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
3606             stream_avl, &top_zfs, cleanup_fd, &action_handle, NULL);
3607 
3608         VERIFY(0 == close(cleanup_fd));
3609 
3610         if (err == 0 && !flags->nomount && top_zfs) {
3611                 zfs_handle_t *zhp;
3612                 prop_changelist_t *clp;
3613 
3614                 zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
3615                 if (zhp != NULL) {
3616                         clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
3617                             CL_GATHER_MOUNT_ALWAYS, 0);
3618                         zfs_close(zhp);
3619                         if (clp != NULL) {
3620                                 /* mount and share received datasets */
3621                                 err = changelist_postfix(clp);
3622                                 changelist_free(clp);
3623                         }
3624                 }
3625                 if (zhp == NULL || clp == NULL || err)
3626                         err = -1;
 |