The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/lib/libzfs/libzfs_sendrecv.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   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, 2020 by Delphix. All rights reserved.
   25  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
   26  * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
   27  * All rights reserved
   28  * Copyright (c) 2013 Steven Hartland. All rights reserved.
   29  * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
   30  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
   31  * Copyright (c) 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
   32  * Copyright (c) 2019 Datto Inc.
   33  */
   34 
   35 #include <assert.h>
   36 #include <ctype.h>
   37 #include <errno.h>
   38 #include <libintl.h>
   39 #include <stdio.h>
   40 #include <stdlib.h>
   41 #include <string.h>
   42 #include <unistd.h>
   43 #include <stddef.h>
   44 #include <fcntl.h>
   45 #include <sys/mount.h>
   46 #include <sys/mntent.h>
   47 #include <sys/mnttab.h>
   48 #include <sys/avl.h>
   49 #include <sys/debug.h>
   50 #include <sys/stat.h>
   51 #include <pthread.h>
   52 #include <umem.h>
   53 #include <time.h>
   54 
   55 #include <libzfs.h>
   56 #include <libzfs_core.h>
   57 #include <libzutil.h>
   58 
   59 #include "zfs_namecheck.h"
   60 #include "zfs_prop.h"
   61 #include "zfs_fletcher.h"
   62 #include "libzfs_impl.h"
   63 #include <cityhash.h>
   64 #include <zlib.h>
   65 #include <sys/zio_checksum.h>
   66 #include <sys/dsl_crypt.h>
   67 #include <sys/ddt.h>
   68 #include <sys/socket.h>
   69 #include <sys/sha2.h>
   70 
   71 static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
   72     recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **,
   73     const char *, nvlist_t *);
   74 static int guid_to_name_redact_snaps(libzfs_handle_t *hdl, const char *parent,
   75     uint64_t guid, boolean_t bookmark_ok, uint64_t *redact_snap_guids,
   76     uint64_t num_redact_snaps, char *name);
   77 static int guid_to_name(libzfs_handle_t *, const char *,
   78     uint64_t, boolean_t, char *);
   79 
   80 typedef struct progress_arg {
   81         zfs_handle_t *pa_zhp;
   82         int pa_fd;
   83         boolean_t pa_parsable;
   84         boolean_t pa_estimate;
   85         int pa_verbosity;
   86         boolean_t pa_astitle;
   87         uint64_t pa_size;
   88 } progress_arg_t;
   89 
   90 static int
   91 dump_record(dmu_replay_record_t *drr, void *payload, size_t payload_len,
   92     zio_cksum_t *zc, int outfd)
   93 {
   94         ASSERT3U(offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum),
   95             ==, sizeof (dmu_replay_record_t) - sizeof (zio_cksum_t));
   96         fletcher_4_incremental_native(drr,
   97             offsetof(dmu_replay_record_t, drr_u.drr_checksum.drr_checksum), zc);
   98         if (drr->drr_type != DRR_BEGIN) {
   99                 ASSERT(ZIO_CHECKSUM_IS_ZERO(&drr->drr_u.
  100                     drr_checksum.drr_checksum));
  101                 drr->drr_u.drr_checksum.drr_checksum = *zc;
  102         }
  103         fletcher_4_incremental_native(&drr->drr_u.drr_checksum.drr_checksum,
  104             sizeof (zio_cksum_t), zc);
  105         if (write(outfd, drr, sizeof (*drr)) == -1)
  106                 return (errno);
  107         if (payload_len != 0) {
  108                 fletcher_4_incremental_native(payload, payload_len, zc);
  109                 if (write(outfd, payload, payload_len) == -1)
  110                         return (errno);
  111         }
  112         return (0);
  113 }
  114 
  115 /*
  116  * Routines for dealing with the AVL tree of fs-nvlists
  117  */
  118 typedef struct fsavl_node {
  119         avl_node_t fn_node;
  120         nvlist_t *fn_nvfs;
  121         char *fn_snapname;
  122         uint64_t fn_guid;
  123 } fsavl_node_t;
  124 
  125 static int
  126 fsavl_compare(const void *arg1, const void *arg2)
  127 {
  128         const fsavl_node_t *fn1 = (const fsavl_node_t *)arg1;
  129         const fsavl_node_t *fn2 = (const fsavl_node_t *)arg2;
  130 
  131         return (TREE_CMP(fn1->fn_guid, fn2->fn_guid));
  132 }
  133 
  134 /*
  135  * Given the GUID of a snapshot, find its containing filesystem and
  136  * (optionally) name.
  137  */
  138 static nvlist_t *
  139 fsavl_find(avl_tree_t *avl, uint64_t snapguid, char **snapname)
  140 {
  141         fsavl_node_t fn_find;
  142         fsavl_node_t *fn;
  143 
  144         fn_find.fn_guid = snapguid;
  145 
  146         fn = avl_find(avl, &fn_find, NULL);
  147         if (fn) {
  148                 if (snapname)
  149                         *snapname = fn->fn_snapname;
  150                 return (fn->fn_nvfs);
  151         }
  152         return (NULL);
  153 }
  154 
  155 static void
  156 fsavl_destroy(avl_tree_t *avl)
  157 {
  158         fsavl_node_t *fn;
  159         void *cookie;
  160 
  161         if (avl == NULL)
  162                 return;
  163 
  164         cookie = NULL;
  165         while ((fn = avl_destroy_nodes(avl, &cookie)) != NULL)
  166                 free(fn);
  167         avl_destroy(avl);
  168         free(avl);
  169 }
  170 
  171 /*
  172  * Given an nvlist, produce an avl tree of snapshots, ordered by guid
  173  */
  174 static avl_tree_t *
  175 fsavl_create(nvlist_t *fss)
  176 {
  177         avl_tree_t *fsavl;
  178         nvpair_t *fselem = NULL;
  179 
  180         if ((fsavl = malloc(sizeof (avl_tree_t))) == NULL)
  181                 return (NULL);
  182 
  183         avl_create(fsavl, fsavl_compare, sizeof (fsavl_node_t),
  184             offsetof(fsavl_node_t, fn_node));
  185 
  186         while ((fselem = nvlist_next_nvpair(fss, fselem)) != NULL) {
  187                 nvlist_t *nvfs, *snaps;
  188                 nvpair_t *snapelem = NULL;
  189 
  190                 nvfs = fnvpair_value_nvlist(fselem);
  191                 snaps = fnvlist_lookup_nvlist(nvfs, "snaps");
  192 
  193                 while ((snapelem =
  194                     nvlist_next_nvpair(snaps, snapelem)) != NULL) {
  195                         fsavl_node_t *fn;
  196 
  197                         if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) {
  198                                 fsavl_destroy(fsavl);
  199                                 return (NULL);
  200                         }
  201                         fn->fn_nvfs = nvfs;
  202                         fn->fn_snapname = nvpair_name(snapelem);
  203                         fn->fn_guid = fnvpair_value_uint64(snapelem);
  204 
  205                         /*
  206                          * Note: if there are multiple snaps with the
  207                          * same GUID, we ignore all but one.
  208                          */
  209                         avl_index_t where = 0;
  210                         if (avl_find(fsavl, fn, &where) == NULL)
  211                                 avl_insert(fsavl, fn, where);
  212                         else
  213                                 free(fn);
  214                 }
  215         }
  216 
  217         return (fsavl);
  218 }
  219 
  220 /*
  221  * Routines for dealing with the giant nvlist of fs-nvlists, etc.
  222  */
  223 typedef struct send_data {
  224         /*
  225          * assigned inside every recursive call,
  226          * restored from *_save on return:
  227          *
  228          * guid of fromsnap snapshot in parent dataset
  229          * txg of fromsnap snapshot in current dataset
  230          * txg of tosnap snapshot in current dataset
  231          */
  232 
  233         uint64_t parent_fromsnap_guid;
  234         uint64_t fromsnap_txg;
  235         uint64_t tosnap_txg;
  236 
  237         /* the nvlists get accumulated during depth-first traversal */
  238         nvlist_t *parent_snaps;
  239         nvlist_t *fss;
  240         nvlist_t *snapprops;
  241         nvlist_t *snapholds;    /* user holds */
  242 
  243         /* send-receive configuration, does not change during traversal */
  244         const char *fsname;
  245         const char *fromsnap;
  246         const char *tosnap;
  247         boolean_t recursive;
  248         boolean_t raw;
  249         boolean_t doall;
  250         boolean_t replicate;
  251         boolean_t skipmissing;
  252         boolean_t verbose;
  253         boolean_t backup;
  254         boolean_t seenfrom;
  255         boolean_t seento;
  256         boolean_t holds;        /* were holds requested with send -h */
  257         boolean_t props;
  258 
  259         /*
  260          * The header nvlist is of the following format:
  261          * {
  262          *   "tosnap" -> string
  263          *   "fromsnap" -> string (if incremental)
  264          *   "fss" -> {
  265          *      id -> {
  266          *
  267          *       "name" -> string (full name; for debugging)
  268          *       "parentfromsnap" -> number (guid of fromsnap in parent)
  269          *
  270          *       "props" -> { name -> value (only if set here) }
  271          *       "snaps" -> { name (lastname) -> number (guid) }
  272          *       "snapprops" -> { name (lastname) -> { name -> value } }
  273          *       "snapholds" -> { name (lastname) -> { holdname -> crtime } }
  274          *
  275          *       "origin" -> number (guid) (if clone)
  276          *       "is_encroot" -> boolean
  277          *       "sent" -> boolean (not on-disk)
  278          *      }
  279          *   }
  280          * }
  281          *
  282          */
  283 } send_data_t;
  284 
  285 static void
  286 send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv);
  287 
  288 /*
  289  * Collect guid, valid props, optionally holds, etc. of a snapshot.
  290  * This interface is intended for use as a zfs_iter_snapshots_sorted visitor.
  291  */
  292 static int
  293 send_iterate_snap(zfs_handle_t *zhp, void *arg)
  294 {
  295         send_data_t *sd = arg;
  296         uint64_t guid = zhp->zfs_dmustats.dds_guid;
  297         uint64_t txg = zhp->zfs_dmustats.dds_creation_txg;
  298         boolean_t isfromsnap, istosnap, istosnapwithnofrom;
  299         char *snapname;
  300         const char *from = sd->fromsnap;
  301         const char *to = sd->tosnap;
  302 
  303         snapname = strrchr(zhp->zfs_name, '@');
  304         assert(snapname != NULL);
  305         ++snapname;
  306 
  307         isfromsnap = (from != NULL && strcmp(from, snapname) == 0);
  308         istosnap = (to != NULL && strcmp(to, snapname) == 0);
  309         istosnapwithnofrom = (istosnap && from == NULL);
  310 
  311         if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) {
  312                 if (sd->verbose) {
  313                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
  314                             "skipping snapshot %s because it was created "
  315                             "after the destination snapshot (%s)\n"),
  316                             zhp->zfs_name, to);
  317                 }
  318                 zfs_close(zhp);
  319                 return (0);
  320         }
  321 
  322         fnvlist_add_uint64(sd->parent_snaps, snapname, guid);
  323 
  324         /*
  325          * NB: if there is no fromsnap here (it's a newly created fs in
  326          * an incremental replication), we will substitute the tosnap.
  327          */
  328         if (isfromsnap || (sd->parent_fromsnap_guid == 0 && istosnap))
  329                 sd->parent_fromsnap_guid = guid;
  330 
  331         if (!sd->recursive) {
  332                 /*
  333                  * To allow a doall stream to work properly
  334                  * with a NULL fromsnap
  335                  */
  336                 if (sd->doall && from == NULL && !sd->seenfrom)
  337                         sd->seenfrom = B_TRUE;
  338 
  339                 if (!sd->seenfrom && isfromsnap) {
  340                         sd->seenfrom = B_TRUE;
  341                         zfs_close(zhp);
  342                         return (0);
  343                 }
  344 
  345                 if ((sd->seento || !sd->seenfrom) && !istosnapwithnofrom) {
  346                         zfs_close(zhp);
  347                         return (0);
  348                 }
  349 
  350                 if (istosnap)
  351                         sd->seento = B_TRUE;
  352         }
  353 
  354         nvlist_t *nv = fnvlist_alloc();
  355         send_iterate_prop(zhp, sd->backup, nv);
  356         fnvlist_add_nvlist(sd->snapprops, snapname, nv);
  357         fnvlist_free(nv);
  358 
  359         if (sd->holds) {
  360                 nvlist_t *holds;
  361                 if (lzc_get_holds(zhp->zfs_name, &holds) == 0) {
  362                         fnvlist_add_nvlist(sd->snapholds, snapname, holds);
  363                         fnvlist_free(holds);
  364                 }
  365         }
  366 
  367         zfs_close(zhp);
  368         return (0);
  369 }
  370 
  371 /*
  372  * Collect all valid props from the handle snap into an nvlist.
  373  */
  374 static void
  375 send_iterate_prop(zfs_handle_t *zhp, boolean_t received_only, nvlist_t *nv)
  376 {
  377         nvlist_t *props;
  378 
  379         if (received_only)
  380                 props = zfs_get_recvd_props(zhp);
  381         else
  382                 props = zhp->zfs_props;
  383 
  384         nvpair_t *elem = NULL;
  385         while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
  386                 char *propname = nvpair_name(elem);
  387                 zfs_prop_t prop = zfs_name_to_prop(propname);
  388 
  389                 if (!zfs_prop_user(propname)) {
  390                         /*
  391                          * Realistically, this should never happen.  However,
  392                          * we want the ability to add DSL properties without
  393                          * needing to make incompatible version changes.  We
  394                          * need to ignore unknown properties to allow older
  395                          * software to still send datasets containing these
  396                          * properties, with the unknown properties elided.
  397                          */
  398                         if (prop == ZPROP_INVAL)
  399                                 continue;
  400 
  401                         if (zfs_prop_readonly(prop))
  402                                 continue;
  403                 }
  404 
  405                 nvlist_t *propnv = fnvpair_value_nvlist(elem);
  406 
  407                 boolean_t isspacelimit = (prop == ZFS_PROP_QUOTA ||
  408                     prop == ZFS_PROP_RESERVATION ||
  409                     prop == ZFS_PROP_REFQUOTA ||
  410                     prop == ZFS_PROP_REFRESERVATION);
  411                 if (isspacelimit && zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
  412                         continue;
  413 
  414                 char *source;
  415                 if (nvlist_lookup_string(propnv, ZPROP_SOURCE, &source) == 0) {
  416                         if (strcmp(source, zhp->zfs_name) != 0 &&
  417                             strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0)
  418                                 continue;
  419                 } else {
  420                         /*
  421                          * May have no source before SPA_VERSION_RECVD_PROPS,
  422                          * but is still modifiable.
  423                          */
  424                         if (!isspacelimit)
  425                                 continue;
  426                 }
  427 
  428                 if (zfs_prop_user(propname) ||
  429                     zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
  430                         char *value;
  431                         value = fnvlist_lookup_string(propnv, ZPROP_VALUE);
  432                         fnvlist_add_string(nv, propname, value);
  433                 } else {
  434                         uint64_t value;
  435                         value = fnvlist_lookup_uint64(propnv, ZPROP_VALUE);
  436                         fnvlist_add_uint64(nv, propname, value);
  437                 }
  438         }
  439 }
  440 
  441 /*
  442  * returns snapshot guid
  443  * and returns 0 if the snapshot does not exist
  444  */
  445 static uint64_t
  446 get_snap_guid(libzfs_handle_t *hdl, const char *fs, const char *snap)
  447 {
  448         char name[MAXPATHLEN + 1];
  449         uint64_t guid = 0;
  450 
  451         if (fs == NULL || fs[0] == '\0' || snap == NULL || snap[0] == '\0')
  452                 return (guid);
  453 
  454         (void) snprintf(name, sizeof (name), "%s@%s", fs, snap);
  455         zfs_handle_t *zhp = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT);
  456         if (zhp != NULL) {
  457                 guid = zfs_prop_get_int(zhp, ZFS_PROP_GUID);
  458                 zfs_close(zhp);
  459         }
  460 
  461         return (guid);
  462 }
  463 
  464 /*
  465  * returns snapshot creation txg
  466  * and returns 0 if the snapshot does not exist
  467  */
  468 static uint64_t
  469 get_snap_txg(libzfs_handle_t *hdl, const char *fs, const char *snap)
  470 {
  471         char name[ZFS_MAX_DATASET_NAME_LEN];
  472         uint64_t txg = 0;
  473 
  474         if (fs == NULL || fs[0] == '\0' || snap == NULL || snap[0] == '\0')
  475                 return (txg);
  476 
  477         (void) snprintf(name, sizeof (name), "%s@%s", fs, snap);
  478         if (zfs_dataset_exists(hdl, name, ZFS_TYPE_SNAPSHOT)) {
  479                 zfs_handle_t *zhp = zfs_open(hdl, name, ZFS_TYPE_SNAPSHOT);
  480                 if (zhp != NULL) {
  481                         txg = zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG);
  482                         zfs_close(zhp);
  483                 }
  484         }
  485 
  486         return (txg);
  487 }
  488 
  489 /*
  490  * Recursively generate nvlists describing datasets.  See comment
  491  * for the data structure send_data_t above for description of contents
  492  * of the nvlist.
  493  */
  494 static int
  495 send_iterate_fs(zfs_handle_t *zhp, void *arg)
  496 {
  497         send_data_t *sd = arg;
  498         nvlist_t *nvfs = NULL, *nv = NULL;
  499         int rv = 0;
  500         uint64_t min_txg = 0, max_txg = 0;
  501         uint64_t txg = zhp->zfs_dmustats.dds_creation_txg;
  502         uint64_t guid = zhp->zfs_dmustats.dds_guid;
  503         uint64_t fromsnap_txg, tosnap_txg;
  504         char guidstring[64];
  505 
  506         /* These fields are restored on return from a recursive call. */
  507         uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid;
  508         uint64_t fromsnap_txg_save = sd->fromsnap_txg;
  509         uint64_t tosnap_txg_save = sd->tosnap_txg;
  510 
  511         fromsnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->fromsnap);
  512         if (fromsnap_txg != 0)
  513                 sd->fromsnap_txg = fromsnap_txg;
  514 
  515         tosnap_txg = get_snap_txg(zhp->zfs_hdl, zhp->zfs_name, sd->tosnap);
  516         if (tosnap_txg != 0)
  517                 sd->tosnap_txg = tosnap_txg;
  518 
  519         /*
  520          * On the send side, if the current dataset does not have tosnap,
  521          * perform two additional checks:
  522          *
  523          * - Skip sending the current dataset if it was created later than
  524          *   the parent tosnap.
  525          * - Return error if the current dataset was created earlier than
  526          *   the parent tosnap, unless --skip-missing specified. Then
  527          *   just print a warning.
  528          */
  529         if (sd->tosnap != NULL && tosnap_txg == 0) {
  530                 if (sd->tosnap_txg != 0 && txg > sd->tosnap_txg) {
  531                         if (sd->verbose) {
  532                                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
  533                                     "skipping dataset %s: snapshot %s does "
  534                                     "not exist\n"), zhp->zfs_name, sd->tosnap);
  535                         }
  536                 } else if (sd->skipmissing) {
  537                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
  538                             "WARNING: skipping dataset %s and its children:"
  539                             " snapshot %s does not exist\n"),
  540                             zhp->zfs_name, sd->tosnap);
  541                 } else {
  542                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
  543                             "cannot send %s@%s%s: snapshot %s@%s does not "
  544                             "exist\n"), sd->fsname, sd->tosnap, sd->recursive ?
  545                             dgettext(TEXT_DOMAIN, " recursively") : "",
  546                             zhp->zfs_name, sd->tosnap);
  547                         rv = EZFS_NOENT;
  548                 }
  549                 goto out;
  550         }
  551 
  552         nvfs = fnvlist_alloc();
  553         fnvlist_add_string(nvfs, "name", zhp->zfs_name);
  554         fnvlist_add_uint64(nvfs, "parentfromsnap", sd->parent_fromsnap_guid);
  555 
  556         if (zhp->zfs_dmustats.dds_origin[0] != '\0') {
  557                 zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
  558                     zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
  559                 if (origin == NULL) {
  560                         rv = -1;
  561                         goto out;
  562                 }
  563                 fnvlist_add_uint64(nvfs, "origin",
  564                     origin->zfs_dmustats.dds_guid);
  565                 zfs_close(origin);
  566         }
  567 
  568         /* Iterate over props. */
  569         if (sd->props || sd->backup || sd->recursive) {
  570                 nv = fnvlist_alloc();
  571                 send_iterate_prop(zhp, sd->backup, nv);
  572                 fnvlist_add_nvlist(nvfs, "props", nv);
  573         }
  574         if (zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) != ZIO_CRYPT_OFF) {
  575                 boolean_t encroot;
  576 
  577                 /* Determine if this dataset is an encryption root. */
  578                 if (zfs_crypto_get_encryption_root(zhp, &encroot, NULL) != 0) {
  579                         rv = -1;
  580                         goto out;
  581                 }
  582 
  583                 if (encroot)
  584                         fnvlist_add_boolean(nvfs, "is_encroot");
  585 
  586                 /*
  587                  * Encrypted datasets can only be sent with properties if
  588                  * the raw flag is specified because the receive side doesn't
  589                  * currently have a mechanism for recursively asking the user
  590                  * for new encryption parameters.
  591                  */
  592                 if (!sd->raw) {
  593                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
  594                             "cannot send %s@%s: encrypted dataset %s may not "
  595                             "be sent with properties without the raw flag\n"),
  596                             sd->fsname, sd->tosnap, zhp->zfs_name);
  597                         rv = -1;
  598                         goto out;
  599                 }
  600 
  601         }
  602 
  603         /*
  604          * Iterate over snaps, and set sd->parent_fromsnap_guid.
  605          *
  606          * If this is a "doall" send, a replicate send or we're just trying
  607          * to gather a list of previous snapshots, iterate through all the
  608          * snaps in the txg range. Otherwise just look at the one we're
  609          * interested in.
  610          */
  611         sd->parent_fromsnap_guid = 0;
  612         sd->parent_snaps = fnvlist_alloc();
  613         sd->snapprops = fnvlist_alloc();
  614         if (sd->holds)
  615                 sd->snapholds = fnvlist_alloc();
  616         if (sd->doall || sd->replicate || sd->tosnap == NULL) {
  617                 if (!sd->replicate && fromsnap_txg != 0)
  618                         min_txg = fromsnap_txg;
  619                 if (!sd->replicate && tosnap_txg != 0)
  620                         max_txg = tosnap_txg;
  621                 (void) zfs_iter_snapshots_sorted(zhp, 0, send_iterate_snap, sd,
  622                     min_txg, max_txg);
  623         } else {
  624                 char snapname[MAXPATHLEN] = { 0 };
  625                 zfs_handle_t *snap;
  626 
  627                 (void) snprintf(snapname, sizeof (snapname), "%s@%s",
  628                     zhp->zfs_name, sd->tosnap);
  629                 if (sd->fromsnap != NULL)
  630                         sd->seenfrom = B_TRUE;
  631                 snap = zfs_open(zhp->zfs_hdl, snapname, ZFS_TYPE_SNAPSHOT);
  632                 if (snap != NULL)
  633                         (void) send_iterate_snap(snap, sd);
  634         }
  635 
  636         fnvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps);
  637         fnvlist_free(sd->parent_snaps);
  638         fnvlist_add_nvlist(nvfs, "snapprops", sd->snapprops);
  639         fnvlist_free(sd->snapprops);
  640         if (sd->holds) {
  641                 fnvlist_add_nvlist(nvfs, "snapholds", sd->snapholds);
  642                 fnvlist_free(sd->snapholds);
  643         }
  644 
  645         /* Do not allow the size of the properties list to exceed the limit */
  646         if ((fnvlist_size(nvfs) + fnvlist_size(sd->fss)) >
  647             zhp->zfs_hdl->libzfs_max_nvlist) {
  648                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
  649                     "warning: cannot send %s@%s: the size of the list of "
  650                     "snapshots and properties is too large to be received "
  651                     "successfully.\n"
  652                     "Select a smaller number of snapshots to send.\n"),
  653                     zhp->zfs_name, sd->tosnap);
  654                 rv = EZFS_NOSPC;
  655                 goto out;
  656         }
  657         /* Add this fs to nvlist. */
  658         (void) snprintf(guidstring, sizeof (guidstring),
  659             "0x%llx", (longlong_t)guid);
  660         fnvlist_add_nvlist(sd->fss, guidstring, nvfs);
  661 
  662         /* Iterate over children. */
  663         if (sd->recursive)
  664                 rv = zfs_iter_filesystems(zhp, 0, send_iterate_fs, sd);
  665 
  666 out:
  667         /* Restore saved fields. */
  668         sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
  669         sd->fromsnap_txg = fromsnap_txg_save;
  670         sd->tosnap_txg = tosnap_txg_save;
  671 
  672         fnvlist_free(nv);
  673         fnvlist_free(nvfs);
  674 
  675         zfs_close(zhp);
  676         return (rv);
  677 }
  678 
  679 static int
  680 gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
  681     const char *tosnap, boolean_t recursive, boolean_t raw, boolean_t doall,
  682     boolean_t replicate, boolean_t skipmissing, boolean_t verbose,
  683     boolean_t backup, boolean_t holds, boolean_t props, nvlist_t **nvlp,
  684     avl_tree_t **avlp)
  685 {
  686         zfs_handle_t *zhp;
  687         send_data_t sd = { 0 };
  688         int error;
  689 
  690         zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
  691         if (zhp == NULL)
  692                 return (EZFS_BADTYPE);
  693 
  694         sd.fss = fnvlist_alloc();
  695         sd.fsname = fsname;
  696         sd.fromsnap = fromsnap;
  697         sd.tosnap = tosnap;
  698         sd.recursive = recursive;
  699         sd.raw = raw;
  700         sd.doall = doall;
  701         sd.replicate = replicate;
  702         sd.skipmissing = skipmissing;
  703         sd.verbose = verbose;
  704         sd.backup = backup;
  705         sd.holds = holds;
  706         sd.props = props;
  707 
  708         if ((error = send_iterate_fs(zhp, &sd)) != 0) {
  709                 fnvlist_free(sd.fss);
  710                 if (avlp != NULL)
  711                         *avlp = NULL;
  712                 *nvlp = NULL;
  713                 return (error);
  714         }
  715 
  716         if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) {
  717                 fnvlist_free(sd.fss);
  718                 *nvlp = NULL;
  719                 return (EZFS_NOMEM);
  720         }
  721 
  722         *nvlp = sd.fss;
  723         return (0);
  724 }
  725 
  726 /*
  727  * Routines specific to "zfs send"
  728  */
  729 typedef struct send_dump_data {
  730         /* these are all just the short snapname (the part after the @) */
  731         const char *fromsnap;
  732         const char *tosnap;
  733         char prevsnap[ZFS_MAX_DATASET_NAME_LEN];
  734         uint64_t prevsnap_obj;
  735         boolean_t seenfrom, seento, replicate, doall, fromorigin;
  736         boolean_t dryrun, parsable, progress, embed_data, std_out;
  737         boolean_t large_block, compress, raw, holds;
  738         boolean_t progressastitle;
  739         int outfd;
  740         boolean_t err;
  741         nvlist_t *fss;
  742         nvlist_t *snapholds;
  743         avl_tree_t *fsavl;
  744         snapfilter_cb_t *filter_cb;
  745         void *filter_cb_arg;
  746         nvlist_t *debugnv;
  747         char holdtag[ZFS_MAX_DATASET_NAME_LEN];
  748         int cleanup_fd;
  749         int verbosity;
  750         uint64_t size;
  751 } send_dump_data_t;
  752 
  753 static int
  754 zfs_send_space(zfs_handle_t *zhp, const char *snapname, const char *from,
  755     enum lzc_send_flags flags, uint64_t *spacep)
  756 {
  757         assert(snapname != NULL);
  758 
  759         int error = lzc_send_space(snapname, from, flags, spacep);
  760         if (error == 0)
  761                 return (0);
  762 
  763         char errbuf[ERRBUFLEN];
  764         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
  765             "warning: cannot estimate space for '%s'"), snapname);
  766 
  767         libzfs_handle_t *hdl = zhp->zfs_hdl;
  768         switch (error) {
  769         case EXDEV:
  770                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  771                     "not an earlier snapshot from the same fs"));
  772                 return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
  773 
  774         case ENOENT:
  775                 if (zfs_dataset_exists(hdl, snapname,
  776                     ZFS_TYPE_SNAPSHOT)) {
  777                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  778                             "incremental source (%s) does not exist"),
  779                             snapname);
  780                 }
  781                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
  782 
  783         case EDQUOT:
  784         case EFBIG:
  785         case EIO:
  786         case ENOLINK:
  787         case ENOSPC:
  788         case ENOSTR:
  789         case ENXIO:
  790         case EPIPE:
  791         case ERANGE:
  792         case EFAULT:
  793         case EROFS:
  794         case EINVAL:
  795                 zfs_error_aux(hdl, "%s", strerror(error));
  796                 return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
  797 
  798         default:
  799                 return (zfs_standard_error(hdl, error, errbuf));
  800         }
  801 }
  802 
  803 /*
  804  * Dumps a backup of the given snapshot (incremental from fromsnap if it's not
  805  * NULL) to the file descriptor specified by outfd.
  806  */
  807 static int
  808 dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, uint64_t fromsnap_obj,
  809     boolean_t fromorigin, int outfd, enum lzc_send_flags flags,
  810     nvlist_t *debugnv)
  811 {
  812         zfs_cmd_t zc = {"\0"};
  813         libzfs_handle_t *hdl = zhp->zfs_hdl;
  814         nvlist_t *thisdbg;
  815 
  816         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
  817         assert(fromsnap_obj == 0 || !fromorigin);
  818 
  819         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
  820         zc.zc_cookie = outfd;
  821         zc.zc_obj = fromorigin;
  822         zc.zc_sendobj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
  823         zc.zc_fromobj = fromsnap_obj;
  824         zc.zc_flags = flags;
  825 
  826         if (debugnv != NULL) {
  827                 thisdbg = fnvlist_alloc();
  828                 if (fromsnap != NULL && fromsnap[0] != '\0')
  829                         fnvlist_add_string(thisdbg, "fromsnap", fromsnap);
  830         }
  831 
  832         if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND, &zc) != 0) {
  833                 char errbuf[ERRBUFLEN];
  834                 int error = errno;
  835 
  836                 (void) snprintf(errbuf, sizeof (errbuf), "%s '%s'",
  837                     dgettext(TEXT_DOMAIN, "warning: cannot send"),
  838                     zhp->zfs_name);
  839 
  840                 if (debugnv != NULL) {
  841                         fnvlist_add_uint64(thisdbg, "error", error);
  842                         fnvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg);
  843                         fnvlist_free(thisdbg);
  844                 }
  845 
  846                 switch (error) {
  847                 case EXDEV:
  848                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  849                             "not an earlier snapshot from the same fs"));
  850                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
  851 
  852                 case EACCES:
  853                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  854                             "source key must be loaded"));
  855                         return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf));
  856 
  857                 case ENOENT:
  858                         if (zfs_dataset_exists(hdl, zc.zc_name,
  859                             ZFS_TYPE_SNAPSHOT)) {
  860                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
  861                                     "incremental source (@%s) does not exist"),
  862                                     zc.zc_value);
  863                         }
  864                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
  865 
  866                 case EDQUOT:
  867                 case EFBIG:
  868                 case EIO:
  869                 case ENOLINK:
  870                 case ENOSPC:
  871                 case ENOSTR:
  872                 case ENXIO:
  873                 case EPIPE:
  874                 case ERANGE:
  875                 case EFAULT:
  876                 case EROFS:
  877                 case EINVAL:
  878                         zfs_error_aux(hdl, "%s", strerror(errno));
  879                         return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
  880 
  881                 default:
  882                         return (zfs_standard_error(hdl, errno, errbuf));
  883                 }
  884         }
  885 
  886         if (debugnv != NULL) {
  887                 fnvlist_add_nvlist(debugnv, zhp->zfs_name, thisdbg);
  888                 fnvlist_free(thisdbg);
  889         }
  890 
  891         return (0);
  892 }
  893 
  894 static void
  895 gather_holds(zfs_handle_t *zhp, send_dump_data_t *sdd)
  896 {
  897         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
  898 
  899         /*
  900          * zfs_send() only sets snapholds for sends that need them,
  901          * e.g. replication and doall.
  902          */
  903         if (sdd->snapholds == NULL)
  904                 return;
  905 
  906         fnvlist_add_string(sdd->snapholds, zhp->zfs_name, sdd->holdtag);
  907 }
  908 
  909 int
  910 zfs_send_progress(zfs_handle_t *zhp, int fd, uint64_t *bytes_written,
  911     uint64_t *blocks_visited)
  912 {
  913         zfs_cmd_t zc = {"\0"};
  914 
  915         if (bytes_written != NULL)
  916                 *bytes_written = 0;
  917         if (blocks_visited != NULL)
  918                 *blocks_visited = 0;
  919         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
  920         zc.zc_cookie = fd;
  921         if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SEND_PROGRESS, &zc) != 0)
  922                 return (errno);
  923         if (bytes_written != NULL)
  924                 *bytes_written = zc.zc_cookie;
  925         if (blocks_visited != NULL)
  926                 *blocks_visited = zc.zc_objset_type;
  927         return (0);
  928 }
  929 
  930 static void *
  931 send_progress_thread(void *arg)
  932 {
  933         progress_arg_t *pa = arg;
  934         zfs_handle_t *zhp = pa->pa_zhp;
  935         uint64_t bytes;
  936         uint64_t blocks;
  937         uint64_t total = pa->pa_size / 100;
  938         char buf[16];
  939         time_t t;
  940         struct tm tm;
  941         int err;
  942 
  943         if (!pa->pa_parsable && pa->pa_verbosity != 0) {
  944                 (void) fprintf(stderr,
  945                     "TIME       %s   %sSNAPSHOT %s\n",
  946                     pa->pa_estimate ? "BYTES" : " SENT",
  947                     pa->pa_verbosity >= 2 ? "   BLOCKS    " : "",
  948                     zhp->zfs_name);
  949         }
  950 
  951         /*
  952          * Print the progress from ZFS_IOC_SEND_PROGRESS every second.
  953          */
  954         for (;;) {
  955                 (void) sleep(1);
  956                 if ((err = zfs_send_progress(zhp, pa->pa_fd, &bytes,
  957                     &blocks)) != 0) {
  958                         if (err == EINTR || err == ENOENT)
  959                                 return ((void *)0);
  960                         return ((void *)(uintptr_t)err);
  961                 }
  962 
  963                 (void) time(&t);
  964                 localtime_r(&t, &tm);
  965 
  966                 if (pa->pa_astitle) {
  967                         char buf_bytes[16];
  968                         char buf_size[16];
  969                         int pct;
  970                         zfs_nicenum(bytes, buf_bytes, sizeof (buf_bytes));
  971                         zfs_nicenum(pa->pa_size, buf_size, sizeof (buf_size));
  972                         pct = (total > 0) ? bytes / total : 100;
  973                         zfs_setproctitle("sending %s (%d%%: %s/%s)",
  974                             zhp->zfs_name, MIN(pct, 100), buf_bytes, buf_size);
  975                 }
  976 
  977                 if (pa->pa_verbosity >= 2 && pa->pa_parsable) {
  978                         (void) fprintf(stderr,
  979                             "%02d:%02d:%02d\t%llu\t%llu\t%s\n",
  980                             tm.tm_hour, tm.tm_min, tm.tm_sec,
  981                             (u_longlong_t)bytes, (u_longlong_t)blocks,
  982                             zhp->zfs_name);
  983                 } else if (pa->pa_verbosity >= 2) {
  984                         zfs_nicenum(bytes, buf, sizeof (buf));
  985                         (void) fprintf(stderr,
  986                             "%02d:%02d:%02d   %5s    %8llu    %s\n",
  987                             tm.tm_hour, tm.tm_min, tm.tm_sec,
  988                             buf, (u_longlong_t)blocks, zhp->zfs_name);
  989                 } else if (pa->pa_parsable) {
  990                         (void) fprintf(stderr, "%02d:%02d:%02d\t%llu\t%s\n",
  991                             tm.tm_hour, tm.tm_min, tm.tm_sec,
  992                             (u_longlong_t)bytes, zhp->zfs_name);
  993                 } else if (pa->pa_verbosity != 0) {
  994                         zfs_nicebytes(bytes, buf, sizeof (buf));
  995                         (void) fprintf(stderr, "%02d:%02d:%02d   %5s   %s\n",
  996                             tm.tm_hour, tm.tm_min, tm.tm_sec,
  997                             buf, zhp->zfs_name);
  998                 }
  999         }
 1000 }
 1001 
 1002 static boolean_t
 1003 send_progress_thread_exit(libzfs_handle_t *hdl, pthread_t ptid)
 1004 {
 1005         void *status = NULL;
 1006         (void) pthread_cancel(ptid);
 1007         (void) pthread_join(ptid, &status);
 1008         int error = (int)(uintptr_t)status;
 1009         if (error != 0 && status != PTHREAD_CANCELED)
 1010                 return (zfs_standard_error(hdl, error,
 1011                     dgettext(TEXT_DOMAIN, "progress thread exited nonzero")));
 1012         else
 1013                 return (B_FALSE);
 1014 }
 1015 
 1016 static void
 1017 send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
 1018     uint64_t size, boolean_t parsable)
 1019 {
 1020         if (parsable) {
 1021                 if (fromsnap != NULL) {
 1022                         (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1023                             "incremental\t%s\t%s"), fromsnap, tosnap);
 1024                 } else {
 1025 /*
 1026  * Workaround for GCC 12+ with UBSan enabled deficencies.
 1027  *
 1028  * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code
 1029  * below as violating -Wformat-overflow.
 1030  */
 1031 #if defined(__GNUC__) && !defined(__clang__) && \
 1032         defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
 1033 #pragma GCC diagnostic push
 1034 #pragma GCC diagnostic ignored "-Wformat-overflow"
 1035 #endif
 1036                         (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1037                             "full\t%s"), tosnap);
 1038 #if defined(__GNUC__) && !defined(__clang__) && \
 1039         defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
 1040 #pragma GCC diagnostic pop
 1041 #endif
 1042                 }
 1043                 (void) fprintf(fout, "\t%llu", (longlong_t)size);
 1044         } else {
 1045                 if (fromsnap != NULL) {
 1046                         if (strchr(fromsnap, '@') == NULL &&
 1047                             strchr(fromsnap, '#') == NULL) {
 1048                                 (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1049                                     "send from @%s to %s"), fromsnap, tosnap);
 1050                         } else {
 1051                                 (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1052                                     "send from %s to %s"), fromsnap, tosnap);
 1053                         }
 1054                 } else {
 1055                         (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1056                             "full send of %s"), tosnap);
 1057                 }
 1058                 if (size != 0) {
 1059                         char buf[16];
 1060                         zfs_nicebytes(size, buf, sizeof (buf));
 1061 /*
 1062  * Workaround for GCC 12+ with UBSan enabled deficencies.
 1063  *
 1064  * GCC 12+ invoked with -fsanitize=undefined incorrectly reports the code
 1065  * below as violating -Wformat-overflow.
 1066  */
 1067 #if defined(__GNUC__) && !defined(__clang__) && \
 1068         defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
 1069 #pragma GCC diagnostic push
 1070 #pragma GCC diagnostic ignored "-Wformat-overflow"
 1071 #endif
 1072                         (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1073                             " estimated size is %s"), buf);
 1074 #if defined(__GNUC__) && !defined(__clang__) && \
 1075         defined(ZFS_UBSAN_ENABLED) && defined(HAVE_FORMAT_OVERFLOW)
 1076 #pragma GCC diagnostic pop
 1077 #endif
 1078                 }
 1079         }
 1080         (void) fprintf(fout, "\n");
 1081 }
 1082 
 1083 /*
 1084  * Send a single filesystem snapshot, updating the send dump data.
 1085  * This interface is intended for use as a zfs_iter_snapshots_sorted visitor.
 1086  */
 1087 static int
 1088 dump_snapshot(zfs_handle_t *zhp, void *arg)
 1089 {
 1090         send_dump_data_t *sdd = arg;
 1091         progress_arg_t pa = { 0 };
 1092         pthread_t tid;
 1093         char *thissnap;
 1094         enum lzc_send_flags flags = 0;
 1095         int err;
 1096         boolean_t isfromsnap, istosnap, fromorigin;
 1097         boolean_t exclude = B_FALSE;
 1098         FILE *fout = sdd->std_out ? stdout : stderr;
 1099 
 1100         err = 0;
 1101         thissnap = strchr(zhp->zfs_name, '@') + 1;
 1102         isfromsnap = (sdd->fromsnap != NULL &&
 1103             strcmp(sdd->fromsnap, thissnap) == 0);
 1104 
 1105         if (!sdd->seenfrom && isfromsnap) {
 1106                 gather_holds(zhp, sdd);
 1107                 sdd->seenfrom = B_TRUE;
 1108                 (void) strlcpy(sdd->prevsnap, thissnap, sizeof (sdd->prevsnap));
 1109                 sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
 1110                 zfs_close(zhp);
 1111                 return (0);
 1112         }
 1113 
 1114         if (sdd->seento || !sdd->seenfrom) {
 1115                 zfs_close(zhp);
 1116                 return (0);
 1117         }
 1118 
 1119         istosnap = (strcmp(sdd->tosnap, thissnap) == 0);
 1120         if (istosnap)
 1121                 sdd->seento = B_TRUE;
 1122 
 1123         if (sdd->large_block)
 1124                 flags |= LZC_SEND_FLAG_LARGE_BLOCK;
 1125         if (sdd->embed_data)
 1126                 flags |= LZC_SEND_FLAG_EMBED_DATA;
 1127         if (sdd->compress)
 1128                 flags |= LZC_SEND_FLAG_COMPRESS;
 1129         if (sdd->raw)
 1130                 flags |= LZC_SEND_FLAG_RAW;
 1131 
 1132         if (!sdd->doall && !isfromsnap && !istosnap) {
 1133                 if (sdd->replicate) {
 1134                         char *snapname;
 1135                         nvlist_t *snapprops;
 1136                         /*
 1137                          * Filter out all intermediate snapshots except origin
 1138                          * snapshots needed to replicate clones.
 1139                          */
 1140                         nvlist_t *nvfs = fsavl_find(sdd->fsavl,
 1141                             zhp->zfs_dmustats.dds_guid, &snapname);
 1142 
 1143                         if (nvfs != NULL) {
 1144                                 snapprops = fnvlist_lookup_nvlist(nvfs,
 1145                                     "snapprops");
 1146                                 snapprops = fnvlist_lookup_nvlist(snapprops,
 1147                                     thissnap);
 1148                                 exclude = !nvlist_exists(snapprops,
 1149                                     "is_clone_origin");
 1150                         }
 1151                 } else {
 1152                         exclude = B_TRUE;
 1153                 }
 1154         }
 1155 
 1156         /*
 1157          * If a filter function exists, call it to determine whether
 1158          * this snapshot will be sent.
 1159          */
 1160         if (exclude || (sdd->filter_cb != NULL &&
 1161             sdd->filter_cb(zhp, sdd->filter_cb_arg) == B_FALSE)) {
 1162                 /*
 1163                  * This snapshot is filtered out.  Don't send it, and don't
 1164                  * set prevsnap_obj, so it will be as if this snapshot didn't
 1165                  * exist, and the next accepted snapshot will be sent as
 1166                  * an incremental from the last accepted one, or as the
 1167                  * first (and full) snapshot in the case of a replication,
 1168                  * non-incremental send.
 1169                  */
 1170                 zfs_close(zhp);
 1171                 return (0);
 1172         }
 1173 
 1174         gather_holds(zhp, sdd);
 1175         fromorigin = sdd->prevsnap[0] == '\0' &&
 1176             (sdd->fromorigin || sdd->replicate);
 1177 
 1178         if (sdd->verbosity != 0) {
 1179                 uint64_t size = 0;
 1180                 char fromds[ZFS_MAX_DATASET_NAME_LEN];
 1181 
 1182                 if (sdd->prevsnap[0] != '\0') {
 1183                         (void) strlcpy(fromds, zhp->zfs_name, sizeof (fromds));
 1184                         *(strchr(fromds, '@') + 1) = '\0';
 1185                         (void) strlcat(fromds, sdd->prevsnap, sizeof (fromds));
 1186                 }
 1187                 if (zfs_send_space(zhp, zhp->zfs_name,
 1188                     sdd->prevsnap[0] ? fromds : NULL, flags, &size) == 0) {
 1189                         send_print_verbose(fout, zhp->zfs_name,
 1190                             sdd->prevsnap[0] ? sdd->prevsnap : NULL,
 1191                             size, sdd->parsable);
 1192                         sdd->size += size;
 1193                 }
 1194         }
 1195 
 1196         if (!sdd->dryrun) {
 1197                 /*
 1198                  * If progress reporting is requested, spawn a new thread to
 1199                  * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
 1200                  */
 1201                 if (sdd->progress || sdd->progressastitle) {
 1202                         pa.pa_zhp = zhp;
 1203                         pa.pa_fd = sdd->outfd;
 1204                         pa.pa_parsable = sdd->parsable;
 1205                         pa.pa_estimate = B_FALSE;
 1206                         pa.pa_verbosity = sdd->verbosity;
 1207                         pa.pa_size = sdd->size;
 1208                         pa.pa_astitle = sdd->progressastitle;
 1209 
 1210                         if ((err = pthread_create(&tid, NULL,
 1211                             send_progress_thread, &pa)) != 0) {
 1212                                 zfs_close(zhp);
 1213                                 return (err);
 1214                         }
 1215                 }
 1216 
 1217                 err = dump_ioctl(zhp, sdd->prevsnap, sdd->prevsnap_obj,
 1218                     fromorigin, sdd->outfd, flags, sdd->debugnv);
 1219 
 1220                 if ((sdd->progress || sdd->progressastitle) &&
 1221                     send_progress_thread_exit(zhp->zfs_hdl, tid))
 1222                         return (-1);
 1223         }
 1224 
 1225         (void) strlcpy(sdd->prevsnap, thissnap, sizeof (sdd->prevsnap));
 1226         sdd->prevsnap_obj = zfs_prop_get_int(zhp, ZFS_PROP_OBJSETID);
 1227         zfs_close(zhp);
 1228         return (err);
 1229 }
 1230 
 1231 /*
 1232  * Send all snapshots for a filesystem, updating the send dump data.
 1233  */
 1234 static int
 1235 dump_filesystem(zfs_handle_t *zhp, send_dump_data_t *sdd)
 1236 {
 1237         int rv = 0;
 1238         boolean_t missingfrom = B_FALSE;
 1239         zfs_cmd_t zc = {"\0"};
 1240         uint64_t min_txg = 0, max_txg = 0;
 1241 
 1242         /*
 1243          * Make sure the tosnap exists.
 1244          */
 1245         (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
 1246             zhp->zfs_name, sdd->tosnap);
 1247         if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
 1248                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 1249                     "WARNING: could not send %s@%s: does not exist\n"),
 1250                     zhp->zfs_name, sdd->tosnap);
 1251                 sdd->err = B_TRUE;
 1252                 return (0);
 1253         }
 1254 
 1255         /*
 1256          * If this fs does not have fromsnap, and we're doing
 1257          * recursive, we need to send a full stream from the
 1258          * beginning (or an incremental from the origin if this
 1259          * is a clone).  If we're doing non-recursive, then let
 1260          * them get the error.
 1261          */
 1262         if (sdd->replicate && sdd->fromsnap) {
 1263                 /*
 1264                  * Make sure the fromsnap exists.
 1265                  */
 1266                 (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
 1267                     zhp->zfs_name, sdd->fromsnap);
 1268                 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_STATS, &zc) != 0)
 1269                         missingfrom = B_TRUE;
 1270         }
 1271 
 1272         sdd->seenfrom = sdd->seento = B_FALSE;
 1273         sdd->prevsnap[0] = '\0';
 1274         sdd->prevsnap_obj = 0;
 1275         if (sdd->fromsnap == NULL || missingfrom)
 1276                 sdd->seenfrom = B_TRUE;
 1277 
 1278         /*
 1279          * Iterate through all snapshots and process the ones we will be
 1280          * sending. If we only have a "from" and "to" snapshot to deal
 1281          * with, we can avoid iterating through all the other snapshots.
 1282          */
 1283         if (sdd->doall || sdd->replicate || sdd->tosnap == NULL) {
 1284                 if (!sdd->replicate) {
 1285                         if (sdd->fromsnap != NULL) {
 1286                                 min_txg = get_snap_txg(zhp->zfs_hdl,
 1287                                     zhp->zfs_name, sdd->fromsnap);
 1288                         }
 1289                         if (sdd->tosnap != NULL) {
 1290                                 max_txg = get_snap_txg(zhp->zfs_hdl,
 1291                                     zhp->zfs_name, sdd->tosnap);
 1292                         }
 1293                 }
 1294                 rv = zfs_iter_snapshots_sorted(zhp, 0, dump_snapshot, sdd,
 1295                     min_txg, max_txg);
 1296         } else {
 1297                 char snapname[MAXPATHLEN] = { 0 };
 1298                 zfs_handle_t *snap;
 1299 
 1300                 /* Dump fromsnap. */
 1301                 if (!sdd->seenfrom) {
 1302                         (void) snprintf(snapname, sizeof (snapname),
 1303                             "%s@%s", zhp->zfs_name, sdd->fromsnap);
 1304                         snap = zfs_open(zhp->zfs_hdl, snapname,
 1305                             ZFS_TYPE_SNAPSHOT);
 1306                         if (snap != NULL)
 1307                                 rv = dump_snapshot(snap, sdd);
 1308                         else
 1309                                 rv = errno;
 1310                 }
 1311 
 1312                 /* Dump tosnap. */
 1313                 if (rv == 0) {
 1314                         (void) snprintf(snapname, sizeof (snapname),
 1315                             "%s@%s", zhp->zfs_name, sdd->tosnap);
 1316                         snap = zfs_open(zhp->zfs_hdl, snapname,
 1317                             ZFS_TYPE_SNAPSHOT);
 1318                         if (snap != NULL)
 1319                                 rv = dump_snapshot(snap, sdd);
 1320                         else
 1321                                 rv = errno;
 1322                 }
 1323         }
 1324 
 1325         if (!sdd->seenfrom) {
 1326                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 1327                     "WARNING: could not send %s@%s:\n"
 1328                     "incremental source (%s@%s) does not exist\n"),
 1329                     zhp->zfs_name, sdd->tosnap,
 1330                     zhp->zfs_name, sdd->fromsnap);
 1331                 sdd->err = B_TRUE;
 1332         } else if (!sdd->seento) {
 1333                 if (sdd->fromsnap) {
 1334                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 1335                             "WARNING: could not send %s@%s:\n"
 1336                             "incremental source (%s@%s) "
 1337                             "is not earlier than it\n"),
 1338                             zhp->zfs_name, sdd->tosnap,
 1339                             zhp->zfs_name, sdd->fromsnap);
 1340                 } else {
 1341                         (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 1342                             "WARNING: "
 1343                             "could not send %s@%s: does not exist\n"),
 1344                             zhp->zfs_name, sdd->tosnap);
 1345                 }
 1346                 sdd->err = B_TRUE;
 1347         }
 1348 
 1349         return (rv);
 1350 }
 1351 
 1352 /*
 1353  * Send all snapshots for all filesystems in sdd.
 1354  */
 1355 static int
 1356 dump_filesystems(zfs_handle_t *rzhp, send_dump_data_t *sdd)
 1357 {
 1358         nvpair_t *fspair;
 1359         boolean_t needagain, progress;
 1360 
 1361         if (!sdd->replicate)
 1362                 return (dump_filesystem(rzhp, sdd));
 1363 
 1364         /* Mark the clone origin snapshots. */
 1365         for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
 1366             fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
 1367                 nvlist_t *nvfs;
 1368                 uint64_t origin_guid = 0;
 1369 
 1370                 nvfs = fnvpair_value_nvlist(fspair);
 1371                 (void) nvlist_lookup_uint64(nvfs, "origin", &origin_guid);
 1372                 if (origin_guid != 0) {
 1373                         char *snapname;
 1374                         nvlist_t *origin_nv = fsavl_find(sdd->fsavl,
 1375                             origin_guid, &snapname);
 1376                         if (origin_nv != NULL) {
 1377                                 nvlist_t *snapprops;
 1378                                 snapprops = fnvlist_lookup_nvlist(origin_nv,
 1379                                     "snapprops");
 1380                                 snapprops = fnvlist_lookup_nvlist(snapprops,
 1381                                     snapname);
 1382                                 fnvlist_add_boolean(snapprops,
 1383                                     "is_clone_origin");
 1384                         }
 1385                 }
 1386         }
 1387 again:
 1388         needagain = progress = B_FALSE;
 1389         for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
 1390             fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
 1391                 nvlist_t *fslist, *parent_nv;
 1392                 char *fsname;
 1393                 zfs_handle_t *zhp;
 1394                 int err;
 1395                 uint64_t origin_guid = 0;
 1396                 uint64_t parent_guid = 0;
 1397 
 1398                 fslist = fnvpair_value_nvlist(fspair);
 1399                 if (nvlist_lookup_boolean(fslist, "sent") == 0)
 1400                         continue;
 1401 
 1402                 fsname = fnvlist_lookup_string(fslist, "name");
 1403                 (void) nvlist_lookup_uint64(fslist, "origin", &origin_guid);
 1404                 (void) nvlist_lookup_uint64(fslist, "parentfromsnap",
 1405                     &parent_guid);
 1406 
 1407                 if (parent_guid != 0) {
 1408                         parent_nv = fsavl_find(sdd->fsavl, parent_guid, NULL);
 1409                         if (!nvlist_exists(parent_nv, "sent")) {
 1410                                 /* Parent has not been sent; skip this one. */
 1411                                 needagain = B_TRUE;
 1412                                 continue;
 1413                         }
 1414                 }
 1415 
 1416                 if (origin_guid != 0) {
 1417                         nvlist_t *origin_nv = fsavl_find(sdd->fsavl,
 1418                             origin_guid, NULL);
 1419                         if (origin_nv != NULL &&
 1420                             !nvlist_exists(origin_nv, "sent")) {
 1421                                 /*
 1422                                  * Origin has not been sent yet;
 1423                                  * skip this clone.
 1424                                  */
 1425                                 needagain = B_TRUE;
 1426                                 continue;
 1427                         }
 1428                 }
 1429 
 1430                 zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET);
 1431                 if (zhp == NULL)
 1432                         return (-1);
 1433                 err = dump_filesystem(zhp, sdd);
 1434                 fnvlist_add_boolean(fslist, "sent");
 1435                 progress = B_TRUE;
 1436                 zfs_close(zhp);
 1437                 if (err)
 1438                         return (err);
 1439         }
 1440         if (needagain) {
 1441                 assert(progress);
 1442                 goto again;
 1443         }
 1444 
 1445         /* Clean out the sent flags in case we reuse this fss. */
 1446         for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
 1447             fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
 1448                 nvlist_t *fslist;
 1449 
 1450                 fslist = fnvpair_value_nvlist(fspair);
 1451                 (void) nvlist_remove_all(fslist, "sent");
 1452         }
 1453 
 1454         return (0);
 1455 }
 1456 
 1457 nvlist_t *
 1458 zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl, const char *token)
 1459 {
 1460         unsigned int version;
 1461         int nread, i;
 1462         unsigned long long checksum, packed_len;
 1463 
 1464         /*
 1465          * Decode token header, which is:
 1466          *   <token version>-<checksum of payload>-<uncompressed payload length>
 1467          * Note that the only supported token version is 1.
 1468          */
 1469         nread = sscanf(token, "%u-%llx-%llx-",
 1470             &version, &checksum, &packed_len);
 1471         if (nread != 3) {
 1472                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1473                     "resume token is corrupt (invalid format)"));
 1474                 return (NULL);
 1475         }
 1476 
 1477         if (version != ZFS_SEND_RESUME_TOKEN_VERSION) {
 1478                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1479                     "resume token is corrupt (invalid version %u)"),
 1480                     version);
 1481                 return (NULL);
 1482         }
 1483 
 1484         /* Convert hexadecimal representation to binary. */
 1485         token = strrchr(token, '-') + 1;
 1486         int len = strlen(token) / 2;
 1487         unsigned char *compressed = zfs_alloc(hdl, len);
 1488         for (i = 0; i < len; i++) {
 1489                 nread = sscanf(token + i * 2, "%2hhx", compressed + i);
 1490                 if (nread != 1) {
 1491                         free(compressed);
 1492                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1493                             "resume token is corrupt "
 1494                             "(payload is not hex-encoded)"));
 1495                         return (NULL);
 1496                 }
 1497         }
 1498 
 1499         /* Verify checksum. */
 1500         zio_cksum_t cksum;
 1501         fletcher_4_native_varsize(compressed, len, &cksum);
 1502         if (cksum.zc_word[0] != checksum) {
 1503                 free(compressed);
 1504                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1505                     "resume token is corrupt (incorrect checksum)"));
 1506                 return (NULL);
 1507         }
 1508 
 1509         /* Uncompress. */
 1510         void *packed = zfs_alloc(hdl, packed_len);
 1511         uLongf packed_len_long = packed_len;
 1512         if (uncompress(packed, &packed_len_long, compressed, len) != Z_OK ||
 1513             packed_len_long != packed_len) {
 1514                 free(packed);
 1515                 free(compressed);
 1516                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1517                     "resume token is corrupt (decompression failed)"));
 1518                 return (NULL);
 1519         }
 1520 
 1521         /* Unpack nvlist. */
 1522         nvlist_t *nv;
 1523         int error = nvlist_unpack(packed, packed_len, &nv, KM_SLEEP);
 1524         free(packed);
 1525         free(compressed);
 1526         if (error != 0) {
 1527                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1528                     "resume token is corrupt (nvlist_unpack failed)"));
 1529                 return (NULL);
 1530         }
 1531         return (nv);
 1532 }
 1533 
 1534 static enum lzc_send_flags
 1535 lzc_flags_from_sendflags(const sendflags_t *flags)
 1536 {
 1537         enum lzc_send_flags lzc_flags = 0;
 1538 
 1539         if (flags->largeblock)
 1540                 lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK;
 1541         if (flags->embed_data)
 1542                 lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
 1543         if (flags->compress)
 1544                 lzc_flags |= LZC_SEND_FLAG_COMPRESS;
 1545         if (flags->raw)
 1546                 lzc_flags |= LZC_SEND_FLAG_RAW;
 1547         if (flags->saved)
 1548                 lzc_flags |= LZC_SEND_FLAG_SAVED;
 1549 
 1550         return (lzc_flags);
 1551 }
 1552 
 1553 static int
 1554 estimate_size(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
 1555     uint64_t resumeobj, uint64_t resumeoff, uint64_t bytes,
 1556     const char *redactbook, char *errbuf, uint64_t *sizep)
 1557 {
 1558         uint64_t size;
 1559         FILE *fout = flags->dryrun ? stdout : stderr;
 1560         progress_arg_t pa = { 0 };
 1561         int err = 0;
 1562         pthread_t ptid;
 1563 
 1564         if (flags->progress || flags->progressastitle) {
 1565                 pa.pa_zhp = zhp;
 1566                 pa.pa_fd = fd;
 1567                 pa.pa_parsable = flags->parsable;
 1568                 pa.pa_estimate = B_TRUE;
 1569                 pa.pa_verbosity = flags->verbosity;
 1570 
 1571                 err = pthread_create(&ptid, NULL,
 1572                     send_progress_thread, &pa);
 1573                 if (err != 0) {
 1574                         zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
 1575                         return (zfs_error(zhp->zfs_hdl,
 1576                             EZFS_THREADCREATEFAILED, errbuf));
 1577                 }
 1578         }
 1579 
 1580         err = lzc_send_space_resume_redacted(zhp->zfs_name, from,
 1581             lzc_flags_from_sendflags(flags), resumeobj, resumeoff, bytes,
 1582             redactbook, fd, &size);
 1583         *sizep = size;
 1584 
 1585         if ((flags->progress || flags->progressastitle) &&
 1586             send_progress_thread_exit(zhp->zfs_hdl, ptid))
 1587                 return (-1);
 1588 
 1589         if (!flags->progress && !flags->parsable)
 1590                 return (err);
 1591 
 1592         if (err != 0) {
 1593                 zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
 1594                 return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
 1595                     errbuf));
 1596         }
 1597         send_print_verbose(fout, zhp->zfs_name, from, size,
 1598             flags->parsable);
 1599 
 1600         if (flags->parsable) {
 1601                 (void) fprintf(fout, "size\t%llu\n", (longlong_t)size);
 1602         } else {
 1603                 char buf[16];
 1604                 zfs_nicenum(size, buf, sizeof (buf));
 1605                 (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1606                     "total estimated size is %s\n"), buf);
 1607         }
 1608         return (0);
 1609 }
 1610 
 1611 static boolean_t
 1612 redact_snaps_contains(const uint64_t *snaps, uint64_t num_snaps, uint64_t guid)
 1613 {
 1614         for (int i = 0; i < num_snaps; i++) {
 1615                 if (snaps[i] == guid)
 1616                         return (B_TRUE);
 1617         }
 1618         return (B_FALSE);
 1619 }
 1620 
 1621 static boolean_t
 1622 redact_snaps_equal(const uint64_t *snaps1, uint64_t num_snaps1,
 1623     const uint64_t *snaps2, uint64_t num_snaps2)
 1624 {
 1625         if (num_snaps1 != num_snaps2)
 1626                 return (B_FALSE);
 1627         for (int i = 0; i < num_snaps1; i++) {
 1628                 if (!redact_snaps_contains(snaps2, num_snaps2, snaps1[i]))
 1629                         return (B_FALSE);
 1630         }
 1631         return (B_TRUE);
 1632 }
 1633 
 1634 static int
 1635 get_bookmarks(const char *path, nvlist_t **bmarksp)
 1636 {
 1637         nvlist_t *props = fnvlist_alloc();
 1638         int error;
 1639 
 1640         fnvlist_add_boolean(props, "redact_complete");
 1641         fnvlist_add_boolean(props, zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS));
 1642         error = lzc_get_bookmarks(path, props, bmarksp);
 1643         fnvlist_free(props);
 1644         return (error);
 1645 }
 1646 
 1647 static nvpair_t *
 1648 find_redact_pair(nvlist_t *bmarks, const uint64_t *redact_snap_guids,
 1649     int num_redact_snaps)
 1650 {
 1651         nvpair_t *pair;
 1652 
 1653         for (pair = nvlist_next_nvpair(bmarks, NULL); pair;
 1654             pair = nvlist_next_nvpair(bmarks, pair)) {
 1655 
 1656                 nvlist_t *bmark = fnvpair_value_nvlist(pair);
 1657                 nvlist_t *vallist = fnvlist_lookup_nvlist(bmark,
 1658                     zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS));
 1659                 uint_t len = 0;
 1660                 uint64_t *bmarksnaps = fnvlist_lookup_uint64_array(vallist,
 1661                     ZPROP_VALUE, &len);
 1662                 if (redact_snaps_equal(redact_snap_guids,
 1663                     num_redact_snaps, bmarksnaps, len)) {
 1664                         break;
 1665                 }
 1666         }
 1667         return (pair);
 1668 }
 1669 
 1670 static boolean_t
 1671 get_redact_complete(nvpair_t *pair)
 1672 {
 1673         nvlist_t *bmark = fnvpair_value_nvlist(pair);
 1674         nvlist_t *vallist = fnvlist_lookup_nvlist(bmark, "redact_complete");
 1675         boolean_t complete = fnvlist_lookup_boolean_value(vallist,
 1676             ZPROP_VALUE);
 1677 
 1678         return (complete);
 1679 }
 1680 
 1681 /*
 1682  * Check that the list of redaction snapshots in the bookmark matches the send
 1683  * we're resuming, and return whether or not it's complete.
 1684  *
 1685  * Note that the caller needs to free the contents of *bookname with free() if
 1686  * this function returns successfully.
 1687  */
 1688 static int
 1689 find_redact_book(libzfs_handle_t *hdl, const char *path,
 1690     const uint64_t *redact_snap_guids, int num_redact_snaps,
 1691     char **bookname)
 1692 {
 1693         char errbuf[ERRBUFLEN];
 1694         nvlist_t *bmarks;
 1695 
 1696         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 1697             "cannot resume send"));
 1698 
 1699         int error = get_bookmarks(path, &bmarks);
 1700         if (error != 0) {
 1701                 if (error == ESRCH) {
 1702                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1703                             "nonexistent redaction bookmark provided"));
 1704                 } else if (error == ENOENT) {
 1705                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1706                             "dataset to be sent no longer exists"));
 1707                 } else {
 1708                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1709                             "unknown error: %s"), strerror(error));
 1710                 }
 1711                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
 1712         }
 1713         nvpair_t *pair = find_redact_pair(bmarks, redact_snap_guids,
 1714             num_redact_snaps);
 1715         if (pair == NULL)  {
 1716                 fnvlist_free(bmarks);
 1717                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1718                     "no appropriate redaction bookmark exists"));
 1719                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
 1720         }
 1721         boolean_t complete = get_redact_complete(pair);
 1722         if (!complete) {
 1723                 fnvlist_free(bmarks);
 1724                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1725                     "incomplete redaction bookmark provided"));
 1726                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
 1727         }
 1728         *bookname = strndup(nvpair_name(pair), ZFS_MAX_DATASET_NAME_LEN);
 1729         ASSERT3P(*bookname, !=, NULL);
 1730         fnvlist_free(bmarks);
 1731         return (0);
 1732 }
 1733 
 1734 static enum lzc_send_flags
 1735 lzc_flags_from_resume_nvl(nvlist_t *resume_nvl)
 1736 {
 1737         enum lzc_send_flags lzc_flags = 0;
 1738 
 1739         if (nvlist_exists(resume_nvl, "largeblockok"))
 1740                 lzc_flags |= LZC_SEND_FLAG_LARGE_BLOCK;
 1741         if (nvlist_exists(resume_nvl, "embedok"))
 1742                 lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
 1743         if (nvlist_exists(resume_nvl, "compressok"))
 1744                 lzc_flags |= LZC_SEND_FLAG_COMPRESS;
 1745         if (nvlist_exists(resume_nvl, "rawok"))
 1746                 lzc_flags |= LZC_SEND_FLAG_RAW;
 1747         if (nvlist_exists(resume_nvl, "savedok"))
 1748                 lzc_flags |= LZC_SEND_FLAG_SAVED;
 1749 
 1750         return (lzc_flags);
 1751 }
 1752 
 1753 static int
 1754 zfs_send_resume_impl_cb_impl(libzfs_handle_t *hdl, sendflags_t *flags,
 1755     int outfd, nvlist_t *resume_nvl)
 1756 {
 1757         char errbuf[ERRBUFLEN];
 1758         char *toname;
 1759         char *fromname = NULL;
 1760         uint64_t resumeobj, resumeoff, toguid, fromguid, bytes;
 1761         zfs_handle_t *zhp;
 1762         int error = 0;
 1763         char name[ZFS_MAX_DATASET_NAME_LEN];
 1764         FILE *fout = (flags->verbosity > 0 && flags->dryrun) ? stdout : stderr;
 1765         uint64_t *redact_snap_guids = NULL;
 1766         int num_redact_snaps = 0;
 1767         char *redact_book = NULL;
 1768         uint64_t size = 0;
 1769 
 1770         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 1771             "cannot resume send"));
 1772 
 1773         if (flags->verbosity != 0) {
 1774                 (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 1775                     "resume token contents:\n"));
 1776                 nvlist_print(fout, resume_nvl);
 1777         }
 1778 
 1779         if (nvlist_lookup_string(resume_nvl, "toname", &toname) != 0 ||
 1780             nvlist_lookup_uint64(resume_nvl, "object", &resumeobj) != 0 ||
 1781             nvlist_lookup_uint64(resume_nvl, "offset", &resumeoff) != 0 ||
 1782             nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 ||
 1783             nvlist_lookup_uint64(resume_nvl, "toguid", &toguid) != 0) {
 1784                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1785                     "resume token is corrupt"));
 1786                 return (zfs_error(hdl, EZFS_FAULT, errbuf));
 1787         }
 1788         fromguid = 0;
 1789         (void) nvlist_lookup_uint64(resume_nvl, "fromguid", &fromguid);
 1790 
 1791         if (flags->saved) {
 1792                 (void) strlcpy(name, toname, sizeof (name));
 1793         } else {
 1794                 error = guid_to_name(hdl, toname, toguid, B_FALSE, name);
 1795                 if (error != 0) {
 1796                         if (zfs_dataset_exists(hdl, toname, ZFS_TYPE_DATASET)) {
 1797                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1798                                     "'%s' is no longer the same snapshot "
 1799                                     "used in the initial send"), toname);
 1800                         } else {
 1801                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1802                                     "'%s' used in the initial send no "
 1803                                     "longer exists"), toname);
 1804                         }
 1805                         return (zfs_error(hdl, EZFS_BADPATH, errbuf));
 1806                 }
 1807         }
 1808 
 1809         zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
 1810         if (zhp == NULL) {
 1811                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1812                     "unable to access '%s'"), name);
 1813                 return (zfs_error(hdl, EZFS_BADPATH, errbuf));
 1814         }
 1815 
 1816         if (nvlist_lookup_uint64_array(resume_nvl, "book_redact_snaps",
 1817             &redact_snap_guids, (uint_t *)&num_redact_snaps) != 0) {
 1818                 num_redact_snaps = -1;
 1819         }
 1820 
 1821         if (fromguid != 0) {
 1822                 if (guid_to_name_redact_snaps(hdl, toname, fromguid, B_TRUE,
 1823                     redact_snap_guids, num_redact_snaps, name) != 0) {
 1824                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1825                             "incremental source %#llx no longer exists"),
 1826                             (longlong_t)fromguid);
 1827                         return (zfs_error(hdl, EZFS_BADPATH, errbuf));
 1828                 }
 1829                 fromname = name;
 1830         }
 1831 
 1832         redact_snap_guids = NULL;
 1833 
 1834         if (nvlist_lookup_uint64_array(resume_nvl,
 1835             zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS), &redact_snap_guids,
 1836             (uint_t *)&num_redact_snaps) == 0) {
 1837                 char path[ZFS_MAX_DATASET_NAME_LEN];
 1838 
 1839                 (void) strlcpy(path, toname, sizeof (path));
 1840                 char *at = strchr(path, '@');
 1841                 ASSERT3P(at, !=, NULL);
 1842 
 1843                 *at = '\0';
 1844 
 1845                 if ((error = find_redact_book(hdl, path, redact_snap_guids,
 1846                     num_redact_snaps, &redact_book)) != 0) {
 1847                         return (error);
 1848                 }
 1849         }
 1850 
 1851         enum lzc_send_flags lzc_flags = lzc_flags_from_sendflags(flags) |
 1852             lzc_flags_from_resume_nvl(resume_nvl);
 1853 
 1854         if (flags->verbosity != 0 || flags->progressastitle) {
 1855                 /*
 1856                  * Some of these may have come from the resume token, set them
 1857                  * here for size estimate purposes.
 1858                  */
 1859                 sendflags_t tmpflags = *flags;
 1860                 if (lzc_flags & LZC_SEND_FLAG_LARGE_BLOCK)
 1861                         tmpflags.largeblock = B_TRUE;
 1862                 if (lzc_flags & LZC_SEND_FLAG_COMPRESS)
 1863                         tmpflags.compress = B_TRUE;
 1864                 if (lzc_flags & LZC_SEND_FLAG_EMBED_DATA)
 1865                         tmpflags.embed_data = B_TRUE;
 1866                 if (lzc_flags & LZC_SEND_FLAG_RAW)
 1867                         tmpflags.raw = B_TRUE;
 1868                 if (lzc_flags & LZC_SEND_FLAG_SAVED)
 1869                         tmpflags.saved = B_TRUE;
 1870                 error = estimate_size(zhp, fromname, outfd, &tmpflags,
 1871                     resumeobj, resumeoff, bytes, redact_book, errbuf, &size);
 1872         }
 1873 
 1874         if (!flags->dryrun) {
 1875                 progress_arg_t pa = { 0 };
 1876                 pthread_t tid;
 1877                 /*
 1878                  * If progress reporting is requested, spawn a new thread to
 1879                  * poll ZFS_IOC_SEND_PROGRESS at a regular interval.
 1880                  */
 1881                 if (flags->progress || flags->progressastitle) {
 1882                         pa.pa_zhp = zhp;
 1883                         pa.pa_fd = outfd;
 1884                         pa.pa_parsable = flags->parsable;
 1885                         pa.pa_estimate = B_FALSE;
 1886                         pa.pa_verbosity = flags->verbosity;
 1887                         pa.pa_size = size;
 1888                         pa.pa_astitle = flags->progressastitle;
 1889 
 1890                         error = pthread_create(&tid, NULL,
 1891                             send_progress_thread, &pa);
 1892                         if (error != 0) {
 1893                                 if (redact_book != NULL)
 1894                                         free(redact_book);
 1895                                 zfs_close(zhp);
 1896                                 return (error);
 1897                         }
 1898                 }
 1899 
 1900                 error = lzc_send_resume_redacted(zhp->zfs_name, fromname, outfd,
 1901                     lzc_flags, resumeobj, resumeoff, redact_book);
 1902                 if (redact_book != NULL)
 1903                         free(redact_book);
 1904 
 1905                 if ((flags->progressastitle || flags->progress) &&
 1906                     send_progress_thread_exit(hdl, tid)) {
 1907                         zfs_close(zhp);
 1908                         return (-1);
 1909                 }
 1910 
 1911                 char errbuf[ERRBUFLEN];
 1912                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 1913                     "warning: cannot send '%s'"), zhp->zfs_name);
 1914 
 1915                 zfs_close(zhp);
 1916 
 1917                 switch (error) {
 1918                 case 0:
 1919                         return (0);
 1920                 case EACCES:
 1921                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1922                             "source key must be loaded"));
 1923                         return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf));
 1924                 case ESRCH:
 1925                         if (lzc_exists(zhp->zfs_name)) {
 1926                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 1927                                     "incremental source could not be found"));
 1928                         }
 1929                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
 1930 
 1931                 case EXDEV:
 1932                 case ENOENT:
 1933                 case EDQUOT:
 1934                 case EFBIG:
 1935                 case EIO:
 1936                 case ENOLINK:
 1937                 case ENOSPC:
 1938                 case ENOSTR:
 1939                 case ENXIO:
 1940                 case EPIPE:
 1941                 case ERANGE:
 1942                 case EFAULT:
 1943                 case EROFS:
 1944                         zfs_error_aux(hdl, "%s", strerror(errno));
 1945                         return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
 1946 
 1947                 default:
 1948                         return (zfs_standard_error(hdl, errno, errbuf));
 1949                 }
 1950         } else {
 1951                 if (redact_book != NULL)
 1952                         free(redact_book);
 1953         }
 1954 
 1955         zfs_close(zhp);
 1956 
 1957         return (error);
 1958 }
 1959 
 1960 struct zfs_send_resume_impl {
 1961         libzfs_handle_t *hdl;
 1962         sendflags_t *flags;
 1963         nvlist_t *resume_nvl;
 1964 };
 1965 
 1966 static int
 1967 zfs_send_resume_impl_cb(int outfd, void *arg)
 1968 {
 1969         struct zfs_send_resume_impl *zsri = arg;
 1970         return (zfs_send_resume_impl_cb_impl(zsri->hdl, zsri->flags, outfd,
 1971             zsri->resume_nvl));
 1972 }
 1973 
 1974 static int
 1975 zfs_send_resume_impl(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
 1976     nvlist_t *resume_nvl)
 1977 {
 1978         struct zfs_send_resume_impl zsri = {
 1979                 .hdl = hdl,
 1980                 .flags = flags,
 1981                 .resume_nvl = resume_nvl,
 1982         };
 1983         return (lzc_send_wrapper(zfs_send_resume_impl_cb, outfd, &zsri));
 1984 }
 1985 
 1986 int
 1987 zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
 1988     const char *resume_token)
 1989 {
 1990         int ret;
 1991         char errbuf[ERRBUFLEN];
 1992         nvlist_t *resume_nvl;
 1993 
 1994         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 1995             "cannot resume send"));
 1996 
 1997         resume_nvl = zfs_send_resume_token_to_nvlist(hdl, resume_token);
 1998         if (resume_nvl == NULL) {
 1999                 /*
 2000                  * zfs_error_aux has already been set by
 2001                  * zfs_send_resume_token_to_nvlist()
 2002                  */
 2003                 return (zfs_error(hdl, EZFS_FAULT, errbuf));
 2004         }
 2005 
 2006         ret = zfs_send_resume_impl(hdl, flags, outfd, resume_nvl);
 2007         fnvlist_free(resume_nvl);
 2008 
 2009         return (ret);
 2010 }
 2011 
 2012 int
 2013 zfs_send_saved(zfs_handle_t *zhp, sendflags_t *flags, int outfd,
 2014     const char *resume_token)
 2015 {
 2016         int ret;
 2017         libzfs_handle_t *hdl = zhp->zfs_hdl;
 2018         nvlist_t *saved_nvl = NULL, *resume_nvl = NULL;
 2019         uint64_t saved_guid = 0, resume_guid = 0;
 2020         uint64_t obj = 0, off = 0, bytes = 0;
 2021         char token_buf[ZFS_MAXPROPLEN];
 2022         char errbuf[ERRBUFLEN];
 2023 
 2024         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 2025             "saved send failed"));
 2026 
 2027         ret = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
 2028             token_buf, sizeof (token_buf), NULL, NULL, 0, B_TRUE);
 2029         if (ret != 0)
 2030                 goto out;
 2031 
 2032         saved_nvl = zfs_send_resume_token_to_nvlist(hdl, token_buf);
 2033         if (saved_nvl == NULL) {
 2034                 /*
 2035                  * zfs_error_aux has already been set by
 2036                  * zfs_send_resume_token_to_nvlist()
 2037                  */
 2038                 ret = zfs_error(hdl, EZFS_FAULT, errbuf);
 2039                 goto out;
 2040         }
 2041 
 2042         /*
 2043          * If a resume token is provided we use the object and offset
 2044          * from that instead of the default, which starts from the
 2045          * beginning.
 2046          */
 2047         if (resume_token != NULL) {
 2048                 resume_nvl = zfs_send_resume_token_to_nvlist(hdl,
 2049                     resume_token);
 2050                 if (resume_nvl == NULL) {
 2051                         ret = zfs_error(hdl, EZFS_FAULT, errbuf);
 2052                         goto out;
 2053                 }
 2054 
 2055                 if (nvlist_lookup_uint64(resume_nvl, "object", &obj) != 0 ||
 2056                     nvlist_lookup_uint64(resume_nvl, "offset", &off) != 0 ||
 2057                     nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 ||
 2058                     nvlist_lookup_uint64(resume_nvl, "toguid",
 2059                     &resume_guid) != 0) {
 2060                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2061                             "provided resume token is corrupt"));
 2062                         ret = zfs_error(hdl, EZFS_FAULT, errbuf);
 2063                         goto out;
 2064                 }
 2065 
 2066                 if (nvlist_lookup_uint64(saved_nvl, "toguid",
 2067                     &saved_guid)) {
 2068                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2069                             "dataset's resume token is corrupt"));
 2070                         ret = zfs_error(hdl, EZFS_FAULT, errbuf);
 2071                         goto out;
 2072                 }
 2073 
 2074                 if (resume_guid != saved_guid) {
 2075                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2076                             "provided resume token does not match dataset"));
 2077                         ret = zfs_error(hdl, EZFS_BADBACKUP, errbuf);
 2078                         goto out;
 2079                 }
 2080         }
 2081 
 2082         (void) nvlist_remove_all(saved_nvl, "object");
 2083         fnvlist_add_uint64(saved_nvl, "object", obj);
 2084 
 2085         (void) nvlist_remove_all(saved_nvl, "offset");
 2086         fnvlist_add_uint64(saved_nvl, "offset", off);
 2087 
 2088         (void) nvlist_remove_all(saved_nvl, "bytes");
 2089         fnvlist_add_uint64(saved_nvl, "bytes", bytes);
 2090 
 2091         (void) nvlist_remove_all(saved_nvl, "toname");
 2092         fnvlist_add_string(saved_nvl, "toname", zhp->zfs_name);
 2093 
 2094         ret = zfs_send_resume_impl(hdl, flags, outfd, saved_nvl);
 2095 
 2096 out:
 2097         fnvlist_free(saved_nvl);
 2098         fnvlist_free(resume_nvl);
 2099         return (ret);
 2100 }
 2101 
 2102 /*
 2103  * This function informs the target system that the recursive send is complete.
 2104  * The record is also expected in the case of a send -p.
 2105  */
 2106 static int
 2107 send_conclusion_record(int fd, zio_cksum_t *zc)
 2108 {
 2109         dmu_replay_record_t drr = { 0 };
 2110         drr.drr_type = DRR_END;
 2111         if (zc != NULL)
 2112                 drr.drr_u.drr_end.drr_checksum = *zc;
 2113         if (write(fd, &drr, sizeof (drr)) == -1) {
 2114                 return (errno);
 2115         }
 2116         return (0);
 2117 }
 2118 
 2119 /*
 2120  * This function is responsible for sending the records that contain the
 2121  * necessary information for the target system's libzfs to be able to set the
 2122  * properties of the filesystem being received, or to be able to prepare for
 2123  * a recursive receive.
 2124  *
 2125  * The "zhp" argument is the handle of the snapshot we are sending
 2126  * (the "tosnap").  The "from" argument is the short snapshot name (the part
 2127  * after the @) of the incremental source.
 2128  */
 2129 static int
 2130 send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
 2131     boolean_t gather_props, boolean_t recursive, boolean_t verbose,
 2132     boolean_t dryrun, boolean_t raw, boolean_t replicate, boolean_t skipmissing,
 2133     boolean_t backup, boolean_t holds, boolean_t props, boolean_t doall,
 2134     nvlist_t **fssp, avl_tree_t **fsavlp)
 2135 {
 2136         int err = 0;
 2137         char *packbuf = NULL;
 2138         size_t buflen = 0;
 2139         zio_cksum_t zc = { {0} };
 2140         int featureflags = 0;
 2141         /* name of filesystem/volume that contains snapshot we are sending */
 2142         char tofs[ZFS_MAX_DATASET_NAME_LEN];
 2143         /* short name of snap we are sending */
 2144         const char *tosnap = "";
 2145 
 2146         char errbuf[ERRBUFLEN];
 2147         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 2148             "warning: cannot send '%s'"), zhp->zfs_name);
 2149         if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM && zfs_prop_get_int(zhp,
 2150             ZFS_PROP_VERSION) >= ZPL_VERSION_SA) {
 2151                 featureflags |= DMU_BACKUP_FEATURE_SA_SPILL;
 2152         }
 2153 
 2154         if (holds)
 2155                 featureflags |= DMU_BACKUP_FEATURE_HOLDS;
 2156 
 2157         (void) strlcpy(tofs, zhp->zfs_name, ZFS_MAX_DATASET_NAME_LEN);
 2158         char *at = strchr(tofs, '@');
 2159         if (at != NULL) {
 2160                 *at = '\0';
 2161                 tosnap = at + 1;
 2162         }
 2163 
 2164         if (gather_props) {
 2165                 nvlist_t *hdrnv = fnvlist_alloc();
 2166                 nvlist_t *fss = NULL;
 2167 
 2168                 if (from != NULL)
 2169                         fnvlist_add_string(hdrnv, "fromsnap", from);
 2170                 fnvlist_add_string(hdrnv, "tosnap", tosnap);
 2171                 if (!recursive)
 2172                         fnvlist_add_boolean(hdrnv, "not_recursive");
 2173 
 2174                 if (raw) {
 2175                         fnvlist_add_boolean(hdrnv, "raw");
 2176                 }
 2177 
 2178                 if (gather_nvlist(zhp->zfs_hdl, tofs,
 2179                     from, tosnap, recursive, raw, doall, replicate, skipmissing,
 2180                     verbose, backup, holds, props, &fss, fsavlp) != 0) {
 2181                         return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
 2182                             errbuf));
 2183                 }
 2184                 /*
 2185                  * Do not allow the size of the properties list to exceed
 2186                  * the limit
 2187                  */
 2188                 if ((fnvlist_size(fss) + fnvlist_size(hdrnv)) >
 2189                     zhp->zfs_hdl->libzfs_max_nvlist) {
 2190                         (void) snprintf(errbuf, sizeof (errbuf),
 2191                             dgettext(TEXT_DOMAIN, "warning: cannot send '%s': "
 2192                             "the size of the list of snapshots and properties "
 2193                             "is too large to be received successfully.\n"
 2194                             "Select a smaller number of snapshots to send.\n"),
 2195                             zhp->zfs_name);
 2196                         return (zfs_error(zhp->zfs_hdl, EZFS_NOSPC,
 2197                             errbuf));
 2198                 }
 2199                 fnvlist_add_nvlist(hdrnv, "fss", fss);
 2200                 VERIFY0(nvlist_pack(hdrnv, &packbuf, &buflen, NV_ENCODE_XDR,
 2201                     0));
 2202                 if (fssp != NULL) {
 2203                         *fssp = fss;
 2204                 } else {
 2205                         fnvlist_free(fss);
 2206                 }
 2207                 fnvlist_free(hdrnv);
 2208         }
 2209 
 2210         if (!dryrun) {
 2211                 dmu_replay_record_t drr = { 0 };
 2212                 /* write first begin record */
 2213                 drr.drr_type = DRR_BEGIN;
 2214                 drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
 2215                 DMU_SET_STREAM_HDRTYPE(drr.drr_u.drr_begin.
 2216                     drr_versioninfo, DMU_COMPOUNDSTREAM);
 2217                 DMU_SET_FEATUREFLAGS(drr.drr_u.drr_begin.
 2218                     drr_versioninfo, featureflags);
 2219                 if (snprintf(drr.drr_u.drr_begin.drr_toname,
 2220                     sizeof (drr.drr_u.drr_begin.drr_toname), "%s@%s", tofs,
 2221                     tosnap) >= sizeof (drr.drr_u.drr_begin.drr_toname)) {
 2222                         return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
 2223                             errbuf));
 2224                 }
 2225                 drr.drr_payloadlen = buflen;
 2226 
 2227                 err = dump_record(&drr, packbuf, buflen, &zc, fd);
 2228                 free(packbuf);
 2229                 if (err != 0) {
 2230                         zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
 2231                         return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
 2232                             errbuf));
 2233                 }
 2234                 err = send_conclusion_record(fd, &zc);
 2235                 if (err != 0) {
 2236                         zfs_error_aux(zhp->zfs_hdl, "%s", strerror(err));
 2237                         return (zfs_error(zhp->zfs_hdl, EZFS_BADBACKUP,
 2238                             errbuf));
 2239                 }
 2240         }
 2241         return (0);
 2242 }
 2243 
 2244 /*
 2245  * Generate a send stream.  The "zhp" argument is the filesystem/volume
 2246  * that contains the snapshot to send.  The "fromsnap" argument is the
 2247  * short name (the part after the '@') of the snapshot that is the
 2248  * incremental source to send from (if non-NULL).  The "tosnap" argument
 2249  * is the short name of the snapshot to send.
 2250  *
 2251  * The content of the send stream is the snapshot identified by
 2252  * 'tosnap'.  Incremental streams are requested in two ways:
 2253  *     - from the snapshot identified by "fromsnap" (if non-null) or
 2254  *     - from the origin of the dataset identified by zhp, which must
 2255  *       be a clone.  In this case, "fromsnap" is null and "fromorigin"
 2256  *       is TRUE.
 2257  *
 2258  * The send stream is recursive (i.e. dumps a hierarchy of snapshots) and
 2259  * uses a special header (with a hdrtype field of DMU_COMPOUNDSTREAM)
 2260  * if "replicate" is set.  If "doall" is set, dump all the intermediate
 2261  * snapshots. The DMU_COMPOUNDSTREAM header is used in the "doall"
 2262  * case too. If "props" is set, send properties.
 2263  *
 2264  * Pre-wrapped (cf. lzc_send_wrapper()).
 2265  */
 2266 static int
 2267 zfs_send_cb_impl(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
 2268     sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
 2269     void *cb_arg, nvlist_t **debugnvp)
 2270 {
 2271         char errbuf[ERRBUFLEN];
 2272         send_dump_data_t sdd = { 0 };
 2273         int err = 0;
 2274         nvlist_t *fss = NULL;
 2275         avl_tree_t *fsavl = NULL;
 2276         static uint64_t holdseq;
 2277         int spa_version;
 2278         FILE *fout;
 2279 
 2280         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 2281             "cannot send '%s'"), zhp->zfs_name);
 2282 
 2283         if (fromsnap && fromsnap[0] == '\0') {
 2284                 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
 2285                     "zero-length incremental source"));
 2286                 return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
 2287         }
 2288 
 2289         if (fromsnap) {
 2290                 char full_fromsnap_name[ZFS_MAX_DATASET_NAME_LEN];
 2291                 if (snprintf(full_fromsnap_name, sizeof (full_fromsnap_name),
 2292                     "%s@%s", zhp->zfs_name, fromsnap) >=
 2293                     sizeof (full_fromsnap_name)) {
 2294                         err = EINVAL;
 2295                         goto stderr_out;
 2296                 }
 2297                 zfs_handle_t *fromsnapn = zfs_open(zhp->zfs_hdl,
 2298                     full_fromsnap_name, ZFS_TYPE_SNAPSHOT);
 2299                 if (fromsnapn == NULL) {
 2300                         err = -1;
 2301                         goto err_out;
 2302                 }
 2303                 zfs_close(fromsnapn);
 2304         }
 2305 
 2306         if (flags->replicate || flags->doall || flags->props ||
 2307             flags->holds || flags->backup) {
 2308                 char full_tosnap_name[ZFS_MAX_DATASET_NAME_LEN];
 2309                 if (snprintf(full_tosnap_name, sizeof (full_tosnap_name),
 2310                     "%s@%s", zhp->zfs_name, tosnap) >=
 2311                     sizeof (full_tosnap_name)) {
 2312                         err = EINVAL;
 2313                         goto stderr_out;
 2314                 }
 2315                 zfs_handle_t *tosnap = zfs_open(zhp->zfs_hdl,
 2316                     full_tosnap_name, ZFS_TYPE_SNAPSHOT);
 2317                 if (tosnap == NULL) {
 2318                         err = -1;
 2319                         goto err_out;
 2320                 }
 2321                 err = send_prelim_records(tosnap, fromsnap, outfd,
 2322                     flags->replicate || flags->props || flags->holds,
 2323                     flags->replicate, flags->verbosity > 0, flags->dryrun,
 2324                     flags->raw, flags->replicate, flags->skipmissing,
 2325                     flags->backup, flags->holds, flags->props, flags->doall,
 2326                     &fss, &fsavl);
 2327                 zfs_close(tosnap);
 2328                 if (err != 0)
 2329                         goto err_out;
 2330         }
 2331 
 2332         /* dump each stream */
 2333         sdd.fromsnap = fromsnap;
 2334         sdd.tosnap = tosnap;
 2335         sdd.outfd = outfd;
 2336         sdd.replicate = flags->replicate;
 2337         sdd.doall = flags->doall;
 2338         sdd.fromorigin = flags->fromorigin;
 2339         sdd.fss = fss;
 2340         sdd.fsavl = fsavl;
 2341         sdd.verbosity = flags->verbosity;
 2342         sdd.parsable = flags->parsable;
 2343         sdd.progress = flags->progress;
 2344         sdd.progressastitle = flags->progressastitle;
 2345         sdd.dryrun = flags->dryrun;
 2346         sdd.large_block = flags->largeblock;
 2347         sdd.embed_data = flags->embed_data;
 2348         sdd.compress = flags->compress;
 2349         sdd.raw = flags->raw;
 2350         sdd.holds = flags->holds;
 2351         sdd.filter_cb = filter_func;
 2352         sdd.filter_cb_arg = cb_arg;
 2353         if (debugnvp)
 2354                 sdd.debugnv = *debugnvp;
 2355         if (sdd.verbosity != 0 && sdd.dryrun)
 2356                 sdd.std_out = B_TRUE;
 2357         fout = sdd.std_out ? stdout : stderr;
 2358 
 2359         /*
 2360          * Some flags require that we place user holds on the datasets that are
 2361          * being sent so they don't get destroyed during the send. We can skip
 2362          * this step if the pool is imported read-only since the datasets cannot
 2363          * be destroyed.
 2364          */
 2365         if (!flags->dryrun && !zpool_get_prop_int(zfs_get_pool_handle(zhp),
 2366             ZPOOL_PROP_READONLY, NULL) &&
 2367             zfs_spa_version(zhp, &spa_version) == 0 &&
 2368             spa_version >= SPA_VERSION_USERREFS &&
 2369             (flags->doall || flags->replicate)) {
 2370                 ++holdseq;
 2371                 (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
 2372                     ".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
 2373                 sdd.cleanup_fd = open(ZFS_DEV, O_RDWR | O_CLOEXEC);
 2374                 if (sdd.cleanup_fd < 0) {
 2375                         err = errno;
 2376                         goto stderr_out;
 2377                 }
 2378                 sdd.snapholds = fnvlist_alloc();
 2379         } else {
 2380                 sdd.cleanup_fd = -1;
 2381                 sdd.snapholds = NULL;
 2382         }
 2383 
 2384         if (flags->verbosity != 0 || sdd.snapholds != NULL) {
 2385                 /*
 2386                  * Do a verbose no-op dry run to get all the verbose output
 2387                  * or to gather snapshot hold's before generating any data,
 2388                  * then do a non-verbose real run to generate the streams.
 2389                  */
 2390                 sdd.dryrun = B_TRUE;
 2391                 err = dump_filesystems(zhp, &sdd);
 2392 
 2393                 if (err != 0)
 2394                         goto stderr_out;
 2395 
 2396                 if (flags->verbosity != 0) {
 2397                         if (flags->parsable) {
 2398                                 (void) fprintf(fout, "size\t%llu\n",
 2399                                     (longlong_t)sdd.size);
 2400                         } else {
 2401                                 char buf[16];
 2402                                 zfs_nicebytes(sdd.size, buf, sizeof (buf));
 2403                                 (void) fprintf(fout, dgettext(TEXT_DOMAIN,
 2404                                     "total estimated size is %s\n"), buf);
 2405                         }
 2406                 }
 2407 
 2408                 /* Ensure no snaps found is treated as an error. */
 2409                 if (!sdd.seento) {
 2410                         err = ENOENT;
 2411                         goto err_out;
 2412                 }
 2413 
 2414                 /* Skip the second run if dryrun was requested. */
 2415                 if (flags->dryrun)
 2416                         goto err_out;
 2417 
 2418                 if (sdd.snapholds != NULL) {
 2419                         err = zfs_hold_nvl(zhp, sdd.cleanup_fd, sdd.snapholds);
 2420                         if (err != 0)
 2421                                 goto stderr_out;
 2422 
 2423                         fnvlist_free(sdd.snapholds);
 2424                         sdd.snapholds = NULL;
 2425                 }
 2426 
 2427                 sdd.dryrun = B_FALSE;
 2428                 sdd.verbosity = 0;
 2429         }
 2430 
 2431         err = dump_filesystems(zhp, &sdd);
 2432         fsavl_destroy(fsavl);
 2433         fnvlist_free(fss);
 2434 
 2435         /* Ensure no snaps found is treated as an error. */
 2436         if (err == 0 && !sdd.seento)
 2437                 err = ENOENT;
 2438 
 2439         if (sdd.cleanup_fd != -1) {
 2440                 VERIFY(0 == close(sdd.cleanup_fd));
 2441                 sdd.cleanup_fd = -1;
 2442         }
 2443 
 2444         if (!flags->dryrun && (flags->replicate || flags->doall ||
 2445             flags->props || flags->backup || flags->holds)) {
 2446                 /*
 2447                  * write final end record.  NB: want to do this even if
 2448                  * there was some error, because it might not be totally
 2449                  * failed.
 2450                  */
 2451                 int err2 = send_conclusion_record(outfd, NULL);
 2452                 if (err2 != 0)
 2453                         return (zfs_standard_error(zhp->zfs_hdl, err2, errbuf));
 2454         }
 2455 
 2456         return (err || sdd.err);
 2457 
 2458 stderr_out:
 2459         err = zfs_standard_error(zhp->zfs_hdl, err, errbuf);
 2460 err_out:
 2461         fsavl_destroy(fsavl);
 2462         fnvlist_free(fss);
 2463         fnvlist_free(sdd.snapholds);
 2464 
 2465         if (sdd.cleanup_fd != -1)
 2466                 VERIFY(0 == close(sdd.cleanup_fd));
 2467         return (err);
 2468 }
 2469 
 2470 struct zfs_send {
 2471         zfs_handle_t *zhp;
 2472         const char *fromsnap;
 2473         const char *tosnap;
 2474         sendflags_t *flags;
 2475         snapfilter_cb_t *filter_func;
 2476         void *cb_arg;
 2477         nvlist_t **debugnvp;
 2478 };
 2479 
 2480 static int
 2481 zfs_send_cb(int outfd, void *arg)
 2482 {
 2483         struct zfs_send *zs = arg;
 2484         return (zfs_send_cb_impl(zs->zhp, zs->fromsnap, zs->tosnap, zs->flags,
 2485             outfd, zs->filter_func, zs->cb_arg, zs->debugnvp));
 2486 }
 2487 
 2488 int
 2489 zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
 2490     sendflags_t *flags, int outfd, snapfilter_cb_t filter_func,
 2491     void *cb_arg, nvlist_t **debugnvp)
 2492 {
 2493         struct zfs_send arg = {
 2494                 .zhp = zhp,
 2495                 .fromsnap = fromsnap,
 2496                 .tosnap = tosnap,
 2497                 .flags = flags,
 2498                 .filter_func = filter_func,
 2499                 .cb_arg = cb_arg,
 2500                 .debugnvp = debugnvp,
 2501         };
 2502         return (lzc_send_wrapper(zfs_send_cb, outfd, &arg));
 2503 }
 2504 
 2505 
 2506 static zfs_handle_t *
 2507 name_to_dir_handle(libzfs_handle_t *hdl, const char *snapname)
 2508 {
 2509         char dirname[ZFS_MAX_DATASET_NAME_LEN];
 2510         (void) strlcpy(dirname, snapname, ZFS_MAX_DATASET_NAME_LEN);
 2511         char *c = strchr(dirname, '@');
 2512         if (c != NULL)
 2513                 *c = '\0';
 2514         return (zfs_open(hdl, dirname, ZFS_TYPE_DATASET));
 2515 }
 2516 
 2517 /*
 2518  * Returns B_TRUE if earlier is an earlier snapshot in later's timeline; either
 2519  * an earlier snapshot in the same filesystem, or a snapshot before later's
 2520  * origin, or it's origin's origin, etc.
 2521  */
 2522 static boolean_t
 2523 snapshot_is_before(zfs_handle_t *earlier, zfs_handle_t *later)
 2524 {
 2525         boolean_t ret;
 2526         uint64_t later_txg =
 2527             (later->zfs_type == ZFS_TYPE_FILESYSTEM ||
 2528             later->zfs_type == ZFS_TYPE_VOLUME ?
 2529             UINT64_MAX : zfs_prop_get_int(later, ZFS_PROP_CREATETXG));
 2530         uint64_t earlier_txg = zfs_prop_get_int(earlier, ZFS_PROP_CREATETXG);
 2531 
 2532         if (earlier_txg >= later_txg)
 2533                 return (B_FALSE);
 2534 
 2535         zfs_handle_t *earlier_dir = name_to_dir_handle(earlier->zfs_hdl,
 2536             earlier->zfs_name);
 2537         zfs_handle_t *later_dir = name_to_dir_handle(later->zfs_hdl,
 2538             later->zfs_name);
 2539 
 2540         if (strcmp(earlier_dir->zfs_name, later_dir->zfs_name) == 0) {
 2541                 zfs_close(earlier_dir);
 2542                 zfs_close(later_dir);
 2543                 return (B_TRUE);
 2544         }
 2545 
 2546         char clonename[ZFS_MAX_DATASET_NAME_LEN];
 2547         if (zfs_prop_get(later_dir, ZFS_PROP_ORIGIN, clonename,
 2548             ZFS_MAX_DATASET_NAME_LEN, NULL, NULL, 0, B_TRUE) != 0) {
 2549                 zfs_close(earlier_dir);
 2550                 zfs_close(later_dir);
 2551                 return (B_FALSE);
 2552         }
 2553 
 2554         zfs_handle_t *origin = zfs_open(earlier->zfs_hdl, clonename,
 2555             ZFS_TYPE_DATASET);
 2556         uint64_t origin_txg = zfs_prop_get_int(origin, ZFS_PROP_CREATETXG);
 2557 
 2558         /*
 2559          * If "earlier" is exactly the origin, then
 2560          * snapshot_is_before(earlier, origin) will return false (because
 2561          * they're the same).
 2562          */
 2563         if (origin_txg == earlier_txg &&
 2564             strcmp(origin->zfs_name, earlier->zfs_name) == 0) {
 2565                 zfs_close(earlier_dir);
 2566                 zfs_close(later_dir);
 2567                 zfs_close(origin);
 2568                 return (B_TRUE);
 2569         }
 2570         zfs_close(earlier_dir);
 2571         zfs_close(later_dir);
 2572 
 2573         ret = snapshot_is_before(earlier, origin);
 2574         zfs_close(origin);
 2575         return (ret);
 2576 }
 2577 
 2578 /*
 2579  * The "zhp" argument is the handle of the dataset to send (typically a
 2580  * snapshot).  The "from" argument is the full name of the snapshot or
 2581  * bookmark that is the incremental source.
 2582  *
 2583  * Pre-wrapped (cf. lzc_send_wrapper()).
 2584  */
 2585 static int
 2586 zfs_send_one_cb_impl(zfs_handle_t *zhp, const char *from, int fd,
 2587     sendflags_t *flags, const char *redactbook)
 2588 {
 2589         int err;
 2590         libzfs_handle_t *hdl = zhp->zfs_hdl;
 2591         char *name = zhp->zfs_name;
 2592         pthread_t ptid;
 2593         progress_arg_t pa = { 0 };
 2594         uint64_t size = 0;
 2595 
 2596         char errbuf[ERRBUFLEN];
 2597         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 2598             "warning: cannot send '%s'"), name);
 2599 
 2600         if (from != NULL && strchr(from, '@')) {
 2601                 zfs_handle_t *from_zhp = zfs_open(hdl, from,
 2602                     ZFS_TYPE_DATASET);
 2603                 if (from_zhp == NULL)
 2604                         return (-1);
 2605                 if (!snapshot_is_before(from_zhp, zhp)) {
 2606                         zfs_close(from_zhp);
 2607                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2608                             "not an earlier snapshot from the same fs"));
 2609                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
 2610                 }
 2611                 zfs_close(from_zhp);
 2612         }
 2613 
 2614         if (redactbook != NULL) {
 2615                 char bookname[ZFS_MAX_DATASET_NAME_LEN];
 2616                 nvlist_t *redact_snaps;
 2617                 zfs_handle_t *book_zhp;
 2618                 char *at, *pound;
 2619                 int dsnamelen;
 2620 
 2621                 pound = strchr(redactbook, '#');
 2622                 if (pound != NULL)
 2623                         redactbook = pound + 1;
 2624                 at = strchr(name, '@');
 2625                 if (at == NULL) {
 2626                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2627                             "cannot do a redacted send to a filesystem"));
 2628                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
 2629                 }
 2630                 dsnamelen = at - name;
 2631                 if (snprintf(bookname, sizeof (bookname), "%.*s#%s",
 2632                     dsnamelen, name, redactbook)
 2633                     >= sizeof (bookname)) {
 2634                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2635                             "invalid bookmark name"));
 2636                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
 2637                 }
 2638                 book_zhp = zfs_open(hdl, bookname, ZFS_TYPE_BOOKMARK);
 2639                 if (book_zhp == NULL)
 2640                         return (-1);
 2641                 if (nvlist_lookup_nvlist(book_zhp->zfs_props,
 2642                     zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS),
 2643                     &redact_snaps) != 0 || redact_snaps == NULL) {
 2644                         zfs_close(book_zhp);
 2645                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2646                             "not a redaction bookmark"));
 2647                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
 2648                 }
 2649                 zfs_close(book_zhp);
 2650         }
 2651 
 2652         /*
 2653          * Send fs properties
 2654          */
 2655         if (flags->props || flags->holds || flags->backup) {
 2656                 /*
 2657                  * Note: the header generated by send_prelim_records()
 2658                  * assumes that the incremental source is in the same
 2659                  * filesystem/volume as the target (which is a requirement
 2660                  * when doing "zfs send -R").  But that isn't always the
 2661                  * case here (e.g. send from snap in origin, or send from
 2662                  * bookmark).  We pass from=NULL, which will omit this
 2663                  * information from the prelim records; it isn't used
 2664                  * when receiving this type of stream.
 2665                  */
 2666                 err = send_prelim_records(zhp, NULL, fd, B_TRUE, B_FALSE,
 2667                     flags->verbosity > 0, flags->dryrun, flags->raw,
 2668                     flags->replicate, B_FALSE, flags->backup, flags->holds,
 2669                     flags->props, flags->doall, NULL, NULL);
 2670                 if (err != 0)
 2671                         return (err);
 2672         }
 2673 
 2674         /*
 2675          * Perform size estimate if verbose was specified.
 2676          */
 2677         if (flags->verbosity != 0 || flags->progressastitle) {
 2678                 err = estimate_size(zhp, from, fd, flags, 0, 0, 0, redactbook,
 2679                     errbuf, &size);
 2680                 if (err != 0)
 2681                         return (err);
 2682         }
 2683 
 2684         if (flags->dryrun)
 2685                 return (0);
 2686 
 2687         /*
 2688          * If progress reporting is requested, spawn a new thread to poll
 2689          * ZFS_IOC_SEND_PROGRESS at a regular interval.
 2690          */
 2691         if (flags->progress || flags->progressastitle) {
 2692                 pa.pa_zhp = zhp;
 2693                 pa.pa_fd = fd;
 2694                 pa.pa_parsable = flags->parsable;
 2695                 pa.pa_estimate = B_FALSE;
 2696                 pa.pa_verbosity = flags->verbosity;
 2697                 pa.pa_size = size;
 2698                 pa.pa_astitle = flags->progressastitle;
 2699 
 2700                 err = pthread_create(&ptid, NULL,
 2701                     send_progress_thread, &pa);
 2702                 if (err != 0) {
 2703                         zfs_error_aux(zhp->zfs_hdl, "%s", strerror(errno));
 2704                         return (zfs_error(zhp->zfs_hdl,
 2705                             EZFS_THREADCREATEFAILED, errbuf));
 2706                 }
 2707         }
 2708 
 2709         err = lzc_send_redacted(name, from, fd,
 2710             lzc_flags_from_sendflags(flags), redactbook);
 2711 
 2712         if ((flags->progress || flags->progressastitle) &&
 2713             send_progress_thread_exit(hdl, ptid))
 2714                         return (-1);
 2715 
 2716         if (err == 0 && (flags->props || flags->holds || flags->backup)) {
 2717                 /* Write the final end record. */
 2718                 err = send_conclusion_record(fd, NULL);
 2719                 if (err != 0)
 2720                         return (zfs_standard_error(hdl, err, errbuf));
 2721         }
 2722         if (err != 0) {
 2723                 switch (errno) {
 2724                 case EXDEV:
 2725                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2726                             "not an earlier snapshot from the same fs"));
 2727                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
 2728 
 2729                 case ENOENT:
 2730                 case ESRCH:
 2731                         if (lzc_exists(name)) {
 2732                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2733                                     "incremental source (%s) does not exist"),
 2734                                     from);
 2735                         }
 2736                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
 2737 
 2738                 case EACCES:
 2739                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2740                             "dataset key must be loaded"));
 2741                         return (zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf));
 2742 
 2743                 case EBUSY:
 2744                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2745                             "target is busy; if a filesystem, "
 2746                             "it must not be mounted"));
 2747                         return (zfs_error(hdl, EZFS_BUSY, errbuf));
 2748 
 2749                 case EDQUOT:
 2750                 case EFAULT:
 2751                 case EFBIG:
 2752                 case EINVAL:
 2753                 case EIO:
 2754                 case ENOLINK:
 2755                 case ENOSPC:
 2756                 case ENOSTR:
 2757                 case ENXIO:
 2758                 case EPIPE:
 2759                 case ERANGE:
 2760                 case EROFS:
 2761                         zfs_error_aux(hdl, "%s", strerror(errno));
 2762                         return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
 2763 
 2764                 default:
 2765                         return (zfs_standard_error(hdl, errno, errbuf));
 2766                 }
 2767         }
 2768         return (err != 0);
 2769 }
 2770 
 2771 struct zfs_send_one {
 2772         zfs_handle_t *zhp;
 2773         const char *from;
 2774         sendflags_t *flags;
 2775         const char *redactbook;
 2776 };
 2777 
 2778 static int
 2779 zfs_send_one_cb(int fd, void *arg)
 2780 {
 2781         struct zfs_send_one *zso = arg;
 2782         return (zfs_send_one_cb_impl(zso->zhp, zso->from, fd, zso->flags,
 2783             zso->redactbook));
 2784 }
 2785 
 2786 int
 2787 zfs_send_one(zfs_handle_t *zhp, const char *from, int fd, sendflags_t *flags,
 2788     const char *redactbook)
 2789 {
 2790         struct zfs_send_one zso = {
 2791                 .zhp = zhp,
 2792                 .from = from,
 2793                 .flags = flags,
 2794                 .redactbook = redactbook,
 2795         };
 2796         return (lzc_send_wrapper(zfs_send_one_cb, fd, &zso));
 2797 }
 2798 
 2799 /*
 2800  * Routines specific to "zfs recv"
 2801  */
 2802 
 2803 static int
 2804 recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen,
 2805     boolean_t byteswap, zio_cksum_t *zc)
 2806 {
 2807         char *cp = buf;
 2808         int rv;
 2809         int len = ilen;
 2810 
 2811         do {
 2812                 rv = read(fd, cp, len);
 2813                 cp += rv;
 2814                 len -= rv;
 2815         } while (rv > 0);
 2816 
 2817         if (rv < 0 || len != 0) {
 2818                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 2819                     "failed to read from stream"));
 2820                 return (zfs_error(hdl, EZFS_BADSTREAM, dgettext(TEXT_DOMAIN,
 2821                     "cannot receive")));
 2822         }
 2823 
 2824         if (zc) {
 2825                 if (byteswap)
 2826                         fletcher_4_incremental_byteswap(buf, ilen, zc);
 2827                 else
 2828                         fletcher_4_incremental_native(buf, ilen, zc);
 2829         }
 2830         return (0);
 2831 }
 2832 
 2833 static int
 2834 recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp,
 2835     boolean_t byteswap, zio_cksum_t *zc)
 2836 {
 2837         char *buf;
 2838         int err;
 2839 
 2840         buf = zfs_alloc(hdl, len);
 2841 
 2842         if (len > hdl->libzfs_max_nvlist) {
 2843                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "nvlist too large"));
 2844                 free(buf);
 2845                 return (ENOMEM);
 2846         }
 2847 
 2848         err = recv_read(hdl, fd, buf, len, byteswap, zc);
 2849         if (err != 0) {
 2850                 free(buf);
 2851                 return (err);
 2852         }
 2853 
 2854         err = nvlist_unpack(buf, len, nvp, 0);
 2855         free(buf);
 2856         if (err != 0) {
 2857                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
 2858                     "stream (malformed nvlist)"));
 2859                 return (EINVAL);
 2860         }
 2861         return (0);
 2862 }
 2863 
 2864 /*
 2865  * Returns the grand origin (origin of origin of origin...) of a given handle.
 2866  * If this dataset is not a clone, it simply returns a copy of the original
 2867  * handle.
 2868  */
 2869 static zfs_handle_t *
 2870 recv_open_grand_origin(zfs_handle_t *zhp)
 2871 {
 2872         char origin[ZFS_MAX_DATASET_NAME_LEN];
 2873         zprop_source_t src;
 2874         zfs_handle_t *ozhp = zfs_handle_dup(zhp);
 2875 
 2876         while (ozhp != NULL) {
 2877                 if (zfs_prop_get(ozhp, ZFS_PROP_ORIGIN, origin,
 2878                     sizeof (origin), &src, NULL, 0, B_FALSE) != 0)
 2879                         break;
 2880 
 2881                 (void) zfs_close(ozhp);
 2882                 ozhp = zfs_open(zhp->zfs_hdl, origin, ZFS_TYPE_FILESYSTEM);
 2883         }
 2884 
 2885         return (ozhp);
 2886 }
 2887 
 2888 static int
 2889 recv_rename_impl(zfs_handle_t *zhp, const char *name, const char *newname)
 2890 {
 2891         int err;
 2892         zfs_handle_t *ozhp = NULL;
 2893 
 2894         /*
 2895          * Attempt to rename the dataset. If it fails with EACCES we have
 2896          * attempted to rename the dataset outside of its encryption root.
 2897          * Force the dataset to become an encryption root and try again.
 2898          */
 2899         err = lzc_rename(name, newname);
 2900         if (err == EACCES) {
 2901                 ozhp = recv_open_grand_origin(zhp);
 2902                 if (ozhp == NULL) {
 2903                         err = ENOENT;
 2904                         goto out;
 2905                 }
 2906 
 2907                 err = lzc_change_key(ozhp->zfs_name, DCP_CMD_FORCE_NEW_KEY,
 2908                     NULL, NULL, 0);
 2909                 if (err != 0)
 2910                         goto out;
 2911 
 2912                 err = lzc_rename(name, newname);
 2913         }
 2914 
 2915 out:
 2916         if (ozhp != NULL)
 2917                 zfs_close(ozhp);
 2918         return (err);
 2919 }
 2920 
 2921 static int
 2922 recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
 2923     int baselen, char *newname, recvflags_t *flags)
 2924 {
 2925         static int seq;
 2926         int err;
 2927         prop_changelist_t *clp = NULL;
 2928         zfs_handle_t *zhp = NULL;
 2929 
 2930         zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
 2931         if (zhp == NULL) {
 2932                 err = -1;
 2933                 goto out;
 2934         }
 2935         clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
 2936             flags->force ? MS_FORCE : 0);
 2937         if (clp == NULL) {
 2938                 err = -1;
 2939                 goto out;
 2940         }
 2941         err = changelist_prefix(clp);
 2942         if (err)
 2943                 goto out;
 2944 
 2945         if (tryname) {
 2946                 (void) strlcpy(newname, tryname, ZFS_MAX_DATASET_NAME_LEN);
 2947                 if (flags->verbose) {
 2948                         (void) printf("attempting rename %s to %s\n",
 2949                             name, newname);
 2950                 }
 2951                 err = recv_rename_impl(zhp, name, newname);
 2952                 if (err == 0)
 2953                         changelist_rename(clp, name, tryname);
 2954         } else {
 2955                 err = ENOENT;
 2956         }
 2957 
 2958         if (err != 0 && strncmp(name + baselen, "recv-", 5) != 0) {
 2959                 seq++;
 2960 
 2961                 (void) snprintf(newname, ZFS_MAX_DATASET_NAME_LEN,
 2962                     "%.*srecv-%u-%u", baselen, name, getpid(), seq);
 2963 
 2964                 if (flags->verbose) {
 2965                         (void) printf("failed - trying rename %s to %s\n",
 2966                             name, newname);
 2967                 }
 2968                 err = recv_rename_impl(zhp, name, newname);
 2969                 if (err == 0)
 2970                         changelist_rename(clp, name, newname);
 2971                 if (err && flags->verbose) {
 2972                         (void) printf("failed (%u) - "
 2973                             "will try again on next pass\n", errno);
 2974                 }
 2975                 err = EAGAIN;
 2976         } else if (flags->verbose) {
 2977                 if (err == 0)
 2978                         (void) printf("success\n");
 2979                 else
 2980                         (void) printf("failed (%u)\n", errno);
 2981         }
 2982 
 2983         (void) changelist_postfix(clp);
 2984 
 2985 out:
 2986         if (clp != NULL)
 2987                 changelist_free(clp);
 2988         if (zhp != NULL)
 2989                 zfs_close(zhp);
 2990 
 2991         return (err);
 2992 }
 2993 
 2994 static int
 2995 recv_promote(libzfs_handle_t *hdl, const char *fsname,
 2996     const char *origin_fsname, recvflags_t *flags)
 2997 {
 2998         int err;
 2999         zfs_cmd_t zc = {"\0"};
 3000         zfs_handle_t *zhp = NULL, *ozhp = NULL;
 3001 
 3002         if (flags->verbose)
 3003                 (void) printf("promoting %s\n", fsname);
 3004 
 3005         (void) strlcpy(zc.zc_value, origin_fsname, sizeof (zc.zc_value));
 3006         (void) strlcpy(zc.zc_name, fsname, sizeof (zc.zc_name));
 3007 
 3008         /*
 3009          * Attempt to promote the dataset. If it fails with EACCES the
 3010          * promotion would cause this dataset to leave its encryption root.
 3011          * Force the origin to become an encryption root and try again.
 3012          */
 3013         err = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
 3014         if (err == EACCES) {
 3015                 zhp = zfs_open(hdl, fsname, ZFS_TYPE_DATASET);
 3016                 if (zhp == NULL) {
 3017                         err = -1;
 3018                         goto out;
 3019                 }
 3020 
 3021                 ozhp = recv_open_grand_origin(zhp);
 3022                 if (ozhp == NULL) {
 3023                         err = -1;
 3024                         goto out;
 3025                 }
 3026 
 3027                 err = lzc_change_key(ozhp->zfs_name, DCP_CMD_FORCE_NEW_KEY,
 3028                     NULL, NULL, 0);
 3029                 if (err != 0)
 3030                         goto out;
 3031 
 3032                 err = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
 3033         }
 3034 
 3035 out:
 3036         if (zhp != NULL)
 3037                 zfs_close(zhp);
 3038         if (ozhp != NULL)
 3039                 zfs_close(ozhp);
 3040 
 3041         return (err);
 3042 }
 3043 
 3044 static int
 3045 recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
 3046     char *newname, recvflags_t *flags)
 3047 {
 3048         int err = 0;
 3049         prop_changelist_t *clp;
 3050         zfs_handle_t *zhp;
 3051         boolean_t defer = B_FALSE;
 3052         int spa_version;
 3053 
 3054         zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
 3055         if (zhp == NULL)
 3056                 return (-1);
 3057         zfs_type_t type = zfs_get_type(zhp);
 3058         if (type == ZFS_TYPE_SNAPSHOT &&
 3059             zfs_spa_version(zhp, &spa_version) == 0 &&
 3060             spa_version >= SPA_VERSION_USERREFS)
 3061                 defer = B_TRUE;
 3062         clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
 3063             flags->force ? MS_FORCE : 0);
 3064         zfs_close(zhp);
 3065         if (clp == NULL)
 3066                 return (-1);
 3067 
 3068         err = changelist_prefix(clp);
 3069         if (err)
 3070                 return (err);
 3071 
 3072         if (flags->verbose)
 3073                 (void) printf("attempting destroy %s\n", name);
 3074         if (type == ZFS_TYPE_SNAPSHOT) {
 3075                 nvlist_t *nv = fnvlist_alloc();
 3076                 fnvlist_add_boolean(nv, name);
 3077                 err = lzc_destroy_snaps(nv, defer, NULL);
 3078                 fnvlist_free(nv);
 3079         } else {
 3080                 err = lzc_destroy(name);
 3081         }
 3082         if (err == 0) {
 3083                 if (flags->verbose)
 3084                         (void) printf("success\n");
 3085                 changelist_remove(clp, name);
 3086         }
 3087 
 3088         (void) changelist_postfix(clp);
 3089         changelist_free(clp);
 3090 
 3091         /*
 3092          * Deferred destroy might destroy the snapshot or only mark it to be
 3093          * destroyed later, and it returns success in either case.
 3094          */
 3095         if (err != 0 || (defer && zfs_dataset_exists(hdl, name,
 3096             ZFS_TYPE_SNAPSHOT))) {
 3097                 err = recv_rename(hdl, name, NULL, baselen, newname, flags);
 3098         }
 3099 
 3100         return (err);
 3101 }
 3102 
 3103 typedef struct guid_to_name_data {
 3104         uint64_t guid;
 3105         boolean_t bookmark_ok;
 3106         char *name;
 3107         char *skip;
 3108         uint64_t *redact_snap_guids;
 3109         uint64_t num_redact_snaps;
 3110 } guid_to_name_data_t;
 3111 
 3112 static boolean_t
 3113 redact_snaps_match(zfs_handle_t *zhp, guid_to_name_data_t *gtnd)
 3114 {
 3115         uint64_t *bmark_snaps;
 3116         uint_t bmark_num_snaps;
 3117         nvlist_t *nvl;
 3118         if (zhp->zfs_type != ZFS_TYPE_BOOKMARK)
 3119                 return (B_FALSE);
 3120 
 3121         nvl = fnvlist_lookup_nvlist(zhp->zfs_props,
 3122             zfs_prop_to_name(ZFS_PROP_REDACT_SNAPS));
 3123         bmark_snaps = fnvlist_lookup_uint64_array(nvl, ZPROP_VALUE,
 3124             &bmark_num_snaps);
 3125         if (bmark_num_snaps != gtnd->num_redact_snaps)
 3126                 return (B_FALSE);
 3127         int i = 0;
 3128         for (; i < bmark_num_snaps; i++) {
 3129                 int j = 0;
 3130                 for (; j < bmark_num_snaps; j++) {
 3131                         if (bmark_snaps[i] == gtnd->redact_snap_guids[j])
 3132                                 break;
 3133                 }
 3134                 if (j == bmark_num_snaps)
 3135                         break;
 3136         }
 3137         return (i == bmark_num_snaps);
 3138 }
 3139 
 3140 static int
 3141 guid_to_name_cb(zfs_handle_t *zhp, void *arg)
 3142 {
 3143         guid_to_name_data_t *gtnd = arg;
 3144         const char *slash;
 3145         int err;
 3146 
 3147         if (gtnd->skip != NULL &&
 3148             (slash = strrchr(zhp->zfs_name, '/')) != NULL &&
 3149             strcmp(slash + 1, gtnd->skip) == 0) {
 3150                 zfs_close(zhp);
 3151                 return (0);
 3152         }
 3153 
 3154         if (zfs_prop_get_int(zhp, ZFS_PROP_GUID) == gtnd->guid &&
 3155             (gtnd->num_redact_snaps == -1 || redact_snaps_match(zhp, gtnd))) {
 3156                 (void) strcpy(gtnd->name, zhp->zfs_name);
 3157                 zfs_close(zhp);
 3158                 return (EEXIST);
 3159         }
 3160 
 3161         err = zfs_iter_children(zhp, 0, guid_to_name_cb, gtnd);
 3162         if (err != EEXIST && gtnd->bookmark_ok)
 3163                 err = zfs_iter_bookmarks(zhp, 0, guid_to_name_cb, gtnd);
 3164         zfs_close(zhp);
 3165         return (err);
 3166 }
 3167 
 3168 /*
 3169  * Attempt to find the local dataset associated with this guid.  In the case of
 3170  * multiple matches, we attempt to find the "best" match by searching
 3171  * progressively larger portions of the hierarchy.  This allows one to send a
 3172  * tree of datasets individually and guarantee that we will find the source
 3173  * guid within that hierarchy, even if there are multiple matches elsewhere.
 3174  *
 3175  * If num_redact_snaps is not -1, we attempt to find a redaction bookmark with
 3176  * the specified number of redaction snapshots.  If num_redact_snaps isn't 0 or
 3177  * -1, then redact_snap_guids will be an array of the guids of the snapshots the
 3178  * redaction bookmark was created with.  If num_redact_snaps is -1, then we will
 3179  * attempt to find a snapshot or bookmark (if bookmark_ok is passed) with the
 3180  * given guid.  Note that a redaction bookmark can be returned if
 3181  * num_redact_snaps == -1.
 3182  */
 3183 static int
 3184 guid_to_name_redact_snaps(libzfs_handle_t *hdl, const char *parent,
 3185     uint64_t guid, boolean_t bookmark_ok, uint64_t *redact_snap_guids,
 3186     uint64_t num_redact_snaps, char *name)
 3187 {
 3188         char pname[ZFS_MAX_DATASET_NAME_LEN];
 3189         guid_to_name_data_t gtnd;
 3190 
 3191         gtnd.guid = guid;
 3192         gtnd.bookmark_ok = bookmark_ok;
 3193         gtnd.name = name;
 3194         gtnd.skip = NULL;
 3195         gtnd.redact_snap_guids = redact_snap_guids;
 3196         gtnd.num_redact_snaps = num_redact_snaps;
 3197 
 3198         /*
 3199          * Search progressively larger portions of the hierarchy, starting
 3200          * with the filesystem specified by 'parent'.  This will
 3201          * select the "most local" version of the origin snapshot in the case
 3202          * that there are multiple matching snapshots in the system.
 3203          */
 3204         (void) strlcpy(pname, parent, sizeof (pname));
 3205         char *cp = strrchr(pname, '@');
 3206         if (cp == NULL)
 3207                 cp = strchr(pname, '\0');
 3208         for (; cp != NULL; cp = strrchr(pname, '/')) {
 3209                 /* Chop off the last component and open the parent */
 3210                 *cp = '\0';
 3211                 zfs_handle_t *zhp = make_dataset_handle(hdl, pname);
 3212 
 3213                 if (zhp == NULL)
 3214                         continue;
 3215                 int err = guid_to_name_cb(zfs_handle_dup(zhp), &gtnd);
 3216                 if (err != EEXIST)
 3217                         err = zfs_iter_children(zhp, 0, guid_to_name_cb, &gtnd);
 3218                 if (err != EEXIST && bookmark_ok)
 3219                         err = zfs_iter_bookmarks(zhp, 0, guid_to_name_cb,
 3220                             &gtnd);
 3221                 zfs_close(zhp);
 3222                 if (err == EEXIST)
 3223                         return (0);
 3224 
 3225                 /*
 3226                  * Remember the last portion of the dataset so we skip it next
 3227                  * time through (as we've already searched that portion of the
 3228                  * hierarchy).
 3229                  */
 3230                 gtnd.skip = strrchr(pname, '/') + 1;
 3231         }
 3232 
 3233         return (ENOENT);
 3234 }
 3235 
 3236 static int
 3237 guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
 3238     boolean_t bookmark_ok, char *name)
 3239 {
 3240         return (guid_to_name_redact_snaps(hdl, parent, guid, bookmark_ok, NULL,
 3241             -1, name));
 3242 }
 3243 
 3244 /*
 3245  * Return +1 if guid1 is before guid2, 0 if they are the same, and -1 if
 3246  * guid1 is after guid2.
 3247  */
 3248 static int
 3249 created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
 3250     uint64_t guid1, uint64_t guid2)
 3251 {
 3252         nvlist_t *nvfs;
 3253         char *fsname = NULL, *snapname = NULL;
 3254         char buf[ZFS_MAX_DATASET_NAME_LEN];
 3255         int rv;
 3256         zfs_handle_t *guid1hdl, *guid2hdl;
 3257         uint64_t create1, create2;
 3258 
 3259         if (guid2 == 0)
 3260                 return (0);
 3261         if (guid1 == 0)
 3262                 return (1);
 3263 
 3264         nvfs = fsavl_find(avl, guid1, &snapname);
 3265         fsname = fnvlist_lookup_string(nvfs, "name");
 3266         (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
 3267         guid1hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
 3268         if (guid1hdl == NULL)
 3269                 return (-1);
 3270 
 3271         nvfs = fsavl_find(avl, guid2, &snapname);
 3272         fsname = fnvlist_lookup_string(nvfs, "name");
 3273         (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
 3274         guid2hdl = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
 3275         if (guid2hdl == NULL) {
 3276                 zfs_close(guid1hdl);
 3277                 return (-1);
 3278         }
 3279 
 3280         create1 = zfs_prop_get_int(guid1hdl, ZFS_PROP_CREATETXG);
 3281         create2 = zfs_prop_get_int(guid2hdl, ZFS_PROP_CREATETXG);
 3282 
 3283         if (create1 < create2)
 3284                 rv = -1;
 3285         else if (create1 > create2)
 3286                 rv = +1;
 3287         else
 3288                 rv = 0;
 3289 
 3290         zfs_close(guid1hdl);
 3291         zfs_close(guid2hdl);
 3292 
 3293         return (rv);
 3294 }
 3295 
 3296 /*
 3297  * This function reestablishes the hierarchy of encryption roots after a
 3298  * recursive incremental receive has completed. This must be done after the
 3299  * second call to recv_incremental_replication() has renamed and promoted all
 3300  * sent datasets to their final locations in the dataset hierarchy.
 3301  */
 3302 static int
 3303 recv_fix_encryption_hierarchy(libzfs_handle_t *hdl, const char *top_zfs,
 3304     nvlist_t *stream_nv)
 3305 {
 3306         int err;
 3307         nvpair_t *fselem = NULL;
 3308         nvlist_t *stream_fss;
 3309 
 3310         stream_fss = fnvlist_lookup_nvlist(stream_nv, "fss");
 3311 
 3312         while ((fselem = nvlist_next_nvpair(stream_fss, fselem)) != NULL) {
 3313                 zfs_handle_t *zhp = NULL;
 3314                 uint64_t crypt;
 3315                 nvlist_t *snaps, *props, *stream_nvfs = NULL;
 3316                 nvpair_t *snapel = NULL;
 3317                 boolean_t is_encroot, is_clone, stream_encroot;
 3318                 char *cp;
 3319                 char *stream_keylocation = NULL;
 3320                 char keylocation[MAXNAMELEN];
 3321                 char fsname[ZFS_MAX_DATASET_NAME_LEN];
 3322 
 3323                 keylocation[0] = '\0';
 3324                 stream_nvfs = fnvpair_value_nvlist(fselem);
 3325                 snaps = fnvlist_lookup_nvlist(stream_nvfs, "snaps");
 3326                 props = fnvlist_lookup_nvlist(stream_nvfs, "props");
 3327                 stream_encroot = nvlist_exists(stream_nvfs, "is_encroot");
 3328 
 3329                 /* find a snapshot from the stream that exists locally */
 3330                 err = ENOENT;
 3331                 while ((snapel = nvlist_next_nvpair(snaps, snapel)) != NULL) {
 3332                         uint64_t guid;
 3333 
 3334                         guid = fnvpair_value_uint64(snapel);
 3335                         err = guid_to_name(hdl, top_zfs, guid, B_FALSE,
 3336                             fsname);
 3337                         if (err == 0)
 3338                                 break;
 3339                 }
 3340 
 3341                 if (err != 0)
 3342                         continue;
 3343 
 3344                 cp = strchr(fsname, '@');
 3345                 if (cp != NULL)
 3346                         *cp = '\0';
 3347 
 3348                 zhp = zfs_open(hdl, fsname, ZFS_TYPE_DATASET);
 3349                 if (zhp == NULL) {
 3350                         err = ENOENT;
 3351                         goto error;
 3352                 }
 3353 
 3354                 crypt = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION);
 3355                 is_clone = zhp->zfs_dmustats.dds_origin[0] != '\0';
 3356                 (void) zfs_crypto_get_encryption_root(zhp, &is_encroot, NULL);
 3357 
 3358                 /* we don't need to do anything for unencrypted datasets */
 3359                 if (crypt == ZIO_CRYPT_OFF) {
 3360                         zfs_close(zhp);
 3361                         continue;
 3362                 }
 3363 
 3364                 /*
 3365                  * If the dataset is flagged as an encryption root, was not
 3366                  * received as a clone and is not currently an encryption root,
 3367                  * force it to become one. Fixup the keylocation if necessary.
 3368                  */
 3369                 if (stream_encroot) {
 3370                         if (!is_clone && !is_encroot) {
 3371                                 err = lzc_change_key(fsname,
 3372                                     DCP_CMD_FORCE_NEW_KEY, NULL, NULL, 0);
 3373                                 if (err != 0) {
 3374                                         zfs_close(zhp);
 3375                                         goto error;
 3376                                 }
 3377                         }
 3378 
 3379                         stream_keylocation = fnvlist_lookup_string(props,
 3380                             zfs_prop_to_name(ZFS_PROP_KEYLOCATION));
 3381 
 3382                         /*
 3383                          * Refresh the properties in case the call to
 3384                          * lzc_change_key() changed the value.
 3385                          */
 3386                         zfs_refresh_properties(zhp);
 3387                         err = zfs_prop_get(zhp, ZFS_PROP_KEYLOCATION,
 3388                             keylocation, sizeof (keylocation), NULL, NULL,
 3389                             0, B_TRUE);
 3390                         if (err != 0) {
 3391                                 zfs_close(zhp);
 3392                                 goto error;
 3393                         }
 3394 
 3395                         if (strcmp(keylocation, stream_keylocation) != 0) {
 3396                                 err = zfs_prop_set(zhp,
 3397                                     zfs_prop_to_name(ZFS_PROP_KEYLOCATION),
 3398                                     stream_keylocation);
 3399                                 if (err != 0) {
 3400                                         zfs_close(zhp);
 3401                                         goto error;
 3402                                 }
 3403                         }
 3404                 }
 3405 
 3406                 /*
 3407                  * If the dataset is not flagged as an encryption root and is
 3408                  * currently an encryption root, force it to inherit from its
 3409                  * parent. The root of a raw send should never be
 3410                  * force-inherited.
 3411                  */
 3412                 if (!stream_encroot && is_encroot &&
 3413                     strcmp(top_zfs, fsname) != 0) {
 3414                         err = lzc_change_key(fsname, DCP_CMD_FORCE_INHERIT,
 3415                             NULL, NULL, 0);
 3416                         if (err != 0) {
 3417                                 zfs_close(zhp);
 3418                                 goto error;
 3419                         }
 3420                 }
 3421 
 3422                 zfs_close(zhp);
 3423         }
 3424 
 3425         return (0);
 3426 
 3427 error:
 3428         return (err);
 3429 }
 3430 
 3431 static int
 3432 recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
 3433     recvflags_t *flags, nvlist_t *stream_nv, avl_tree_t *stream_avl,
 3434     nvlist_t *renamed)
 3435 {
 3436         nvlist_t *local_nv, *deleted = NULL;
 3437         avl_tree_t *local_avl;
 3438         nvpair_t *fselem, *nextfselem;
 3439         char *fromsnap;
 3440         char newname[ZFS_MAX_DATASET_NAME_LEN];
 3441         char guidname[32];
 3442         int error;
 3443         boolean_t needagain, progress, recursive;
 3444         char *s1, *s2;
 3445 
 3446         fromsnap = fnvlist_lookup_string(stream_nv, "fromsnap");
 3447 
 3448         recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
 3449             ENOENT);
 3450 
 3451         if (flags->dryrun)
 3452                 return (0);
 3453 
 3454 again:
 3455         needagain = progress = B_FALSE;
 3456 
 3457         deleted = fnvlist_alloc();
 3458 
 3459         if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
 3460             recursive, B_TRUE, B_FALSE, recursive, B_FALSE, B_FALSE, B_FALSE,
 3461             B_FALSE, B_TRUE, &local_nv, &local_avl)) != 0)
 3462                 return (error);
 3463 
 3464         /*
 3465          * Process deletes and renames
 3466          */
 3467         for (fselem = nvlist_next_nvpair(local_nv, NULL);
 3468             fselem; fselem = nextfselem) {
 3469                 nvlist_t *nvfs, *snaps;
 3470                 nvlist_t *stream_nvfs = NULL;
 3471                 nvpair_t *snapelem, *nextsnapelem;
 3472                 uint64_t fromguid = 0;
 3473                 uint64_t originguid = 0;
 3474                 uint64_t stream_originguid = 0;
 3475                 uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
 3476                 char *fsname, *stream_fsname;
 3477 
 3478                 nextfselem = nvlist_next_nvpair(local_nv, fselem);
 3479 
 3480                 nvfs = fnvpair_value_nvlist(fselem);
 3481                 snaps = fnvlist_lookup_nvlist(nvfs, "snaps");
 3482                 fsname = fnvlist_lookup_string(nvfs, "name");
 3483                 parent_fromsnap_guid = fnvlist_lookup_uint64(nvfs,
 3484                     "parentfromsnap");
 3485                 (void) nvlist_lookup_uint64(nvfs, "origin", &originguid);
 3486 
 3487                 /*
 3488                  * First find the stream's fs, so we can check for
 3489                  * a different origin (due to "zfs promote")
 3490                  */
 3491                 for (snapelem = nvlist_next_nvpair(snaps, NULL);
 3492                     snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) {
 3493                         uint64_t thisguid;
 3494 
 3495                         thisguid = fnvpair_value_uint64(snapelem);
 3496                         stream_nvfs = fsavl_find(stream_avl, thisguid, NULL);
 3497 
 3498                         if (stream_nvfs != NULL)
 3499                                 break;
 3500                 }
 3501 
 3502                 /* check for promote */
 3503                 (void) nvlist_lookup_uint64(stream_nvfs, "origin",
 3504                     &stream_originguid);
 3505                 if (stream_nvfs && originguid != stream_originguid) {
 3506                         switch (created_before(hdl, local_avl,
 3507                             stream_originguid, originguid)) {
 3508                         case 1: {
 3509                                 /* promote it! */
 3510                                 nvlist_t *origin_nvfs;
 3511                                 char *origin_fsname;
 3512 
 3513                                 origin_nvfs = fsavl_find(local_avl, originguid,
 3514                                     NULL);
 3515                                 origin_fsname = fnvlist_lookup_string(
 3516                                     origin_nvfs, "name");
 3517                                 error = recv_promote(hdl, fsname, origin_fsname,
 3518                                     flags);
 3519                                 if (error == 0)
 3520                                         progress = B_TRUE;
 3521                                 break;
 3522                         }
 3523                         default:
 3524                                 break;
 3525                         case -1:
 3526                                 fsavl_destroy(local_avl);
 3527                                 fnvlist_free(local_nv);
 3528                                 return (-1);
 3529                         }
 3530                         /*
 3531                          * We had/have the wrong origin, therefore our
 3532                          * list of snapshots is wrong.  Need to handle
 3533                          * them on the next pass.
 3534                          */
 3535                         needagain = B_TRUE;
 3536                         continue;
 3537                 }
 3538 
 3539                 for (snapelem = nvlist_next_nvpair(snaps, NULL);
 3540                     snapelem; snapelem = nextsnapelem) {
 3541                         uint64_t thisguid;
 3542                         char *stream_snapname;
 3543                         nvlist_t *found, *props;
 3544 
 3545                         nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
 3546 
 3547                         thisguid = fnvpair_value_uint64(snapelem);
 3548                         found = fsavl_find(stream_avl, thisguid,
 3549                             &stream_snapname);
 3550 
 3551                         /* check for delete */
 3552                         if (found == NULL) {
 3553                                 char name[ZFS_MAX_DATASET_NAME_LEN];
 3554 
 3555                                 if (!flags->force)
 3556                                         continue;
 3557 
 3558                                 (void) snprintf(name, sizeof (name), "%s@%s",
 3559                                     fsname, nvpair_name(snapelem));
 3560 
 3561                                 error = recv_destroy(hdl, name,
 3562                                     strlen(fsname)+1, newname, flags);
 3563                                 if (error)
 3564                                         needagain = B_TRUE;
 3565                                 else
 3566                                         progress = B_TRUE;
 3567                                 sprintf(guidname, "%llu",
 3568                                     (u_longlong_t)thisguid);
 3569                                 nvlist_add_boolean(deleted, guidname);
 3570                                 continue;
 3571                         }
 3572 
 3573                         stream_nvfs = found;
 3574 
 3575                         if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
 3576                             &props) && 0 == nvlist_lookup_nvlist(props,
 3577                             stream_snapname, &props)) {
 3578                                 zfs_cmd_t zc = {"\0"};
 3579 
 3580                                 zc.zc_cookie = B_TRUE; /* received */
 3581                                 (void) snprintf(zc.zc_name, sizeof (zc.zc_name),
 3582                                     "%s@%s", fsname, nvpair_name(snapelem));
 3583                                 zcmd_write_src_nvlist(hdl, &zc, props);
 3584                                 (void) zfs_ioctl(hdl,
 3585                                     ZFS_IOC_SET_PROP, &zc);
 3586                                 zcmd_free_nvlists(&zc);
 3587                         }
 3588 
 3589                         /* check for different snapname */
 3590                         if (strcmp(nvpair_name(snapelem),
 3591                             stream_snapname) != 0) {
 3592                                 char name[ZFS_MAX_DATASET_NAME_LEN];
 3593                                 char tryname[ZFS_MAX_DATASET_NAME_LEN];
 3594 
 3595                                 (void) snprintf(name, sizeof (name), "%s@%s",
 3596                                     fsname, nvpair_name(snapelem));
 3597                                 (void) snprintf(tryname, sizeof (name), "%s@%s",
 3598                                     fsname, stream_snapname);
 3599 
 3600                                 error = recv_rename(hdl, name, tryname,
 3601                                     strlen(fsname)+1, newname, flags);
 3602                                 if (error)
 3603                                         needagain = B_TRUE;
 3604                                 else
 3605                                         progress = B_TRUE;
 3606                         }
 3607 
 3608                         if (strcmp(stream_snapname, fromsnap) == 0)
 3609                                 fromguid = thisguid;
 3610                 }
 3611 
 3612                 /* check for delete */
 3613                 if (stream_nvfs == NULL) {
 3614                         if (!flags->force)
 3615                                 continue;
 3616 
 3617                         error = recv_destroy(hdl, fsname, strlen(tofs)+1,
 3618                             newname, flags);
 3619                         if (error)
 3620                                 needagain = B_TRUE;
 3621                         else
 3622                                 progress = B_TRUE;
 3623                         sprintf(guidname, "%llu",
 3624                             (u_longlong_t)parent_fromsnap_guid);
 3625                         nvlist_add_boolean(deleted, guidname);
 3626                         continue;
 3627                 }
 3628 
 3629                 if (fromguid == 0) {
 3630                         if (flags->verbose) {
 3631                                 (void) printf("local fs %s does not have "
 3632                                     "fromsnap (%s in stream); must have "
 3633                                     "been deleted locally; ignoring\n",
 3634                                     fsname, fromsnap);
 3635                         }
 3636                         continue;
 3637                 }
 3638 
 3639                 stream_fsname = fnvlist_lookup_string(stream_nvfs, "name");
 3640                 stream_parent_fromsnap_guid = fnvlist_lookup_uint64(
 3641                     stream_nvfs, "parentfromsnap");
 3642 
 3643                 s1 = strrchr(fsname, '/');
 3644                 s2 = strrchr(stream_fsname, '/');
 3645 
 3646                 /*
 3647                  * Check if we're going to rename based on parent guid change
 3648                  * and the current parent guid was also deleted. If it was then
 3649                  * rename will fail and is likely unneeded, so avoid this and
 3650                  * force an early retry to determine the new
 3651                  * parent_fromsnap_guid.
 3652                  */
 3653                 if (stream_parent_fromsnap_guid != 0 &&
 3654                     parent_fromsnap_guid != 0 &&
 3655                     stream_parent_fromsnap_guid != parent_fromsnap_guid) {
 3656                         sprintf(guidname, "%llu",
 3657                             (u_longlong_t)parent_fromsnap_guid);
 3658                         if (nvlist_exists(deleted, guidname)) {
 3659                                 progress = B_TRUE;
 3660                                 needagain = B_TRUE;
 3661                                 goto doagain;
 3662                         }
 3663                 }
 3664 
 3665                 /*
 3666                  * Check for rename. If the exact receive path is specified, it
 3667                  * does not count as a rename, but we still need to check the
 3668                  * datasets beneath it.
 3669                  */
 3670                 if ((stream_parent_fromsnap_guid != 0 &&
 3671                     parent_fromsnap_guid != 0 &&
 3672                     stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
 3673                     ((flags->isprefix || strcmp(tofs, fsname) != 0) &&
 3674                     (s1 != NULL) && (s2 != NULL) && strcmp(s1, s2) != 0)) {
 3675                         nvlist_t *parent;
 3676                         char tryname[ZFS_MAX_DATASET_NAME_LEN];
 3677 
 3678                         parent = fsavl_find(local_avl,
 3679                             stream_parent_fromsnap_guid, NULL);
 3680                         /*
 3681                          * NB: parent might not be found if we used the
 3682                          * tosnap for stream_parent_fromsnap_guid,
 3683                          * because the parent is a newly-created fs;
 3684                          * we'll be able to rename it after we recv the
 3685                          * new fs.
 3686                          */
 3687                         if (parent != NULL) {
 3688                                 char *pname;
 3689 
 3690                                 pname = fnvlist_lookup_string(parent, "name");
 3691                                 (void) snprintf(tryname, sizeof (tryname),
 3692                                     "%s%s", pname, strrchr(stream_fsname, '/'));
 3693                         } else {
 3694                                 tryname[0] = '\0';
 3695                                 if (flags->verbose) {
 3696                                         (void) printf("local fs %s new parent "
 3697                                             "not found\n", fsname);
 3698                                 }
 3699                         }
 3700 
 3701                         newname[0] = '\0';
 3702 
 3703                         error = recv_rename(hdl, fsname, tryname,
 3704                             strlen(tofs)+1, newname, flags);
 3705 
 3706                         if (renamed != NULL && newname[0] != '\0') {
 3707                                 fnvlist_add_boolean(renamed, newname);
 3708                         }
 3709 
 3710                         if (error)
 3711                                 needagain = B_TRUE;
 3712                         else
 3713                                 progress = B_TRUE;
 3714                 }
 3715         }
 3716 
 3717 doagain:
 3718         fsavl_destroy(local_avl);
 3719         fnvlist_free(local_nv);
 3720         fnvlist_free(deleted);
 3721 
 3722         if (needagain && progress) {
 3723                 /* do another pass to fix up temporary names */
 3724                 if (flags->verbose)
 3725                         (void) printf("another pass:\n");
 3726                 goto again;
 3727         }
 3728 
 3729         return (needagain || error != 0);
 3730 }
 3731 
 3732 static int
 3733 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
 3734     recvflags_t *flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
 3735     char **top_zfs, nvlist_t *cmdprops)
 3736 {
 3737         nvlist_t *stream_nv = NULL;
 3738         avl_tree_t *stream_avl = NULL;
 3739         char *fromsnap = NULL;
 3740         char *sendsnap = NULL;
 3741         char *cp;
 3742         char tofs[ZFS_MAX_DATASET_NAME_LEN];
 3743         char sendfs[ZFS_MAX_DATASET_NAME_LEN];
 3744         char errbuf[ERRBUFLEN];
 3745         dmu_replay_record_t drre;
 3746         int error;
 3747         boolean_t anyerr = B_FALSE;
 3748         boolean_t softerr = B_FALSE;
 3749         boolean_t recursive, raw;
 3750 
 3751         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 3752             "cannot receive"));
 3753 
 3754         assert(drr->drr_type == DRR_BEGIN);
 3755         assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
 3756         assert(DMU_GET_STREAM_HDRTYPE(drr->drr_u.drr_begin.drr_versioninfo) ==
 3757             DMU_COMPOUNDSTREAM);
 3758 
 3759         /*
 3760          * Read in the nvlist from the stream.
 3761          */
 3762         if (drr->drr_payloadlen != 0) {
 3763                 error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen,
 3764                     &stream_nv, flags->byteswap, zc);
 3765                 if (error) {
 3766                         error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 3767                         goto out;
 3768                 }
 3769         }
 3770 
 3771         recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
 3772             ENOENT);
 3773         raw = (nvlist_lookup_boolean(stream_nv, "raw") == 0);
 3774 
 3775         if (recursive && strchr(destname, '@')) {
 3776                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 3777                     "cannot specify snapshot name for multi-snapshot stream"));
 3778                 error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 3779                 goto out;
 3780         }
 3781 
 3782         /*
 3783          * Read in the end record and verify checksum.
 3784          */
 3785         if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre),
 3786             flags->byteswap, NULL)))
 3787                 goto out;
 3788         if (flags->byteswap) {
 3789                 drre.drr_type = BSWAP_32(drre.drr_type);
 3790                 drre.drr_u.drr_end.drr_checksum.zc_word[0] =
 3791                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]);
 3792                 drre.drr_u.drr_end.drr_checksum.zc_word[1] =
 3793                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[1]);
 3794                 drre.drr_u.drr_end.drr_checksum.zc_word[2] =
 3795                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[2]);
 3796                 drre.drr_u.drr_end.drr_checksum.zc_word[3] =
 3797                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[3]);
 3798         }
 3799         if (drre.drr_type != DRR_END) {
 3800                 error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 3801                 goto out;
 3802         }
 3803         if (!ZIO_CHECKSUM_EQUAL(drre.drr_u.drr_end.drr_checksum, *zc)) {
 3804                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 3805                     "incorrect header checksum"));
 3806                 error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 3807                 goto out;
 3808         }
 3809 
 3810         (void) nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap);
 3811 
 3812         if (drr->drr_payloadlen != 0) {
 3813                 nvlist_t *stream_fss;
 3814 
 3815                 stream_fss = fnvlist_lookup_nvlist(stream_nv, "fss");
 3816                 if ((stream_avl = fsavl_create(stream_fss)) == NULL) {
 3817                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 3818                             "couldn't allocate avl tree"));
 3819                         error = zfs_error(hdl, EZFS_NOMEM, errbuf);
 3820                         goto out;
 3821                 }
 3822 
 3823                 if (fromsnap != NULL && recursive) {
 3824                         nvlist_t *renamed = NULL;
 3825                         nvpair_t *pair = NULL;
 3826 
 3827                         (void) strlcpy(tofs, destname, sizeof (tofs));
 3828                         if (flags->isprefix) {
 3829                                 struct drr_begin *drrb = &drr->drr_u.drr_begin;
 3830                                 int i;
 3831 
 3832                                 if (flags->istail) {
 3833                                         cp = strrchr(drrb->drr_toname, '/');
 3834                                         if (cp == NULL) {
 3835                                                 (void) strlcat(tofs, "/",
 3836                                                     sizeof (tofs));
 3837                                                 i = 0;
 3838                                         } else {
 3839                                                 i = (cp - drrb->drr_toname);
 3840                                         }
 3841                                 } else {
 3842                                         i = strcspn(drrb->drr_toname, "/@");
 3843                                 }
 3844                                 /* zfs_receive_one() will create_parents() */
 3845                                 (void) strlcat(tofs, &drrb->drr_toname[i],
 3846                                     sizeof (tofs));
 3847                                 *strchr(tofs, '@') = '\0';
 3848                         }
 3849 
 3850                         if (!flags->dryrun && !flags->nomount) {
 3851                                 renamed = fnvlist_alloc();
 3852                         }
 3853 
 3854                         softerr = recv_incremental_replication(hdl, tofs, flags,
 3855                             stream_nv, stream_avl, renamed);
 3856 
 3857                         /* Unmount renamed filesystems before receiving. */
 3858                         while ((pair = nvlist_next_nvpair(renamed,
 3859                             pair)) != NULL) {
 3860                                 zfs_handle_t *zhp;
 3861                                 prop_changelist_t *clp = NULL;
 3862 
 3863                                 zhp = zfs_open(hdl, nvpair_name(pair),
 3864                                     ZFS_TYPE_FILESYSTEM);
 3865                                 if (zhp != NULL) {
 3866                                         clp = changelist_gather(zhp,
 3867                                             ZFS_PROP_MOUNTPOINT, 0,
 3868                                             flags->forceunmount ? MS_FORCE : 0);
 3869                                         zfs_close(zhp);
 3870                                         if (clp != NULL) {
 3871                                                 softerr |=
 3872                                                     changelist_prefix(clp);
 3873                                                 changelist_free(clp);
 3874                                         }
 3875                                 }
 3876                         }
 3877 
 3878                         fnvlist_free(renamed);
 3879                 }
 3880         }
 3881 
 3882         /*
 3883          * Get the fs specified by the first path in the stream (the top level
 3884          * specified by 'zfs send') and pass it to each invocation of
 3885          * zfs_receive_one().
 3886          */
 3887         (void) strlcpy(sendfs, drr->drr_u.drr_begin.drr_toname,
 3888             sizeof (sendfs));
 3889         if ((cp = strchr(sendfs, '@')) != NULL) {
 3890                 *cp = '\0';
 3891                 /*
 3892                  * Find the "sendsnap", the final snapshot in a replication
 3893                  * stream.  zfs_receive_one() handles certain errors
 3894                  * differently, depending on if the contained stream is the
 3895                  * last one or not.
 3896                  */
 3897                 sendsnap = (cp + 1);
 3898         }
 3899 
 3900         /* Finally, receive each contained stream */
 3901         do {
 3902                 /*
 3903                  * we should figure out if it has a recoverable
 3904                  * error, in which case do a recv_skip() and drive on.
 3905                  * Note, if we fail due to already having this guid,
 3906                  * zfs_receive_one() will take care of it (ie,
 3907                  * recv_skip() and return 0).
 3908                  */
 3909                 error = zfs_receive_impl(hdl, destname, NULL, flags, fd,
 3910                     sendfs, stream_nv, stream_avl, top_zfs, sendsnap, cmdprops);
 3911                 if (error == ENODATA) {
 3912                         error = 0;
 3913                         break;
 3914                 }
 3915                 anyerr |= error;
 3916         } while (error == 0);
 3917 
 3918         if (drr->drr_payloadlen != 0 && recursive && fromsnap != NULL) {
 3919                 /*
 3920                  * Now that we have the fs's they sent us, try the
 3921                  * renames again.
 3922                  */
 3923                 softerr = recv_incremental_replication(hdl, tofs, flags,
 3924                     stream_nv, stream_avl, NULL);
 3925         }
 3926 
 3927         if (raw && softerr == 0 && *top_zfs != NULL) {
 3928                 softerr = recv_fix_encryption_hierarchy(hdl, *top_zfs,
 3929                     stream_nv);
 3930         }
 3931 
 3932 out:
 3933         fsavl_destroy(stream_avl);
 3934         fnvlist_free(stream_nv);
 3935         if (softerr)
 3936                 error = -2;
 3937         if (anyerr)
 3938                 error = -1;
 3939         return (error);
 3940 }
 3941 
 3942 static void
 3943 trunc_prop_errs(int truncated)
 3944 {
 3945         ASSERT(truncated != 0);
 3946 
 3947         if (truncated == 1)
 3948                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 3949                     "1 more property could not be set\n"));
 3950         else
 3951                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 3952                     "%d more properties could not be set\n"), truncated);
 3953 }
 3954 
 3955 static int
 3956 recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
 3957 {
 3958         dmu_replay_record_t *drr;
 3959         void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);
 3960         uint64_t payload_size;
 3961         char errbuf[ERRBUFLEN];
 3962 
 3963         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 3964             "cannot receive"));
 3965 
 3966         /* XXX would be great to use lseek if possible... */
 3967         drr = buf;
 3968 
 3969         while (recv_read(hdl, fd, drr, sizeof (dmu_replay_record_t),
 3970             byteswap, NULL) == 0) {
 3971                 if (byteswap)
 3972                         drr->drr_type = BSWAP_32(drr->drr_type);
 3973 
 3974                 switch (drr->drr_type) {
 3975                 case DRR_BEGIN:
 3976                         if (drr->drr_payloadlen != 0) {
 3977                                 (void) recv_read(hdl, fd, buf,
 3978                                     drr->drr_payloadlen, B_FALSE, NULL);
 3979                         }
 3980                         break;
 3981 
 3982                 case DRR_END:
 3983                         free(buf);
 3984                         return (0);
 3985 
 3986                 case DRR_OBJECT:
 3987                         if (byteswap) {
 3988                                 drr->drr_u.drr_object.drr_bonuslen =
 3989                                     BSWAP_32(drr->drr_u.drr_object.
 3990                                     drr_bonuslen);
 3991                                 drr->drr_u.drr_object.drr_raw_bonuslen =
 3992                                     BSWAP_32(drr->drr_u.drr_object.
 3993                                     drr_raw_bonuslen);
 3994                         }
 3995 
 3996                         payload_size =
 3997                             DRR_OBJECT_PAYLOAD_SIZE(&drr->drr_u.drr_object);
 3998                         (void) recv_read(hdl, fd, buf, payload_size,
 3999                             B_FALSE, NULL);
 4000                         break;
 4001 
 4002                 case DRR_WRITE:
 4003                         if (byteswap) {
 4004                                 drr->drr_u.drr_write.drr_logical_size =
 4005                                     BSWAP_64(
 4006                                     drr->drr_u.drr_write.drr_logical_size);
 4007                                 drr->drr_u.drr_write.drr_compressed_size =
 4008                                     BSWAP_64(
 4009                                     drr->drr_u.drr_write.drr_compressed_size);
 4010                         }
 4011                         payload_size =
 4012                             DRR_WRITE_PAYLOAD_SIZE(&drr->drr_u.drr_write);
 4013                         assert(payload_size <= SPA_MAXBLOCKSIZE);
 4014                         (void) recv_read(hdl, fd, buf,
 4015                             payload_size, B_FALSE, NULL);
 4016                         break;
 4017                 case DRR_SPILL:
 4018                         if (byteswap) {
 4019                                 drr->drr_u.drr_spill.drr_length =
 4020                                     BSWAP_64(drr->drr_u.drr_spill.drr_length);
 4021                                 drr->drr_u.drr_spill.drr_compressed_size =
 4022                                     BSWAP_64(drr->drr_u.drr_spill.
 4023                                     drr_compressed_size);
 4024                         }
 4025 
 4026                         payload_size =
 4027                             DRR_SPILL_PAYLOAD_SIZE(&drr->drr_u.drr_spill);
 4028                         (void) recv_read(hdl, fd, buf, payload_size,
 4029                             B_FALSE, NULL);
 4030                         break;
 4031                 case DRR_WRITE_EMBEDDED:
 4032                         if (byteswap) {
 4033                                 drr->drr_u.drr_write_embedded.drr_psize =
 4034                                     BSWAP_32(drr->drr_u.drr_write_embedded.
 4035                                     drr_psize);
 4036                         }
 4037                         (void) recv_read(hdl, fd, buf,
 4038                             P2ROUNDUP(drr->drr_u.drr_write_embedded.drr_psize,
 4039                             8), B_FALSE, NULL);
 4040                         break;
 4041                 case DRR_OBJECT_RANGE:
 4042                 case DRR_WRITE_BYREF:
 4043                 case DRR_FREEOBJECTS:
 4044                 case DRR_FREE:
 4045                         break;
 4046 
 4047                 default:
 4048                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4049                             "invalid record type"));
 4050                         free(buf);
 4051                         return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
 4052                 }
 4053         }
 4054 
 4055         free(buf);
 4056         return (-1);
 4057 }
 4058 
 4059 static void
 4060 recv_ecksum_set_aux(libzfs_handle_t *hdl, const char *target_snap,
 4061     boolean_t resumable, boolean_t checksum)
 4062 {
 4063         char target_fs[ZFS_MAX_DATASET_NAME_LEN];
 4064 
 4065         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, (checksum ?
 4066             "checksum mismatch" : "incomplete stream")));
 4067 
 4068         if (!resumable)
 4069                 return;
 4070         (void) strlcpy(target_fs, target_snap, sizeof (target_fs));
 4071         *strchr(target_fs, '@') = '\0';
 4072         zfs_handle_t *zhp = zfs_open(hdl, target_fs,
 4073             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
 4074         if (zhp == NULL)
 4075                 return;
 4076 
 4077         char token_buf[ZFS_MAXPROPLEN];
 4078         int error = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
 4079             token_buf, sizeof (token_buf),
 4080             NULL, NULL, 0, B_TRUE);
 4081         if (error == 0) {
 4082                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4083                     "checksum mismatch or incomplete stream.\n"
 4084                     "Partially received snapshot is saved.\n"
 4085                     "A resuming stream can be generated on the sending "
 4086                     "system by running:\n"
 4087                     "    zfs send -t %s"),
 4088                     token_buf);
 4089         }
 4090         zfs_close(zhp);
 4091 }
 4092 
 4093 /*
 4094  * Prepare a new nvlist of properties that are to override (-o) or be excluded
 4095  * (-x) from the received dataset
 4096  * recvprops: received properties from the send stream
 4097  * cmdprops: raw input properties from command line
 4098  * origprops: properties, both locally-set and received, currently set on the
 4099  *            target dataset if it exists, NULL otherwise.
 4100  * oxprops: valid output override (-o) and excluded (-x) properties
 4101  */
 4102 static int
 4103 zfs_setup_cmdline_props(libzfs_handle_t *hdl, zfs_type_t type,
 4104     char *fsname, boolean_t zoned, boolean_t recursive, boolean_t newfs,
 4105     boolean_t raw, boolean_t toplevel, nvlist_t *recvprops, nvlist_t *cmdprops,
 4106     nvlist_t *origprops, nvlist_t **oxprops, uint8_t **wkeydata_out,
 4107     uint_t *wkeylen_out, const char *errbuf)
 4108 {
 4109         nvpair_t *nvp;
 4110         nvlist_t *oprops, *voprops;
 4111         zfs_handle_t *zhp = NULL;
 4112         zpool_handle_t *zpool_hdl = NULL;
 4113         char *cp;
 4114         int ret = 0;
 4115         char namebuf[ZFS_MAX_DATASET_NAME_LEN];
 4116 
 4117         if (nvlist_empty(cmdprops))
 4118                 return (0); /* No properties to override or exclude */
 4119 
 4120         *oxprops = fnvlist_alloc();
 4121         oprops = fnvlist_alloc();
 4122 
 4123         strlcpy(namebuf, fsname, ZFS_MAX_DATASET_NAME_LEN);
 4124 
 4125         /*
 4126          * Get our dataset handle. The target dataset may not exist yet.
 4127          */
 4128         if (zfs_dataset_exists(hdl, namebuf, ZFS_TYPE_DATASET)) {
 4129                 zhp = zfs_open(hdl, namebuf, ZFS_TYPE_DATASET);
 4130                 if (zhp == NULL) {
 4131                         ret = -1;
 4132                         goto error;
 4133                 }
 4134         }
 4135 
 4136         /* open the zpool handle */
 4137         cp = strchr(namebuf, '/');
 4138         if (cp != NULL)
 4139                 *cp = '\0';
 4140         zpool_hdl = zpool_open(hdl, namebuf);
 4141         if (zpool_hdl == NULL) {
 4142                 ret = -1;
 4143                 goto error;
 4144         }
 4145 
 4146         /* restore namebuf to match fsname for later use */
 4147         if (cp != NULL)
 4148                 *cp = '/';
 4149 
 4150         /*
 4151          * first iteration: process excluded (-x) properties now and gather
 4152          * added (-o) properties to be later processed by zfs_valid_proplist()
 4153          */
 4154         nvp = NULL;
 4155         while ((nvp = nvlist_next_nvpair(cmdprops, nvp)) != NULL) {
 4156                 const char *name = nvpair_name(nvp);
 4157                 zfs_prop_t prop = zfs_name_to_prop(name);
 4158 
 4159                 /*
 4160                  * It turns out, if we don't normalize "aliased" names
 4161                  * e.g. compress= against the "real" names (e.g. compression)
 4162                  * here, then setting/excluding them does not work as
 4163                  * intended.
 4164                  *
 4165                  * But since user-defined properties wouldn't have a valid
 4166                  * mapping here, we do this conditional dance.
 4167                  */
 4168                 const char *newname = name;
 4169                 if (prop >= ZFS_PROP_TYPE)
 4170                         newname = zfs_prop_to_name(prop);
 4171 
 4172                 /* "origin" is processed separately, don't handle it here */
 4173                 if (prop == ZFS_PROP_ORIGIN)
 4174                         continue;
 4175 
 4176                 /* raw streams can't override encryption properties */
 4177                 if ((zfs_prop_encryption_key_param(prop) ||
 4178                     prop == ZFS_PROP_ENCRYPTION) && raw) {
 4179                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4180                             "encryption property '%s' cannot "
 4181                             "be set or excluded for raw streams."), name);
 4182                         ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
 4183                         goto error;
 4184                 }
 4185 
 4186                 /*
 4187                  * For plain replicated send, we can ignore encryption
 4188                  * properties other than first stream
 4189                  */
 4190                 if ((zfs_prop_encryption_key_param(prop) || prop ==
 4191                     ZFS_PROP_ENCRYPTION) && !newfs && recursive && !raw) {
 4192                         continue;
 4193                 }
 4194 
 4195                 /* incremental streams can only exclude encryption properties */
 4196                 if ((zfs_prop_encryption_key_param(prop) ||
 4197                     prop == ZFS_PROP_ENCRYPTION) && !newfs &&
 4198                     nvpair_type(nvp) != DATA_TYPE_BOOLEAN) {
 4199                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4200                             "encryption property '%s' cannot "
 4201                             "be set for incremental streams."), name);
 4202                         ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
 4203                         goto error;
 4204                 }
 4205 
 4206                 switch (nvpair_type(nvp)) {
 4207                 case DATA_TYPE_BOOLEAN: /* -x property */
 4208                         /*
 4209                          * DATA_TYPE_BOOLEAN is the way we're asked to "exclude"
 4210                          * a property: this is done by forcing an explicit
 4211                          * inherit on the destination so the effective value is
 4212                          * not the one we received from the send stream.
 4213                          */
 4214                         if (!zfs_prop_valid_for_type(prop, type, B_FALSE) &&
 4215                             !zfs_prop_user(name)) {
 4216                                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
 4217                                     "Warning: %s: property '%s' does not "
 4218                                     "apply to datasets of this type\n"),
 4219                                     fsname, name);
 4220                                 continue;
 4221                         }
 4222                         /*
 4223                          * We do this only if the property is not already
 4224                          * locally-set, in which case its value will take
 4225                          * priority over the received anyway.
 4226                          */
 4227                         if (nvlist_exists(origprops, newname)) {
 4228                                 nvlist_t *attrs;
 4229                                 char *source = NULL;
 4230 
 4231                                 attrs = fnvlist_lookup_nvlist(origprops,
 4232                                     newname);
 4233                                 if (nvlist_lookup_string(attrs,
 4234                                     ZPROP_SOURCE, &source) == 0 &&
 4235                                     strcmp(source, ZPROP_SOURCE_VAL_RECVD) != 0)
 4236                                         continue;
 4237                         }
 4238                         /*
 4239                          * We can't force an explicit inherit on non-inheritable
 4240                          * properties: if we're asked to exclude this kind of
 4241                          * values we remove them from "recvprops" input nvlist.
 4242                          */
 4243                         if (!zfs_prop_user(name) && /* can be inherited too */
 4244                             !zfs_prop_inheritable(prop) &&
 4245                             nvlist_exists(recvprops, newname))
 4246                                 fnvlist_remove(recvprops, newname);
 4247                         else
 4248                                 fnvlist_add_boolean(*oxprops, newname);
 4249                         break;
 4250                 case DATA_TYPE_STRING: /* -o property=value */
 4251                         /*
 4252                          * we're trying to override a property that does not
 4253                          * make sense for this type of dataset, but we don't
 4254                          * want to fail if the receive is recursive: this comes
 4255                          * in handy when the send stream contains, for
 4256                          * instance, a child ZVOL and we're trying to receive
 4257                          * it with "-o atime=on"
 4258                          */
 4259                         if (!zfs_prop_valid_for_type(prop, type, B_FALSE) &&
 4260                             !zfs_prop_user(name)) {
 4261                                 if (recursive)
 4262                                         continue;
 4263                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4264                                     "property '%s' does not apply to datasets "
 4265                                     "of this type"), name);
 4266                                 ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
 4267                                 goto error;
 4268                         }
 4269                         fnvlist_add_string(oprops, newname,
 4270                             fnvpair_value_string(nvp));
 4271                         break;
 4272                 default:
 4273                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4274                             "property '%s' must be a string or boolean"), name);
 4275                         ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
 4276                         goto error;
 4277                 }
 4278         }
 4279 
 4280         if (toplevel) {
 4281                 /* convert override strings properties to native */
 4282                 if ((voprops = zfs_valid_proplist(hdl, ZFS_TYPE_DATASET,
 4283                     oprops, zoned, zhp, zpool_hdl, B_FALSE, errbuf)) == NULL) {
 4284                         ret = zfs_error(hdl, EZFS_BADPROP, errbuf);
 4285                         goto error;
 4286                 }
 4287 
 4288                 /*
 4289                  * zfs_crypto_create() requires the parent name. Get it
 4290                  * by truncating the fsname copy stored in namebuf.
 4291                  */
 4292                 cp = strrchr(namebuf, '/');
 4293                 if (cp != NULL)
 4294                         *cp = '\0';
 4295 
 4296                 if (!raw && !(!newfs && recursive) &&
 4297                     zfs_crypto_create(hdl, namebuf, voprops, NULL,
 4298                     B_FALSE, wkeydata_out, wkeylen_out) != 0) {
 4299                         fnvlist_free(voprops);
 4300                         ret = zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
 4301                         goto error;
 4302                 }
 4303 
 4304                 /* second pass: process "-o" properties */
 4305                 fnvlist_merge(*oxprops, voprops);
 4306                 fnvlist_free(voprops);
 4307         } else {
 4308                 /* override props on child dataset are inherited */
 4309                 nvp = NULL;
 4310                 while ((nvp = nvlist_next_nvpair(oprops, nvp)) != NULL) {
 4311                         const char *name = nvpair_name(nvp);
 4312                         fnvlist_add_boolean(*oxprops, name);
 4313                 }
 4314         }
 4315 
 4316 error:
 4317         if (zhp != NULL)
 4318                 zfs_close(zhp);
 4319         if (zpool_hdl != NULL)
 4320                 zpool_close(zpool_hdl);
 4321         fnvlist_free(oprops);
 4322         return (ret);
 4323 }
 4324 
 4325 /*
 4326  * Restores a backup of tosnap from the file descriptor specified by infd.
 4327  */
 4328 static int
 4329 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
 4330     const char *originsnap, recvflags_t *flags, dmu_replay_record_t *drr,
 4331     dmu_replay_record_t *drr_noswap, const char *sendfs, nvlist_t *stream_nv,
 4332     avl_tree_t *stream_avl, char **top_zfs,
 4333     const char *finalsnap, nvlist_t *cmdprops)
 4334 {
 4335         struct timespec begin_time;
 4336         int ioctl_err, ioctl_errno, err;
 4337         char *cp;
 4338         struct drr_begin *drrb = &drr->drr_u.drr_begin;
 4339         char errbuf[ERRBUFLEN];
 4340         const char *chopprefix;
 4341         boolean_t newfs = B_FALSE;
 4342         boolean_t stream_wantsnewfs, stream_resumingnewfs;
 4343         boolean_t newprops = B_FALSE;
 4344         uint64_t read_bytes = 0;
 4345         uint64_t errflags = 0;
 4346         uint64_t parent_snapguid = 0;
 4347         prop_changelist_t *clp = NULL;
 4348         nvlist_t *snapprops_nvlist = NULL;
 4349         nvlist_t *snapholds_nvlist = NULL;
 4350         zprop_errflags_t prop_errflags;
 4351         nvlist_t *prop_errors = NULL;
 4352         boolean_t recursive;
 4353         char *snapname = NULL;
 4354         char destsnap[MAXPATHLEN * 2];
 4355         char origin[MAXNAMELEN] = {0};
 4356         char name[MAXPATHLEN];
 4357         char tmp_keylocation[MAXNAMELEN] = {0};
 4358         nvlist_t *rcvprops = NULL; /* props received from the send stream */
 4359         nvlist_t *oxprops = NULL; /* override (-o) and exclude (-x) props */
 4360         nvlist_t *origprops = NULL; /* original props (if destination exists) */
 4361         zfs_type_t type = ZFS_TYPE_INVALID;
 4362         boolean_t toplevel = B_FALSE;
 4363         boolean_t zoned = B_FALSE;
 4364         boolean_t hastoken = B_FALSE;
 4365         boolean_t redacted;
 4366         uint8_t *wkeydata = NULL;
 4367         uint_t wkeylen = 0;
 4368 
 4369 #ifndef CLOCK_MONOTONIC_RAW
 4370 #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
 4371 #endif
 4372         clock_gettime(CLOCK_MONOTONIC_RAW, &begin_time);
 4373 
 4374         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 4375             "cannot receive"));
 4376 
 4377         recursive = (nvlist_lookup_boolean(stream_nv, "not_recursive") ==
 4378             ENOENT);
 4379 
 4380         /* Did the user request holds be skipped via zfs recv -k? */
 4381         boolean_t holds = flags->holds && !flags->skipholds;
 4382 
 4383         if (stream_avl != NULL) {
 4384                 char *keylocation = NULL;
 4385                 nvlist_t *lookup = NULL;
 4386                 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
 4387                     &snapname);
 4388 
 4389                 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
 4390                     &parent_snapguid);
 4391                 err = nvlist_lookup_nvlist(fs, "props", &rcvprops);
 4392                 if (err) {
 4393                         rcvprops = fnvlist_alloc();
 4394                         newprops = B_TRUE;
 4395                 }
 4396 
 4397                 /*
 4398                  * The keylocation property may only be set on encryption roots,
 4399                  * but this dataset might not become an encryption root until
 4400                  * recv_fix_encryption_hierarchy() is called. That function
 4401                  * will fixup the keylocation anyway, so we temporarily unset
 4402                  * the keylocation for now to avoid any errors from the receive
 4403                  * ioctl.
 4404                  */
 4405                 err = nvlist_lookup_string(rcvprops,
 4406                     zfs_prop_to_name(ZFS_PROP_KEYLOCATION), &keylocation);
 4407                 if (err == 0) {
 4408                         strlcpy(tmp_keylocation, keylocation, MAXNAMELEN);
 4409                         (void) nvlist_remove_all(rcvprops,
 4410                             zfs_prop_to_name(ZFS_PROP_KEYLOCATION));
 4411                 }
 4412 
 4413                 if (flags->canmountoff) {
 4414                         fnvlist_add_uint64(rcvprops,
 4415                             zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0);
 4416                 } else if (newprops) {  /* nothing in rcvprops, eliminate it */
 4417                         fnvlist_free(rcvprops);
 4418                         rcvprops = NULL;
 4419                         newprops = B_FALSE;
 4420                 }
 4421                 if (0 == nvlist_lookup_nvlist(fs, "snapprops", &lookup)) {
 4422                         snapprops_nvlist = fnvlist_lookup_nvlist(lookup,
 4423                             snapname);
 4424                 }
 4425                 if (holds) {
 4426                         if (0 == nvlist_lookup_nvlist(fs, "snapholds",
 4427                             &lookup)) {
 4428                                 snapholds_nvlist = fnvlist_lookup_nvlist(
 4429                                     lookup, snapname);
 4430                         }
 4431                 }
 4432         }
 4433 
 4434         cp = NULL;
 4435 
 4436         /*
 4437          * Determine how much of the snapshot name stored in the stream
 4438          * we are going to tack on to the name they specified on the
 4439          * command line, and how much we are going to chop off.
 4440          *
 4441          * If they specified a snapshot, chop the entire name stored in
 4442          * the stream.
 4443          */
 4444         if (flags->istail) {
 4445                 /*
 4446                  * A filesystem was specified with -e. We want to tack on only
 4447                  * the tail of the sent snapshot path.
 4448                  */
 4449                 if (strchr(tosnap, '@')) {
 4450                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
 4451                             "argument - snapshot not allowed with -e"));
 4452                         err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 4453                         goto out;
 4454                 }
 4455 
 4456                 chopprefix = strrchr(sendfs, '/');
 4457 
 4458                 if (chopprefix == NULL) {
 4459                         /*
 4460                          * The tail is the poolname, so we need to
 4461                          * prepend a path separator.
 4462                          */
 4463                         int len = strlen(drrb->drr_toname);
 4464                         cp = umem_alloc(len + 2, UMEM_NOFAIL);
 4465                         cp[0] = '/';
 4466                         (void) strcpy(&cp[1], drrb->drr_toname);
 4467                         chopprefix = cp;
 4468                 } else {
 4469                         chopprefix = drrb->drr_toname + (chopprefix - sendfs);
 4470                 }
 4471         } else if (flags->isprefix) {
 4472                 /*
 4473                  * A filesystem was specified with -d. We want to tack on
 4474                  * everything but the first element of the sent snapshot path
 4475                  * (all but the pool name).
 4476                  */
 4477                 if (strchr(tosnap, '@')) {
 4478                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
 4479                             "argument - snapshot not allowed with -d"));
 4480                         err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 4481                         goto out;
 4482                 }
 4483 
 4484                 chopprefix = strchr(drrb->drr_toname, '/');
 4485                 if (chopprefix == NULL)
 4486                         chopprefix = strchr(drrb->drr_toname, '@');
 4487         } else if (strchr(tosnap, '@') == NULL) {
 4488                 /*
 4489                  * If a filesystem was specified without -d or -e, we want to
 4490                  * tack on everything after the fs specified by 'zfs send'.
 4491                  */
 4492                 chopprefix = drrb->drr_toname + strlen(sendfs);
 4493         } else {
 4494                 /* A snapshot was specified as an exact path (no -d or -e). */
 4495                 if (recursive) {
 4496                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4497                             "cannot specify snapshot name for multi-snapshot "
 4498                             "stream"));
 4499                         err = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 4500                         goto out;
 4501                 }
 4502                 chopprefix = drrb->drr_toname + strlen(drrb->drr_toname);
 4503         }
 4504 
 4505         ASSERT(strstr(drrb->drr_toname, sendfs) == drrb->drr_toname);
 4506         ASSERT(chopprefix > drrb->drr_toname || strchr(sendfs, '/') == NULL);
 4507         ASSERT(chopprefix <= drrb->drr_toname + strlen(drrb->drr_toname) ||
 4508             strchr(sendfs, '/') == NULL);
 4509         ASSERT(chopprefix[0] == '/' || chopprefix[0] == '@' ||
 4510             chopprefix[0] == '\0');
 4511 
 4512         /*
 4513          * Determine name of destination snapshot.
 4514          */
 4515         (void) strlcpy(destsnap, tosnap, sizeof (destsnap));
 4516         (void) strlcat(destsnap, chopprefix, sizeof (destsnap));
 4517         if (cp != NULL)
 4518                 umem_free(cp, strlen(cp) + 1);
 4519         if (!zfs_name_valid(destsnap, ZFS_TYPE_SNAPSHOT)) {
 4520                 err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 4521                 goto out;
 4522         }
 4523 
 4524         /*
 4525          * Determine the name of the origin snapshot.
 4526          */
 4527         if (originsnap) {
 4528                 (void) strlcpy(origin, originsnap, sizeof (origin));
 4529                 if (flags->verbose)
 4530                         (void) printf("using provided clone origin %s\n",
 4531                             origin);
 4532         } else if (drrb->drr_flags & DRR_FLAG_CLONE) {
 4533                 if (guid_to_name(hdl, destsnap,
 4534                     drrb->drr_fromguid, B_FALSE, origin) != 0) {
 4535                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4536                             "local origin for clone %s does not exist"),
 4537                             destsnap);
 4538                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
 4539                         goto out;
 4540                 }
 4541                 if (flags->verbose)
 4542                         (void) printf("found clone origin %s\n", origin);
 4543         }
 4544 
 4545         if ((DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
 4546             DMU_BACKUP_FEATURE_DEDUP)) {
 4547                 (void) fprintf(stderr,
 4548                     gettext("ERROR: \"zfs receive\" no longer supports "
 4549                     "deduplicated send streams.  Use\n"
 4550                     "the \"zstream redup\" command to convert this stream "
 4551                     "to a regular,\n"
 4552                     "non-deduplicated stream.\n"));
 4553                 err = zfs_error(hdl, EZFS_NOTSUP, errbuf);
 4554                 goto out;
 4555         }
 4556 
 4557         boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
 4558             DMU_BACKUP_FEATURE_RESUMING;
 4559         boolean_t raw = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
 4560             DMU_BACKUP_FEATURE_RAW;
 4561         boolean_t embedded = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
 4562             DMU_BACKUP_FEATURE_EMBED_DATA;
 4563         stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
 4564             (drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
 4565         stream_resumingnewfs = (drrb->drr_fromguid == 0 ||
 4566             (drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && resuming;
 4567 
 4568         if (stream_wantsnewfs) {
 4569                 /*
 4570                  * if the parent fs does not exist, look for it based on
 4571                  * the parent snap GUID
 4572                  */
 4573                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 4574                     "cannot receive new filesystem stream"));
 4575 
 4576                 (void) strlcpy(name, destsnap, sizeof (name));
 4577                 cp = strrchr(name, '/');
 4578                 if (cp)
 4579                         *cp = '\0';
 4580                 if (cp &&
 4581                     !zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
 4582                         char suffix[ZFS_MAX_DATASET_NAME_LEN];
 4583                         (void) strlcpy(suffix, strrchr(destsnap, '/'),
 4584                             sizeof (suffix));
 4585                         if (guid_to_name(hdl, name, parent_snapguid,
 4586                             B_FALSE, destsnap) == 0) {
 4587                                 *strchr(destsnap, '@') = '\0';
 4588                                 (void) strlcat(destsnap, suffix,
 4589                                     sizeof (destsnap) - strlen(destsnap));
 4590                         }
 4591                 }
 4592         } else {
 4593                 /*
 4594                  * If the fs does not exist, look for it based on the
 4595                  * fromsnap GUID.
 4596                  */
 4597                 if (resuming) {
 4598                         (void) snprintf(errbuf, sizeof (errbuf),
 4599                             dgettext(TEXT_DOMAIN,
 4600                             "cannot receive resume stream"));
 4601                 } else {
 4602                         (void) snprintf(errbuf, sizeof (errbuf),
 4603                             dgettext(TEXT_DOMAIN,
 4604                             "cannot receive incremental stream"));
 4605                 }
 4606 
 4607                 (void) strlcpy(name, destsnap, sizeof (name));
 4608                 *strchr(name, '@') = '\0';
 4609 
 4610                 /*
 4611                  * If the exact receive path was specified and this is the
 4612                  * topmost path in the stream, then if the fs does not exist we
 4613                  * should look no further.
 4614                  */
 4615                 if ((flags->isprefix || (*(chopprefix = drrb->drr_toname +
 4616                     strlen(sendfs)) != '\0' && *chopprefix != '@')) &&
 4617                     !zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
 4618                         char snap[ZFS_MAX_DATASET_NAME_LEN];
 4619                         (void) strlcpy(snap, strchr(destsnap, '@'),
 4620                             sizeof (snap));
 4621                         if (guid_to_name(hdl, name, drrb->drr_fromguid,
 4622                             B_FALSE, destsnap) == 0) {
 4623                                 *strchr(destsnap, '@') = '\0';
 4624                                 (void) strlcat(destsnap, snap,
 4625                                     sizeof (destsnap) - strlen(destsnap));
 4626                         }
 4627                 }
 4628         }
 4629 
 4630         (void) strlcpy(name, destsnap, sizeof (name));
 4631         *strchr(name, '@') = '\0';
 4632 
 4633         redacted = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
 4634             DMU_BACKUP_FEATURE_REDACTED;
 4635 
 4636         if (flags->heal) {
 4637                 if (flags->isprefix || flags->istail || flags->force ||
 4638                     flags->canmountoff || flags->resumable || flags->nomount ||
 4639                     flags->skipholds) {
 4640                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4641                             "corrective recv can not be used when combined with"
 4642                             " this flag"));
 4643                         err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 4644                         goto out;
 4645                 }
 4646                 uint64_t guid =
 4647                     get_snap_guid(hdl, name, strchr(destsnap, '@') + 1);
 4648                 if (guid == 0) {
 4649                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4650                             "corrective recv must specify an existing snapshot"
 4651                             " to heal"));
 4652                         err = zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
 4653                         goto out;
 4654                 } else if (guid != drrb->drr_toguid) {
 4655                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4656                             "local snapshot doesn't match the snapshot"
 4657                             " in the provided stream"));
 4658                         err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf);
 4659                         goto out;
 4660                 }
 4661         } else if (zfs_dataset_exists(hdl, name, ZFS_TYPE_DATASET)) {
 4662                 zfs_cmd_t zc = {"\0"};
 4663                 zfs_handle_t *zhp = NULL;
 4664                 boolean_t encrypted;
 4665 
 4666                 (void) strcpy(zc.zc_name, name);
 4667 
 4668                 /*
 4669                  * Destination fs exists.  It must be one of these cases:
 4670                  *  - an incremental send stream
 4671                  *  - the stream specifies a new fs (full stream or clone)
 4672                  *    and they want us to blow away the existing fs (and
 4673                  *    have therefore specified -F and removed any snapshots)
 4674                  *  - we are resuming a failed receive.
 4675                  */
 4676                 if (stream_wantsnewfs) {
 4677                         boolean_t is_volume = drrb->drr_type == DMU_OST_ZVOL;
 4678                         if (!flags->force) {
 4679                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4680                                     "destination '%s' exists\n"
 4681                                     "must specify -F to overwrite it"), name);
 4682                                 err = zfs_error(hdl, EZFS_EXISTS, errbuf);
 4683                                 goto out;
 4684                         }
 4685                         if (zfs_ioctl(hdl, ZFS_IOC_SNAPSHOT_LIST_NEXT,
 4686                             &zc) == 0) {
 4687                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4688                                     "destination has snapshots (eg. %s)\n"
 4689                                     "must destroy them to overwrite it"),
 4690                                     zc.zc_name);
 4691                                 err = zfs_error(hdl, EZFS_EXISTS, errbuf);
 4692                                 goto out;
 4693                         }
 4694                         if (is_volume && strrchr(name, '/') == NULL) {
 4695                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4696                                     "destination %s is the root dataset\n"
 4697                                     "cannot overwrite with a ZVOL"),
 4698                                     name);
 4699                                 err = zfs_error(hdl, EZFS_EXISTS, errbuf);
 4700                                 goto out;
 4701                         }
 4702                         if (is_volume &&
 4703                             zfs_ioctl(hdl, ZFS_IOC_DATASET_LIST_NEXT,
 4704                             &zc) == 0) {
 4705                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4706                                     "destination has children (eg. %s)\n"
 4707                                     "cannot overwrite with a ZVOL"),
 4708                                     zc.zc_name);
 4709                                 err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf);
 4710                                 goto out;
 4711                         }
 4712                 }
 4713 
 4714                 if ((zhp = zfs_open(hdl, name,
 4715                     ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
 4716                         err = -1;
 4717                         goto out;
 4718                 }
 4719 
 4720                 /*
 4721                  * When receiving full/newfs on existing dataset, then it
 4722                  * should be done with "-F" flag. Its enforced for initial
 4723                  * receive in previous checks in this function.
 4724                  * Similarly, on resuming full/newfs recv on existing dataset,
 4725                  * it should be done with "-F" flag.
 4726                  *
 4727                  * When dataset doesn't exist, then full/newfs recv is done on
 4728                  * newly created dataset and it's marked INCONSISTENT. But
 4729                  * When receiving on existing dataset, recv is first done on
 4730                  * %recv and its marked INCONSISTENT. Existing dataset is not
 4731                  * marked INCONSISTENT.
 4732                  * Resume of full/newfs receive with dataset not INCONSISTENT
 4733                  * indicates that its resuming newfs on existing dataset. So,
 4734                  * enforce "-F" flag in this case.
 4735                  */
 4736                 if (stream_resumingnewfs &&
 4737                     !zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
 4738                     !flags->force) {
 4739                         zfs_close(zhp);
 4740                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4741                             "Resuming recv on existing destination '%s'\n"
 4742                             "must specify -F to overwrite it"), name);
 4743                         err = zfs_error(hdl, EZFS_RESUME_EXISTS, errbuf);
 4744                         goto out;
 4745                 }
 4746 
 4747                 if (stream_wantsnewfs &&
 4748                     zhp->zfs_dmustats.dds_origin[0]) {
 4749                         zfs_close(zhp);
 4750                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4751                             "destination '%s' is a clone\n"
 4752                             "must destroy it to overwrite it"), name);
 4753                         err = zfs_error(hdl, EZFS_EXISTS, errbuf);
 4754                         goto out;
 4755                 }
 4756 
 4757                 /*
 4758                  * Raw sends can not be performed as an incremental on top
 4759                  * of existing unencrypted datasets. zfs recv -F can't be
 4760                  * used to blow away an existing encrypted filesystem. This
 4761                  * is because it would require the dsl dir to point to the
 4762                  * new key (or lack of a key) and the old key at the same
 4763                  * time. The -F flag may still be used for deleting
 4764                  * intermediate snapshots that would otherwise prevent the
 4765                  * receive from working.
 4766                  */
 4767                 encrypted = zfs_prop_get_int(zhp, ZFS_PROP_ENCRYPTION) !=
 4768                     ZIO_CRYPT_OFF;
 4769                 if (!stream_wantsnewfs && !encrypted && raw) {
 4770                         zfs_close(zhp);
 4771                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4772                             "cannot perform raw receive on top of "
 4773                             "existing unencrypted dataset"));
 4774                         err = zfs_error(hdl, EZFS_BADRESTORE, errbuf);
 4775                         goto out;
 4776                 }
 4777 
 4778                 if (stream_wantsnewfs && flags->force &&
 4779                     ((raw && !encrypted) || encrypted)) {
 4780                         zfs_close(zhp);
 4781                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4782                             "zfs receive -F cannot be used to destroy an "
 4783                             "encrypted filesystem or overwrite an "
 4784                             "unencrypted one with an encrypted one"));
 4785                         err = zfs_error(hdl, EZFS_BADRESTORE, errbuf);
 4786                         goto out;
 4787                 }
 4788 
 4789                 if (!flags->dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
 4790                     (stream_wantsnewfs || stream_resumingnewfs)) {
 4791                         /* We can't do online recv in this case */
 4792                         clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
 4793                             flags->forceunmount ? MS_FORCE : 0);
 4794                         if (clp == NULL) {
 4795                                 zfs_close(zhp);
 4796                                 err = -1;
 4797                                 goto out;
 4798                         }
 4799                         if (changelist_prefix(clp) != 0) {
 4800                                 changelist_free(clp);
 4801                                 zfs_close(zhp);
 4802                                 err = -1;
 4803                                 goto out;
 4804                         }
 4805                 }
 4806 
 4807                 /*
 4808                  * If we are resuming a newfs, set newfs here so that we will
 4809                  * mount it if the recv succeeds this time.  We can tell
 4810                  * that it was a newfs on the first recv because the fs
 4811                  * itself will be inconsistent (if the fs existed when we
 4812                  * did the first recv, we would have received it into
 4813                  * .../%recv).
 4814                  */
 4815                 if (resuming && zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT))
 4816                         newfs = B_TRUE;
 4817 
 4818                 /* we want to know if we're zoned when validating -o|-x props */
 4819                 zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
 4820 
 4821                 /* may need this info later, get it now we have zhp around */
 4822                 if (zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN, NULL, 0,
 4823                     NULL, NULL, 0, B_TRUE) == 0)
 4824                         hastoken = B_TRUE;
 4825 
 4826                 /* gather existing properties on destination */
 4827                 origprops = fnvlist_alloc();
 4828                 fnvlist_merge(origprops, zhp->zfs_props);
 4829                 fnvlist_merge(origprops, zhp->zfs_user_props);
 4830 
 4831                 zfs_close(zhp);
 4832         } else {
 4833                 zfs_handle_t *zhp;
 4834 
 4835                 /*
 4836                  * Destination filesystem does not exist.  Therefore we better
 4837                  * be creating a new filesystem (either from a full backup, or
 4838                  * a clone).  It would therefore be invalid if the user
 4839                  * specified only the pool name (i.e. if the destination name
 4840                  * contained no slash character).
 4841                  */
 4842                 cp = strrchr(name, '/');
 4843 
 4844                 if (!stream_wantsnewfs || cp == NULL) {
 4845                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4846                             "destination '%s' does not exist"), name);
 4847                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
 4848                         goto out;
 4849                 }
 4850 
 4851                 /*
 4852                  * Trim off the final dataset component so we perform the
 4853                  * recvbackup ioctl to the filesystems's parent.
 4854                  */
 4855                 *cp = '\0';
 4856 
 4857                 if (flags->isprefix && !flags->istail && !flags->dryrun &&
 4858                     create_parents(hdl, destsnap, strlen(tosnap)) != 0) {
 4859                         err = zfs_error(hdl, EZFS_BADRESTORE, errbuf);
 4860                         goto out;
 4861                 }
 4862 
 4863                 /* validate parent */
 4864                 zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
 4865                 if (zhp == NULL) {
 4866                         err = zfs_error(hdl, EZFS_BADRESTORE, errbuf);
 4867                         goto out;
 4868                 }
 4869                 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
 4870                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4871                             "parent '%s' is not a filesystem"), name);
 4872                         err = zfs_error(hdl, EZFS_WRONG_PARENT, errbuf);
 4873                         zfs_close(zhp);
 4874                         goto out;
 4875                 }
 4876 
 4877                 zfs_close(zhp);
 4878 
 4879                 newfs = B_TRUE;
 4880                 *cp = '/';
 4881         }
 4882 
 4883         if (flags->verbose) {
 4884                 (void) printf("%s %s%s stream of %s into %s\n",
 4885                     flags->dryrun ? "would receive" : "receiving",
 4886                     flags->heal ? " corrective" : "",
 4887                     drrb->drr_fromguid ? "incremental" : "full",
 4888                     drrb->drr_toname, destsnap);
 4889                 (void) fflush(stdout);
 4890         }
 4891 
 4892         /*
 4893          * If this is the top-level dataset, record it so we can use it
 4894          * for recursive operations later.
 4895          */
 4896         if (top_zfs != NULL &&
 4897             (*top_zfs == NULL || strcmp(*top_zfs, name) == 0)) {
 4898                 toplevel = B_TRUE;
 4899                 if (*top_zfs == NULL)
 4900                         *top_zfs = zfs_strdup(hdl, name);
 4901         }
 4902 
 4903         if (drrb->drr_type == DMU_OST_ZVOL) {
 4904                 type = ZFS_TYPE_VOLUME;
 4905         } else if (drrb->drr_type == DMU_OST_ZFS) {
 4906                 type = ZFS_TYPE_FILESYSTEM;
 4907         } else {
 4908                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 4909                     "invalid record type: 0x%d"), drrb->drr_type);
 4910                 err = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 4911                 goto out;
 4912         }
 4913         if ((err = zfs_setup_cmdline_props(hdl, type, name, zoned, recursive,
 4914             stream_wantsnewfs, raw, toplevel, rcvprops, cmdprops, origprops,
 4915             &oxprops, &wkeydata, &wkeylen, errbuf)) != 0)
 4916                 goto out;
 4917 
 4918         /*
 4919          * When sending with properties (zfs send -p), the encryption property
 4920          * is not included because it is a SETONCE property and therefore
 4921          * treated as read only. However, we are always able to determine its
 4922          * value because raw sends will include it in the DRR_BDEGIN payload
 4923          * and non-raw sends with properties are not allowed for encrypted
 4924          * datasets. Therefore, if this is a non-raw properties stream, we can
 4925          * infer that the value should be ZIO_CRYPT_OFF and manually add that
 4926          * to the received properties.
 4927          */
 4928         if (stream_wantsnewfs && !raw && rcvprops != NULL &&
 4929             !nvlist_exists(cmdprops, zfs_prop_to_name(ZFS_PROP_ENCRYPTION))) {
 4930                 if (oxprops == NULL)
 4931                         oxprops = fnvlist_alloc();
 4932                 fnvlist_add_uint64(oxprops,
 4933                     zfs_prop_to_name(ZFS_PROP_ENCRYPTION), ZIO_CRYPT_OFF);
 4934         }
 4935 
 4936         if (flags->dryrun) {
 4937                 void *buf = zfs_alloc(hdl, SPA_MAXBLOCKSIZE);
 4938 
 4939                 /*
 4940                  * We have read the DRR_BEGIN record, but we have
 4941                  * not yet read the payload. For non-dryrun sends
 4942                  * this will be done by the kernel, so we must
 4943                  * emulate that here, before attempting to read
 4944                  * more records.
 4945                  */
 4946                 err = recv_read(hdl, infd, buf, drr->drr_payloadlen,
 4947                     flags->byteswap, NULL);
 4948                 free(buf);
 4949                 if (err != 0)
 4950                         goto out;
 4951 
 4952                 err = recv_skip(hdl, infd, flags->byteswap);
 4953                 goto out;
 4954         }
 4955 
 4956         if (flags->heal) {
 4957                 err = ioctl_err = lzc_receive_with_heal(destsnap, rcvprops,
 4958                     oxprops, wkeydata, wkeylen, origin, flags->force,
 4959                     flags->heal, flags->resumable, raw, infd, drr_noswap, -1,
 4960                     &read_bytes, &errflags, NULL, &prop_errors);
 4961         } else {
 4962                 err = ioctl_err = lzc_receive_with_cmdprops(destsnap, rcvprops,
 4963                     oxprops, wkeydata, wkeylen, origin, flags->force,
 4964                     flags->resumable, raw, infd, drr_noswap, -1, &read_bytes,
 4965                     &errflags, NULL, &prop_errors);
 4966         }
 4967         ioctl_errno = ioctl_err;
 4968         prop_errflags = errflags;
 4969 
 4970         if (err == 0) {
 4971                 nvpair_t *prop_err = NULL;
 4972 
 4973                 while ((prop_err = nvlist_next_nvpair(prop_errors,
 4974                     prop_err)) != NULL) {
 4975                         char tbuf[1024];
 4976                         zfs_prop_t prop;
 4977                         int intval;
 4978 
 4979                         prop = zfs_name_to_prop(nvpair_name(prop_err));
 4980                         (void) nvpair_value_int32(prop_err, &intval);
 4981                         if (strcmp(nvpair_name(prop_err),
 4982                             ZPROP_N_MORE_ERRORS) == 0) {
 4983                                 trunc_prop_errs(intval);
 4984                                 break;
 4985                         } else if (snapname == NULL || finalsnap == NULL ||
 4986                             strcmp(finalsnap, snapname) == 0 ||
 4987                             strcmp(nvpair_name(prop_err),
 4988                             zfs_prop_to_name(ZFS_PROP_REFQUOTA)) != 0) {
 4989                                 /*
 4990                                  * Skip the special case of, for example,
 4991                                  * "refquota", errors on intermediate
 4992                                  * snapshots leading up to a final one.
 4993                                  * That's why we have all of the checks above.
 4994                                  *
 4995                                  * See zfs_ioctl.c's extract_delay_props() for
 4996                                  * a list of props which can fail on
 4997                                  * intermediate snapshots, but shouldn't
 4998                                  * affect the overall receive.
 4999                                  */
 5000                                 (void) snprintf(tbuf, sizeof (tbuf),
 5001                                     dgettext(TEXT_DOMAIN,
 5002                                     "cannot receive %s property on %s"),
 5003                                     nvpair_name(prop_err), name);
 5004                                 zfs_setprop_error(hdl, prop, intval, tbuf);
 5005                         }
 5006                 }
 5007         }
 5008 
 5009         if (err == 0 && snapprops_nvlist) {
 5010                 zfs_cmd_t zc = {"\0"};
 5011 
 5012                 (void) strlcpy(zc.zc_name, destsnap, sizeof (zc.zc_name));
 5013                 zc.zc_cookie = B_TRUE; /* received */
 5014                 zcmd_write_src_nvlist(hdl, &zc, snapprops_nvlist);
 5015                 (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
 5016                 zcmd_free_nvlists(&zc);
 5017         }
 5018         if (err == 0 && snapholds_nvlist) {
 5019                 nvpair_t *pair;
 5020                 nvlist_t *holds, *errors = NULL;
 5021                 int cleanup_fd = -1;
 5022 
 5023                 VERIFY(0 == nvlist_alloc(&holds, 0, KM_SLEEP));
 5024                 for (pair = nvlist_next_nvpair(snapholds_nvlist, NULL);
 5025                     pair != NULL;
 5026                     pair = nvlist_next_nvpair(snapholds_nvlist, pair)) {
 5027                         fnvlist_add_string(holds, destsnap, nvpair_name(pair));
 5028                 }
 5029                 (void) lzc_hold(holds, cleanup_fd, &errors);
 5030                 fnvlist_free(snapholds_nvlist);
 5031                 fnvlist_free(holds);
 5032         }
 5033 
 5034         if (err && (ioctl_errno == ENOENT || ioctl_errno == EEXIST)) {
 5035                 /*
 5036                  * It may be that this snapshot already exists,
 5037                  * in which case we want to consume & ignore it
 5038                  * rather than failing.
 5039                  */
 5040                 avl_tree_t *local_avl;
 5041                 nvlist_t *local_nv, *fs;
 5042                 cp = strchr(destsnap, '@');
 5043 
 5044                 /*
 5045                  * XXX Do this faster by just iterating over snaps in
 5046                  * this fs.  Also if zc_value does not exist, we will
 5047                  * get a strange "does not exist" error message.
 5048                  */
 5049                 *cp = '\0';
 5050                 if (gather_nvlist(hdl, destsnap, NULL, NULL, B_FALSE, B_TRUE,
 5051                     B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE,
 5052                     B_TRUE, &local_nv, &local_avl) == 0) {
 5053                         *cp = '@';
 5054                         fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
 5055                         fsavl_destroy(local_avl);
 5056                         fnvlist_free(local_nv);
 5057 
 5058                         if (fs != NULL) {
 5059                                 if (flags->verbose) {
 5060                                         (void) printf("snap %s already exists; "
 5061                                             "ignoring\n", destsnap);
 5062                                 }
 5063                                 err = ioctl_err = recv_skip(hdl, infd,
 5064                                     flags->byteswap);
 5065                         }
 5066                 }
 5067                 *cp = '@';
 5068         }
 5069 
 5070         if (ioctl_err != 0) {
 5071                 switch (ioctl_errno) {
 5072                 case ENODEV:
 5073                         cp = strchr(destsnap, '@');
 5074                         *cp = '\0';
 5075                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5076                             "most recent snapshot of %s does not\n"
 5077                             "match incremental source"), destsnap);
 5078                         (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
 5079                         *cp = '@';
 5080                         break;
 5081                 case ETXTBSY:
 5082                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5083                             "destination %s has been modified\n"
 5084                             "since most recent snapshot"), name);
 5085                         (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
 5086                         break;
 5087                 case EACCES:
 5088                         if (flags->heal) {
 5089                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5090                                     "key must be loaded to do a non-raw "
 5091                                     "corrective recv on an encrypted "
 5092                                     "dataset."));
 5093                         } else if (raw && stream_wantsnewfs) {
 5094                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5095                                     "failed to create encryption key"));
 5096                         } else if (raw && !stream_wantsnewfs) {
 5097                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5098                                     "encryption key does not match "
 5099                                     "existing key"));
 5100                         } else {
 5101                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5102                                     "inherited key must be loaded"));
 5103                         }
 5104                         (void) zfs_error(hdl, EZFS_CRYPTOFAILED, errbuf);
 5105                         break;
 5106                 case EEXIST:
 5107                         cp = strchr(destsnap, '@');
 5108                         if (newfs) {
 5109                                 /* it's the containing fs that exists */
 5110                                 *cp = '\0';
 5111                         }
 5112                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5113                             "destination already exists"));
 5114                         (void) zfs_error_fmt(hdl, EZFS_EXISTS,
 5115                             dgettext(TEXT_DOMAIN, "cannot restore to %s"),
 5116                             destsnap);
 5117                         *cp = '@';
 5118                         break;
 5119                 case EINVAL:
 5120                         if (embedded && !raw) {
 5121                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5122                                     "incompatible embedded data stream "
 5123                                     "feature with encrypted receive."));
 5124                         } else if (flags->resumable) {
 5125                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5126                                     "kernel modules must be upgraded to "
 5127                                     "receive this stream."));
 5128                         }
 5129                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5130                         break;
 5131                 case ECKSUM:
 5132                 case ZFS_ERR_STREAM_TRUNCATED:
 5133                         if (flags->heal)
 5134                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5135                                     "corrective receive was not able to "
 5136                                     "reconstruct the data needed for "
 5137                                     "healing."));
 5138                         else
 5139                                 recv_ecksum_set_aux(hdl, destsnap,
 5140                                     flags->resumable, ioctl_err == ECKSUM);
 5141                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5142                         break;
 5143                 case ZFS_ERR_STREAM_LARGE_BLOCK_MISMATCH:
 5144                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5145                             "incremental send stream requires -L "
 5146                             "(--large-block), to match previous receive."));
 5147                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5148                         break;
 5149                 case ENOTSUP:
 5150                         if (flags->heal)
 5151                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5152                                     "stream is not compatible with the "
 5153                                     "data in the pool."));
 5154                         else
 5155                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5156                                     "pool must be upgraded to receive this "
 5157                                     "stream."));
 5158                         (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
 5159                         break;
 5160                 case EDQUOT:
 5161                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5162                             "destination %s space quota exceeded."), name);
 5163                         (void) zfs_error(hdl, EZFS_NOSPC, errbuf);
 5164                         break;
 5165                 case ZFS_ERR_FROM_IVSET_GUID_MISSING:
 5166                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5167                             "IV set guid missing. See errata %u at "
 5168                             "https://openzfs.github.io/openzfs-docs/msg/"
 5169                             "ZFS-8000-ER."),
 5170                             ZPOOL_ERRATA_ZOL_8308_ENCRYPTION);
 5171                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5172                         break;
 5173                 case ZFS_ERR_FROM_IVSET_GUID_MISMATCH:
 5174                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5175                             "IV set guid mismatch. See the 'zfs receive' "
 5176                             "man page section\n discussing the limitations "
 5177                             "of raw encrypted send streams."));
 5178                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5179                         break;
 5180                 case ZFS_ERR_SPILL_BLOCK_FLAG_MISSING:
 5181                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5182                             "Spill block flag missing for raw send.\n"
 5183                             "The zfs software on the sending system must "
 5184                             "be updated."));
 5185                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5186                         break;
 5187                 case ZFS_ERR_RESUME_EXISTS:
 5188                         cp = strchr(destsnap, '@');
 5189                         if (newfs) {
 5190                                 /* it's the containing fs that exists */
 5191                                 *cp = '\0';
 5192                         }
 5193                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5194                             "Resuming recv on existing dataset without force"));
 5195                         (void) zfs_error_fmt(hdl, EZFS_RESUME_EXISTS,
 5196                             dgettext(TEXT_DOMAIN, "cannot resume recv %s"),
 5197                             destsnap);
 5198                         *cp = '@';
 5199                         break;
 5200                 case E2BIG:
 5201                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5202                             "zfs receive required kernel memory allocation "
 5203                             "larger than the system can support. Please file "
 5204                             "an issue at the OpenZFS issue tracker:\n"
 5205                             "https://github.com/openzfs/zfs/issues/new"));
 5206                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
 5207                         break;
 5208                 case EBUSY:
 5209                         if (hastoken) {
 5210                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5211                                     "destination %s contains "
 5212                                     "partially-complete state from "
 5213                                     "\"zfs receive -s\"."), name);
 5214                                 (void) zfs_error(hdl, EZFS_BUSY, errbuf);
 5215                                 break;
 5216                         }
 5217                         zfs_fallthrough;
 5218                 default:
 5219                         (void) zfs_standard_error(hdl, ioctl_errno, errbuf);
 5220                 }
 5221         }
 5222 
 5223         /*
 5224          * Mount the target filesystem (if created).  Also mount any
 5225          * children of the target filesystem if we did a replication
 5226          * receive (indicated by stream_avl being non-NULL).
 5227          */
 5228         if (clp) {
 5229                 if (!flags->nomount)
 5230                         err |= changelist_postfix(clp);
 5231                 changelist_free(clp);
 5232         }
 5233 
 5234         if ((newfs || stream_avl) && type == ZFS_TYPE_FILESYSTEM && !redacted)
 5235                 flags->domount = B_TRUE;
 5236 
 5237         if (prop_errflags & ZPROP_ERR_NOCLEAR) {
 5238                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: "
 5239                     "failed to clear unreceived properties on %s"), name);
 5240                 (void) fprintf(stderr, "\n");
 5241         }
 5242         if (prop_errflags & ZPROP_ERR_NORESTORE) {
 5243                 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Warning: "
 5244                     "failed to restore original properties on %s"), name);
 5245                 (void) fprintf(stderr, "\n");
 5246         }
 5247 
 5248         if (err || ioctl_err) {
 5249                 err = -1;
 5250                 goto out;
 5251         }
 5252 
 5253         if (flags->verbose) {
 5254                 char buf1[64];
 5255                 char buf2[64];
 5256                 uint64_t bytes = read_bytes;
 5257                 struct timespec delta;
 5258                 clock_gettime(CLOCK_MONOTONIC_RAW, &delta);
 5259                 if (begin_time.tv_nsec > delta.tv_nsec) {
 5260                         delta.tv_nsec =
 5261                             1000000000 + delta.tv_nsec - begin_time.tv_nsec;
 5262                         delta.tv_sec -= 1;
 5263                 } else
 5264                         delta.tv_nsec -= begin_time.tv_nsec;
 5265                 delta.tv_sec -= begin_time.tv_sec;
 5266                 if (delta.tv_sec == 0 && delta.tv_nsec == 0)
 5267                         delta.tv_nsec = 1;
 5268                 double delta_f = delta.tv_sec + (delta.tv_nsec / 1e9);
 5269                 zfs_nicebytes(bytes, buf1, sizeof (buf1));
 5270                 zfs_nicebytes(bytes / delta_f, buf2, sizeof (buf2));
 5271 
 5272                 (void) printf("received %s stream in %.2f seconds (%s/sec)\n",
 5273                     buf1, delta_f, buf2);
 5274         }
 5275 
 5276         err = 0;
 5277 out:
 5278         if (prop_errors != NULL)
 5279                 fnvlist_free(prop_errors);
 5280 
 5281         if (tmp_keylocation[0] != '\0') {
 5282                 fnvlist_add_string(rcvprops,
 5283                     zfs_prop_to_name(ZFS_PROP_KEYLOCATION), tmp_keylocation);
 5284         }
 5285 
 5286         if (newprops)
 5287                 fnvlist_free(rcvprops);
 5288 
 5289         fnvlist_free(oxprops);
 5290         fnvlist_free(origprops);
 5291 
 5292         return (err);
 5293 }
 5294 
 5295 /*
 5296  * Check properties we were asked to override (both -o|-x)
 5297  */
 5298 static boolean_t
 5299 zfs_receive_checkprops(libzfs_handle_t *hdl, nvlist_t *props,
 5300     const char *errbuf)
 5301 {
 5302         nvpair_t *nvp = NULL;
 5303         zfs_prop_t prop;
 5304         const char *name;
 5305 
 5306         while ((nvp = nvlist_next_nvpair(props, nvp)) != NULL) {
 5307                 name = nvpair_name(nvp);
 5308                 prop = zfs_name_to_prop(name);
 5309 
 5310                 if (prop == ZPROP_USERPROP) {
 5311                         if (!zfs_prop_user(name)) {
 5312                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5313                                     "%s: invalid property '%s'"), errbuf, name);
 5314                                 return (B_FALSE);
 5315                         }
 5316                         continue;
 5317                 }
 5318                 /*
 5319                  * "origin" is readonly but is used to receive datasets as
 5320                  * clones so we don't raise an error here
 5321                  */
 5322                 if (prop == ZFS_PROP_ORIGIN)
 5323                         continue;
 5324 
 5325                 /* encryption params have their own verification later */
 5326                 if (prop == ZFS_PROP_ENCRYPTION ||
 5327                     zfs_prop_encryption_key_param(prop))
 5328                         continue;
 5329 
 5330                 /*
 5331                  * cannot override readonly, set-once and other specific
 5332                  * settable properties
 5333                  */
 5334                 if (zfs_prop_readonly(prop) || prop == ZFS_PROP_VERSION ||
 5335                     prop == ZFS_PROP_VOLSIZE) {
 5336                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5337                             "%s: invalid property '%s'"), errbuf, name);
 5338                         return (B_FALSE);
 5339                 }
 5340         }
 5341 
 5342         return (B_TRUE);
 5343 }
 5344 
 5345 static int
 5346 zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
 5347     const char *originsnap, recvflags_t *flags, int infd, const char *sendfs,
 5348     nvlist_t *stream_nv, avl_tree_t *stream_avl, char **top_zfs,
 5349     const char *finalsnap, nvlist_t *cmdprops)
 5350 {
 5351         int err;
 5352         dmu_replay_record_t drr, drr_noswap;
 5353         struct drr_begin *drrb = &drr.drr_u.drr_begin;
 5354         char errbuf[ERRBUFLEN];
 5355         zio_cksum_t zcksum = { { 0 } };
 5356         uint64_t featureflags;
 5357         int hdrtype;
 5358 
 5359         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
 5360             "cannot receive"));
 5361 
 5362         /* check cmdline props, raise an error if they cannot be received */
 5363         if (!zfs_receive_checkprops(hdl, cmdprops, errbuf))
 5364                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
 5365 
 5366         if (flags->isprefix &&
 5367             !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
 5368                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
 5369                     "(%s) does not exist"), tosnap);
 5370                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
 5371         }
 5372         if (originsnap &&
 5373             !zfs_dataset_exists(hdl, originsnap, ZFS_TYPE_DATASET)) {
 5374                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified origin fs "
 5375                     "(%s) does not exist"), originsnap);
 5376                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
 5377         }
 5378 
 5379         /* read in the BEGIN record */
 5380         if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE,
 5381             &zcksum)))
 5382                 return (err);
 5383 
 5384         if (drr.drr_type == DRR_END || drr.drr_type == BSWAP_32(DRR_END)) {
 5385                 /* It's the double end record at the end of a package */
 5386                 return (ENODATA);
 5387         }
 5388 
 5389         /* the kernel needs the non-byteswapped begin record */
 5390         drr_noswap = drr;
 5391 
 5392         flags->byteswap = B_FALSE;
 5393         if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
 5394                 /*
 5395                  * We computed the checksum in the wrong byteorder in
 5396                  * recv_read() above; do it again correctly.
 5397                  */
 5398                 memset(&zcksum, 0, sizeof (zio_cksum_t));
 5399                 fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum);
 5400                 flags->byteswap = B_TRUE;
 5401 
 5402                 drr.drr_type = BSWAP_32(drr.drr_type);
 5403                 drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen);
 5404                 drrb->drr_magic = BSWAP_64(drrb->drr_magic);
 5405                 drrb->drr_versioninfo = BSWAP_64(drrb->drr_versioninfo);
 5406                 drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
 5407                 drrb->drr_type = BSWAP_32(drrb->drr_type);
 5408                 drrb->drr_flags = BSWAP_32(drrb->drr_flags);
 5409                 drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
 5410                 drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
 5411         }
 5412 
 5413         if (drrb->drr_magic != DMU_BACKUP_MAGIC || drr.drr_type != DRR_BEGIN) {
 5414                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
 5415                     "stream (bad magic number)"));
 5416                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
 5417         }
 5418 
 5419         featureflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
 5420         hdrtype = DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo);
 5421 
 5422         if (!DMU_STREAM_SUPPORTED(featureflags) ||
 5423             (hdrtype != DMU_SUBSTREAM && hdrtype != DMU_COMPOUNDSTREAM)) {
 5424                 /*
 5425                  * Let's be explicit about this one, since rather than
 5426                  * being a new feature we can't know, it's an old
 5427                  * feature we dropped.
 5428                  */
 5429                 if (featureflags & DMU_BACKUP_FEATURE_DEDUP) {
 5430                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5431                             "stream has deprecated feature: dedup, try "
 5432                             "'zstream redup [send in a file] | zfs recv "
 5433                             "[...]'"));
 5434                 } else {
 5435                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
 5436                             "stream has unsupported feature, feature flags = "
 5437                             "%llx (unknown flags = %llx)"),
 5438                             (u_longlong_t)featureflags,
 5439                             (u_longlong_t)((featureflags) &
 5440                             ~DMU_BACKUP_FEATURE_MASK));
 5441                 }
 5442                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
 5443         }
 5444 
 5445         /* Holds feature is set once in the compound stream header. */
 5446         if (featureflags & DMU_BACKUP_FEATURE_HOLDS)
 5447                 flags->holds = B_TRUE;
 5448 
 5449         if (strchr(drrb->drr_toname, '@') == NULL) {
 5450                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
 5451                     "stream (bad snapshot name)"));
 5452                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
 5453         }
 5454 
 5455         if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) == DMU_SUBSTREAM) {
 5456                 char nonpackage_sendfs[ZFS_MAX_DATASET_NAME_LEN];
 5457                 if (sendfs == NULL) {
 5458                         /*
 5459                          * We were not called from zfs_receive_package(). Get
 5460                          * the fs specified by 'zfs send'.
 5461                          */
 5462                         char *cp;
 5463                         (void) strlcpy(nonpackage_sendfs,
 5464                             drr.drr_u.drr_begin.drr_toname,
 5465                             sizeof (nonpackage_sendfs));
 5466                         if ((cp = strchr(nonpackage_sendfs, '@')) != NULL)
 5467                                 *cp = '\0';
 5468                         sendfs = nonpackage_sendfs;
 5469                         VERIFY(finalsnap == NULL);
 5470                 }
 5471                 return (zfs_receive_one(hdl, infd, tosnap, originsnap, flags,
 5472                     &drr, &drr_noswap, sendfs, stream_nv, stream_avl, top_zfs,
 5473                     finalsnap, cmdprops));
 5474         } else {
 5475                 assert(DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
 5476                     DMU_COMPOUNDSTREAM);
 5477                 return (zfs_receive_package(hdl, infd, tosnap, flags, &drr,
 5478                     &zcksum, top_zfs, cmdprops));
 5479         }
 5480 }
 5481 
 5482 /*
 5483  * Restores a backup of tosnap from the file descriptor specified by infd.
 5484  * Return 0 on total success, -2 if some things couldn't be
 5485  * destroyed/renamed/promoted, -1 if some things couldn't be received.
 5486  * (-1 will override -2, if -1 and the resumable flag was specified the
 5487  * transfer can be resumed if the sending side supports it).
 5488  */
 5489 int
 5490 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,
 5491     recvflags_t *flags, int infd, avl_tree_t *stream_avl)
 5492 {
 5493         char *top_zfs = NULL;
 5494         int err;
 5495         struct stat sb;
 5496         char *originsnap = NULL;
 5497 
 5498         /*
 5499          * The only way fstat can fail is if we do not have a valid file
 5500          * descriptor.
 5501          */
 5502         if (fstat(infd, &sb) == -1) {
 5503                 perror("fstat");
 5504                 return (-2);
 5505         }
 5506 
 5507         if (props) {
 5508                 err = nvlist_lookup_string(props, "origin", &originsnap);
 5509                 if (err && err != ENOENT)
 5510                         return (err);
 5511         }
 5512 
 5513         err = zfs_receive_impl(hdl, tosnap, originsnap, flags, infd, NULL, NULL,
 5514             stream_avl, &top_zfs, NULL, props);
 5515 
 5516         if (err == 0 && !flags->nomount && flags->domount && top_zfs) {
 5517                 zfs_handle_t *zhp = NULL;
 5518                 prop_changelist_t *clp = NULL;
 5519 
 5520                 zhp = zfs_open(hdl, top_zfs,
 5521                     ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
 5522                 if (zhp == NULL) {
 5523                         err = -1;
 5524                         goto out;
 5525                 } else {
 5526                         if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
 5527                                 zfs_close(zhp);
 5528                                 goto out;
 5529                         }
 5530 
 5531                         clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
 5532                             CL_GATHER_MOUNT_ALWAYS,
 5533                             flags->forceunmount ? MS_FORCE : 0);
 5534                         zfs_close(zhp);
 5535                         if (clp == NULL) {
 5536                                 err = -1;
 5537                                 goto out;
 5538                         }
 5539 
 5540                         /* mount and share received datasets */
 5541                         err = changelist_postfix(clp);
 5542                         changelist_free(clp);
 5543                         if (err != 0)
 5544                                 err = -1;
 5545                 }
 5546         }
 5547 
 5548 out:
 5549         if (top_zfs)
 5550                 free(top_zfs);
 5551 
 5552         return (err);
 5553 }

Cache object: 7185a5cf66a0b31a69a0f6d2a680d158


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.