libzfs_sendrecv.c revision 186515
1185029Spjd/*
2185029Spjd * CDDL HEADER START
3185029Spjd *
4185029Spjd * The contents of this file are subject to the terms of the
5185029Spjd * Common Development and Distribution License (the "License").
6185029Spjd * You may not use this file except in compliance with the License.
7185029Spjd *
8185029Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9185029Spjd * or http://www.opensolaris.org/os/licensing.
10185029Spjd * See the License for the specific language governing permissions
11185029Spjd * and limitations under the License.
12185029Spjd *
13185029Spjd * When distributing Covered Code, include this CDDL HEADER in each
14185029Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15185029Spjd * If applicable, add the following below this CDDL HEADER, with the
16185029Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17185029Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18185029Spjd *
19185029Spjd * CDDL HEADER END
20185029Spjd */
21185029Spjd
22185029Spjd/*
23185029Spjd * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24185029Spjd * Use is subject to license terms.
25185029Spjd */
26185029Spjd
27185029Spjd#include <assert.h>
28185029Spjd#include <ctype.h>
29185029Spjd#include <errno.h>
30185029Spjd#include <libintl.h>
31185029Spjd#include <stdio.h>
32185029Spjd#include <stdlib.h>
33185029Spjd#include <strings.h>
34185029Spjd#include <unistd.h>
35185029Spjd#include <stddef.h>
36185029Spjd#include <fcntl.h>
37186515Srwatson#include <sys/param.h>
38185029Spjd#include <sys/mount.h>
39185029Spjd#include <sys/mntent.h>
40185029Spjd#include <sys/mnttab.h>
41185029Spjd#include <sys/avl.h>
42185029Spjd#include <stddef.h>
43185029Spjd
44185029Spjd#include <libzfs.h>
45185029Spjd
46185029Spjd#include "zfs_namecheck.h"
47185029Spjd#include "zfs_prop.h"
48185029Spjd#include "libzfs_impl.h"
49185029Spjd
50185029Spjd#include <fletcher.c> /* XXX */
51185029Spjd
52185029Spjd/* We need to use something for ENODATA. */
53185029Spjd#define	ENODATA	EIDRM
54185029Spjd
55185029Spjdstatic int zfs_receive_impl(libzfs_handle_t *, const char *, recvflags_t,
56185029Spjd    int, avl_tree_t *, char **);
57185029Spjd
58185029Spjd/*
59185029Spjd * Routines for dealing with the AVL tree of fs-nvlists
60185029Spjd */
61185029Spjdtypedef struct fsavl_node {
62185029Spjd	avl_node_t fn_node;
63185029Spjd	nvlist_t *fn_nvfs;
64185029Spjd	char *fn_snapname;
65185029Spjd	uint64_t fn_guid;
66185029Spjd} fsavl_node_t;
67185029Spjd
68185029Spjdstatic int
69185029Spjdfsavl_compare(const void *arg1, const void *arg2)
70185029Spjd{
71185029Spjd	const fsavl_node_t *fn1 = arg1;
72185029Spjd	const fsavl_node_t *fn2 = arg2;
73185029Spjd
74185029Spjd	if (fn1->fn_guid > fn2->fn_guid)
75185029Spjd		return (+1);
76185029Spjd	else if (fn1->fn_guid < fn2->fn_guid)
77185029Spjd		return (-1);
78185029Spjd	else
79185029Spjd		return (0);
80185029Spjd}
81185029Spjd
82185029Spjd/*
83185029Spjd * Given the GUID of a snapshot, find its containing filesystem and
84185029Spjd * (optionally) name.
85185029Spjd */
86185029Spjdstatic nvlist_t *
87185029Spjdfsavl_find(avl_tree_t *avl, uint64_t snapguid, char **snapname)
88185029Spjd{
89185029Spjd	fsavl_node_t fn_find;
90185029Spjd	fsavl_node_t *fn;
91185029Spjd
92185029Spjd	fn_find.fn_guid = snapguid;
93185029Spjd
94185029Spjd	fn = avl_find(avl, &fn_find, NULL);
95185029Spjd	if (fn) {
96185029Spjd		if (snapname)
97185029Spjd			*snapname = fn->fn_snapname;
98185029Spjd		return (fn->fn_nvfs);
99185029Spjd	}
100185029Spjd	return (NULL);
101185029Spjd}
102185029Spjd
103185029Spjdstatic void
104185029Spjdfsavl_destroy(avl_tree_t *avl)
105185029Spjd{
106185029Spjd	fsavl_node_t *fn;
107185029Spjd	void *cookie;
108185029Spjd
109185029Spjd	if (avl == NULL)
110185029Spjd		return;
111185029Spjd
112185029Spjd	cookie = NULL;
113185029Spjd	while ((fn = avl_destroy_nodes(avl, &cookie)) != NULL)
114185029Spjd		free(fn);
115185029Spjd	avl_destroy(avl);
116185029Spjd	free(avl);
117185029Spjd}
118185029Spjd
119185029Spjdstatic avl_tree_t *
120185029Spjdfsavl_create(nvlist_t *fss)
121185029Spjd{
122185029Spjd	avl_tree_t *fsavl;
123185029Spjd	nvpair_t *fselem = NULL;
124185029Spjd
125185029Spjd	if ((fsavl = malloc(sizeof (avl_tree_t))) == NULL)
126185029Spjd		return (NULL);
127185029Spjd
128185029Spjd	avl_create(fsavl, fsavl_compare, sizeof (fsavl_node_t),
129185029Spjd	    offsetof(fsavl_node_t, fn_node));
130185029Spjd
131185029Spjd	while ((fselem = nvlist_next_nvpair(fss, fselem)) != NULL) {
132185029Spjd		nvlist_t *nvfs, *snaps;
133185029Spjd		nvpair_t *snapelem = NULL;
134185029Spjd
135185029Spjd		VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
136185029Spjd		VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
137185029Spjd
138185029Spjd		while ((snapelem =
139185029Spjd		    nvlist_next_nvpair(snaps, snapelem)) != NULL) {
140185029Spjd			fsavl_node_t *fn;
141185029Spjd			uint64_t guid;
142185029Spjd
143185029Spjd			VERIFY(0 == nvpair_value_uint64(snapelem, &guid));
144185029Spjd			if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) {
145185029Spjd				fsavl_destroy(fsavl);
146185029Spjd				return (NULL);
147185029Spjd			}
148185029Spjd			fn->fn_nvfs = nvfs;
149185029Spjd			fn->fn_snapname = nvpair_name(snapelem);
150185029Spjd			fn->fn_guid = guid;
151185029Spjd
152185029Spjd			/*
153185029Spjd			 * Note: if there are multiple snaps with the
154185029Spjd			 * same GUID, we ignore all but one.
155185029Spjd			 */
156185029Spjd			if (avl_find(fsavl, fn, NULL) == NULL)
157185029Spjd				avl_add(fsavl, fn);
158185029Spjd			else
159185029Spjd				free(fn);
160185029Spjd		}
161185029Spjd	}
162185029Spjd
163185029Spjd	return (fsavl);
164185029Spjd}
165185029Spjd
166185029Spjd/*
167185029Spjd * Routines for dealing with the giant nvlist of fs-nvlists, etc.
168185029Spjd */
169185029Spjdtypedef struct send_data {
170185029Spjd	uint64_t parent_fromsnap_guid;
171185029Spjd	nvlist_t *parent_snaps;
172185029Spjd	nvlist_t *fss;
173185029Spjd	nvlist_t *snapprops;
174185029Spjd	const char *fromsnap;
175185029Spjd	const char *tosnap;
176185029Spjd
177185029Spjd	/*
178185029Spjd	 * The header nvlist is of the following format:
179185029Spjd	 * {
180185029Spjd	 *   "tosnap" -> string
181185029Spjd	 *   "fromsnap" -> string (if incremental)
182185029Spjd	 *   "fss" -> {
183185029Spjd	 *	id -> {
184185029Spjd	 *
185185029Spjd	 *	 "name" -> string (full name; for debugging)
186185029Spjd	 *	 "parentfromsnap" -> number (guid of fromsnap in parent)
187185029Spjd	 *
188185029Spjd	 *	 "props" -> { name -> value (only if set here) }
189185029Spjd	 *	 "snaps" -> { name (lastname) -> number (guid) }
190185029Spjd	 *	 "snapprops" -> { name (lastname) -> { name -> value } }
191185029Spjd	 *
192185029Spjd	 *	 "origin" -> number (guid) (if clone)
193185029Spjd	 *	 "sent" -> boolean (not on-disk)
194185029Spjd	 *	}
195185029Spjd	 *   }
196185029Spjd	 * }
197185029Spjd	 *
198185029Spjd	 */
199185029Spjd} send_data_t;
200185029Spjd
201185029Spjdstatic void send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv);
202185029Spjd
203185029Spjdstatic int
204185029Spjdsend_iterate_snap(zfs_handle_t *zhp, void *arg)
205185029Spjd{
206185029Spjd	send_data_t *sd = arg;
207185029Spjd	uint64_t guid = zhp->zfs_dmustats.dds_guid;
208185029Spjd	char *snapname;
209185029Spjd	nvlist_t *nv;
210185029Spjd
211185029Spjd	snapname = strrchr(zhp->zfs_name, '@')+1;
212185029Spjd
213185029Spjd	VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
214185029Spjd	/*
215185029Spjd	 * NB: if there is no fromsnap here (it's a newly created fs in
216185029Spjd	 * an incremental replication), we will substitute the tosnap.
217185029Spjd	 */
218185029Spjd	if ((sd->fromsnap && strcmp(snapname, sd->fromsnap) == 0) ||
219185029Spjd	    (sd->parent_fromsnap_guid == 0 && sd->tosnap &&
220185029Spjd	    strcmp(snapname, sd->tosnap) == 0)) {
221185029Spjd		sd->parent_fromsnap_guid = guid;
222185029Spjd	}
223185029Spjd
224185029Spjd	VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
225185029Spjd	send_iterate_prop(zhp, nv);
226185029Spjd	VERIFY(0 == nvlist_add_nvlist(sd->snapprops, snapname, nv));
227185029Spjd	nvlist_free(nv);
228185029Spjd
229185029Spjd	zfs_close(zhp);
230185029Spjd	return (0);
231185029Spjd}
232185029Spjd
233185029Spjdstatic void
234185029Spjdsend_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
235185029Spjd{
236185029Spjd	nvpair_t *elem = NULL;
237185029Spjd
238185029Spjd	while ((elem = nvlist_next_nvpair(zhp->zfs_props, elem)) != NULL) {
239185029Spjd		char *propname = nvpair_name(elem);
240185029Spjd		zfs_prop_t prop = zfs_name_to_prop(propname);
241185029Spjd		nvlist_t *propnv;
242185029Spjd
243185029Spjd		if (!zfs_prop_user(propname) && zfs_prop_readonly(prop))
244185029Spjd			continue;
245185029Spjd
246185029Spjd		verify(nvpair_value_nvlist(elem, &propnv) == 0);
247185029Spjd		if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION) {
248185029Spjd			/* these guys are modifyable, but have no source */
249185029Spjd			uint64_t value;
250185029Spjd			verify(nvlist_lookup_uint64(propnv,
251185029Spjd			    ZPROP_VALUE, &value) == 0);
252185029Spjd			if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
253185029Spjd				continue;
254185029Spjd		} else {
255185029Spjd			char *source;
256185029Spjd			if (nvlist_lookup_string(propnv,
257185029Spjd			    ZPROP_SOURCE, &source) != 0)
258185029Spjd				continue;
259185029Spjd			if (strcmp(source, zhp->zfs_name) != 0)
260185029Spjd				continue;
261185029Spjd		}
262185029Spjd
263185029Spjd		if (zfs_prop_user(propname) ||
264185029Spjd		    zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
265185029Spjd			char *value;
266185029Spjd			verify(nvlist_lookup_string(propnv,
267185029Spjd			    ZPROP_VALUE, &value) == 0);
268185029Spjd			VERIFY(0 == nvlist_add_string(nv, propname, value));
269185029Spjd		} else {
270185029Spjd			uint64_t value;
271185029Spjd			verify(nvlist_lookup_uint64(propnv,
272185029Spjd			    ZPROP_VALUE, &value) == 0);
273185029Spjd			VERIFY(0 == nvlist_add_uint64(nv, propname, value));
274185029Spjd		}
275185029Spjd	}
276185029Spjd}
277185029Spjd
278185029Spjdstatic int
279185029Spjdsend_iterate_fs(zfs_handle_t *zhp, void *arg)
280185029Spjd{
281185029Spjd	send_data_t *sd = arg;
282185029Spjd	nvlist_t *nvfs, *nv;
283185029Spjd	int rv;
284185029Spjd	uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid;
285185029Spjd	uint64_t guid = zhp->zfs_dmustats.dds_guid;
286185029Spjd	char guidstring[64];
287185029Spjd
288185029Spjd	VERIFY(0 == nvlist_alloc(&nvfs, NV_UNIQUE_NAME, 0));
289185029Spjd	VERIFY(0 == nvlist_add_string(nvfs, "name", zhp->zfs_name));
290185029Spjd	VERIFY(0 == nvlist_add_uint64(nvfs, "parentfromsnap",
291185029Spjd	    sd->parent_fromsnap_guid));
292185029Spjd
293185029Spjd	if (zhp->zfs_dmustats.dds_origin[0]) {
294185029Spjd		zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
295185029Spjd		    zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
296185029Spjd		if (origin == NULL)
297185029Spjd			return (-1);
298185029Spjd		VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
299185029Spjd		    origin->zfs_dmustats.dds_guid));
300185029Spjd	}
301185029Spjd
302185029Spjd	/* iterate over props */
303185029Spjd	VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
304185029Spjd	send_iterate_prop(zhp, nv);
305185029Spjd	VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
306185029Spjd	nvlist_free(nv);
307185029Spjd
308185029Spjd	/* iterate over snaps, and set sd->parent_fromsnap_guid */
309185029Spjd	sd->parent_fromsnap_guid = 0;
310185029Spjd	VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
311185029Spjd	VERIFY(0 == nvlist_alloc(&sd->snapprops, NV_UNIQUE_NAME, 0));
312185029Spjd	(void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
313185029Spjd	VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
314185029Spjd	VERIFY(0 == nvlist_add_nvlist(nvfs, "snapprops", sd->snapprops));
315185029Spjd	nvlist_free(sd->parent_snaps);
316185029Spjd	nvlist_free(sd->snapprops);
317185029Spjd
318185029Spjd	/* add this fs to nvlist */
319185029Spjd	(void) snprintf(guidstring, sizeof (guidstring),
320185029Spjd	    "0x%llx", (longlong_t)guid);
321185029Spjd	VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
322185029Spjd	nvlist_free(nvfs);
323185029Spjd
324185029Spjd	/* iterate over children */
325185029Spjd	rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
326185029Spjd
327185029Spjd	sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
328185029Spjd
329185029Spjd	zfs_close(zhp);
330185029Spjd	return (rv);
331185029Spjd}
332185029Spjd
333185029Spjdstatic int
334185029Spjdgather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
335185029Spjd    const char *tosnap, nvlist_t **nvlp, avl_tree_t **avlp)
336185029Spjd{
337185029Spjd	zfs_handle_t *zhp;
338185029Spjd	send_data_t sd = { 0 };
339185029Spjd	int error;
340185029Spjd
341185029Spjd	zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
342185029Spjd	if (zhp == NULL)
343185029Spjd		return (EZFS_BADTYPE);
344185029Spjd
345185029Spjd	VERIFY(0 == nvlist_alloc(&sd.fss, NV_UNIQUE_NAME, 0));
346185029Spjd	sd.fromsnap = fromsnap;
347185029Spjd	sd.tosnap = tosnap;
348185029Spjd
349185029Spjd	if ((error = send_iterate_fs(zhp, &sd)) != 0) {
350185029Spjd		nvlist_free(sd.fss);
351185029Spjd		if (avlp != NULL)
352185029Spjd			*avlp = NULL;
353185029Spjd		*nvlp = NULL;
354185029Spjd		return (error);
355185029Spjd	}
356185029Spjd
357185029Spjd	if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) {
358185029Spjd		nvlist_free(sd.fss);
359185029Spjd		*nvlp = NULL;
360185029Spjd		return (EZFS_NOMEM);
361185029Spjd	}
362185029Spjd
363185029Spjd	*nvlp = sd.fss;
364185029Spjd	return (0);
365185029Spjd}
366185029Spjd
367185029Spjd/*
368185029Spjd * Routines for dealing with the sorted snapshot functionality
369185029Spjd */
370185029Spjdtypedef struct zfs_node {
371185029Spjd	zfs_handle_t	*zn_handle;
372185029Spjd	avl_node_t	zn_avlnode;
373185029Spjd} zfs_node_t;
374185029Spjd
375185029Spjdstatic int
376185029Spjdzfs_sort_snaps(zfs_handle_t *zhp, void *data)
377185029Spjd{
378185029Spjd	avl_tree_t *avl = data;
379185029Spjd	zfs_node_t *node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t));
380185029Spjd
381185029Spjd	node->zn_handle = zhp;
382185029Spjd	avl_add(avl, node);
383185029Spjd	return (0);
384185029Spjd}
385185029Spjd
386185029Spjd/* ARGSUSED */
387185029Spjdstatic int
388185029Spjdzfs_snapshot_compare(const void *larg, const void *rarg)
389185029Spjd{
390185029Spjd	zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
391185029Spjd	zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
392185029Spjd	uint64_t lcreate, rcreate;
393185029Spjd
394185029Spjd	/*
395185029Spjd	 * Sort them according to creation time.  We use the hidden
396185029Spjd	 * CREATETXG property to get an absolute ordering of snapshots.
397185029Spjd	 */
398185029Spjd	lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
399185029Spjd	rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
400185029Spjd
401185029Spjd	if (lcreate < rcreate)
402185029Spjd		return (-1);
403185029Spjd	else if (lcreate > rcreate)
404185029Spjd		return (+1);
405185029Spjd	else
406185029Spjd		return (0);
407185029Spjd}
408185029Spjd
409185029Spjdstatic int
410185029Spjdzfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
411185029Spjd{
412185029Spjd	int ret = 0;
413185029Spjd	zfs_node_t *node;
414185029Spjd	avl_tree_t avl;
415185029Spjd	void *cookie = NULL;
416185029Spjd
417185029Spjd	avl_create(&avl, zfs_snapshot_compare,
418185029Spjd	    sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode));
419185029Spjd
420185029Spjd	ret = zfs_iter_snapshots(zhp, zfs_sort_snaps, &avl);
421185029Spjd
422185029Spjd	for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
423185029Spjd		ret |= callback(node->zn_handle, data);
424185029Spjd
425185029Spjd	while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL)
426185029Spjd		free(node);
427185029Spjd
428185029Spjd	avl_destroy(&avl);
429185029Spjd
430185029Spjd	return (ret);
431185029Spjd}
432185029Spjd
433185029Spjd/*
434185029Spjd * Routines specific to "zfs send"
435185029Spjd */
436185029Spjdtypedef struct send_dump_data {
437185029Spjd	/* these are all just the short snapname (the part after the @) */
438185029Spjd	const char *fromsnap;
439185029Spjd	const char *tosnap;
440185029Spjd	char lastsnap[ZFS_MAXNAMELEN];
441185029Spjd	boolean_t seenfrom, seento, replicate, doall, fromorigin;
442185029Spjd	boolean_t verbose;
443185029Spjd	int outfd;
444185029Spjd	boolean_t err;
445185029Spjd	nvlist_t *fss;
446185029Spjd	avl_tree_t *fsavl;
447185029Spjd} send_dump_data_t;
448185029Spjd
449185029Spjd/*
450185029Spjd * Dumps a backup of the given snapshot (incremental from fromsnap if it's not
451185029Spjd * NULL) to the file descriptor specified by outfd.
452185029Spjd */
453185029Spjdstatic int
454185029Spjddump_ioctl(zfs_handle_t *zhp, const char *fromsnap, boolean_t fromorigin,
455185029Spjd    int outfd)
456185029Spjd{
457185029Spjd	zfs_cmd_t zc = { 0 };
458185029Spjd	libzfs_handle_t *hdl = zhp->zfs_hdl;
459185029Spjd
460185029Spjd	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
461185029Spjd	assert(fromsnap == NULL || fromsnap[0] == '\0' || !fromorigin);
462185029Spjd
463185029Spjd	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
464185029Spjd	if (fromsnap)
465185029Spjd		(void) strlcpy(zc.zc_value, fromsnap, sizeof (zc.zc_value));
466185029Spjd	zc.zc_cookie = outfd;
467185029Spjd	zc.zc_obj = fromorigin;
468185029Spjd
469185029Spjd	if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SEND, &zc) != 0) {
470185029Spjd		char errbuf[1024];
471185029Spjd		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
472185029Spjd		    "warning: cannot send '%s'"), zhp->zfs_name);
473185029Spjd
474185029Spjd		switch (errno) {
475185029Spjd
476185029Spjd		case EXDEV:
477185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
478185029Spjd			    "not an earlier snapshot from the same fs"));
479185029Spjd			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
480185029Spjd
481185029Spjd		case ENOENT:
482185029Spjd			if (zfs_dataset_exists(hdl, zc.zc_name,
483185029Spjd			    ZFS_TYPE_SNAPSHOT)) {
484185029Spjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
485185029Spjd				    "incremental source (@%s) does not exist"),
486185029Spjd				    zc.zc_value);
487185029Spjd			}
488185029Spjd			return (zfs_error(hdl, EZFS_NOENT, errbuf));
489185029Spjd
490185029Spjd		case EDQUOT:
491185029Spjd		case EFBIG:
492185029Spjd		case EIO:
493185029Spjd		case ENOLINK:
494185029Spjd		case ENOSPC:
495185029Spjd		case ENXIO:
496185029Spjd		case EPIPE:
497185029Spjd		case ERANGE:
498185029Spjd		case EFAULT:
499185029Spjd		case EROFS:
500185029Spjd			zfs_error_aux(hdl, strerror(errno));
501185029Spjd			return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
502185029Spjd
503185029Spjd		default:
504185029Spjd			return (zfs_standard_error(hdl, errno, errbuf));
505185029Spjd		}
506185029Spjd	}
507185029Spjd
508185029Spjd	return (0);
509185029Spjd}
510185029Spjd
511185029Spjdstatic int
512185029Spjddump_snapshot(zfs_handle_t *zhp, void *arg)
513185029Spjd{
514185029Spjd	send_dump_data_t *sdd = arg;
515185029Spjd	const char *thissnap;
516185029Spjd	int err;
517185029Spjd
518185029Spjd	thissnap = strchr(zhp->zfs_name, '@') + 1;
519185029Spjd
520185029Spjd	if (sdd->fromsnap && !sdd->seenfrom &&
521185029Spjd	    strcmp(sdd->fromsnap, thissnap) == 0) {
522185029Spjd		sdd->seenfrom = B_TRUE;
523185029Spjd		(void) strcpy(sdd->lastsnap, thissnap);
524185029Spjd		zfs_close(zhp);
525185029Spjd		return (0);
526185029Spjd	}
527185029Spjd
528185029Spjd	if (sdd->seento || !sdd->seenfrom) {
529185029Spjd		zfs_close(zhp);
530185029Spjd		return (0);
531185029Spjd	}
532185029Spjd
533185029Spjd	/* send it */
534185029Spjd	if (sdd->verbose) {
535185029Spjd		(void) fprintf(stderr, "sending from @%s to %s\n",
536185029Spjd		    sdd->lastsnap, zhp->zfs_name);
537185029Spjd	}
538185029Spjd
539185029Spjd	err = dump_ioctl(zhp, sdd->lastsnap,
540185029Spjd	    sdd->lastsnap[0] == '\0' && (sdd->fromorigin || sdd->replicate),
541185029Spjd	    sdd->outfd);
542185029Spjd
543185029Spjd	if (!sdd->seento && strcmp(sdd->tosnap, thissnap) == 0)
544185029Spjd		sdd->seento = B_TRUE;
545185029Spjd
546185029Spjd	(void) strcpy(sdd->lastsnap, thissnap);
547185029Spjd	zfs_close(zhp);
548185029Spjd	return (err);
549185029Spjd}
550185029Spjd
551185029Spjdstatic int
552185029Spjddump_filesystem(zfs_handle_t *zhp, void *arg)
553185029Spjd{
554185029Spjd	int rv = 0;
555185029Spjd	send_dump_data_t *sdd = arg;
556185029Spjd	boolean_t missingfrom = B_FALSE;
557185029Spjd	zfs_cmd_t zc = { 0 };
558185029Spjd
559185029Spjd	(void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
560185029Spjd	    zhp->zfs_name, sdd->tosnap);
561185029Spjd	if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
562185029Spjd		(void) fprintf(stderr, "WARNING: "
563185029Spjd		    "could not send %s@%s: does not exist\n",
564185029Spjd		    zhp->zfs_name, sdd->tosnap);
565185029Spjd		sdd->err = B_TRUE;
566185029Spjd		return (0);
567185029Spjd	}
568185029Spjd
569185029Spjd	if (sdd->replicate && sdd->fromsnap) {
570185029Spjd		/*
571185029Spjd		 * If this fs does not have fromsnap, and we're doing
572185029Spjd		 * recursive, we need to send a full stream from the
573185029Spjd		 * beginning (or an incremental from the origin if this
574185029Spjd		 * is a clone).  If we're doing non-recursive, then let
575185029Spjd		 * them get the error.
576185029Spjd		 */
577185029Spjd		(void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
578185029Spjd		    zhp->zfs_name, sdd->fromsnap);
579185029Spjd		if (ioctl(zhp->zfs_hdl->libzfs_fd,
580185029Spjd		    ZFS_IOC_OBJSET_STATS, &zc) != 0) {
581185029Spjd			missingfrom = B_TRUE;
582185029Spjd		}
583185029Spjd	}
584185029Spjd
585185029Spjd	if (sdd->doall) {
586185029Spjd		sdd->seenfrom = sdd->seento = sdd->lastsnap[0] = 0;
587185029Spjd		if (sdd->fromsnap == NULL || missingfrom)
588185029Spjd			sdd->seenfrom = B_TRUE;
589185029Spjd
590185029Spjd		rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg);
591185029Spjd		if (!sdd->seenfrom) {
592185029Spjd			(void) fprintf(stderr,
593185029Spjd			    "WARNING: could not send %s@%s:\n"
594185029Spjd			    "incremental source (%s@%s) does not exist\n",
595185029Spjd			    zhp->zfs_name, sdd->tosnap,
596185029Spjd			    zhp->zfs_name, sdd->fromsnap);
597185029Spjd			sdd->err = B_TRUE;
598185029Spjd		} else if (!sdd->seento) {
599185029Spjd			(void) fprintf(stderr,
600185029Spjd			    "WARNING: could not send %s@%s:\n"
601185029Spjd			    "incremental source (%s@%s) "
602185029Spjd			    "is not earlier than it\n",
603185029Spjd			    zhp->zfs_name, sdd->tosnap,
604185029Spjd			    zhp->zfs_name, sdd->fromsnap);
605185029Spjd			sdd->err = B_TRUE;
606185029Spjd		}
607185029Spjd	} else {
608185029Spjd		zfs_handle_t *snapzhp;
609185029Spjd		char snapname[ZFS_MAXNAMELEN];
610185029Spjd
611185029Spjd		(void) snprintf(snapname, sizeof (snapname), "%s@%s",
612185029Spjd		    zfs_get_name(zhp), sdd->tosnap);
613185029Spjd		snapzhp = zfs_open(zhp->zfs_hdl, snapname, ZFS_TYPE_SNAPSHOT);
614185029Spjd		if (snapzhp == NULL) {
615185029Spjd			rv = -1;
616185029Spjd		} else {
617185029Spjd			rv = dump_ioctl(snapzhp,
618185029Spjd			    missingfrom ? NULL : sdd->fromsnap,
619185029Spjd			    sdd->fromorigin || missingfrom,
620185029Spjd			    sdd->outfd);
621185029Spjd			sdd->seento = B_TRUE;
622185029Spjd			zfs_close(snapzhp);
623185029Spjd		}
624185029Spjd	}
625185029Spjd
626185029Spjd	return (rv);
627185029Spjd}
628185029Spjd
629185029Spjdstatic int
630185029Spjddump_filesystems(zfs_handle_t *rzhp, void *arg)
631185029Spjd{
632185029Spjd	send_dump_data_t *sdd = arg;
633185029Spjd	nvpair_t *fspair;
634185029Spjd	boolean_t needagain, progress;
635185029Spjd
636185029Spjd	if (!sdd->replicate)
637185029Spjd		return (dump_filesystem(rzhp, sdd));
638185029Spjd
639185029Spjdagain:
640185029Spjd	needagain = progress = B_FALSE;
641185029Spjd	for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
642185029Spjd	    fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
643185029Spjd		nvlist_t *fslist;
644185029Spjd		char *fsname;
645185029Spjd		zfs_handle_t *zhp;
646185029Spjd		int err;
647185029Spjd		uint64_t origin_guid = 0;
648185029Spjd		nvlist_t *origin_nv;
649185029Spjd
650185029Spjd		VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0);
651185029Spjd		if (nvlist_lookup_boolean(fslist, "sent") == 0)
652185029Spjd			continue;
653185029Spjd
654185029Spjd		VERIFY(nvlist_lookup_string(fslist, "name", &fsname) == 0);
655185029Spjd		(void) nvlist_lookup_uint64(fslist, "origin", &origin_guid);
656185029Spjd
657185029Spjd		origin_nv = fsavl_find(sdd->fsavl, origin_guid, NULL);
658185029Spjd		if (origin_nv &&
659185029Spjd		    nvlist_lookup_boolean(origin_nv, "sent") == ENOENT) {
660185029Spjd			/*
661185029Spjd			 * origin has not been sent yet;
662185029Spjd			 * skip this clone.
663185029Spjd			 */
664185029Spjd			needagain = B_TRUE;
665185029Spjd			continue;
666185029Spjd		}
667185029Spjd
668185029Spjd		zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET);
669185029Spjd		if (zhp == NULL)
670185029Spjd			return (-1);
671185029Spjd		err = dump_filesystem(zhp, sdd);
672185029Spjd		VERIFY(nvlist_add_boolean(fslist, "sent") == 0);
673185029Spjd		progress = B_TRUE;
674185029Spjd		zfs_close(zhp);
675185029Spjd		if (err)
676185029Spjd			return (err);
677185029Spjd	}
678185029Spjd	if (needagain) {
679185029Spjd		assert(progress);
680185029Spjd		goto again;
681185029Spjd	}
682185029Spjd	return (0);
683185029Spjd}
684185029Spjd
685185029Spjd/*
686185029Spjd * Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL.
687185029Spjd * If 'doall', dump all intermediate snaps.
688185029Spjd * If 'replicate', dump special header and do recursively.
689185029Spjd */
690185029Spjdint
691185029Spjdzfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
692185029Spjd    boolean_t replicate, boolean_t doall, boolean_t fromorigin,
693185029Spjd    boolean_t verbose, int outfd)
694185029Spjd{
695185029Spjd	char errbuf[1024];
696185029Spjd	send_dump_data_t sdd = { 0 };
697185029Spjd	int err;
698185029Spjd	nvlist_t *fss = NULL;
699185029Spjd	avl_tree_t *fsavl = NULL;
700185029Spjd
701185029Spjd	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
702185029Spjd	    "cannot send '%s'"), zhp->zfs_name);
703185029Spjd
704185029Spjd	if (fromsnap && fromsnap[0] == '\0') {
705185029Spjd		zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
706185029Spjd		    "zero-length incremental source"));
707185029Spjd		return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
708185029Spjd	}
709185029Spjd
710185029Spjd	if (replicate || doall) {
711185029Spjd		dmu_replay_record_t drr = { 0 };
712185029Spjd		char *packbuf = NULL;
713185029Spjd		size_t buflen = 0;
714185029Spjd		zio_cksum_t zc = { 0 };
715185029Spjd
716185029Spjd		assert(fromsnap || doall);
717185029Spjd
718185029Spjd		if (replicate) {
719185029Spjd			nvlist_t *hdrnv;
720185029Spjd
721185029Spjd			VERIFY(0 == nvlist_alloc(&hdrnv, NV_UNIQUE_NAME, 0));
722185029Spjd			if (fromsnap) {
723185029Spjd				VERIFY(0 == nvlist_add_string(hdrnv,
724185029Spjd				    "fromsnap", fromsnap));
725185029Spjd			}
726185029Spjd			VERIFY(0 == nvlist_add_string(hdrnv, "tosnap", tosnap));
727185029Spjd
728185029Spjd			err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
729185029Spjd			    fromsnap, tosnap, &fss, &fsavl);
730185029Spjd			if (err)
731185029Spjd				return (err);
732185029Spjd			VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
733185029Spjd			err = nvlist_pack(hdrnv, &packbuf, &buflen,
734185029Spjd			    NV_ENCODE_XDR, 0);
735185029Spjd			nvlist_free(hdrnv);
736185029Spjd			if (err) {
737185029Spjd				fsavl_destroy(fsavl);
738185029Spjd				nvlist_free(fss);
739185029Spjd				return (zfs_standard_error(zhp->zfs_hdl,
740185029Spjd				    err, errbuf));
741185029Spjd			}
742185029Spjd		}
743185029Spjd
744185029Spjd		/* write first begin record */
745185029Spjd		drr.drr_type = DRR_BEGIN;
746185029Spjd		drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
747185029Spjd		drr.drr_u.drr_begin.drr_version = DMU_BACKUP_HEADER_VERSION;
748185029Spjd		(void) snprintf(drr.drr_u.drr_begin.drr_toname,
749185029Spjd		    sizeof (drr.drr_u.drr_begin.drr_toname),
750185029Spjd		    "%s@%s", zhp->zfs_name, tosnap);
751185029Spjd		drr.drr_payloadlen = buflen;
752185029Spjd		fletcher_4_incremental_native(&drr, sizeof (drr), &zc);
753185029Spjd		err = write(outfd, &drr, sizeof (drr));
754185029Spjd
755185029Spjd		/* write header nvlist */
756185029Spjd		if (err != -1) {
757185029Spjd			fletcher_4_incremental_native(packbuf, buflen, &zc);
758185029Spjd			err = write(outfd, packbuf, buflen);
759185029Spjd		}
760185029Spjd		free(packbuf);
761185029Spjd		if (err == -1) {
762185029Spjd			fsavl_destroy(fsavl);
763185029Spjd			nvlist_free(fss);
764185029Spjd			return (zfs_standard_error(zhp->zfs_hdl,
765185029Spjd			    errno, errbuf));
766185029Spjd		}
767185029Spjd
768185029Spjd		/* write end record */
769185029Spjd		if (err != -1) {
770185029Spjd			bzero(&drr, sizeof (drr));
771185029Spjd			drr.drr_type = DRR_END;
772185029Spjd			drr.drr_u.drr_end.drr_checksum = zc;
773185029Spjd			err = write(outfd, &drr, sizeof (drr));
774185029Spjd			if (err == -1) {
775185029Spjd				fsavl_destroy(fsavl);
776185029Spjd				nvlist_free(fss);
777185029Spjd				return (zfs_standard_error(zhp->zfs_hdl,
778185029Spjd				    errno, errbuf));
779185029Spjd			}
780185029Spjd		}
781185029Spjd	}
782185029Spjd
783185029Spjd	/* dump each stream */
784185029Spjd	sdd.fromsnap = fromsnap;
785185029Spjd	sdd.tosnap = tosnap;
786185029Spjd	sdd.outfd = outfd;
787185029Spjd	sdd.replicate = replicate;
788185029Spjd	sdd.doall = doall;
789185029Spjd	sdd.fromorigin = fromorigin;
790185029Spjd	sdd.fss = fss;
791185029Spjd	sdd.fsavl = fsavl;
792185029Spjd	sdd.verbose = verbose;
793185029Spjd	err = dump_filesystems(zhp, &sdd);
794185029Spjd	fsavl_destroy(fsavl);
795185029Spjd	nvlist_free(fss);
796185029Spjd
797185029Spjd	if (replicate || doall) {
798185029Spjd		/*
799185029Spjd		 * write final end record.  NB: want to do this even if
800185029Spjd		 * there was some error, because it might not be totally
801185029Spjd		 * failed.
802185029Spjd		 */
803185029Spjd		dmu_replay_record_t drr = { 0 };
804185029Spjd		drr.drr_type = DRR_END;
805185029Spjd		if (write(outfd, &drr, sizeof (drr)) == -1) {
806185029Spjd			return (zfs_standard_error(zhp->zfs_hdl,
807185029Spjd			    errno, errbuf));
808185029Spjd		}
809185029Spjd	}
810185029Spjd
811185029Spjd	return (err || sdd.err);
812185029Spjd}
813185029Spjd
814185029Spjd/*
815185029Spjd * Routines specific to "zfs recv"
816185029Spjd */
817185029Spjd
818185029Spjdstatic int
819185029Spjdrecv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen,
820185029Spjd    boolean_t byteswap, zio_cksum_t *zc)
821185029Spjd{
822185029Spjd	char *cp = buf;
823185029Spjd	int rv;
824185029Spjd	int len = ilen;
825185029Spjd
826185029Spjd	do {
827185029Spjd		rv = read(fd, cp, len);
828185029Spjd		cp += rv;
829185029Spjd		len -= rv;
830185029Spjd	} while (rv > 0);
831185029Spjd
832185029Spjd	if (rv < 0 || len != 0) {
833185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
834185029Spjd		    "failed to read from stream"));
835185029Spjd		return (zfs_error(hdl, EZFS_BADSTREAM, dgettext(TEXT_DOMAIN,
836185029Spjd		    "cannot receive")));
837185029Spjd	}
838185029Spjd
839185029Spjd	if (zc) {
840185029Spjd		if (byteswap)
841185029Spjd			fletcher_4_incremental_byteswap(buf, ilen, zc);
842185029Spjd		else
843185029Spjd			fletcher_4_incremental_native(buf, ilen, zc);
844185029Spjd	}
845185029Spjd	return (0);
846185029Spjd}
847185029Spjd
848185029Spjdstatic int
849185029Spjdrecv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp,
850185029Spjd    boolean_t byteswap, zio_cksum_t *zc)
851185029Spjd{
852185029Spjd	char *buf;
853185029Spjd	int err;
854185029Spjd
855185029Spjd	buf = zfs_alloc(hdl, len);
856185029Spjd	if (buf == NULL)
857185029Spjd		return (ENOMEM);
858185029Spjd
859185029Spjd	err = recv_read(hdl, fd, buf, len, byteswap, zc);
860185029Spjd	if (err != 0) {
861185029Spjd		free(buf);
862185029Spjd		return (err);
863185029Spjd	}
864185029Spjd
865185029Spjd	err = nvlist_unpack(buf, len, nvp, 0);
866185029Spjd	free(buf);
867185029Spjd	if (err != 0) {
868185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
869185029Spjd		    "stream (malformed nvlist)"));
870185029Spjd		return (EINVAL);
871185029Spjd	}
872185029Spjd	return (0);
873185029Spjd}
874185029Spjd
875185029Spjdstatic int
876185029Spjdrecv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
877185029Spjd    int baselen, char *newname, recvflags_t flags)
878185029Spjd{
879185029Spjd	static int seq;
880185029Spjd	zfs_cmd_t zc = { 0 };
881185029Spjd	int err;
882185029Spjd	prop_changelist_t *clp;
883185029Spjd	zfs_handle_t *zhp;
884185029Spjd
885185029Spjd	zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
886185029Spjd	if (zhp == NULL)
887185029Spjd		return (-1);
888185029Spjd	clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
889185029Spjd	    flags.force ? MS_FORCE : 0);
890185029Spjd	zfs_close(zhp);
891185029Spjd	if (clp == NULL)
892185029Spjd		return (-1);
893185029Spjd	err = changelist_prefix(clp);
894185029Spjd	if (err)
895185029Spjd		return (err);
896185029Spjd
897185029Spjd	if (tryname) {
898185029Spjd		(void) strcpy(newname, tryname);
899185029Spjd
900185029Spjd		zc.zc_objset_type = DMU_OST_ZFS;
901185029Spjd		(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
902185029Spjd		(void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value));
903185029Spjd
904185029Spjd		if (flags.verbose) {
905185029Spjd			(void) printf("attempting rename %s to %s\n",
906185029Spjd			    zc.zc_name, zc.zc_value);
907185029Spjd		}
908185029Spjd		err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
909185029Spjd		if (err == 0)
910185029Spjd			changelist_rename(clp, name, tryname);
911185029Spjd	} else {
912185029Spjd		err = ENOENT;
913185029Spjd	}
914185029Spjd
915185029Spjd	if (err != 0 && strncmp(name+baselen, "recv-", 5) != 0) {
916185029Spjd		seq++;
917185029Spjd
918185029Spjd		(void) strncpy(newname, name, baselen);
919185029Spjd		(void) snprintf(newname+baselen, ZFS_MAXNAMELEN-baselen,
920185029Spjd		    "recv-%u-%u", getpid(), seq);
921185029Spjd		(void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value));
922185029Spjd
923185029Spjd		if (flags.verbose) {
924185029Spjd			(void) printf("failed - trying rename %s to %s\n",
925185029Spjd			    zc.zc_name, zc.zc_value);
926185029Spjd		}
927185029Spjd		err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
928185029Spjd		if (err == 0)
929185029Spjd			changelist_rename(clp, name, newname);
930185029Spjd		if (err && flags.verbose) {
931185029Spjd			(void) printf("failed (%u) - "
932185029Spjd			    "will try again on next pass\n", errno);
933185029Spjd		}
934185029Spjd		err = EAGAIN;
935185029Spjd	} else if (flags.verbose) {
936185029Spjd		if (err == 0)
937185029Spjd			(void) printf("success\n");
938185029Spjd		else
939185029Spjd			(void) printf("failed (%u)\n", errno);
940185029Spjd	}
941185029Spjd
942185029Spjd	(void) changelist_postfix(clp);
943185029Spjd	changelist_free(clp);
944185029Spjd
945185029Spjd	return (err);
946185029Spjd}
947185029Spjd
948185029Spjdstatic int
949185029Spjdrecv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
950185029Spjd    char *newname, recvflags_t flags)
951185029Spjd{
952185029Spjd	zfs_cmd_t zc = { 0 };
953185029Spjd	int err = 0;
954185029Spjd	prop_changelist_t *clp;
955185029Spjd	zfs_handle_t *zhp;
956185029Spjd
957185029Spjd	zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
958185029Spjd	if (zhp == NULL)
959185029Spjd		return (-1);
960185029Spjd	clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
961185029Spjd	    flags.force ? MS_FORCE : 0);
962185029Spjd	zfs_close(zhp);
963185029Spjd	if (clp == NULL)
964185029Spjd		return (-1);
965185029Spjd	err = changelist_prefix(clp);
966185029Spjd	if (err)
967185029Spjd		return (err);
968185029Spjd
969185029Spjd	zc.zc_objset_type = DMU_OST_ZFS;
970185029Spjd	(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
971185029Spjd
972185029Spjd	if (flags.verbose)
973185029Spjd		(void) printf("attempting destroy %s\n", zc.zc_name);
974185029Spjd	err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
975185029Spjd
976185029Spjd	if (err == 0) {
977185029Spjd		if (flags.verbose)
978185029Spjd			(void) printf("success\n");
979185029Spjd		changelist_remove(clp, zc.zc_name);
980185029Spjd	}
981185029Spjd
982185029Spjd	(void) changelist_postfix(clp);
983185029Spjd	changelist_free(clp);
984185029Spjd
985185029Spjd	if (err != 0)
986185029Spjd		err = recv_rename(hdl, name, NULL, baselen, newname, flags);
987185029Spjd
988185029Spjd	return (err);
989185029Spjd}
990185029Spjd
991185029Spjdtypedef struct guid_to_name_data {
992185029Spjd	uint64_t guid;
993185029Spjd	char *name;
994185029Spjd} guid_to_name_data_t;
995185029Spjd
996185029Spjdstatic int
997185029Spjdguid_to_name_cb(zfs_handle_t *zhp, void *arg)
998185029Spjd{
999185029Spjd	guid_to_name_data_t *gtnd = arg;
1000185029Spjd	int err;
1001185029Spjd
1002185029Spjd	if (zhp->zfs_dmustats.dds_guid == gtnd->guid) {
1003185029Spjd		(void) strcpy(gtnd->name, zhp->zfs_name);
1004185029Spjd		return (EEXIST);
1005185029Spjd	}
1006185029Spjd	err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
1007185029Spjd	zfs_close(zhp);
1008185029Spjd	return (err);
1009185029Spjd}
1010185029Spjd
1011185029Spjdstatic int
1012185029Spjdguid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
1013185029Spjd    char *name)
1014185029Spjd{
1015185029Spjd	/* exhaustive search all local snapshots */
1016185029Spjd	guid_to_name_data_t gtnd;
1017185029Spjd	int err = 0;
1018185029Spjd	zfs_handle_t *zhp;
1019185029Spjd	char *cp;
1020185029Spjd
1021185029Spjd	gtnd.guid = guid;
1022185029Spjd	gtnd.name = name;
1023185029Spjd
1024185029Spjd	if (strchr(parent, '@') == NULL) {
1025185029Spjd		zhp = make_dataset_handle(hdl, parent);
1026185029Spjd		if (zhp != NULL) {
1027185029Spjd			err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
1028185029Spjd			zfs_close(zhp);
1029185029Spjd			if (err == EEXIST)
1030185029Spjd				return (0);
1031185029Spjd		}
1032185029Spjd	}
1033185029Spjd
1034185029Spjd	cp = strchr(parent, '/');
1035185029Spjd	if (cp)
1036185029Spjd		*cp = '\0';
1037185029Spjd	zhp = make_dataset_handle(hdl, parent);
1038185029Spjd	if (cp)
1039185029Spjd		*cp = '/';
1040185029Spjd
1041185029Spjd	if (zhp) {
1042185029Spjd		err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
1043185029Spjd		zfs_close(zhp);
1044185029Spjd	}
1045185029Spjd
1046185029Spjd	return (err == EEXIST ? 0 : ENOENT);
1047185029Spjd
1048185029Spjd}
1049185029Spjd
1050185029Spjd/*
1051185029Spjd * Return true if dataset guid1 is created before guid2.
1052185029Spjd */
1053185029Spjdstatic int
1054185029Spjdcreated_before(libzfs_handle_t *hdl, avl_tree_t *avl,
1055185029Spjd    uint64_t guid1, uint64_t guid2)
1056185029Spjd{
1057185029Spjd	nvlist_t *nvfs;
1058185029Spjd	char *fsname, *snapname;
1059185029Spjd	char buf[ZFS_MAXNAMELEN];
1060185029Spjd	int rv;
1061185029Spjd	zfs_node_t zn1, zn2;
1062185029Spjd
1063185029Spjd	if (guid2 == 0)
1064185029Spjd		return (0);
1065185029Spjd	if (guid1 == 0)
1066185029Spjd		return (1);
1067185029Spjd
1068185029Spjd	nvfs = fsavl_find(avl, guid1, &snapname);
1069185029Spjd	VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1070185029Spjd	(void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
1071185029Spjd	zn1.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
1072185029Spjd	if (zn1.zn_handle == NULL)
1073185029Spjd		return (-1);
1074185029Spjd
1075185029Spjd	nvfs = fsavl_find(avl, guid2, &snapname);
1076185029Spjd	VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1077185029Spjd	(void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
1078185029Spjd	zn2.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
1079185029Spjd	if (zn2.zn_handle == NULL) {
1080185029Spjd		zfs_close(zn2.zn_handle);
1081185029Spjd		return (-1);
1082185029Spjd	}
1083185029Spjd
1084185029Spjd	rv = (zfs_snapshot_compare(&zn1, &zn2) == -1);
1085185029Spjd
1086185029Spjd	zfs_close(zn1.zn_handle);
1087185029Spjd	zfs_close(zn2.zn_handle);
1088185029Spjd
1089185029Spjd	return (rv);
1090185029Spjd}
1091185029Spjd
1092185029Spjdstatic int
1093185029Spjdrecv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
1094185029Spjd    recvflags_t flags, nvlist_t *stream_nv, avl_tree_t *stream_avl)
1095185029Spjd{
1096185029Spjd	nvlist_t *local_nv;
1097185029Spjd	avl_tree_t *local_avl;
1098185029Spjd	nvpair_t *fselem, *nextfselem;
1099185029Spjd	char *tosnap, *fromsnap;
1100185029Spjd	char newname[ZFS_MAXNAMELEN];
1101185029Spjd	int error;
1102185029Spjd	boolean_t needagain, progress;
1103185029Spjd
1104185029Spjd	VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
1105185029Spjd	VERIFY(0 == nvlist_lookup_string(stream_nv, "tosnap", &tosnap));
1106185029Spjd
1107185029Spjd	if (flags.dryrun)
1108185029Spjd		return (0);
1109185029Spjd
1110185029Spjdagain:
1111185029Spjd	needagain = progress = B_FALSE;
1112185029Spjd
1113185029Spjd	if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
1114185029Spjd	    &local_nv, &local_avl)) != 0)
1115185029Spjd		return (error);
1116185029Spjd
1117185029Spjd	/*
1118185029Spjd	 * Process deletes and renames
1119185029Spjd	 */
1120185029Spjd	for (fselem = nvlist_next_nvpair(local_nv, NULL);
1121185029Spjd	    fselem; fselem = nextfselem) {
1122185029Spjd		nvlist_t *nvfs, *snaps;
1123185029Spjd		nvlist_t *stream_nvfs = NULL;
1124185029Spjd		nvpair_t *snapelem, *nextsnapelem;
1125185029Spjd		uint64_t fromguid = 0;
1126185029Spjd		uint64_t originguid = 0;
1127185029Spjd		uint64_t stream_originguid = 0;
1128185029Spjd		uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
1129185029Spjd		char *fsname, *stream_fsname;
1130185029Spjd
1131185029Spjd		nextfselem = nvlist_next_nvpair(local_nv, fselem);
1132185029Spjd
1133185029Spjd		VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
1134185029Spjd		VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
1135185029Spjd		VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1136185029Spjd		VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",
1137185029Spjd		    &parent_fromsnap_guid));
1138185029Spjd		(void) nvlist_lookup_uint64(nvfs, "origin", &originguid);
1139185029Spjd
1140185029Spjd		/*
1141185029Spjd		 * First find the stream's fs, so we can check for
1142185029Spjd		 * a different origin (due to "zfs promote")
1143185029Spjd		 */
1144185029Spjd		for (snapelem = nvlist_next_nvpair(snaps, NULL);
1145185029Spjd		    snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) {
1146185029Spjd			uint64_t thisguid;
1147185029Spjd
1148185029Spjd			VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
1149185029Spjd			stream_nvfs = fsavl_find(stream_avl, thisguid, NULL);
1150185029Spjd
1151185029Spjd			if (stream_nvfs != NULL)
1152185029Spjd				break;
1153185029Spjd		}
1154185029Spjd
1155185029Spjd		/* check for promote */
1156185029Spjd		(void) nvlist_lookup_uint64(stream_nvfs, "origin",
1157185029Spjd		    &stream_originguid);
1158185029Spjd		if (stream_nvfs && originguid != stream_originguid) {
1159185029Spjd			switch (created_before(hdl, local_avl,
1160185029Spjd			    stream_originguid, originguid)) {
1161185029Spjd			case 1: {
1162185029Spjd				/* promote it! */
1163185029Spjd				zfs_cmd_t zc = { 0 };
1164185029Spjd				nvlist_t *origin_nvfs;
1165185029Spjd				char *origin_fsname;
1166185029Spjd
1167185029Spjd				if (flags.verbose)
1168185029Spjd					(void) printf("promoting %s\n", fsname);
1169185029Spjd
1170185029Spjd				origin_nvfs = fsavl_find(local_avl, originguid,
1171185029Spjd				    NULL);
1172185029Spjd				VERIFY(0 == nvlist_lookup_string(origin_nvfs,
1173185029Spjd				    "name", &origin_fsname));
1174185029Spjd				(void) strlcpy(zc.zc_value, origin_fsname,
1175185029Spjd				    sizeof (zc.zc_value));
1176185029Spjd				(void) strlcpy(zc.zc_name, fsname,
1177185029Spjd				    sizeof (zc.zc_name));
1178185029Spjd				error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
1179185029Spjd				if (error == 0)
1180185029Spjd					progress = B_TRUE;
1181185029Spjd				break;
1182185029Spjd			}
1183185029Spjd			default:
1184185029Spjd				break;
1185185029Spjd			case -1:
1186185029Spjd				fsavl_destroy(local_avl);
1187185029Spjd				nvlist_free(local_nv);
1188185029Spjd				return (-1);
1189185029Spjd			}
1190185029Spjd			/*
1191185029Spjd			 * We had/have the wrong origin, therefore our
1192185029Spjd			 * list of snapshots is wrong.  Need to handle
1193185029Spjd			 * them on the next pass.
1194185029Spjd			 */
1195185029Spjd			needagain = B_TRUE;
1196185029Spjd			continue;
1197185029Spjd		}
1198185029Spjd
1199185029Spjd		for (snapelem = nvlist_next_nvpair(snaps, NULL);
1200185029Spjd		    snapelem; snapelem = nextsnapelem) {
1201185029Spjd			uint64_t thisguid;
1202185029Spjd			char *stream_snapname;
1203185029Spjd			nvlist_t *found, *props;
1204185029Spjd
1205185029Spjd			nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
1206185029Spjd
1207185029Spjd			VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
1208185029Spjd			found = fsavl_find(stream_avl, thisguid,
1209185029Spjd			    &stream_snapname);
1210185029Spjd
1211185029Spjd			/* check for delete */
1212185029Spjd			if (found == NULL) {
1213185029Spjd				char name[ZFS_MAXNAMELEN];
1214185029Spjd
1215185029Spjd				if (!flags.force)
1216185029Spjd					continue;
1217185029Spjd
1218185029Spjd				(void) snprintf(name, sizeof (name), "%s@%s",
1219185029Spjd				    fsname, nvpair_name(snapelem));
1220185029Spjd
1221185029Spjd				error = recv_destroy(hdl, name,
1222185029Spjd				    strlen(fsname)+1, newname, flags);
1223185029Spjd				if (error)
1224185029Spjd					needagain = B_TRUE;
1225185029Spjd				else
1226185029Spjd					progress = B_TRUE;
1227185029Spjd				continue;
1228185029Spjd			}
1229185029Spjd
1230185029Spjd			stream_nvfs = found;
1231185029Spjd
1232185029Spjd			if (0 == nvlist_lookup_nvlist(stream_nvfs, "snapprops",
1233185029Spjd			    &props) && 0 == nvlist_lookup_nvlist(props,
1234185029Spjd			    stream_snapname, &props)) {
1235185029Spjd				zfs_cmd_t zc = { 0 };
1236185029Spjd
1237185029Spjd				zc.zc_cookie = B_TRUE; /* clear current props */
1238185029Spjd				(void) snprintf(zc.zc_name, sizeof (zc.zc_name),
1239185029Spjd				    "%s@%s", fsname, nvpair_name(snapelem));
1240185029Spjd				if (zcmd_write_src_nvlist(hdl, &zc,
1241185029Spjd				    props) == 0) {
1242185029Spjd					(void) zfs_ioctl(hdl,
1243185029Spjd					    ZFS_IOC_SET_PROP, &zc);
1244185029Spjd					zcmd_free_nvlists(&zc);
1245185029Spjd				}
1246185029Spjd			}
1247185029Spjd
1248185029Spjd			/* check for different snapname */
1249185029Spjd			if (strcmp(nvpair_name(snapelem),
1250185029Spjd			    stream_snapname) != 0) {
1251185029Spjd				char name[ZFS_MAXNAMELEN];
1252185029Spjd				char tryname[ZFS_MAXNAMELEN];
1253185029Spjd
1254185029Spjd				(void) snprintf(name, sizeof (name), "%s@%s",
1255185029Spjd				    fsname, nvpair_name(snapelem));
1256185029Spjd				(void) snprintf(tryname, sizeof (name), "%s@%s",
1257185029Spjd				    fsname, stream_snapname);
1258185029Spjd
1259185029Spjd				error = recv_rename(hdl, name, tryname,
1260185029Spjd				    strlen(fsname)+1, newname, flags);
1261185029Spjd				if (error)
1262185029Spjd					needagain = B_TRUE;
1263185029Spjd				else
1264185029Spjd					progress = B_TRUE;
1265185029Spjd			}
1266185029Spjd
1267185029Spjd			if (strcmp(stream_snapname, fromsnap) == 0)
1268185029Spjd				fromguid = thisguid;
1269185029Spjd		}
1270185029Spjd
1271185029Spjd		/* check for delete */
1272185029Spjd		if (stream_nvfs == NULL) {
1273185029Spjd			if (!flags.force)
1274185029Spjd				continue;
1275185029Spjd
1276185029Spjd			error = recv_destroy(hdl, fsname, strlen(tofs)+1,
1277185029Spjd			    newname, flags);
1278185029Spjd			if (error)
1279185029Spjd				needagain = B_TRUE;
1280185029Spjd			else
1281185029Spjd				progress = B_TRUE;
1282185029Spjd			continue;
1283185029Spjd		}
1284185029Spjd
1285185029Spjd		if (fromguid == 0 && flags.verbose) {
1286185029Spjd			(void) printf("local fs %s does not have fromsnap "
1287185029Spjd			    "(%s in stream); must have been deleted locally; "
1288185029Spjd			    "ignoring\n", fsname, fromsnap);
1289185029Spjd			continue;
1290185029Spjd		}
1291185029Spjd
1292185029Spjd		VERIFY(0 == nvlist_lookup_string(stream_nvfs,
1293185029Spjd		    "name", &stream_fsname));
1294185029Spjd		VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
1295185029Spjd		    "parentfromsnap", &stream_parent_fromsnap_guid));
1296185029Spjd
1297185029Spjd		/* check for rename */
1298185029Spjd		if ((stream_parent_fromsnap_guid != 0 &&
1299185029Spjd		    stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
1300185029Spjd		    strcmp(strrchr(fsname, '/'),
1301185029Spjd		    strrchr(stream_fsname, '/')) != 0) {
1302185029Spjd			nvlist_t *parent;
1303185029Spjd			char tryname[ZFS_MAXNAMELEN];
1304185029Spjd
1305185029Spjd			parent = fsavl_find(local_avl,
1306185029Spjd			    stream_parent_fromsnap_guid, NULL);
1307185029Spjd			/*
1308185029Spjd			 * NB: parent might not be found if we used the
1309185029Spjd			 * tosnap for stream_parent_fromsnap_guid,
1310185029Spjd			 * because the parent is a newly-created fs;
1311185029Spjd			 * we'll be able to rename it after we recv the
1312185029Spjd			 * new fs.
1313185029Spjd			 */
1314185029Spjd			if (parent != NULL) {
1315185029Spjd				char *pname;
1316185029Spjd
1317185029Spjd				VERIFY(0 == nvlist_lookup_string(parent, "name",
1318185029Spjd				    &pname));
1319185029Spjd				(void) snprintf(tryname, sizeof (tryname),
1320185029Spjd				    "%s%s", pname, strrchr(stream_fsname, '/'));
1321185029Spjd			} else {
1322185029Spjd				tryname[0] = '\0';
1323185029Spjd				if (flags.verbose) {
1324185029Spjd					(void) printf("local fs %s new parent "
1325185029Spjd					    "not found\n", fsname);
1326185029Spjd				}
1327185029Spjd			}
1328185029Spjd
1329185029Spjd			error = recv_rename(hdl, fsname, tryname,
1330185029Spjd			    strlen(tofs)+1, newname, flags);
1331185029Spjd			if (error)
1332185029Spjd				needagain = B_TRUE;
1333185029Spjd			else
1334185029Spjd				progress = B_TRUE;
1335185029Spjd		}
1336185029Spjd	}
1337185029Spjd
1338185029Spjd	fsavl_destroy(local_avl);
1339185029Spjd	nvlist_free(local_nv);
1340185029Spjd
1341185029Spjd	if (needagain && progress) {
1342185029Spjd		/* do another pass to fix up temporary names */
1343185029Spjd		if (flags.verbose)
1344185029Spjd			(void) printf("another pass:\n");
1345185029Spjd		goto again;
1346185029Spjd	}
1347185029Spjd
1348185029Spjd	return (needagain);
1349185029Spjd}
1350185029Spjd
1351185029Spjdstatic int
1352185029Spjdzfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
1353185029Spjd    recvflags_t flags, dmu_replay_record_t *drr, zio_cksum_t *zc,
1354185029Spjd    char **top_zfs)
1355185029Spjd{
1356185029Spjd	nvlist_t *stream_nv = NULL;
1357185029Spjd	avl_tree_t *stream_avl = NULL;
1358185029Spjd	char *fromsnap = NULL;
1359185029Spjd	char tofs[ZFS_MAXNAMELEN];
1360185029Spjd	char errbuf[1024];
1361185029Spjd	dmu_replay_record_t drre;
1362185029Spjd	int error;
1363185029Spjd	boolean_t anyerr = B_FALSE;
1364185029Spjd	boolean_t softerr = B_FALSE;
1365185029Spjd
1366185029Spjd	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1367185029Spjd	    "cannot receive"));
1368185029Spjd
1369185029Spjd	if (strchr(destname, '@')) {
1370185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1371185029Spjd		    "can not specify snapshot name for multi-snapshot stream"));
1372185029Spjd		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
1373185029Spjd	}
1374185029Spjd
1375185029Spjd	assert(drr->drr_type == DRR_BEGIN);
1376185029Spjd	assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
1377185029Spjd	assert(drr->drr_u.drr_begin.drr_version == DMU_BACKUP_HEADER_VERSION);
1378185029Spjd
1379185029Spjd	/*
1380185029Spjd	 * Read in the nvlist from the stream.
1381185029Spjd	 */
1382185029Spjd	if (drr->drr_payloadlen != 0) {
1383185029Spjd		if (!flags.isprefix) {
1384185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1385185029Spjd			    "must use -d to receive replication "
1386185029Spjd			    "(send -R) stream"));
1387185029Spjd			return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
1388185029Spjd		}
1389185029Spjd
1390185029Spjd		error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen,
1391185029Spjd		    &stream_nv, flags.byteswap, zc);
1392185029Spjd		if (error) {
1393185029Spjd			error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1394185029Spjd			goto out;
1395185029Spjd		}
1396185029Spjd	}
1397185029Spjd
1398185029Spjd	/*
1399185029Spjd	 * Read in the end record and verify checksum.
1400185029Spjd	 */
1401185029Spjd	if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre),
1402185029Spjd	    flags.byteswap, NULL)))
1403185029Spjd		goto out;
1404185029Spjd	if (flags.byteswap) {
1405185029Spjd		drre.drr_type = BSWAP_32(drre.drr_type);
1406185029Spjd		drre.drr_u.drr_end.drr_checksum.zc_word[0] =
1407185029Spjd		    BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]);
1408185029Spjd		drre.drr_u.drr_end.drr_checksum.zc_word[1] =
1409185029Spjd		    BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[1]);
1410185029Spjd		drre.drr_u.drr_end.drr_checksum.zc_word[2] =
1411185029Spjd		    BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[2]);
1412185029Spjd		drre.drr_u.drr_end.drr_checksum.zc_word[3] =
1413185029Spjd		    BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[3]);
1414185029Spjd	}
1415185029Spjd	if (drre.drr_type != DRR_END) {
1416185029Spjd		error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1417185029Spjd		goto out;
1418185029Spjd	}
1419185029Spjd	if (!ZIO_CHECKSUM_EQUAL(drre.drr_u.drr_end.drr_checksum, *zc)) {
1420185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1421185029Spjd		    "incorrect header checksum"));
1422185029Spjd		error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1423185029Spjd		goto out;
1424185029Spjd	}
1425185029Spjd
1426185029Spjd	(void) nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap);
1427185029Spjd
1428185029Spjd	if (drr->drr_payloadlen != 0) {
1429185029Spjd		nvlist_t *stream_fss;
1430185029Spjd
1431185029Spjd		VERIFY(0 == nvlist_lookup_nvlist(stream_nv, "fss",
1432185029Spjd		    &stream_fss));
1433185029Spjd		if ((stream_avl = fsavl_create(stream_fss)) == NULL) {
1434185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1435185029Spjd			    "couldn't allocate avl tree"));
1436185029Spjd			error = zfs_error(hdl, EZFS_NOMEM, errbuf);
1437185029Spjd			goto out;
1438185029Spjd		}
1439185029Spjd
1440185029Spjd		if (fromsnap != NULL) {
1441185029Spjd			(void) strlcpy(tofs, destname, ZFS_MAXNAMELEN);
1442185029Spjd			if (flags.isprefix) {
1443185029Spjd				int i = strcspn(drr->drr_u.drr_begin.drr_toname,
1444185029Spjd				    "/@");
1445185029Spjd				/* zfs_receive_one() will create_parents() */
1446185029Spjd				(void) strlcat(tofs,
1447185029Spjd				    &drr->drr_u.drr_begin.drr_toname[i],
1448185029Spjd				    ZFS_MAXNAMELEN);
1449185029Spjd				*strchr(tofs, '@') = '\0';
1450185029Spjd			}
1451185029Spjd			softerr = recv_incremental_replication(hdl, tofs,
1452185029Spjd			    flags, stream_nv, stream_avl);
1453185029Spjd		}
1454185029Spjd	}
1455185029Spjd
1456185029Spjd
1457185029Spjd	/* Finally, receive each contained stream */
1458185029Spjd	do {
1459185029Spjd		/*
1460185029Spjd		 * we should figure out if it has a recoverable
1461185029Spjd		 * error, in which case do a recv_skip() and drive on.
1462185029Spjd		 * Note, if we fail due to already having this guid,
1463185029Spjd		 * zfs_receive_one() will take care of it (ie,
1464185029Spjd		 * recv_skip() and return 0).
1465185029Spjd		 */
1466185029Spjd		error = zfs_receive_impl(hdl, destname, flags, fd,
1467185029Spjd		    stream_avl, top_zfs);
1468185029Spjd		if (error == ENODATA) {
1469185029Spjd			error = 0;
1470185029Spjd			break;
1471185029Spjd		}
1472185029Spjd		anyerr |= error;
1473185029Spjd	} while (error == 0);
1474185029Spjd
1475185029Spjd	if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
1476185029Spjd		/*
1477185029Spjd		 * Now that we have the fs's they sent us, try the
1478185029Spjd		 * renames again.
1479185029Spjd		 */
1480185029Spjd		softerr = recv_incremental_replication(hdl, tofs, flags,
1481185029Spjd		    stream_nv, stream_avl);
1482185029Spjd	}
1483185029Spjd
1484185029Spjdout:
1485185029Spjd	fsavl_destroy(stream_avl);
1486185029Spjd	if (stream_nv)
1487185029Spjd		nvlist_free(stream_nv);
1488185029Spjd	if (softerr)
1489185029Spjd		error = -2;
1490185029Spjd	if (anyerr)
1491185029Spjd		error = -1;
1492185029Spjd	return (error);
1493185029Spjd}
1494185029Spjd
1495185029Spjdstatic int
1496185029Spjdrecv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
1497185029Spjd{
1498185029Spjd	dmu_replay_record_t *drr;
1499185029Spjd	void *buf = malloc(1<<20);
1500185029Spjd
1501185029Spjd	/* XXX would be great to use lseek if possible... */
1502185029Spjd	drr = buf;
1503185029Spjd
1504185029Spjd	while (recv_read(hdl, fd, drr, sizeof (dmu_replay_record_t),
1505185029Spjd	    byteswap, NULL) == 0) {
1506185029Spjd		if (byteswap)
1507185029Spjd			drr->drr_type = BSWAP_32(drr->drr_type);
1508185029Spjd
1509185029Spjd		switch (drr->drr_type) {
1510185029Spjd		case DRR_BEGIN:
1511185029Spjd			/* NB: not to be used on v2 stream packages */
1512185029Spjd			assert(drr->drr_payloadlen == 0);
1513185029Spjd			break;
1514185029Spjd
1515185029Spjd		case DRR_END:
1516185029Spjd			free(buf);
1517185029Spjd			return (0);
1518185029Spjd
1519185029Spjd		case DRR_OBJECT:
1520185029Spjd			if (byteswap) {
1521185029Spjd				drr->drr_u.drr_object.drr_bonuslen =
1522185029Spjd				    BSWAP_32(drr->drr_u.drr_object.
1523185029Spjd				    drr_bonuslen);
1524185029Spjd			}
1525185029Spjd			(void) recv_read(hdl, fd, buf,
1526185029Spjd			    P2ROUNDUP(drr->drr_u.drr_object.drr_bonuslen, 8),
1527185029Spjd			    B_FALSE, NULL);
1528185029Spjd			break;
1529185029Spjd
1530185029Spjd		case DRR_WRITE:
1531185029Spjd			if (byteswap) {
1532185029Spjd				drr->drr_u.drr_write.drr_length =
1533185029Spjd				    BSWAP_64(drr->drr_u.drr_write.drr_length);
1534185029Spjd			}
1535185029Spjd			(void) recv_read(hdl, fd, buf,
1536185029Spjd			    drr->drr_u.drr_write.drr_length, B_FALSE, NULL);
1537185029Spjd			break;
1538185029Spjd
1539185029Spjd		case DRR_FREEOBJECTS:
1540185029Spjd		case DRR_FREE:
1541185029Spjd			break;
1542185029Spjd
1543185029Spjd		default:
1544185029Spjd			assert(!"invalid record type");
1545185029Spjd		}
1546185029Spjd	}
1547185029Spjd
1548185029Spjd	free(buf);
1549185029Spjd	return (-1);
1550185029Spjd}
1551185029Spjd
1552185029Spjd/*
1553185029Spjd * Restores a backup of tosnap from the file descriptor specified by infd.
1554185029Spjd */
1555185029Spjdstatic int
1556185029Spjdzfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
1557185029Spjd    recvflags_t flags, dmu_replay_record_t *drr,
1558185029Spjd    dmu_replay_record_t *drr_noswap, avl_tree_t *stream_avl,
1559185029Spjd    char **top_zfs)
1560185029Spjd{
1561185029Spjd	zfs_cmd_t zc = { 0 };
1562185029Spjd	time_t begin_time;
1563185029Spjd	int ioctl_err, ioctl_errno, err, choplen;
1564185029Spjd	char *cp;
1565185029Spjd	struct drr_begin *drrb = &drr->drr_u.drr_begin;
1566185029Spjd	char errbuf[1024];
1567185029Spjd	char chopprefix[ZFS_MAXNAMELEN];
1568185029Spjd	boolean_t newfs = B_FALSE;
1569185029Spjd	boolean_t stream_wantsnewfs;
1570185029Spjd	uint64_t parent_snapguid = 0;
1571185029Spjd	prop_changelist_t *clp = NULL;
1572185029Spjd	nvlist_t *snapprops_nvlist = NULL;
1573185029Spjd
1574185029Spjd	begin_time = time(NULL);
1575185029Spjd
1576185029Spjd	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1577185029Spjd	    "cannot receive"));
1578185029Spjd
1579185029Spjd	if (stream_avl != NULL) {
1580185029Spjd		char *snapname;
1581185029Spjd		nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid,
1582185029Spjd		    &snapname);
1583185029Spjd		nvlist_t *props;
1584185029Spjd		int ret;
1585185029Spjd
1586185029Spjd		(void) nvlist_lookup_uint64(fs, "parentfromsnap",
1587185029Spjd		    &parent_snapguid);
1588185029Spjd		err = nvlist_lookup_nvlist(fs, "props", &props);
1589185029Spjd		if (err)
1590185029Spjd			VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
1591185029Spjd
1592185029Spjd		if (flags.canmountoff) {
1593185029Spjd			VERIFY(0 == nvlist_add_uint64(props,
1594185029Spjd			    zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
1595185029Spjd		}
1596185029Spjd		ret = zcmd_write_src_nvlist(hdl, &zc, props);
1597185029Spjd		if (err)
1598185029Spjd			nvlist_free(props);
1599185029Spjd
1600185029Spjd		if (0 == nvlist_lookup_nvlist(fs, "snapprops", &props)) {
1601185029Spjd			VERIFY(0 == nvlist_lookup_nvlist(props,
1602185029Spjd			    snapname, &snapprops_nvlist));
1603185029Spjd		}
1604185029Spjd
1605185029Spjd		if (ret != 0)
1606185029Spjd			return (-1);
1607185029Spjd	}
1608185029Spjd
1609185029Spjd	/*
1610185029Spjd	 * Determine how much of the snapshot name stored in the stream
1611185029Spjd	 * we are going to tack on to the name they specified on the
1612185029Spjd	 * command line, and how much we are going to chop off.
1613185029Spjd	 *
1614185029Spjd	 * If they specified a snapshot, chop the entire name stored in
1615185029Spjd	 * the stream.
1616185029Spjd	 */
1617185029Spjd	(void) strcpy(chopprefix, drrb->drr_toname);
1618185029Spjd	if (flags.isprefix) {
1619185029Spjd		/*
1620185029Spjd		 * They specified a fs with -d, we want to tack on
1621185029Spjd		 * everything but the pool name stored in the stream
1622185029Spjd		 */
1623185029Spjd		if (strchr(tosnap, '@')) {
1624185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
1625185029Spjd			    "argument - snapshot not allowed with -d"));
1626185029Spjd			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1627185029Spjd		}
1628185029Spjd		cp = strchr(chopprefix, '/');
1629185029Spjd		if (cp == NULL)
1630185029Spjd			cp = strchr(chopprefix, '@');
1631185029Spjd		*cp = '\0';
1632185029Spjd	} else if (strchr(tosnap, '@') == NULL) {
1633185029Spjd		/*
1634185029Spjd		 * If they specified a filesystem without -d, we want to
1635185029Spjd		 * tack on everything after the fs specified in the
1636185029Spjd		 * first name from the stream.
1637185029Spjd		 */
1638185029Spjd		cp = strchr(chopprefix, '@');
1639185029Spjd		*cp = '\0';
1640185029Spjd	}
1641185029Spjd	choplen = strlen(chopprefix);
1642185029Spjd
1643185029Spjd	/*
1644185029Spjd	 * Determine name of destination snapshot, store in zc_value.
1645185029Spjd	 */
1646185029Spjd	(void) strcpy(zc.zc_value, tosnap);
1647185029Spjd	(void) strncat(zc.zc_value, drrb->drr_toname+choplen,
1648185029Spjd	    sizeof (zc.zc_value));
1649185029Spjd	if (!zfs_name_valid(zc.zc_value, ZFS_TYPE_SNAPSHOT)) {
1650185029Spjd		zcmd_free_nvlists(&zc);
1651185029Spjd		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1652185029Spjd	}
1653185029Spjd
1654185029Spjd	/*
1655185029Spjd	 * Determine the name of the origin snapshot, store in zc_string.
1656185029Spjd	 */
1657185029Spjd	if (drrb->drr_flags & DRR_FLAG_CLONE) {
1658185029Spjd		if (guid_to_name(hdl, tosnap,
1659185029Spjd		    drrb->drr_fromguid, zc.zc_string) != 0) {
1660185029Spjd			zcmd_free_nvlists(&zc);
1661185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1662185029Spjd			    "local origin for clone %s does not exist"),
1663185029Spjd			    zc.zc_value);
1664185029Spjd			return (zfs_error(hdl, EZFS_NOENT, errbuf));
1665185029Spjd		}
1666185029Spjd		if (flags.verbose)
1667185029Spjd			(void) printf("found clone origin %s\n", zc.zc_string);
1668185029Spjd	}
1669185029Spjd
1670185029Spjd	stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
1671185029Spjd	    (drrb->drr_flags & DRR_FLAG_CLONE));
1672185029Spjd
1673185029Spjd	if (stream_wantsnewfs) {
1674185029Spjd		/*
1675185029Spjd		 * if the parent fs does not exist, look for it based on
1676185029Spjd		 * the parent snap GUID
1677185029Spjd		 */
1678185029Spjd		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1679185029Spjd		    "cannot receive new filesystem stream"));
1680185029Spjd
1681185029Spjd		(void) strcpy(zc.zc_name, zc.zc_value);
1682185029Spjd		cp = strrchr(zc.zc_name, '/');
1683185029Spjd		if (cp)
1684185029Spjd			*cp = '\0';
1685185029Spjd		if (cp &&
1686185029Spjd		    !zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
1687185029Spjd			char suffix[ZFS_MAXNAMELEN];
1688185029Spjd			(void) strcpy(suffix, strrchr(zc.zc_value, '/'));
1689185029Spjd			if (guid_to_name(hdl, tosnap, parent_snapguid,
1690185029Spjd			    zc.zc_value) == 0) {
1691185029Spjd				*strchr(zc.zc_value, '@') = '\0';
1692185029Spjd				(void) strcat(zc.zc_value, suffix);
1693185029Spjd			}
1694185029Spjd		}
1695185029Spjd	} else {
1696185029Spjd		/*
1697185029Spjd		 * if the fs does not exist, look for it based on the
1698185029Spjd		 * fromsnap GUID
1699185029Spjd		 */
1700185029Spjd		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1701185029Spjd		    "cannot receive incremental stream"));
1702185029Spjd
1703185029Spjd		(void) strcpy(zc.zc_name, zc.zc_value);
1704185029Spjd		*strchr(zc.zc_name, '@') = '\0';
1705185029Spjd
1706185029Spjd		if (!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
1707185029Spjd			char snap[ZFS_MAXNAMELEN];
1708185029Spjd			(void) strcpy(snap, strchr(zc.zc_value, '@'));
1709185029Spjd			if (guid_to_name(hdl, tosnap, drrb->drr_fromguid,
1710185029Spjd			    zc.zc_value) == 0) {
1711185029Spjd				*strchr(zc.zc_value, '@') = '\0';
1712185029Spjd				(void) strcat(zc.zc_value, snap);
1713185029Spjd			}
1714185029Spjd		}
1715185029Spjd	}
1716185029Spjd
1717185029Spjd	(void) strcpy(zc.zc_name, zc.zc_value);
1718185029Spjd	*strchr(zc.zc_name, '@') = '\0';
1719185029Spjd
1720185029Spjd	if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
1721185029Spjd		zfs_handle_t *zhp;
1722185029Spjd		/*
1723185029Spjd		 * Destination fs exists.  Therefore this should either
1724185029Spjd		 * be an incremental, or the stream specifies a new fs
1725185029Spjd		 * (full stream or clone) and they want us to blow it
1726185029Spjd		 * away (and have therefore specified -F and removed any
1727185029Spjd		 * snapshots).
1728185029Spjd		 */
1729185029Spjd
1730185029Spjd		if (stream_wantsnewfs) {
1731185029Spjd			if (!flags.force) {
1732185029Spjd				zcmd_free_nvlists(&zc);
1733185029Spjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1734185029Spjd				    "destination '%s' exists\n"
1735185029Spjd				    "must specify -F to overwrite it"),
1736185029Spjd				    zc.zc_name);
1737185029Spjd				return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1738185029Spjd			}
1739185029Spjd			if (ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT,
1740185029Spjd			    &zc) == 0) {
1741185029Spjd				zcmd_free_nvlists(&zc);
1742185029Spjd				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1743185029Spjd				    "destination has snapshots (eg. %s)\n"
1744185029Spjd				    "must destroy them to overwrite it"),
1745185029Spjd				    zc.zc_name);
1746185029Spjd				return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1747185029Spjd			}
1748185029Spjd		}
1749185029Spjd
1750185029Spjd		if ((zhp = zfs_open(hdl, zc.zc_name,
1751185029Spjd		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
1752185029Spjd			zcmd_free_nvlists(&zc);
1753185029Spjd			return (-1);
1754185029Spjd		}
1755185029Spjd
1756185029Spjd		if (stream_wantsnewfs &&
1757185029Spjd		    zhp->zfs_dmustats.dds_origin[0]) {
1758185029Spjd			zcmd_free_nvlists(&zc);
1759185029Spjd			zfs_close(zhp);
1760185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1761185029Spjd			    "destination '%s' is a clone\n"
1762185029Spjd			    "must destroy it to overwrite it"),
1763185029Spjd			    zc.zc_name);
1764185029Spjd			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1765185029Spjd		}
1766185029Spjd
1767185029Spjd		if (!flags.dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
1768185029Spjd		    stream_wantsnewfs) {
1769185029Spjd			/* We can't do online recv in this case */
1770185029Spjd			clp = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0);
1771185029Spjd			if (clp == NULL) {
1772185029Spjd				zcmd_free_nvlists(&zc);
1773185029Spjd				return (-1);
1774185029Spjd			}
1775185029Spjd			if (changelist_prefix(clp) != 0) {
1776185029Spjd				changelist_free(clp);
1777185029Spjd				zcmd_free_nvlists(&zc);
1778185029Spjd				return (-1);
1779185029Spjd			}
1780185029Spjd		}
1781185029Spjd		if (!flags.dryrun && zhp->zfs_type == ZFS_TYPE_VOLUME &&
1782185029Spjd		    zvol_remove_link(hdl, zhp->zfs_name) != 0) {
1783185029Spjd			zfs_close(zhp);
1784185029Spjd			zcmd_free_nvlists(&zc);
1785185029Spjd			return (-1);
1786185029Spjd		}
1787185029Spjd		zfs_close(zhp);
1788185029Spjd	} else {
1789185029Spjd		/*
1790185029Spjd		 * Destination filesystem does not exist.  Therefore we better
1791185029Spjd		 * be creating a new filesystem (either from a full backup, or
1792185029Spjd		 * a clone).  It would therefore be invalid if the user
1793185029Spjd		 * specified only the pool name (i.e. if the destination name
1794185029Spjd		 * contained no slash character).
1795185029Spjd		 */
1796185029Spjd		if (!stream_wantsnewfs ||
1797185029Spjd		    (cp = strrchr(zc.zc_name, '/')) == NULL) {
1798185029Spjd			zcmd_free_nvlists(&zc);
1799185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1800185029Spjd			    "destination '%s' does not exist"), zc.zc_name);
1801185029Spjd			return (zfs_error(hdl, EZFS_NOENT, errbuf));
1802185029Spjd		}
1803185029Spjd
1804185029Spjd		/*
1805185029Spjd		 * Trim off the final dataset component so we perform the
1806185029Spjd		 * recvbackup ioctl to the filesystems's parent.
1807185029Spjd		 */
1808185029Spjd		*cp = '\0';
1809185029Spjd
1810185029Spjd		if (flags.isprefix && !flags.dryrun &&
1811185029Spjd		    create_parents(hdl, zc.zc_value, strlen(tosnap)) != 0) {
1812185029Spjd			zcmd_free_nvlists(&zc);
1813185029Spjd			return (zfs_error(hdl, EZFS_BADRESTORE, errbuf));
1814185029Spjd		}
1815185029Spjd
1816185029Spjd		newfs = B_TRUE;
1817185029Spjd	}
1818185029Spjd
1819185029Spjd	zc.zc_begin_record = drr_noswap->drr_u.drr_begin;
1820185029Spjd	zc.zc_cookie = infd;
1821185029Spjd	zc.zc_guid = flags.force;
1822185029Spjd	if (flags.verbose) {
1823185029Spjd		(void) printf("%s %s stream of %s into %s\n",
1824185029Spjd		    flags.dryrun ? "would receive" : "receiving",
1825185029Spjd		    drrb->drr_fromguid ? "incremental" : "full",
1826185029Spjd		    drrb->drr_toname, zc.zc_value);
1827185029Spjd		(void) fflush(stdout);
1828185029Spjd	}
1829185029Spjd
1830185029Spjd	if (flags.dryrun) {
1831185029Spjd		zcmd_free_nvlists(&zc);
1832185029Spjd		return (recv_skip(hdl, infd, flags.byteswap));
1833185029Spjd	}
1834185029Spjd
1835185029Spjd	err = ioctl_err = zfs_ioctl(hdl, ZFS_IOC_RECV, &zc);
1836185029Spjd	ioctl_errno = errno;
1837185029Spjd	zcmd_free_nvlists(&zc);
1838185029Spjd
1839185029Spjd	if (err == 0 && snapprops_nvlist) {
1840185029Spjd		zfs_cmd_t zc2 = { 0 };
1841185029Spjd
1842185029Spjd		(void) strcpy(zc2.zc_name, zc.zc_value);
1843185029Spjd		if (zcmd_write_src_nvlist(hdl, &zc2, snapprops_nvlist) == 0) {
1844185029Spjd			(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc2);
1845185029Spjd			zcmd_free_nvlists(&zc2);
1846185029Spjd		}
1847185029Spjd	}
1848185029Spjd
1849185029Spjd	if (err && (ioctl_errno == ENOENT || ioctl_errno == ENODEV)) {
1850185029Spjd		/*
1851185029Spjd		 * It may be that this snapshot already exists,
1852185029Spjd		 * in which case we want to consume & ignore it
1853185029Spjd		 * rather than failing.
1854185029Spjd		 */
1855185029Spjd		avl_tree_t *local_avl;
1856185029Spjd		nvlist_t *local_nv, *fs;
1857185029Spjd		char *cp = strchr(zc.zc_value, '@');
1858185029Spjd
1859185029Spjd		/*
1860185029Spjd		 * XXX Do this faster by just iterating over snaps in
1861185029Spjd		 * this fs.  Also if zc_value does not exist, we will
1862185029Spjd		 * get a strange "does not exist" error message.
1863185029Spjd		 */
1864185029Spjd		*cp = '\0';
1865185029Spjd		if (gather_nvlist(hdl, zc.zc_value, NULL, NULL,
1866185029Spjd		    &local_nv, &local_avl) == 0) {
1867185029Spjd			*cp = '@';
1868185029Spjd			fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
1869185029Spjd			fsavl_destroy(local_avl);
1870185029Spjd			nvlist_free(local_nv);
1871185029Spjd
1872185029Spjd			if (fs != NULL) {
1873185029Spjd				if (flags.verbose) {
1874185029Spjd					(void) printf("snap %s already exists; "
1875185029Spjd					    "ignoring\n", zc.zc_value);
1876185029Spjd				}
1877185029Spjd				ioctl_err = recv_skip(hdl, infd,
1878185029Spjd				    flags.byteswap);
1879185029Spjd			}
1880185029Spjd		}
1881185029Spjd		*cp = '@';
1882185029Spjd	}
1883185029Spjd
1884185029Spjd
1885185029Spjd	if (ioctl_err != 0) {
1886185029Spjd		switch (ioctl_errno) {
1887185029Spjd		case ENODEV:
1888185029Spjd			cp = strchr(zc.zc_value, '@');
1889185029Spjd			*cp = '\0';
1890185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1891185029Spjd			    "most recent snapshot of %s does not\n"
1892185029Spjd			    "match incremental source"), zc.zc_value);
1893185029Spjd			(void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
1894185029Spjd			*cp = '@';
1895185029Spjd			break;
1896185029Spjd		case ETXTBSY:
1897185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1898185029Spjd			    "destination %s has been modified\n"
1899185029Spjd			    "since most recent snapshot"), zc.zc_name);
1900185029Spjd			(void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
1901185029Spjd			break;
1902185029Spjd		case EEXIST:
1903185029Spjd			cp = strchr(zc.zc_value, '@');
1904185029Spjd			if (newfs) {
1905185029Spjd				/* it's the containing fs that exists */
1906185029Spjd				*cp = '\0';
1907185029Spjd			}
1908185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1909185029Spjd			    "destination already exists"));
1910185029Spjd			(void) zfs_error_fmt(hdl, EZFS_EXISTS,
1911185029Spjd			    dgettext(TEXT_DOMAIN, "cannot restore to %s"),
1912185029Spjd			    zc.zc_value);
1913185029Spjd			*cp = '@';
1914185029Spjd			break;
1915185029Spjd		case EINVAL:
1916185029Spjd			(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1917185029Spjd			break;
1918185029Spjd		case ECKSUM:
1919185029Spjd			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1920185029Spjd			    "invalid stream (checksum mismatch)"));
1921185029Spjd			(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1922185029Spjd			break;
1923185029Spjd		default:
1924185029Spjd			(void) zfs_standard_error(hdl, ioctl_errno, errbuf);
1925185029Spjd		}
1926185029Spjd	}
1927185029Spjd
1928185029Spjd	/*
1929185029Spjd	 * Mount or recreate the /dev links for the target filesystem
1930185029Spjd	 * (if created, or if we tore them down to do an incremental
1931185029Spjd	 * restore), and the /dev links for the new snapshot (if
1932185029Spjd	 * created). Also mount any children of the target filesystem
1933185029Spjd	 * if we did an incremental receive.
1934185029Spjd	 */
1935185029Spjd	cp = strchr(zc.zc_value, '@');
1936185029Spjd	if (cp && (ioctl_err == 0 || !newfs)) {
1937185029Spjd		zfs_handle_t *h;
1938185029Spjd
1939185029Spjd		*cp = '\0';
1940185029Spjd		h = zfs_open(hdl, zc.zc_value,
1941185029Spjd		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
1942185029Spjd		if (h != NULL) {
1943185029Spjd			if (h->zfs_type == ZFS_TYPE_VOLUME) {
1944185029Spjd				*cp = '@';
1945185029Spjd				err = zvol_create_link(hdl, h->zfs_name);
1946185029Spjd				if (err == 0 && ioctl_err == 0)
1947185029Spjd					err = zvol_create_link(hdl,
1948185029Spjd					    zc.zc_value);
1949185029Spjd			} else if (newfs) {
1950185029Spjd				/*
1951185029Spjd				 * Track the first/top of hierarchy fs,
1952185029Spjd				 * for mounting and sharing later.
1953185029Spjd				 */
1954185029Spjd				if (top_zfs && *top_zfs == NULL)
1955185029Spjd					*top_zfs = zfs_strdup(hdl, zc.zc_value);
1956185029Spjd			}
1957185029Spjd			zfs_close(h);
1958185029Spjd		}
1959185029Spjd		*cp = '@';
1960185029Spjd	}
1961185029Spjd
1962185029Spjd	if (clp) {
1963185029Spjd		err |= changelist_postfix(clp);
1964185029Spjd		changelist_free(clp);
1965185029Spjd	}
1966185029Spjd
1967185029Spjd	if (err || ioctl_err)
1968185029Spjd		return (-1);
1969185029Spjd
1970185029Spjd	if (flags.verbose) {
1971185029Spjd		char buf1[64];
1972185029Spjd		char buf2[64];
1973185029Spjd		uint64_t bytes = zc.zc_cookie;
1974185029Spjd		time_t delta = time(NULL) - begin_time;
1975185029Spjd		if (delta == 0)
1976185029Spjd			delta = 1;
1977185029Spjd		zfs_nicenum(bytes, buf1, sizeof (buf1));
1978185029Spjd		zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
1979185029Spjd
1980185029Spjd		(void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
1981185029Spjd		    buf1, delta, buf2);
1982185029Spjd	}
1983185029Spjd
1984185029Spjd	return (0);
1985185029Spjd}
1986185029Spjd
1987185029Spjdstatic int
1988185029Spjdzfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags,
1989185029Spjd    int infd, avl_tree_t *stream_avl, char **top_zfs)
1990185029Spjd{
1991185029Spjd	int err;
1992185029Spjd	dmu_replay_record_t drr, drr_noswap;
1993185029Spjd	struct drr_begin *drrb = &drr.drr_u.drr_begin;
1994185029Spjd	char errbuf[1024];
1995185029Spjd	zio_cksum_t zcksum = { 0 };
1996185029Spjd
1997185029Spjd	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1998185029Spjd	    "cannot receive"));
1999185029Spjd
2000185029Spjd	if (flags.isprefix &&
2001185029Spjd	    !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
2002185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
2003185029Spjd		    "(%s) does not exist"), tosnap);
2004185029Spjd		return (zfs_error(hdl, EZFS_NOENT, errbuf));
2005185029Spjd	}
2006185029Spjd
2007185029Spjd	/* read in the BEGIN record */
2008185029Spjd	if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE,
2009185029Spjd	    &zcksum)))
2010185029Spjd		return (err);
2011185029Spjd
2012185029Spjd	if (drr.drr_type == DRR_END || drr.drr_type == BSWAP_32(DRR_END)) {
2013185029Spjd		/* It's the double end record at the end of a package */
2014185029Spjd		return (ENODATA);
2015185029Spjd	}
2016185029Spjd
2017185029Spjd	/* the kernel needs the non-byteswapped begin record */
2018185029Spjd	drr_noswap = drr;
2019185029Spjd
2020185029Spjd	flags.byteswap = B_FALSE;
2021185029Spjd	if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
2022185029Spjd		/*
2023185029Spjd		 * We computed the checksum in the wrong byteorder in
2024185029Spjd		 * recv_read() above; do it again correctly.
2025185029Spjd		 */
2026185029Spjd		bzero(&zcksum, sizeof (zio_cksum_t));
2027185029Spjd		fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum);
2028185029Spjd		flags.byteswap = B_TRUE;
2029185029Spjd
2030185029Spjd		drr.drr_type = BSWAP_32(drr.drr_type);
2031185029Spjd		drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen);
2032185029Spjd		drrb->drr_magic = BSWAP_64(drrb->drr_magic);
2033185029Spjd		drrb->drr_version = BSWAP_64(drrb->drr_version);
2034185029Spjd		drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
2035185029Spjd		drrb->drr_type = BSWAP_32(drrb->drr_type);
2036185029Spjd		drrb->drr_flags = BSWAP_32(drrb->drr_flags);
2037185029Spjd		drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
2038185029Spjd		drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
2039185029Spjd	}
2040185029Spjd
2041185029Spjd	if (drrb->drr_magic != DMU_BACKUP_MAGIC || drr.drr_type != DRR_BEGIN) {
2042185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2043185029Spjd		    "stream (bad magic number)"));
2044185029Spjd		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2045185029Spjd	}
2046185029Spjd
2047185029Spjd	if (strchr(drrb->drr_toname, '@') == NULL) {
2048185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2049185029Spjd		    "stream (bad snapshot name)"));
2050185029Spjd		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2051185029Spjd	}
2052185029Spjd
2053185029Spjd	if (drrb->drr_version == DMU_BACKUP_STREAM_VERSION) {
2054185029Spjd		return (zfs_receive_one(hdl, infd, tosnap, flags,
2055185029Spjd		    &drr, &drr_noswap, stream_avl, top_zfs));
2056185029Spjd	} else if (drrb->drr_version == DMU_BACKUP_HEADER_VERSION) {
2057185029Spjd		return (zfs_receive_package(hdl, infd, tosnap, flags,
2058185029Spjd		    &drr, &zcksum, top_zfs));
2059185029Spjd	} else {
2060185029Spjd		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2061185029Spjd		    "stream is unsupported version %llu"),
2062185029Spjd		    drrb->drr_version);
2063185029Spjd		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2064185029Spjd	}
2065185029Spjd}
2066185029Spjd
2067185029Spjd/*
2068185029Spjd * Restores a backup of tosnap from the file descriptor specified by infd.
2069185029Spjd * Return 0 on total success, -2 if some things couldn't be
2070185029Spjd * destroyed/renamed/promoted, -1 if some things couldn't be received.
2071185029Spjd * (-1 will override -2).
2072185029Spjd */
2073185029Spjdint
2074185029Spjdzfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags,
2075185029Spjd    int infd, avl_tree_t *stream_avl)
2076185029Spjd{
2077185029Spjd	char *top_zfs = NULL;
2078185029Spjd	int err;
2079185029Spjd
2080185029Spjd	err = zfs_receive_impl(hdl, tosnap, flags, infd, stream_avl, &top_zfs);
2081185029Spjd
2082185029Spjd	if (err == 0 && top_zfs) {
2083185029Spjd		zfs_handle_t *zhp;
2084185029Spjd		prop_changelist_t *clp;
2085185029Spjd
2086185029Spjd		zhp = zfs_open(hdl, top_zfs, ZFS_TYPE_FILESYSTEM);
2087185029Spjd		if (zhp != NULL) {
2088185029Spjd			clp = changelist_gather(zhp, ZFS_PROP_MOUNTPOINT,
2089185029Spjd			    CL_GATHER_MOUNT_ALWAYS, 0);
2090185029Spjd			zfs_close(zhp);
2091185029Spjd			if (clp != NULL) {
2092185029Spjd				/* mount and share received datasets */
2093185029Spjd				err = changelist_postfix(clp);
2094185029Spjd				changelist_free(clp);
2095185029Spjd			}
2096185029Spjd		}
2097185029Spjd		if (zhp == NULL || clp == NULL || err)
2098185029Spjd			err = -1;
2099185029Spjd	}
2100185029Spjd	if (top_zfs)
2101185029Spjd		free(top_zfs);
2102185029Spjd
2103185029Spjd	return (err);
2104185029Spjd}
2105