Removed build system from master branch, will relocate to linux-zfs-branch
[zfs.git] / zfs / lib / libzfs / libzfs_sendrecv.c
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 http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26
27 #pragma ident   "@(#)libzfs_sendrecv.c  1.7     08/04/23 SMI"
28
29 #include <assert.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <libdevinfo.h>
33 #include <libintl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <strings.h>
37 #include <unistd.h>
38 #include <stddef.h>
39 #include <fcntl.h>
40 #include <sys/mount.h>
41 #include <sys/mntent.h>
42 #include <sys/mnttab.h>
43 #include <sys/avl.h>
44 #include <stddef.h>
45
46 #include <libzfs.h>
47
48 #include "zfs_namecheck.h"
49 #include "zfs_prop.h"
50 #include "libzfs_impl.h"
51
52 #include <fletcher.c> /* XXX */
53
54 /*
55  * Routines for dealing with the AVL tree of fs-nvlists
56  */
57 typedef struct fsavl_node {
58         avl_node_t fn_node;
59         nvlist_t *fn_nvfs;
60         char *fn_snapname;
61         uint64_t fn_guid;
62 } fsavl_node_t;
63
64 static int
65 fsavl_compare(const void *arg1, const void *arg2)
66 {
67         const fsavl_node_t *fn1 = arg1;
68         const fsavl_node_t *fn2 = arg2;
69
70         if (fn1->fn_guid > fn2->fn_guid)
71                 return (+1);
72         else if (fn1->fn_guid < fn2->fn_guid)
73                 return (-1);
74         else
75                 return (0);
76 }
77
78 /*
79  * Given the GUID of a snapshot, find its containing filesystem and
80  * (optionally) name.
81  */
82 static nvlist_t *
83 fsavl_find(avl_tree_t *avl, uint64_t snapguid, char **snapname)
84 {
85         fsavl_node_t fn_find;
86         fsavl_node_t *fn;
87
88         fn_find.fn_guid = snapguid;
89
90         fn = avl_find(avl, &fn_find, NULL);
91         if (fn) {
92                 if (snapname)
93                         *snapname = fn->fn_snapname;
94                 return (fn->fn_nvfs);
95         }
96         return (NULL);
97 }
98
99 static void
100 fsavl_destroy(avl_tree_t *avl)
101 {
102         fsavl_node_t *fn;
103         void *cookie;
104
105         if (avl == NULL)
106                 return;
107
108         cookie = NULL;
109         while ((fn = avl_destroy_nodes(avl, &cookie)) != NULL)
110                 free(fn);
111         avl_destroy(avl);
112         free(avl);
113 }
114
115 static avl_tree_t *
116 fsavl_create(nvlist_t *fss)
117 {
118         avl_tree_t *fsavl;
119         nvpair_t *fselem = NULL;
120
121         if ((fsavl = malloc(sizeof (avl_tree_t))) == NULL)
122                 return (NULL);
123
124         avl_create(fsavl, fsavl_compare, sizeof (fsavl_node_t),
125             offsetof(fsavl_node_t, fn_node));
126
127         while ((fselem = nvlist_next_nvpair(fss, fselem)) != NULL) {
128                 nvlist_t *nvfs, *snaps;
129                 nvpair_t *snapelem = NULL;
130
131                 VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
132                 VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
133
134                 while ((snapelem =
135                     nvlist_next_nvpair(snaps, snapelem)) != NULL) {
136                         fsavl_node_t *fn;
137                         uint64_t guid;
138
139                         VERIFY(0 == nvpair_value_uint64(snapelem, &guid));
140                         if ((fn = malloc(sizeof (fsavl_node_t))) == NULL) {
141                                 fsavl_destroy(fsavl);
142                                 return (NULL);
143                         }
144                         fn->fn_nvfs = nvfs;
145                         fn->fn_snapname = nvpair_name(snapelem);
146                         fn->fn_guid = guid;
147
148                         /*
149                          * Note: if there are multiple snaps with the
150                          * same GUID, we ignore all but one.
151                          */
152                         if (avl_find(fsavl, fn, NULL) == NULL)
153                                 avl_add(fsavl, fn);
154                         else
155                                 free(fn);
156                 }
157         }
158
159         return (fsavl);
160 }
161
162 /*
163  * Routines for dealing with the giant nvlist of fs-nvlists, etc.
164  */
165 typedef struct send_data {
166         uint64_t parent_fromsnap_guid;
167         nvlist_t *parent_snaps;
168         nvlist_t *fss;
169         const char *fromsnap;
170         const char *tosnap;
171
172         /*
173          * The header nvlist is of the following format:
174          * {
175          *   "tosnap" -> string
176          *   "fromsnap" -> string (if incremental)
177          *   "fss" -> {
178          *      id -> {
179          *
180          *       "name" -> string (full name; for debugging)
181          *       "parentfromsnap" -> number (guid of fromsnap in parent)
182          *
183          *       "props" -> { name -> value (only if set here) }
184          *       "snaps" -> { name (lastname) -> number (guid) }
185          *
186          *       "origin" -> number (guid) (if clone)
187          *       "sent" -> boolean (not on-disk)
188          *      }
189          *   }
190          * }
191          *
192          */
193 } send_data_t;
194
195 static int
196 send_iterate_snap(zfs_handle_t *zhp, void *arg)
197 {
198         send_data_t *sd = arg;
199         uint64_t guid = zhp->zfs_dmustats.dds_guid;
200         char *snapname;
201
202         snapname = strrchr(zhp->zfs_name, '@')+1;
203
204         VERIFY(0 == nvlist_add_uint64(sd->parent_snaps, snapname, guid));
205         /*
206          * NB: if there is no fromsnap here (it's a newly created fs in
207          * an incremental replication), we will substitute the tosnap.
208          */
209         if ((sd->fromsnap && strcmp(snapname, sd->fromsnap) == 0) ||
210             (sd->parent_fromsnap_guid == 0 && sd->tosnap &&
211             strcmp(snapname, sd->tosnap) == 0)) {
212                 sd->parent_fromsnap_guid = guid;
213         }
214
215         zfs_close(zhp);
216         return (0);
217 }
218
219 static void
220 send_iterate_prop(zfs_handle_t *zhp, nvlist_t *nv)
221 {
222         nvpair_t *elem = NULL;
223
224         while ((elem = nvlist_next_nvpair(zhp->zfs_props, elem)) != NULL) {
225                 char *propname = nvpair_name(elem);
226                 zfs_prop_t prop = zfs_name_to_prop(propname);
227                 nvlist_t *propnv;
228
229                 if (!zfs_prop_user(propname) && zfs_prop_readonly(prop))
230                         continue;
231
232                 verify(nvpair_value_nvlist(elem, &propnv) == 0);
233                 if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION) {
234                         /* these guys are modifyable, but have no source */
235                         uint64_t value;
236                         verify(nvlist_lookup_uint64(propnv,
237                             ZPROP_VALUE, &value) == 0);
238                 } else {
239                         char *source;
240                         if (nvlist_lookup_string(propnv,
241                             ZPROP_SOURCE, &source) != 0)
242                                 continue;
243                         if (strcmp(source, zhp->zfs_name) != 0)
244                                 continue;
245                 }
246
247                 if (zfs_prop_user(propname) ||
248                     zfs_prop_get_type(prop) == PROP_TYPE_STRING) {
249                         char *value;
250                         verify(nvlist_lookup_string(propnv,
251                             ZPROP_VALUE, &value) == 0);
252                         VERIFY(0 == nvlist_add_string(nv, propname, value));
253                 } else {
254                         uint64_t value;
255                         verify(nvlist_lookup_uint64(propnv,
256                             ZPROP_VALUE, &value) == 0);
257                         VERIFY(0 == nvlist_add_uint64(nv, propname, value));
258                 }
259         }
260 }
261
262 static int
263 send_iterate_fs(zfs_handle_t *zhp, void *arg)
264 {
265         send_data_t *sd = arg;
266         nvlist_t *nvfs, *nv;
267         int rv;
268         uint64_t parent_fromsnap_guid_save = sd->parent_fromsnap_guid;
269         uint64_t guid = zhp->zfs_dmustats.dds_guid;
270         char guidstring[64];
271
272         VERIFY(0 == nvlist_alloc(&nvfs, NV_UNIQUE_NAME, 0));
273         VERIFY(0 == nvlist_add_string(nvfs, "name", zhp->zfs_name));
274         VERIFY(0 == nvlist_add_uint64(nvfs, "parentfromsnap",
275             sd->parent_fromsnap_guid));
276
277         if (zhp->zfs_dmustats.dds_origin[0]) {
278                 zfs_handle_t *origin = zfs_open(zhp->zfs_hdl,
279                     zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
280                 if (origin == NULL)
281                         return (-1);
282                 VERIFY(0 == nvlist_add_uint64(nvfs, "origin",
283                     origin->zfs_dmustats.dds_guid));
284         }
285
286         /* iterate over props */
287         VERIFY(0 == nvlist_alloc(&nv, NV_UNIQUE_NAME, 0));
288         send_iterate_prop(zhp, nv);
289         VERIFY(0 == nvlist_add_nvlist(nvfs, "props", nv));
290         nvlist_free(nv);
291
292         /* iterate over snaps, and set sd->parent_fromsnap_guid */
293         sd->parent_fromsnap_guid = 0;
294         VERIFY(0 == nvlist_alloc(&sd->parent_snaps, NV_UNIQUE_NAME, 0));
295         (void) zfs_iter_snapshots(zhp, send_iterate_snap, sd);
296         VERIFY(0 == nvlist_add_nvlist(nvfs, "snaps", sd->parent_snaps));
297         nvlist_free(sd->parent_snaps);
298
299         /* add this fs to nvlist */
300         (void) snprintf(guidstring, sizeof (guidstring),
301             "0x%llx", (longlong_t)guid);
302         VERIFY(0 == nvlist_add_nvlist(sd->fss, guidstring, nvfs));
303         nvlist_free(nvfs);
304
305         /* iterate over children */
306         rv = zfs_iter_filesystems(zhp, send_iterate_fs, sd);
307
308         sd->parent_fromsnap_guid = parent_fromsnap_guid_save;
309
310         zfs_close(zhp);
311         return (rv);
312 }
313
314 static int
315 gather_nvlist(libzfs_handle_t *hdl, const char *fsname, const char *fromsnap,
316     const char *tosnap, nvlist_t **nvlp, avl_tree_t **avlp)
317 {
318         zfs_handle_t *zhp;
319         send_data_t sd = { 0 };
320         int error;
321
322         zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
323         if (zhp == NULL)
324                 return (EZFS_BADTYPE);
325
326         VERIFY(0 == nvlist_alloc(&sd.fss, NV_UNIQUE_NAME, 0));
327         sd.fromsnap = fromsnap;
328         sd.tosnap = tosnap;
329
330         if ((error = send_iterate_fs(zhp, &sd)) != 0) {
331                 nvlist_free(sd.fss);
332                 if (avlp != NULL)
333                         *avlp = NULL;
334                 *nvlp = NULL;
335                 return (error);
336         }
337
338         if (avlp != NULL && (*avlp = fsavl_create(sd.fss)) == NULL) {
339                 nvlist_free(sd.fss);
340                 *nvlp = NULL;
341                 return (EZFS_NOMEM);
342         }
343
344         *nvlp = sd.fss;
345         return (0);
346 }
347
348 /*
349  * Routines for dealing with the sorted snapshot functionality
350  */
351 typedef struct zfs_node {
352         zfs_handle_t    *zn_handle;
353         avl_node_t      zn_avlnode;
354 } zfs_node_t;
355
356 static int
357 zfs_sort_snaps(zfs_handle_t *zhp, void *data)
358 {
359         avl_tree_t *avl = data;
360         zfs_node_t *node = zfs_alloc(zhp->zfs_hdl, sizeof (zfs_node_t));
361
362         node->zn_handle = zhp;
363         avl_add(avl, node);
364         return (0);
365 }
366
367 /* ARGSUSED */
368 static int
369 zfs_snapshot_compare(const void *larg, const void *rarg)
370 {
371         zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle;
372         zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle;
373         uint64_t lcreate, rcreate;
374
375         /*
376          * Sort them according to creation time.  We use the hidden
377          * CREATETXG property to get an absolute ordering of snapshots.
378          */
379         lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
380         rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
381
382         if (lcreate < rcreate)
383                 return (-1);
384         else if (lcreate > rcreate)
385                 return (+1);
386         else
387                 return (0);
388 }
389
390 static int
391 zfs_iter_snapshots_sorted(zfs_handle_t *zhp, zfs_iter_f callback, void *data)
392 {
393         int ret = 0;
394         zfs_node_t *node;
395         avl_tree_t avl;
396         void *cookie = NULL;
397
398         avl_create(&avl, zfs_snapshot_compare,
399             sizeof (zfs_node_t), offsetof(zfs_node_t, zn_avlnode));
400
401         ret = zfs_iter_snapshots(zhp, zfs_sort_snaps, &avl);
402
403         for (node = avl_first(&avl); node != NULL; node = AVL_NEXT(&avl, node))
404                 ret |= callback(node->zn_handle, data);
405
406         while ((node = avl_destroy_nodes(&avl, &cookie)) != NULL)
407                 free(node);
408
409         avl_destroy(&avl);
410
411         return (ret);
412 }
413
414 /*
415  * Routines specific to "zfs send"
416  */
417 typedef struct send_dump_data {
418         /* these are all just the short snapname (the part after the @) */
419         const char *fromsnap;
420         const char *tosnap;
421         char lastsnap[ZFS_MAXNAMELEN];
422         boolean_t seenfrom, seento, replicate, doall, fromorigin;
423         boolean_t verbose;
424         int outfd;
425         boolean_t err;
426         nvlist_t *fss;
427         avl_tree_t *fsavl;
428 } send_dump_data_t;
429
430 /*
431  * Dumps a backup of the given snapshot (incremental from fromsnap if it's not
432  * NULL) to the file descriptor specified by outfd.
433  */
434 static int
435 dump_ioctl(zfs_handle_t *zhp, const char *fromsnap, boolean_t fromorigin,
436     int outfd)
437 {
438         zfs_cmd_t zc = { 0 };
439         libzfs_handle_t *hdl = zhp->zfs_hdl;
440
441         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
442         assert(fromsnap == NULL || fromsnap[0] == '\0' || !fromorigin);
443
444         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
445         if (fromsnap)
446                 (void) strlcpy(zc.zc_value, fromsnap, sizeof (zc.zc_value));
447         zc.zc_cookie = outfd;
448         zc.zc_obj = fromorigin;
449
450         if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SEND, &zc) != 0) {
451                 char errbuf[1024];
452                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
453                     "warning: cannot send '%s'"), zhp->zfs_name);
454
455                 switch (errno) {
456
457                 case EXDEV:
458                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
459                             "not an earlier snapshot from the same fs"));
460                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
461
462                 case ENOENT:
463                         if (zfs_dataset_exists(hdl, zc.zc_name,
464                             ZFS_TYPE_SNAPSHOT)) {
465                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
466                                     "incremental source (@%s) does not exist"),
467                                     zc.zc_value);
468                         }
469                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
470
471                 case EDQUOT:
472                 case EFBIG:
473                 case EIO:
474                 case ENOLINK:
475                 case ENOSPC:
476                 case ENOSTR:
477                 case ENXIO:
478                 case EPIPE:
479                 case ERANGE:
480                 case EFAULT:
481                 case EROFS:
482                         zfs_error_aux(hdl, strerror(errno));
483                         return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
484
485                 default:
486                         return (zfs_standard_error(hdl, errno, errbuf));
487                 }
488         }
489
490         return (0);
491 }
492
493 static int
494 dump_snapshot(zfs_handle_t *zhp, void *arg)
495 {
496         send_dump_data_t *sdd = arg;
497         const char *thissnap;
498         int err;
499
500         thissnap = strchr(zhp->zfs_name, '@') + 1;
501
502         if (sdd->fromsnap && !sdd->seenfrom &&
503             strcmp(sdd->fromsnap, thissnap) == 0) {
504                 sdd->seenfrom = B_TRUE;
505                 (void) strcpy(sdd->lastsnap, thissnap);
506                 zfs_close(zhp);
507                 return (0);
508         }
509
510         if (sdd->seento || !sdd->seenfrom) {
511                 zfs_close(zhp);
512                 return (0);
513         }
514
515         /* send it */
516         if (sdd->verbose) {
517                 (void) fprintf(stderr, "sending from @%s to %s\n",
518                     sdd->lastsnap, zhp->zfs_name);
519         }
520
521         err = dump_ioctl(zhp, sdd->lastsnap,
522             sdd->lastsnap[0] == '\0' && (sdd->fromorigin || sdd->replicate),
523             sdd->outfd);
524
525         if (!sdd->seento && strcmp(sdd->tosnap, thissnap) == 0)
526                 sdd->seento = B_TRUE;
527
528         (void) strcpy(sdd->lastsnap, thissnap);
529         zfs_close(zhp);
530         return (err);
531 }
532
533 static int
534 dump_filesystem(zfs_handle_t *zhp, void *arg)
535 {
536         int rv = 0;
537         send_dump_data_t *sdd = arg;
538         boolean_t missingfrom = B_FALSE;
539         zfs_cmd_t zc = { 0 };
540
541         (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
542             zhp->zfs_name, sdd->tosnap);
543         if (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
544                 (void) fprintf(stderr, "WARNING: "
545                     "could not send %s@%s: does not exist\n",
546                     zhp->zfs_name, sdd->tosnap);
547                 sdd->err = B_TRUE;
548                 return (0);
549         }
550
551         if (sdd->replicate && sdd->fromsnap) {
552                 /*
553                  * If this fs does not have fromsnap, and we're doing
554                  * recursive, we need to send a full stream from the
555                  * beginning (or an incremental from the origin if this
556                  * is a clone).  If we're doing non-recursive, then let
557                  * them get the error.
558                  */
559                 (void) snprintf(zc.zc_name, sizeof (zc.zc_name), "%s@%s",
560                     zhp->zfs_name, sdd->fromsnap);
561                 if (ioctl(zhp->zfs_hdl->libzfs_fd,
562                     ZFS_IOC_OBJSET_STATS, &zc) != 0) {
563                         missingfrom = B_TRUE;
564                 }
565         }
566
567         if (sdd->doall) {
568                 sdd->seenfrom = sdd->seento = sdd->lastsnap[0] = 0;
569                 if (sdd->fromsnap == NULL || missingfrom)
570                         sdd->seenfrom = B_TRUE;
571
572                 rv = zfs_iter_snapshots_sorted(zhp, dump_snapshot, arg);
573                 if (!sdd->seenfrom) {
574                         (void) fprintf(stderr,
575                             "WARNING: could not send %s@%s:\n"
576                             "incremental source (%s@%s) does not exist\n",
577                             zhp->zfs_name, sdd->tosnap,
578                             zhp->zfs_name, sdd->fromsnap);
579                         sdd->err = B_TRUE;
580                 } else if (!sdd->seento) {
581                         (void) fprintf(stderr,
582                             "WARNING: could not send %s@%s:\n"
583                             "incremental source (%s@%s) "
584                             "is not earlier than it\n",
585                             zhp->zfs_name, sdd->tosnap,
586                             zhp->zfs_name, sdd->fromsnap);
587                         sdd->err = B_TRUE;
588                 }
589         } else {
590                 zfs_handle_t *snapzhp;
591                 char snapname[ZFS_MAXNAMELEN];
592
593                 (void) snprintf(snapname, sizeof (snapname), "%s@%s",
594                     zfs_get_name(zhp), sdd->tosnap);
595                 snapzhp = zfs_open(zhp->zfs_hdl, snapname, ZFS_TYPE_SNAPSHOT);
596                 if (snapzhp == NULL) {
597                         rv = -1;
598                 } else {
599                         rv = dump_ioctl(snapzhp,
600                             missingfrom ? NULL : sdd->fromsnap,
601                             sdd->fromorigin || missingfrom,
602                             sdd->outfd);
603                         sdd->seento = B_TRUE;
604                         zfs_close(snapzhp);
605                 }
606         }
607
608         return (rv);
609 }
610
611 static int
612 dump_filesystems(zfs_handle_t *rzhp, void *arg)
613 {
614         send_dump_data_t *sdd = arg;
615         nvpair_t *fspair;
616         boolean_t needagain, progress;
617
618         if (!sdd->replicate)
619                 return (dump_filesystem(rzhp, sdd));
620
621 again:
622         needagain = progress = B_FALSE;
623         for (fspair = nvlist_next_nvpair(sdd->fss, NULL); fspair;
624             fspair = nvlist_next_nvpair(sdd->fss, fspair)) {
625                 nvlist_t *fslist;
626                 char *fsname;
627                 zfs_handle_t *zhp;
628                 int err;
629                 uint64_t origin_guid = 0;
630                 nvlist_t *origin_nv;
631
632                 VERIFY(nvpair_value_nvlist(fspair, &fslist) == 0);
633                 if (nvlist_lookup_boolean(fslist, "sent") == 0)
634                         continue;
635
636                 VERIFY(nvlist_lookup_string(fslist, "name", &fsname) == 0);
637                 (void) nvlist_lookup_uint64(fslist, "origin", &origin_guid);
638
639                 origin_nv = fsavl_find(sdd->fsavl, origin_guid, NULL);
640                 if (origin_nv &&
641                     nvlist_lookup_boolean(origin_nv, "sent") == ENOENT) {
642                         /*
643                          * origin has not been sent yet;
644                          * skip this clone.
645                          */
646                         needagain = B_TRUE;
647                         continue;
648                 }
649
650                 zhp = zfs_open(rzhp->zfs_hdl, fsname, ZFS_TYPE_DATASET);
651                 if (zhp == NULL)
652                         return (-1);
653                 err = dump_filesystem(zhp, sdd);
654                 VERIFY(nvlist_add_boolean(fslist, "sent") == 0);
655                 progress = B_TRUE;
656                 zfs_close(zhp);
657                 if (err)
658                         return (err);
659         }
660         if (needagain) {
661                 assert(progress);
662                 goto again;
663         }
664         return (0);
665 }
666
667 /*
668  * Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL.
669  * If 'doall', dump all intermediate snaps.
670  * If 'replicate', dump special header and do recursively.
671  */
672 int
673 zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
674     boolean_t replicate, boolean_t doall, boolean_t fromorigin,
675     boolean_t verbose, int outfd)
676 {
677         char errbuf[1024];
678         send_dump_data_t sdd = { 0 };
679         int err;
680         nvlist_t *fss = NULL;
681         avl_tree_t *fsavl = NULL;
682
683         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
684             "cannot send '%s'"), zhp->zfs_name);
685
686         if (fromsnap && fromsnap[0] == '\0') {
687                 zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
688                     "zero-length incremental source"));
689                 return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
690         }
691
692         if (replicate || doall) {
693                 dmu_replay_record_t drr = { 0 };
694                 char *packbuf = NULL;
695                 size_t buflen = 0;
696                 zio_cksum_t zc = { 0 };
697
698                 assert(fromsnap || doall);
699
700                 if (replicate) {
701                         nvlist_t *hdrnv;
702
703                         VERIFY(0 == nvlist_alloc(&hdrnv, NV_UNIQUE_NAME, 0));
704                         if (fromsnap) {
705                                 VERIFY(0 == nvlist_add_string(hdrnv,
706                                     "fromsnap", fromsnap));
707                         }
708                         VERIFY(0 == nvlist_add_string(hdrnv, "tosnap", tosnap));
709
710                         err = gather_nvlist(zhp->zfs_hdl, zhp->zfs_name,
711                             fromsnap, tosnap, &fss, &fsavl);
712                         if (err)
713                                 return (err);
714                         VERIFY(0 == nvlist_add_nvlist(hdrnv, "fss", fss));
715                         err = nvlist_pack(hdrnv, &packbuf, &buflen,
716                             NV_ENCODE_XDR, 0);
717                         nvlist_free(hdrnv);
718                         if (err) {
719                                 fsavl_destroy(fsavl);
720                                 nvlist_free(fss);
721                                 return (zfs_standard_error(zhp->zfs_hdl,
722                                     err, errbuf));
723                         }
724                 }
725
726                 /* write first begin record */
727                 drr.drr_type = DRR_BEGIN;
728                 drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
729                 drr.drr_u.drr_begin.drr_version = DMU_BACKUP_HEADER_VERSION;
730                 (void) snprintf(drr.drr_u.drr_begin.drr_toname,
731                     sizeof (drr.drr_u.drr_begin.drr_toname),
732                     "%s@%s", zhp->zfs_name, tosnap);
733                 drr.drr_payloadlen = buflen;
734                 fletcher_4_incremental_native(&drr, sizeof (drr), &zc);
735                 err = write(outfd, &drr, sizeof (drr));
736
737                 /* write header nvlist */
738                 if (err != -1) {
739                         fletcher_4_incremental_native(packbuf, buflen, &zc);
740                         err = write(outfd, packbuf, buflen);
741                 }
742                 free(packbuf);
743                 if (err == -1) {
744                         fsavl_destroy(fsavl);
745                         nvlist_free(fss);
746                         return (zfs_standard_error(zhp->zfs_hdl,
747                             errno, errbuf));
748                 }
749
750                 /* write end record */
751                 if (err != -1) {
752                         bzero(&drr, sizeof (drr));
753                         drr.drr_type = DRR_END;
754                         drr.drr_u.drr_end.drr_checksum = zc;
755                         err = write(outfd, &drr, sizeof (drr));
756                         if (err == -1) {
757                                 fsavl_destroy(fsavl);
758                                 nvlist_free(fss);
759                                 return (zfs_standard_error(zhp->zfs_hdl,
760                                     errno, errbuf));
761                         }
762                 }
763         }
764
765         /* dump each stream */
766         sdd.fromsnap = fromsnap;
767         sdd.tosnap = tosnap;
768         sdd.outfd = outfd;
769         sdd.replicate = replicate;
770         sdd.doall = doall;
771         sdd.fromorigin = fromorigin;
772         sdd.fss = fss;
773         sdd.fsavl = fsavl;
774         sdd.verbose = verbose;
775         err = dump_filesystems(zhp, &sdd);
776         fsavl_destroy(fsavl);
777         nvlist_free(fss);
778
779         if (replicate || doall) {
780                 /*
781                  * write final end record.  NB: want to do this even if
782                  * there was some error, because it might not be totally
783                  * failed.
784                  */
785                 dmu_replay_record_t drr = { 0 };
786                 drr.drr_type = DRR_END;
787                 if (write(outfd, &drr, sizeof (drr)) == -1) {
788                         return (zfs_standard_error(zhp->zfs_hdl,
789                             errno, errbuf));
790                 }
791         }
792
793         return (err || sdd.err);
794 }
795
796 /*
797  * Routines specific to "zfs recv"
798  */
799
800 static int
801 recv_read(libzfs_handle_t *hdl, int fd, void *buf, int ilen,
802     boolean_t byteswap, zio_cksum_t *zc)
803 {
804         char *cp = buf;
805         int rv;
806         int len = ilen;
807
808         do {
809                 rv = read(fd, cp, len);
810                 cp += rv;
811                 len -= rv;
812         } while (rv > 0);
813
814         if (rv < 0 || len != 0) {
815                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
816                     "failed to read from stream"));
817                 return (zfs_error(hdl, EZFS_BADSTREAM, dgettext(TEXT_DOMAIN,
818                     "cannot receive")));
819         }
820
821         if (zc) {
822                 if (byteswap)
823                         fletcher_4_incremental_byteswap(buf, ilen, zc);
824                 else
825                         fletcher_4_incremental_native(buf, ilen, zc);
826         }
827         return (0);
828 }
829
830 static int
831 recv_read_nvlist(libzfs_handle_t *hdl, int fd, int len, nvlist_t **nvp,
832     boolean_t byteswap, zio_cksum_t *zc)
833 {
834         char *buf;
835         int err;
836
837         buf = zfs_alloc(hdl, len);
838         if (buf == NULL)
839                 return (ENOMEM);
840
841         err = recv_read(hdl, fd, buf, len, byteswap, zc);
842         if (err != 0) {
843                 free(buf);
844                 return (err);
845         }
846
847         err = nvlist_unpack(buf, len, nvp, 0);
848         free(buf);
849         if (err != 0) {
850                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
851                     "stream (malformed nvlist)"));
852                 return (EINVAL);
853         }
854         return (0);
855 }
856
857 static int
858 recv_rename(libzfs_handle_t *hdl, const char *name, const char *tryname,
859     int baselen, char *newname, recvflags_t flags)
860 {
861         static int seq;
862         zfs_cmd_t zc = { 0 };
863         int err;
864         prop_changelist_t *clp;
865         zfs_handle_t *zhp;
866
867         zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
868         if (zhp == NULL)
869                 return (-1);
870         clp = changelist_gather(zhp, ZFS_PROP_NAME, flags.force ? MS_FORCE : 0);
871         zfs_close(zhp);
872         if (clp == NULL)
873                 return (-1);
874         err = changelist_prefix(clp);
875         if (err)
876                 return (err);
877
878         if (tryname) {
879                 (void) strcpy(newname, tryname);
880
881                 zc.zc_objset_type = DMU_OST_ZFS;
882                 (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
883                 (void) strlcpy(zc.zc_value, tryname, sizeof (zc.zc_value));
884
885                 if (flags.verbose) {
886                         (void) printf("attempting rename %s to %s\n",
887                             zc.zc_name, zc.zc_value);
888                 }
889                 err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
890                 if (err == 0)
891                         changelist_rename(clp, name, tryname);
892         } else {
893                 err = ENOENT;
894         }
895
896         if (err != 0 && strncmp(name+baselen, "recv-", 5) != 0) {
897                 seq++;
898
899                 (void) strncpy(newname, name, baselen);
900                 (void) snprintf(newname+baselen, ZFS_MAXNAMELEN-baselen,
901                     "recv-%u-%u", getpid(), seq);
902                 (void) strlcpy(zc.zc_value, newname, sizeof (zc.zc_value));
903
904                 if (flags.verbose) {
905                         (void) printf("failed - trying rename %s to %s\n",
906                             zc.zc_name, zc.zc_value);
907                 }
908                 err = ioctl(hdl->libzfs_fd, ZFS_IOC_RENAME, &zc);
909                 if (err == 0)
910                         changelist_rename(clp, name, newname);
911                 if (err && flags.verbose) {
912                         (void) printf("failed (%u) - "
913                             "will try again on next pass\n", errno);
914                 }
915                 err = EAGAIN;
916         } else if (flags.verbose) {
917                 if (err == 0)
918                         (void) printf("success\n");
919                 else
920                         (void) printf("failed (%u)\n", errno);
921         }
922
923         (void) changelist_postfix(clp);
924         changelist_free(clp);
925
926         return (err);
927 }
928
929 static int
930 recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
931     char *newname, recvflags_t flags)
932 {
933         zfs_cmd_t zc = { 0 };
934         int err = 0;
935         prop_changelist_t *clp;
936         zfs_handle_t *zhp;
937
938         zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
939         if (zhp == NULL)
940                 return (-1);
941         clp = changelist_gather(zhp, ZFS_PROP_NAME, flags.force ? MS_FORCE : 0);
942         zfs_close(zhp);
943         if (clp == NULL)
944                 return (-1);
945         err = changelist_prefix(clp);
946         if (err)
947                 return (err);
948
949         zc.zc_objset_type = DMU_OST_ZFS;
950         (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
951
952         if (flags.verbose)
953                 (void) printf("attempting destroy %s\n", zc.zc_name);
954         err = ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
955
956         if (err == 0) {
957                 if (flags.verbose)
958                         (void) printf("success\n");
959                 changelist_remove(clp, zc.zc_name);
960         }
961
962         (void) changelist_postfix(clp);
963         changelist_free(clp);
964
965         if (err != 0)
966                 err = recv_rename(hdl, name, NULL, baselen, newname, flags);
967
968         return (err);
969 }
970
971 typedef struct guid_to_name_data {
972         uint64_t guid;
973         char *name;
974 } guid_to_name_data_t;
975
976 static int
977 guid_to_name_cb(zfs_handle_t *zhp, void *arg)
978 {
979         guid_to_name_data_t *gtnd = arg;
980         int err;
981
982         if (zhp->zfs_dmustats.dds_guid == gtnd->guid) {
983                 (void) strcpy(gtnd->name, zhp->zfs_name);
984                 return (EEXIST);
985         }
986         err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
987         zfs_close(zhp);
988         return (err);
989 }
990
991 static int
992 guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
993     char *name)
994 {
995         /* exhaustive search all local snapshots */
996         guid_to_name_data_t gtnd;
997         int err = 0;
998         zfs_handle_t *zhp;
999         char *cp;
1000
1001         gtnd.guid = guid;
1002         gtnd.name = name;
1003
1004         if (strchr(parent, '@') == NULL) {
1005                 zhp = make_dataset_handle(hdl, parent);
1006                 if (zhp != NULL) {
1007                         err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
1008                         zfs_close(zhp);
1009                         if (err == EEXIST)
1010                                 return (0);
1011                 }
1012         }
1013
1014         cp = strchr(parent, '/');
1015         if (cp)
1016                 *cp = '\0';
1017         zhp = make_dataset_handle(hdl, parent);
1018         if (cp)
1019                 *cp = '/';
1020
1021         if (zhp) {
1022                 err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
1023                 zfs_close(zhp);
1024         }
1025
1026         return (err == EEXIST ? 0 : ENOENT);
1027
1028 }
1029
1030 /*
1031  * Return true if dataset guid1 is created before guid2.
1032  */
1033 static int
1034 created_before(libzfs_handle_t *hdl, avl_tree_t *avl,
1035     uint64_t guid1, uint64_t guid2)
1036 {
1037         nvlist_t *nvfs;
1038         char *fsname, *snapname;
1039         char buf[ZFS_MAXNAMELEN];
1040         int rv;
1041         zfs_node_t zn1, zn2;
1042
1043         if (guid2 == 0)
1044                 return (0);
1045         if (guid1 == 0)
1046                 return (1);
1047
1048         nvfs = fsavl_find(avl, guid1, &snapname);
1049         VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1050         (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
1051         zn1.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
1052         if (zn1.zn_handle == NULL)
1053                 return (-1);
1054
1055         nvfs = fsavl_find(avl, guid2, &snapname);
1056         VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1057         (void) snprintf(buf, sizeof (buf), "%s@%s", fsname, snapname);
1058         zn2.zn_handle = zfs_open(hdl, buf, ZFS_TYPE_SNAPSHOT);
1059         if (zn2.zn_handle == NULL) {
1060                 zfs_close(zn2.zn_handle);
1061                 return (-1);
1062         }
1063
1064         rv = (zfs_snapshot_compare(&zn1, &zn2) == -1);
1065
1066         zfs_close(zn1.zn_handle);
1067         zfs_close(zn2.zn_handle);
1068
1069         return (rv);
1070 }
1071
1072 static int
1073 recv_incremental_replication(libzfs_handle_t *hdl, const char *tofs,
1074     recvflags_t flags, nvlist_t *stream_nv, avl_tree_t *stream_avl)
1075 {
1076         nvlist_t *local_nv;
1077         avl_tree_t *local_avl;
1078         nvpair_t *fselem, *nextfselem;
1079         char *tosnap, *fromsnap;
1080         char newname[ZFS_MAXNAMELEN];
1081         int error;
1082         boolean_t needagain, progress;
1083
1084         VERIFY(0 == nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap));
1085         VERIFY(0 == nvlist_lookup_string(stream_nv, "tosnap", &tosnap));
1086
1087         if (flags.dryrun)
1088                 return (0);
1089
1090 again:
1091         needagain = progress = B_FALSE;
1092
1093         if ((error = gather_nvlist(hdl, tofs, fromsnap, NULL,
1094             &local_nv, &local_avl)) != 0)
1095                 return (error);
1096
1097         /*
1098          * Process deletes and renames
1099          */
1100         for (fselem = nvlist_next_nvpair(local_nv, NULL);
1101             fselem; fselem = nextfselem) {
1102                 nvlist_t *nvfs, *snaps;
1103                 nvlist_t *stream_nvfs = NULL;
1104                 nvpair_t *snapelem, *nextsnapelem;
1105                 uint64_t fromguid = 0;
1106                 uint64_t originguid = 0;
1107                 uint64_t stream_originguid = 0;
1108                 uint64_t parent_fromsnap_guid, stream_parent_fromsnap_guid;
1109                 char *fsname, *stream_fsname;
1110
1111                 nextfselem = nvlist_next_nvpair(local_nv, fselem);
1112
1113                 VERIFY(0 == nvpair_value_nvlist(fselem, &nvfs));
1114                 VERIFY(0 == nvlist_lookup_nvlist(nvfs, "snaps", &snaps));
1115                 VERIFY(0 == nvlist_lookup_string(nvfs, "name", &fsname));
1116                 VERIFY(0 == nvlist_lookup_uint64(nvfs, "parentfromsnap",
1117                     &parent_fromsnap_guid));
1118                 (void) nvlist_lookup_uint64(nvfs, "origin", &originguid);
1119
1120                 /*
1121                  * First find the stream's fs, so we can check for
1122                  * a different origin (due to "zfs promote")
1123                  */
1124                 for (snapelem = nvlist_next_nvpair(snaps, NULL);
1125                     snapelem; snapelem = nvlist_next_nvpair(snaps, snapelem)) {
1126                         uint64_t thisguid;
1127
1128                         VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
1129                         stream_nvfs = fsavl_find(stream_avl, thisguid, NULL);
1130
1131                         if (stream_nvfs != NULL)
1132                                 break;
1133                 }
1134
1135                 /* check for promote */
1136                 (void) nvlist_lookup_uint64(stream_nvfs, "origin",
1137                     &stream_originguid);
1138                 if (stream_nvfs && originguid != stream_originguid) {
1139                         switch (created_before(hdl, local_avl,
1140                             stream_originguid, originguid)) {
1141                         case 1: {
1142                                 /* promote it! */
1143                                 zfs_cmd_t zc = { 0 };
1144                                 nvlist_t *origin_nvfs;
1145                                 char *origin_fsname;
1146
1147                                 if (flags.verbose)
1148                                         (void) printf("promoting %s\n", fsname);
1149
1150                                 origin_nvfs = fsavl_find(local_avl, originguid,
1151                                     NULL);
1152                                 VERIFY(0 == nvlist_lookup_string(origin_nvfs,
1153                                     "name", &origin_fsname));
1154                                 (void) strlcpy(zc.zc_value, origin_fsname,
1155                                     sizeof (zc.zc_value));
1156                                 (void) strlcpy(zc.zc_name, fsname,
1157                                     sizeof (zc.zc_name));
1158                                 error = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
1159                                 if (error == 0)
1160                                         progress = B_TRUE;
1161                                 break;
1162                         }
1163                         default:
1164                                 break;
1165                         case -1:
1166                                 fsavl_destroy(local_avl);
1167                                 nvlist_free(local_nv);
1168                                 return (-1);
1169                         }
1170                         /*
1171                          * We had/have the wrong origin, therefore our
1172                          * list of snapshots is wrong.  Need to handle
1173                          * them on the next pass.
1174                          */
1175                         needagain = B_TRUE;
1176                         continue;
1177                 }
1178
1179                 for (snapelem = nvlist_next_nvpair(snaps, NULL);
1180                     snapelem; snapelem = nextsnapelem) {
1181                         uint64_t thisguid;
1182                         char *stream_snapname;
1183                         nvlist_t *found;
1184
1185                         nextsnapelem = nvlist_next_nvpair(snaps, snapelem);
1186
1187                         VERIFY(0 == nvpair_value_uint64(snapelem, &thisguid));
1188                         found = fsavl_find(stream_avl, thisguid,
1189                             &stream_snapname);
1190
1191                         /* check for delete */
1192                         if (found == NULL) {
1193                                 char name[ZFS_MAXNAMELEN];
1194
1195                                 if (!flags.force)
1196                                         continue;
1197
1198                                 (void) snprintf(name, sizeof (name), "%s@%s",
1199                                     fsname, nvpair_name(snapelem));
1200
1201                                 error = recv_destroy(hdl, name,
1202                                     strlen(fsname)+1, newname, flags);
1203                                 if (error)
1204                                         needagain = B_TRUE;
1205                                 else
1206                                         progress = B_TRUE;
1207                                 continue;
1208                         }
1209
1210                         stream_nvfs = found;
1211
1212                         /* check for different snapname */
1213                         if (strcmp(nvpair_name(snapelem),
1214                             stream_snapname) != 0) {
1215                                 char name[ZFS_MAXNAMELEN];
1216                                 char tryname[ZFS_MAXNAMELEN];
1217
1218                                 (void) snprintf(name, sizeof (name), "%s@%s",
1219                                     fsname, nvpair_name(snapelem));
1220                                 (void) snprintf(tryname, sizeof (name), "%s@%s",
1221                                     fsname, stream_snapname);
1222
1223                                 error = recv_rename(hdl, name, tryname,
1224                                     strlen(fsname)+1, newname, flags);
1225                                 if (error)
1226                                         needagain = B_TRUE;
1227                                 else
1228                                         progress = B_TRUE;
1229                         }
1230
1231                         if (strcmp(stream_snapname, fromsnap) == 0)
1232                                 fromguid = thisguid;
1233                 }
1234
1235                 /* check for delete */
1236                 if (stream_nvfs == NULL) {
1237                         if (!flags.force)
1238                                 continue;
1239
1240                         error = recv_destroy(hdl, fsname, strlen(tofs)+1,
1241                             newname, flags);
1242                         if (error)
1243                                 needagain = B_TRUE;
1244                         else
1245                                 progress = B_TRUE;
1246                         continue;
1247                 }
1248
1249                 if (fromguid == 0 && flags.verbose) {
1250                         (void) printf("local fs %s does not have fromsnap "
1251                             "(%s in stream); must have been deleted locally; "
1252                             "ignoring\n", fsname, fromsnap);
1253                         continue;
1254                 }
1255
1256                 VERIFY(0 == nvlist_lookup_string(stream_nvfs,
1257                     "name", &stream_fsname));
1258                 VERIFY(0 == nvlist_lookup_uint64(stream_nvfs,
1259                     "parentfromsnap", &stream_parent_fromsnap_guid));
1260
1261                 /* check for rename */
1262                 if ((stream_parent_fromsnap_guid != 0 &&
1263                     stream_parent_fromsnap_guid != parent_fromsnap_guid) ||
1264                     strcmp(strrchr(fsname, '/'),
1265                     strrchr(stream_fsname, '/')) != 0) {
1266                         nvlist_t *parent;
1267                         char tryname[ZFS_MAXNAMELEN];
1268
1269                         parent = fsavl_find(local_avl,
1270                             stream_parent_fromsnap_guid, NULL);
1271                         /*
1272                          * NB: parent might not be found if we used the
1273                          * tosnap for stream_parent_fromsnap_guid,
1274                          * because the parent is a newly-created fs;
1275                          * we'll be able to rename it after we recv the
1276                          * new fs.
1277                          */
1278                         if (parent != NULL) {
1279                                 char *pname;
1280
1281                                 VERIFY(0 == nvlist_lookup_string(parent, "name",
1282                                     &pname));
1283                                 (void) snprintf(tryname, sizeof (tryname),
1284                                     "%s%s", pname, strrchr(stream_fsname, '/'));
1285                         } else {
1286                                 tryname[0] = '\0';
1287                                 if (flags.verbose) {
1288                                         (void) printf("local fs %s new parent "
1289                                             "not found\n", fsname);
1290                                 }
1291                         }
1292
1293                         error = recv_rename(hdl, fsname, tryname,
1294                             strlen(tofs)+1, newname, flags);
1295                         if (error)
1296                                 needagain = B_TRUE;
1297                         else
1298                                 progress = B_TRUE;
1299                 }
1300         }
1301
1302         fsavl_destroy(local_avl);
1303         nvlist_free(local_nv);
1304
1305         if (needagain && progress) {
1306                 /* do another pass to fix up temporary names */
1307                 if (flags.verbose)
1308                         (void) printf("another pass:\n");
1309                 goto again;
1310         }
1311
1312         return (needagain);
1313 }
1314
1315 static int
1316 zfs_receive_package(libzfs_handle_t *hdl, int fd, const char *destname,
1317     recvflags_t flags, dmu_replay_record_t *drr, zio_cksum_t *zc)
1318 {
1319         nvlist_t *stream_nv = NULL;
1320         avl_tree_t *stream_avl = NULL;
1321         char *fromsnap = NULL;
1322         char tofs[ZFS_MAXNAMELEN];
1323         char errbuf[1024];
1324         dmu_replay_record_t drre;
1325         int error;
1326         boolean_t anyerr = B_FALSE;
1327         boolean_t softerr = B_FALSE;
1328
1329         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1330             "cannot receive"));
1331
1332         if (strchr(destname, '@')) {
1333                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1334                     "can not specify snapshot name for multi-snapshot stream"));
1335                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
1336         }
1337
1338         assert(drr->drr_type == DRR_BEGIN);
1339         assert(drr->drr_u.drr_begin.drr_magic == DMU_BACKUP_MAGIC);
1340         assert(drr->drr_u.drr_begin.drr_version == DMU_BACKUP_HEADER_VERSION);
1341
1342         /*
1343          * Read in the nvlist from the stream.
1344          */
1345         if (drr->drr_payloadlen != 0) {
1346                 if (!flags.isprefix) {
1347                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1348                             "must use -d to receive replication "
1349                             "(send -R) stream"));
1350                         return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
1351                 }
1352
1353                 error = recv_read_nvlist(hdl, fd, drr->drr_payloadlen,
1354                     &stream_nv, flags.byteswap, zc);
1355                 if (error) {
1356                         error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1357                         goto out;
1358                 }
1359         }
1360
1361         /*
1362          * Read in the end record and verify checksum.
1363          */
1364         if (0 != (error = recv_read(hdl, fd, &drre, sizeof (drre),
1365             flags.byteswap, NULL)))
1366                 goto out;
1367         if (flags.byteswap) {
1368                 drre.drr_type = BSWAP_32(drre.drr_type);
1369                 drre.drr_u.drr_end.drr_checksum.zc_word[0] =
1370                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[0]);
1371                 drre.drr_u.drr_end.drr_checksum.zc_word[1] =
1372                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[1]);
1373                 drre.drr_u.drr_end.drr_checksum.zc_word[2] =
1374                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[2]);
1375                 drre.drr_u.drr_end.drr_checksum.zc_word[3] =
1376                     BSWAP_64(drre.drr_u.drr_end.drr_checksum.zc_word[3]);
1377         }
1378         if (drre.drr_type != DRR_END) {
1379                 error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1380                 goto out;
1381         }
1382         if (!ZIO_CHECKSUM_EQUAL(drre.drr_u.drr_end.drr_checksum, *zc)) {
1383                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1384                     "incorrect header checksum"));
1385                 error = zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1386                 goto out;
1387         }
1388
1389         (void) nvlist_lookup_string(stream_nv, "fromsnap", &fromsnap);
1390
1391         if (drr->drr_payloadlen != 0) {
1392                 nvlist_t *stream_fss;
1393
1394                 VERIFY(0 == nvlist_lookup_nvlist(stream_nv, "fss",
1395                     &stream_fss));
1396                 if ((stream_avl = fsavl_create(stream_fss)) == NULL) {
1397                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1398                             "couldn't allocate avl tree"));
1399                         error = zfs_error(hdl, EZFS_NOMEM, errbuf);
1400                         goto out;
1401                 }
1402
1403                 if (fromsnap != NULL) {
1404                         (void) strlcpy(tofs, destname, ZFS_MAXNAMELEN);
1405                         if (flags.isprefix) {
1406                                 int i = strcspn(drr->drr_u.drr_begin.drr_toname,
1407                                     "/@");
1408                                 /* zfs_receive_one() will create_parents() */
1409                                 (void) strlcat(tofs,
1410                                     &drr->drr_u.drr_begin.drr_toname[i],
1411                                     ZFS_MAXNAMELEN);
1412                                 *strchr(tofs, '@') = '\0';
1413                         }
1414                         softerr = recv_incremental_replication(hdl, tofs,
1415                             flags, stream_nv, stream_avl);
1416                 }
1417         }
1418
1419
1420         /* Finally, receive each contained stream */
1421         do {
1422                 /*
1423                  * we should figure out if it has a recoverable
1424                  * error, in which case do a recv_skip() and drive on.
1425                  * Note, if we fail due to already having this guid,
1426                  * zfs_receive_one() will take care of it (ie,
1427                  * recv_skip() and return 0).
1428                  */
1429                 error = zfs_receive(hdl, destname, flags, fd, stream_avl);
1430                 if (error == ENODATA) {
1431                         error = 0;
1432                         break;
1433                 }
1434                 anyerr |= error;
1435         } while (error == 0);
1436
1437         if (drr->drr_payloadlen != 0 && fromsnap != NULL) {
1438                 /*
1439                  * Now that we have the fs's they sent us, try the
1440                  * renames again.
1441                  */
1442                 softerr = recv_incremental_replication(hdl, tofs, flags,
1443                     stream_nv, stream_avl);
1444         }
1445
1446 out:
1447         fsavl_destroy(stream_avl);
1448         if (stream_nv)
1449                 nvlist_free(stream_nv);
1450         if (softerr)
1451                 error = -2;
1452         if (anyerr)
1453                 error = -1;
1454         return (error);
1455 }
1456
1457 static int
1458 recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
1459 {
1460         dmu_replay_record_t *drr;
1461         void *buf = malloc(1<<20);
1462
1463         /* XXX would be great to use lseek if possible... */
1464         drr = buf;
1465
1466         while (recv_read(hdl, fd, drr, sizeof (dmu_replay_record_t),
1467             byteswap, NULL) == 0) {
1468                 if (byteswap)
1469                         drr->drr_type = BSWAP_32(drr->drr_type);
1470
1471                 switch (drr->drr_type) {
1472                 case DRR_BEGIN:
1473                         /* NB: not to be used on v2 stream packages */
1474                         assert(drr->drr_payloadlen == 0);
1475                         break;
1476
1477                 case DRR_END:
1478                         free(buf);
1479                         return (0);
1480
1481                 case DRR_OBJECT:
1482                         if (byteswap) {
1483                                 drr->drr_u.drr_object.drr_bonuslen =
1484                                     BSWAP_32(drr->drr_u.drr_object.
1485                                     drr_bonuslen);
1486                         }
1487                         (void) recv_read(hdl, fd, buf,
1488                             P2ROUNDUP(drr->drr_u.drr_object.drr_bonuslen, 8),
1489                             B_FALSE, NULL);
1490                         break;
1491
1492                 case DRR_WRITE:
1493                         if (byteswap) {
1494                                 drr->drr_u.drr_write.drr_length =
1495                                     BSWAP_32(drr->drr_u.drr_write.drr_length);
1496                         }
1497                         (void) recv_read(hdl, fd, buf,
1498                             drr->drr_u.drr_write.drr_length, B_FALSE, NULL);
1499                         break;
1500
1501                 case DRR_FREEOBJECTS:
1502                 case DRR_FREE:
1503                         break;
1504
1505                 default:
1506                         assert(!"invalid record type");
1507                 }
1508         }
1509
1510         free(buf);
1511         return (-1);
1512 }
1513
1514 /*
1515  * Restores a backup of tosnap from the file descriptor specified by infd.
1516  */
1517 static int
1518 zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
1519     recvflags_t flags, dmu_replay_record_t *drr,
1520     dmu_replay_record_t *drr_noswap, avl_tree_t *stream_avl)
1521 {
1522         zfs_cmd_t zc = { 0 };
1523         time_t begin_time;
1524         int ioctl_err, ioctl_errno, err, choplen;
1525         char *cp;
1526         struct drr_begin *drrb = &drr->drr_u.drr_begin;
1527         char errbuf[1024];
1528         char chopprefix[ZFS_MAXNAMELEN];
1529         boolean_t newfs = B_FALSE;
1530         boolean_t stream_wantsnewfs;
1531         uint64_t parent_snapguid = 0;
1532         prop_changelist_t *clp = NULL;
1533
1534         begin_time = time(NULL);
1535
1536         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1537             "cannot receive"));
1538
1539         if (stream_avl != NULL) {
1540                 nvlist_t *fs = fsavl_find(stream_avl, drrb->drr_toguid, NULL);
1541                 nvlist_t *props;
1542                 int ret;
1543
1544                 (void) nvlist_lookup_uint64(fs, "parentfromsnap",
1545                     &parent_snapguid);
1546                 err = nvlist_lookup_nvlist(fs, "props", &props);
1547                 if (err)
1548                         VERIFY(0 == nvlist_alloc(&props, NV_UNIQUE_NAME, 0));
1549
1550                 if (flags.canmountoff) {
1551                         VERIFY(0 == nvlist_add_uint64(props,
1552                             zfs_prop_to_name(ZFS_PROP_CANMOUNT), 0));
1553                 }
1554                 ret = zcmd_write_src_nvlist(hdl, &zc, props);
1555                 if (err)
1556                         nvlist_free(props);
1557
1558                 if (ret != 0)
1559                         return (-1);
1560         }
1561
1562         /*
1563          * Determine how much of the snapshot name stored in the stream
1564          * we are going to tack on to the name they specified on the
1565          * command line, and how much we are going to chop off.
1566          *
1567          * If they specified a snapshot, chop the entire name stored in
1568          * the stream.
1569          */
1570         (void) strcpy(chopprefix, drrb->drr_toname);
1571         if (flags.isprefix) {
1572                 /*
1573                  * They specified a fs with -d, we want to tack on
1574                  * everything but the pool name stored in the stream
1575                  */
1576                 if (strchr(tosnap, '@')) {
1577                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
1578                             "argument - snapshot not allowed with -d"));
1579                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1580                 }
1581                 cp = strchr(chopprefix, '/');
1582                 if (cp == NULL)
1583                         cp = strchr(chopprefix, '@');
1584                 *cp = '\0';
1585         } else if (strchr(tosnap, '@') == NULL) {
1586                 /*
1587                  * If they specified a filesystem without -d, we want to
1588                  * tack on everything after the fs specified in the
1589                  * first name from the stream.
1590                  */
1591                 cp = strchr(chopprefix, '@');
1592                 *cp = '\0';
1593         }
1594         choplen = strlen(chopprefix);
1595
1596         /*
1597          * Determine name of destination snapshot, store in zc_value.
1598          */
1599         (void) strcpy(zc.zc_value, tosnap);
1600         (void) strncat(zc.zc_value, drrb->drr_toname+choplen,
1601             sizeof (zc.zc_value));
1602         if (!zfs_name_valid(zc.zc_value, ZFS_TYPE_SNAPSHOT)) {
1603                 zcmd_free_nvlists(&zc);
1604                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1605         }
1606
1607         /*
1608          * Determine the name of the origin snapshot, store in zc_string.
1609          */
1610         if (drrb->drr_flags & DRR_FLAG_CLONE) {
1611                 if (guid_to_name(hdl, tosnap,
1612                     drrb->drr_fromguid, zc.zc_string) != 0) {
1613                         zcmd_free_nvlists(&zc);
1614                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1615                             "local origin for clone %s does not exist"),
1616                             zc.zc_value);
1617                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
1618                 }
1619                 if (flags.verbose)
1620                         (void) printf("found clone origin %s\n", zc.zc_string);
1621         }
1622
1623         stream_wantsnewfs = (drrb->drr_fromguid == NULL ||
1624             (drrb->drr_flags & DRR_FLAG_CLONE));
1625
1626         if (stream_wantsnewfs) {
1627                 /*
1628                  * if the parent fs does not exist, look for it based on
1629                  * the parent snap GUID
1630                  */
1631                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1632                     "cannot receive new filesystem stream"));
1633
1634                 (void) strcpy(zc.zc_name, zc.zc_value);
1635                 cp = strrchr(zc.zc_name, '/');
1636                 if (cp)
1637                         *cp = '\0';
1638                 if (cp &&
1639                     !zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
1640                         char suffix[ZFS_MAXNAMELEN];
1641                         (void) strcpy(suffix, strrchr(zc.zc_value, '/'));
1642                         if (guid_to_name(hdl, tosnap, parent_snapguid,
1643                             zc.zc_value) == 0) {
1644                                 *strchr(zc.zc_value, '@') = '\0';
1645                                 (void) strcat(zc.zc_value, suffix);
1646                         }
1647                 }
1648         } else {
1649                 /*
1650                  * if the fs does not exist, look for it based on the
1651                  * fromsnap GUID
1652                  */
1653                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1654                     "cannot receive incremental stream"));
1655
1656                 (void) strcpy(zc.zc_name, zc.zc_value);
1657                 *strchr(zc.zc_name, '@') = '\0';
1658
1659                 if (!zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
1660                         char snap[ZFS_MAXNAMELEN];
1661                         (void) strcpy(snap, strchr(zc.zc_value, '@'));
1662                         if (guid_to_name(hdl, tosnap, drrb->drr_fromguid,
1663                             zc.zc_value) == 0) {
1664                                 *strchr(zc.zc_value, '@') = '\0';
1665                                 (void) strcat(zc.zc_value, snap);
1666                         }
1667                 }
1668         }
1669
1670         (void) strcpy(zc.zc_name, zc.zc_value);
1671         *strchr(zc.zc_name, '@') = '\0';
1672
1673         if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
1674                 zfs_handle_t *zhp;
1675                 /*
1676                  * Destination fs exists.  Therefore this should either
1677                  * be an incremental, or the stream specifies a new fs
1678                  * (full stream or clone) and they want us to blow it
1679                  * away (and have therefore specified -F and removed any
1680                  * snapshots).
1681                  */
1682
1683                 if (stream_wantsnewfs) {
1684                         if (!flags.force) {
1685                                 zcmd_free_nvlists(&zc);
1686                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1687                                     "destination '%s' exists\n"
1688                                     "must specify -F to overwrite it"),
1689                                     zc.zc_name);
1690                                 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1691                         }
1692                         if (ioctl(hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT,
1693                             &zc) == 0) {
1694                                 zcmd_free_nvlists(&zc);
1695                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1696                                     "destination has snapshots (eg. %s)\n"
1697                                     "must destroy them to overwrite it"),
1698                                     zc.zc_name);
1699                                 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1700                         }
1701                 }
1702
1703                 if ((zhp = zfs_open(hdl, zc.zc_name,
1704                     ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
1705                         zcmd_free_nvlists(&zc);
1706                         return (-1);
1707                 }
1708
1709                 if (stream_wantsnewfs &&
1710                     zhp->zfs_dmustats.dds_origin[0]) {
1711                         zcmd_free_nvlists(&zc);
1712                         zfs_close(zhp);
1713                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1714                             "destination '%s' is a clone\n"
1715                             "must destroy it to overwrite it"),
1716                             zc.zc_name);
1717                         return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1718                 }
1719
1720                 if (!flags.dryrun && zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
1721                     stream_wantsnewfs) {
1722                         /* We can't do online recv in this case */
1723                         clp = changelist_gather(zhp, ZFS_PROP_NAME, 0);
1724                         if (clp == NULL) {
1725                                 zcmd_free_nvlists(&zc);
1726                                 return (-1);
1727                         }
1728                         if (changelist_prefix(clp) != 0) {
1729                                 changelist_free(clp);
1730                                 zcmd_free_nvlists(&zc);
1731                                 return (-1);
1732                         }
1733                 }
1734                 if (!flags.dryrun && zhp->zfs_type == ZFS_TYPE_VOLUME &&
1735                     zvol_remove_link(hdl, zhp->zfs_name) != 0) {
1736                         zfs_close(zhp);
1737                         zcmd_free_nvlists(&zc);
1738                         return (-1);
1739                 }
1740                 zfs_close(zhp);
1741         } else {
1742                 /*
1743                  * Destination filesystem does not exist.  Therefore we better
1744                  * be creating a new filesystem (either from a full backup, or
1745                  * a clone).  It would therefore be invalid if the user
1746                  * specified only the pool name (i.e. if the destination name
1747                  * contained no slash character).
1748                  */
1749                 if (!stream_wantsnewfs ||
1750                     (cp = strrchr(zc.zc_name, '/')) == NULL) {
1751                         zcmd_free_nvlists(&zc);
1752                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1753                             "destination '%s' does not exist"), zc.zc_name);
1754                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
1755                 }
1756
1757                 /*
1758                  * Trim off the final dataset component so we perform the
1759                  * recvbackup ioctl to the filesystems's parent.
1760                  */
1761                 *cp = '\0';
1762
1763                 if (flags.isprefix && !flags.dryrun &&
1764                     create_parents(hdl, zc.zc_value, strlen(tosnap)) != 0) {
1765                         zcmd_free_nvlists(&zc);
1766                         return (zfs_error(hdl, EZFS_BADRESTORE, errbuf));
1767                 }
1768
1769                 newfs = B_TRUE;
1770         }
1771
1772         zc.zc_begin_record = drr_noswap->drr_u.drr_begin;
1773         zc.zc_cookie = infd;
1774         zc.zc_guid = flags.force;
1775         if (flags.verbose) {
1776                 (void) printf("%s %s stream of %s into %s\n",
1777                     flags.dryrun ? "would receive" : "receiving",
1778                     drrb->drr_fromguid ? "incremental" : "full",
1779                     drrb->drr_toname, zc.zc_value);
1780                 (void) fflush(stdout);
1781         }
1782
1783         if (flags.dryrun) {
1784                 zcmd_free_nvlists(&zc);
1785                 return (recv_skip(hdl, infd, flags.byteswap));
1786         }
1787
1788         err = ioctl_err = zfs_ioctl(hdl, ZFS_IOC_RECV, &zc);
1789         ioctl_errno = errno;
1790         if (err && (ioctl_errno == ENOENT || ioctl_errno == ENODEV)) {
1791                 /*
1792                  * It may be that this snapshot already exists,
1793                  * in which case we want to consume & ignore it
1794                  * rather than failing.
1795                  */
1796                 avl_tree_t *local_avl;
1797                 nvlist_t *local_nv, *fs;
1798                 char *cp = strchr(zc.zc_value, '@');
1799
1800                 /*
1801                  * XXX Do this faster by just iterating over snaps in
1802                  * this fs.  Also if zc_value does not exist, we will
1803                  * get a strange "does not exist" error message.
1804                  */
1805                 *cp = '\0';
1806                 if (gather_nvlist(hdl, zc.zc_value, NULL, NULL,
1807                     &local_nv, &local_avl) == 0) {
1808                         *cp = '@';
1809                         fs = fsavl_find(local_avl, drrb->drr_toguid, NULL);
1810                         fsavl_destroy(local_avl);
1811                         nvlist_free(local_nv);
1812
1813                         if (fs != NULL) {
1814                                 if (flags.verbose) {
1815                                         (void) printf("snap %s already exists; "
1816                                             "ignoring\n", zc.zc_value);
1817                                 }
1818                                 ioctl_err = recv_skip(hdl, infd,
1819                                     flags.byteswap);
1820                         }
1821                 }
1822                 *cp = '@';
1823         }
1824
1825         zcmd_free_nvlists(&zc);
1826
1827         if (ioctl_err != 0) {
1828                 switch (ioctl_errno) {
1829                 case ENODEV:
1830                         cp = strchr(zc.zc_value, '@');
1831                         *cp = '\0';
1832                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1833                             "most recent snapshot of %s does not\n"
1834                             "match incremental source"), zc.zc_value);
1835                         (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
1836                         *cp = '@';
1837                         break;
1838                 case ETXTBSY:
1839                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1840                             "destination %s has been modified\n"
1841                             "since most recent snapshot"), zc.zc_name);
1842                         (void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
1843                         break;
1844                 case EEXIST:
1845                         cp = strchr(zc.zc_value, '@');
1846                         if (newfs) {
1847                                 /* it's the containing fs that exists */
1848                                 *cp = '\0';
1849                         }
1850                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1851                             "destination already exists"));
1852                         (void) zfs_error_fmt(hdl, EZFS_EXISTS,
1853                             dgettext(TEXT_DOMAIN, "cannot restore to %s"),
1854                             zc.zc_value);
1855                         *cp = '@';
1856                         break;
1857                 case EINVAL:
1858                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1859                         break;
1860                 case ECKSUM:
1861                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1862                             "invalid stream (checksum mismatch)"));
1863                         (void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
1864                         break;
1865                 default:
1866                         (void) zfs_standard_error(hdl, ioctl_errno, errbuf);
1867                 }
1868         }
1869
1870         /*
1871          * Mount or recreate the /dev links for the target filesystem
1872          * (if created, or if we tore them down to do an incremental
1873          * restore), and the /dev links for the new snapshot (if
1874          * created). Also mount any children of the target filesystem
1875          * if we did an incremental receive.
1876          */
1877         cp = strchr(zc.zc_value, '@');
1878         if (cp && (ioctl_err == 0 || !newfs)) {
1879                 zfs_handle_t *h;
1880
1881                 *cp = '\0';
1882                 h = zfs_open(hdl, zc.zc_value,
1883                     ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
1884                 *cp = '@';
1885                 if (h != NULL) {
1886                         if (h->zfs_type == ZFS_TYPE_VOLUME) {
1887                                 err = zvol_create_link(hdl, h->zfs_name);
1888                                 if (err == 0 && ioctl_err == 0)
1889                                         err = zvol_create_link(hdl,
1890                                             zc.zc_value);
1891                         } else if (newfs) {
1892                                 err = zfs_mount(h, NULL, 0);
1893                         }
1894                         zfs_close(h);
1895                 }
1896         }
1897
1898         if (clp) {
1899                 err |= changelist_postfix(clp);
1900                 changelist_free(clp);
1901         }
1902
1903         if (err || ioctl_err)
1904                 return (-1);
1905
1906         if (flags.verbose) {
1907                 char buf1[64];
1908                 char buf2[64];
1909                 uint64_t bytes = zc.zc_cookie;
1910                 time_t delta = time(NULL) - begin_time;
1911                 if (delta == 0)
1912                         delta = 1;
1913                 zfs_nicenum(bytes, buf1, sizeof (buf1));
1914                 zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
1915
1916                 (void) printf("received %sB stream in %lu seconds (%sB/sec)\n",
1917                     buf1, delta, buf2);
1918         }
1919
1920         return (0);
1921 }
1922
1923 /*
1924  * Restores a backup of tosnap from the file descriptor specified by infd.
1925  * Return 0 on total success, -2 if some things couldn't be
1926  * destroyed/renamed/promoted, -1 if some things couldn't be received.
1927  * (-1 will override -2).
1928  */
1929 int
1930 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, recvflags_t flags,
1931     int infd, avl_tree_t *stream_avl)
1932 {
1933         int err;
1934         dmu_replay_record_t drr, drr_noswap;
1935         struct drr_begin *drrb = &drr.drr_u.drr_begin;
1936         char errbuf[1024];
1937         zio_cksum_t zcksum = { 0 };
1938
1939         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1940             "cannot receive"));
1941
1942         if (flags.isprefix &&
1943             !zfs_dataset_exists(hdl, tosnap, ZFS_TYPE_DATASET)) {
1944                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "specified fs "
1945                     "(%s) does not exist"), tosnap);
1946                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
1947         }
1948
1949         /* read in the BEGIN record */
1950         if (0 != (err = recv_read(hdl, infd, &drr, sizeof (drr), B_FALSE,
1951             &zcksum)))
1952                 return (err);
1953
1954         if (drr.drr_type == DRR_END || drr.drr_type == BSWAP_32(DRR_END)) {
1955                 /* It's the double end record at the end of a package */
1956                 return (ENODATA);
1957         }
1958
1959         /* the kernel needs the non-byteswapped begin record */
1960         drr_noswap = drr;
1961
1962         flags.byteswap = B_FALSE;
1963         if (drrb->drr_magic == BSWAP_64(DMU_BACKUP_MAGIC)) {
1964                 /*
1965                  * We computed the checksum in the wrong byteorder in
1966                  * recv_read() above; do it again correctly.
1967                  */
1968                 bzero(&zcksum, sizeof (zio_cksum_t));
1969                 fletcher_4_incremental_byteswap(&drr, sizeof (drr), &zcksum);
1970                 flags.byteswap = B_TRUE;
1971
1972                 drr.drr_type = BSWAP_32(drr.drr_type);
1973                 drr.drr_payloadlen = BSWAP_32(drr.drr_payloadlen);
1974                 drrb->drr_magic = BSWAP_64(drrb->drr_magic);
1975                 drrb->drr_version = BSWAP_64(drrb->drr_version);
1976                 drrb->drr_creation_time = BSWAP_64(drrb->drr_creation_time);
1977                 drrb->drr_type = BSWAP_32(drrb->drr_type);
1978                 drrb->drr_flags = BSWAP_32(drrb->drr_flags);
1979                 drrb->drr_toguid = BSWAP_64(drrb->drr_toguid);
1980                 drrb->drr_fromguid = BSWAP_64(drrb->drr_fromguid);
1981         }
1982
1983         if (drrb->drr_magic != DMU_BACKUP_MAGIC || drr.drr_type != DRR_BEGIN) {
1984                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
1985                     "stream (bad magic number)"));
1986                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
1987         }
1988
1989         if (strchr(drrb->drr_toname, '@') == NULL) {
1990                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
1991                     "stream (bad snapshot name)"));
1992                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
1993         }
1994
1995         if (drrb->drr_version == DMU_BACKUP_STREAM_VERSION) {
1996                 return (zfs_receive_one(hdl, infd, tosnap, flags,
1997                     &drr, &drr_noswap, stream_avl));
1998         } else if (drrb->drr_version == DMU_BACKUP_HEADER_VERSION) {
1999                 return (zfs_receive_package(hdl, infd, tosnap, flags,
2000                     &drr, &zcksum));
2001         } else {
2002                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2003                     "stream is unsupported version %llu"),
2004                     drrb->drr_version);
2005                 return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2006         }
2007 }