]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
MFC r260183:
[FreeBSD/stable/9.git] / cddl / contrib / opensolaris / lib / libzfs / common / libzfs_dataset.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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright (c) 2013 by Delphix. All rights reserved.
25  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
26  * Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
27  * All rights reserved.
28  * Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
29  * Copyright (c) 2013 Steven Hartland. All rights reserved.
30  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
31  */
32
33 #include <ctype.h>
34 #include <errno.h>
35 #include <libintl.h>
36 #include <math.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <stddef.h>
42 #include <zone.h>
43 #include <fcntl.h>
44 #include <sys/mntent.h>
45 #include <sys/mount.h>
46 #include <priv.h>
47 #include <pwd.h>
48 #include <grp.h>
49 #include <stddef.h>
50 #include <idmap.h>
51
52 #include <sys/dnode.h>
53 #include <sys/spa.h>
54 #include <sys/zap.h>
55 #include <sys/misc.h>
56 #include <libzfs.h>
57
58 #include "zfs_namecheck.h"
59 #include "zfs_prop.h"
60 #include "libzfs_impl.h"
61 #include "zfs_deleg.h"
62
63 static int userquota_propname_decode(const char *propname, boolean_t zoned,
64     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
65
66 /*
67  * Given a single type (not a mask of types), return the type in a human
68  * readable form.
69  */
70 const char *
71 zfs_type_to_name(zfs_type_t type)
72 {
73         switch (type) {
74         case ZFS_TYPE_FILESYSTEM:
75                 return (dgettext(TEXT_DOMAIN, "filesystem"));
76         case ZFS_TYPE_SNAPSHOT:
77                 return (dgettext(TEXT_DOMAIN, "snapshot"));
78         case ZFS_TYPE_VOLUME:
79                 return (dgettext(TEXT_DOMAIN, "volume"));
80         }
81
82         return (NULL);
83 }
84
85 /*
86  * Given a path and mask of ZFS types, return a string describing this dataset.
87  * This is used when we fail to open a dataset and we cannot get an exact type.
88  * We guess what the type would have been based on the path and the mask of
89  * acceptable types.
90  */
91 static const char *
92 path_to_str(const char *path, int types)
93 {
94         /*
95          * When given a single type, always report the exact type.
96          */
97         if (types == ZFS_TYPE_SNAPSHOT)
98                 return (dgettext(TEXT_DOMAIN, "snapshot"));
99         if (types == ZFS_TYPE_FILESYSTEM)
100                 return (dgettext(TEXT_DOMAIN, "filesystem"));
101         if (types == ZFS_TYPE_VOLUME)
102                 return (dgettext(TEXT_DOMAIN, "volume"));
103
104         /*
105          * The user is requesting more than one type of dataset.  If this is the
106          * case, consult the path itself.  If we're looking for a snapshot, and
107          * a '@' is found, then report it as "snapshot".  Otherwise, remove the
108          * snapshot attribute and try again.
109          */
110         if (types & ZFS_TYPE_SNAPSHOT) {
111                 if (strchr(path, '@') != NULL)
112                         return (dgettext(TEXT_DOMAIN, "snapshot"));
113                 return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
114         }
115
116         /*
117          * The user has requested either filesystems or volumes.
118          * We have no way of knowing a priori what type this would be, so always
119          * report it as "filesystem" or "volume", our two primitive types.
120          */
121         if (types & ZFS_TYPE_FILESYSTEM)
122                 return (dgettext(TEXT_DOMAIN, "filesystem"));
123
124         assert(types & ZFS_TYPE_VOLUME);
125         return (dgettext(TEXT_DOMAIN, "volume"));
126 }
127
128 /*
129  * Validate a ZFS path.  This is used even before trying to open the dataset, to
130  * provide a more meaningful error message.  We call zfs_error_aux() to
131  * explain exactly why the name was not valid.
132  */
133 int
134 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
135     boolean_t modifying)
136 {
137         namecheck_err_t why;
138         char what;
139
140         (void) zfs_prop_get_table();
141         if (dataset_namecheck(path, &why, &what) != 0) {
142                 if (hdl != NULL) {
143                         switch (why) {
144                         case NAME_ERR_TOOLONG:
145                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
146                                     "name is too long"));
147                                 break;
148
149                         case NAME_ERR_LEADING_SLASH:
150                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
151                                     "leading slash in name"));
152                                 break;
153
154                         case NAME_ERR_EMPTY_COMPONENT:
155                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
156                                     "empty component in name"));
157                                 break;
158
159                         case NAME_ERR_TRAILING_SLASH:
160                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
161                                     "trailing slash in name"));
162                                 break;
163
164                         case NAME_ERR_INVALCHAR:
165                                 zfs_error_aux(hdl,
166                                     dgettext(TEXT_DOMAIN, "invalid character "
167                                     "'%c' in name"), what);
168                                 break;
169
170                         case NAME_ERR_MULTIPLE_AT:
171                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
172                                     "multiple '@' delimiters in name"));
173                                 break;
174
175                         case NAME_ERR_NOLETTER:
176                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
177                                     "pool doesn't begin with a letter"));
178                                 break;
179
180                         case NAME_ERR_RESERVED:
181                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
182                                     "name is reserved"));
183                                 break;
184
185                         case NAME_ERR_DISKLIKE:
186                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
187                                     "reserved disk name"));
188                                 break;
189                         }
190                 }
191
192                 return (0);
193         }
194
195         if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
196                 if (hdl != NULL)
197                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
198                             "snapshot delimiter '@' in filesystem name"));
199                 return (0);
200         }
201
202         if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
203                 if (hdl != NULL)
204                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
205                             "missing '@' delimiter in snapshot name"));
206                 return (0);
207         }
208
209         if (modifying && strchr(path, '%') != NULL) {
210                 if (hdl != NULL)
211                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
212                             "invalid character %c in name"), '%');
213                 return (0);
214         }
215
216         return (-1);
217 }
218
219 int
220 zfs_name_valid(const char *name, zfs_type_t type)
221 {
222         if (type == ZFS_TYPE_POOL)
223                 return (zpool_name_valid(NULL, B_FALSE, name));
224         return (zfs_validate_name(NULL, name, type, B_FALSE));
225 }
226
227 /*
228  * This function takes the raw DSL properties, and filters out the user-defined
229  * properties into a separate nvlist.
230  */
231 static nvlist_t *
232 process_user_props(zfs_handle_t *zhp, nvlist_t *props)
233 {
234         libzfs_handle_t *hdl = zhp->zfs_hdl;
235         nvpair_t *elem;
236         nvlist_t *propval;
237         nvlist_t *nvl;
238
239         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
240                 (void) no_memory(hdl);
241                 return (NULL);
242         }
243
244         elem = NULL;
245         while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
246                 if (!zfs_prop_user(nvpair_name(elem)))
247                         continue;
248
249                 verify(nvpair_value_nvlist(elem, &propval) == 0);
250                 if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
251                         nvlist_free(nvl);
252                         (void) no_memory(hdl);
253                         return (NULL);
254                 }
255         }
256
257         return (nvl);
258 }
259
260 static zpool_handle_t *
261 zpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
262 {
263         libzfs_handle_t *hdl = zhp->zfs_hdl;
264         zpool_handle_t *zph;
265
266         if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
267                 if (hdl->libzfs_pool_handles != NULL)
268                         zph->zpool_next = hdl->libzfs_pool_handles;
269                 hdl->libzfs_pool_handles = zph;
270         }
271         return (zph);
272 }
273
274 static zpool_handle_t *
275 zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
276 {
277         libzfs_handle_t *hdl = zhp->zfs_hdl;
278         zpool_handle_t *zph = hdl->libzfs_pool_handles;
279
280         while ((zph != NULL) &&
281             (strncmp(pool_name, zpool_get_name(zph), len) != 0))
282                 zph = zph->zpool_next;
283         return (zph);
284 }
285
286 /*
287  * Returns a handle to the pool that contains the provided dataset.
288  * If a handle to that pool already exists then that handle is returned.
289  * Otherwise, a new handle is created and added to the list of handles.
290  */
291 static zpool_handle_t *
292 zpool_handle(zfs_handle_t *zhp)
293 {
294         char *pool_name;
295         int len;
296         zpool_handle_t *zph;
297
298         len = strcspn(zhp->zfs_name, "/@#") + 1;
299         pool_name = zfs_alloc(zhp->zfs_hdl, len);
300         (void) strlcpy(pool_name, zhp->zfs_name, len);
301
302         zph = zpool_find_handle(zhp, pool_name, len);
303         if (zph == NULL)
304                 zph = zpool_add_handle(zhp, pool_name);
305
306         free(pool_name);
307         return (zph);
308 }
309
310 void
311 zpool_free_handles(libzfs_handle_t *hdl)
312 {
313         zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
314
315         while (zph != NULL) {
316                 next = zph->zpool_next;
317                 zpool_close(zph);
318                 zph = next;
319         }
320         hdl->libzfs_pool_handles = NULL;
321 }
322
323 /*
324  * Utility function to gather stats (objset and zpl) for the given object.
325  */
326 static int
327 get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc)
328 {
329         libzfs_handle_t *hdl = zhp->zfs_hdl;
330
331         (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
332
333         while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) {
334                 if (errno == ENOMEM) {
335                         if (zcmd_expand_dst_nvlist(hdl, zc) != 0) {
336                                 return (-1);
337                         }
338                 } else {
339                         return (-1);
340                 }
341         }
342         return (0);
343 }
344
345 /*
346  * Utility function to get the received properties of the given object.
347  */
348 static int
349 get_recvd_props_ioctl(zfs_handle_t *zhp)
350 {
351         libzfs_handle_t *hdl = zhp->zfs_hdl;
352         nvlist_t *recvdprops;
353         zfs_cmd_t zc = { 0 };
354         int err;
355
356         if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
357                 return (-1);
358
359         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
360
361         while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) {
362                 if (errno == ENOMEM) {
363                         if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
364                                 return (-1);
365                         }
366                 } else {
367                         zcmd_free_nvlists(&zc);
368                         return (-1);
369                 }
370         }
371
372         err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops);
373         zcmd_free_nvlists(&zc);
374         if (err != 0)
375                 return (-1);
376
377         nvlist_free(zhp->zfs_recvd_props);
378         zhp->zfs_recvd_props = recvdprops;
379
380         return (0);
381 }
382
383 static int
384 put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc)
385 {
386         nvlist_t *allprops, *userprops;
387
388         zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */
389
390         if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
391                 return (-1);
392         }
393
394         /*
395          * XXX Why do we store the user props separately, in addition to
396          * storing them in zfs_props?
397          */
398         if ((userprops = process_user_props(zhp, allprops)) == NULL) {
399                 nvlist_free(allprops);
400                 return (-1);
401         }
402
403         nvlist_free(zhp->zfs_props);
404         nvlist_free(zhp->zfs_user_props);
405
406         zhp->zfs_props = allprops;
407         zhp->zfs_user_props = userprops;
408
409         return (0);
410 }
411
412 static int
413 get_stats(zfs_handle_t *zhp)
414 {
415         int rc = 0;
416         zfs_cmd_t zc = { 0 };
417
418         if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
419                 return (-1);
420         if (get_stats_ioctl(zhp, &zc) != 0)
421                 rc = -1;
422         else if (put_stats_zhdl(zhp, &zc) != 0)
423                 rc = -1;
424         zcmd_free_nvlists(&zc);
425         return (rc);
426 }
427
428 /*
429  * Refresh the properties currently stored in the handle.
430  */
431 void
432 zfs_refresh_properties(zfs_handle_t *zhp)
433 {
434         (void) get_stats(zhp);
435 }
436
437 /*
438  * Makes a handle from the given dataset name.  Used by zfs_open() and
439  * zfs_iter_* to create child handles on the fly.
440  */
441 static int
442 make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
443 {
444         if (put_stats_zhdl(zhp, zc) != 0)
445                 return (-1);
446
447         /*
448          * We've managed to open the dataset and gather statistics.  Determine
449          * the high-level type.
450          */
451         if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
452                 zhp->zfs_head_type = ZFS_TYPE_VOLUME;
453         else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
454                 zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
455         else
456                 abort();
457
458         if (zhp->zfs_dmustats.dds_is_snapshot)
459                 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
460         else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
461                 zhp->zfs_type = ZFS_TYPE_VOLUME;
462         else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
463                 zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
464         else
465                 abort();        /* we should never see any other types */
466
467         if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL)
468                 return (-1);
469
470         return (0);
471 }
472
473 zfs_handle_t *
474 make_dataset_handle(libzfs_handle_t *hdl, const char *path)
475 {
476         zfs_cmd_t zc = { 0 };
477
478         zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
479
480         if (zhp == NULL)
481                 return (NULL);
482
483         zhp->zfs_hdl = hdl;
484         (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
485         if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) {
486                 free(zhp);
487                 return (NULL);
488         }
489         if (get_stats_ioctl(zhp, &zc) == -1) {
490                 zcmd_free_nvlists(&zc);
491                 free(zhp);
492                 return (NULL);
493         }
494         if (make_dataset_handle_common(zhp, &zc) == -1) {
495                 free(zhp);
496                 zhp = NULL;
497         }
498         zcmd_free_nvlists(&zc);
499         return (zhp);
500 }
501
502 zfs_handle_t *
503 make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
504 {
505         zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
506
507         if (zhp == NULL)
508                 return (NULL);
509
510         zhp->zfs_hdl = hdl;
511         (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
512         if (make_dataset_handle_common(zhp, zc) == -1) {
513                 free(zhp);
514                 return (NULL);
515         }
516         return (zhp);
517 }
518
519 zfs_handle_t *
520 make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc)
521 {
522         zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
523
524         if (zhp == NULL)
525                 return (NULL);
526
527         zhp->zfs_hdl = pzhp->zfs_hdl;
528         (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
529         zhp->zfs_head_type = pzhp->zfs_type;
530         zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
531         zhp->zpool_hdl = zpool_handle(zhp);
532         return (zhp);
533 }
534
535 zfs_handle_t *
536 zfs_handle_dup(zfs_handle_t *zhp_orig)
537 {
538         zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
539
540         if (zhp == NULL)
541                 return (NULL);
542
543         zhp->zfs_hdl = zhp_orig->zfs_hdl;
544         zhp->zpool_hdl = zhp_orig->zpool_hdl;
545         (void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name,
546             sizeof (zhp->zfs_name));
547         zhp->zfs_type = zhp_orig->zfs_type;
548         zhp->zfs_head_type = zhp_orig->zfs_head_type;
549         zhp->zfs_dmustats = zhp_orig->zfs_dmustats;
550         if (zhp_orig->zfs_props != NULL) {
551                 if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
552                         (void) no_memory(zhp->zfs_hdl);
553                         zfs_close(zhp);
554                         return (NULL);
555                 }
556         }
557         if (zhp_orig->zfs_user_props != NULL) {
558                 if (nvlist_dup(zhp_orig->zfs_user_props,
559                     &zhp->zfs_user_props, 0) != 0) {
560                         (void) no_memory(zhp->zfs_hdl);
561                         zfs_close(zhp);
562                         return (NULL);
563                 }
564         }
565         if (zhp_orig->zfs_recvd_props != NULL) {
566                 if (nvlist_dup(zhp_orig->zfs_recvd_props,
567                     &zhp->zfs_recvd_props, 0)) {
568                         (void) no_memory(zhp->zfs_hdl);
569                         zfs_close(zhp);
570                         return (NULL);
571                 }
572         }
573         zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck;
574         if (zhp_orig->zfs_mntopts != NULL) {
575                 zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl,
576                     zhp_orig->zfs_mntopts);
577         }
578         zhp->zfs_props_table = zhp_orig->zfs_props_table;
579         return (zhp);
580 }
581
582 boolean_t
583 zfs_bookmark_exists(const char *path)
584 {
585         nvlist_t *bmarks;
586         nvlist_t *props;
587         char fsname[ZFS_MAXNAMELEN];
588         char *bmark_name;
589         char *pound;
590         int err;
591         boolean_t rv;
592
593
594         (void) strlcpy(fsname, path, sizeof (fsname));
595         pound = strchr(fsname, '#');
596         if (pound == NULL)
597                 return (B_FALSE);
598
599         *pound = '\0';
600         bmark_name = pound + 1;
601         props = fnvlist_alloc();
602         err = lzc_get_bookmarks(fsname, props, &bmarks);
603         nvlist_free(props);
604         if (err != 0) {
605                 nvlist_free(bmarks);
606                 return (B_FALSE);
607         }
608
609         rv = nvlist_exists(bmarks, bmark_name);
610         nvlist_free(bmarks);
611         return (rv);
612 }
613
614 zfs_handle_t *
615 make_bookmark_handle(zfs_handle_t *parent, const char *path,
616     nvlist_t *bmark_props)
617 {
618         zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
619
620         if (zhp == NULL)
621                 return (NULL);
622
623         /* Fill in the name. */
624         zhp->zfs_hdl = parent->zfs_hdl;
625         (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
626
627         /* Set the property lists. */
628         if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
629                 free(zhp);
630                 return (NULL);
631         }
632
633         /* Set the types. */
634         zhp->zfs_head_type = parent->zfs_head_type;
635         zhp->zfs_type = ZFS_TYPE_BOOKMARK;
636
637         if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) {
638                 nvlist_free(zhp->zfs_props);
639                 free(zhp);
640                 return (NULL);
641         }
642
643         return (zhp);
644 }
645
646 /*
647  * Opens the given snapshot, filesystem, or volume.   The 'types'
648  * argument is a mask of acceptable types.  The function will print an
649  * appropriate error message and return NULL if it can't be opened.
650  */
651 zfs_handle_t *
652 zfs_open(libzfs_handle_t *hdl, const char *path, int types)
653 {
654         zfs_handle_t *zhp;
655         char errbuf[1024];
656
657         (void) snprintf(errbuf, sizeof (errbuf),
658             dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
659
660         /*
661          * Validate the name before we even try to open it.
662          */
663         if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
664                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
665                     "invalid dataset name"));
666                 (void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
667                 return (NULL);
668         }
669
670         /*
671          * Try to get stats for the dataset, which will tell us if it exists.
672          */
673         errno = 0;
674         if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
675                 (void) zfs_standard_error(hdl, errno, errbuf);
676                 return (NULL);
677         }
678
679         if (zhp == NULL) {
680                 char *at = strchr(path, '@');
681
682                 if (at != NULL)
683                         *at = '\0';
684                 errno = 0;
685                 if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
686                         (void) zfs_standard_error(hdl, errno, errbuf);
687                         return (NULL);
688                 }
689                 if (at != NULL)
690                         *at = '@';
691                 (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
692                 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
693         }
694
695         if (!(types & zhp->zfs_type)) {
696                 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
697                 zfs_close(zhp);
698                 return (NULL);
699         }
700
701         return (zhp);
702 }
703
704 /*
705  * Release a ZFS handle.  Nothing to do but free the associated memory.
706  */
707 void
708 zfs_close(zfs_handle_t *zhp)
709 {
710         if (zhp->zfs_mntopts)
711                 free(zhp->zfs_mntopts);
712         nvlist_free(zhp->zfs_props);
713         nvlist_free(zhp->zfs_user_props);
714         nvlist_free(zhp->zfs_recvd_props);
715         free(zhp);
716 }
717
718 typedef struct mnttab_node {
719         struct mnttab mtn_mt;
720         avl_node_t mtn_node;
721 } mnttab_node_t;
722
723 static int
724 libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
725 {
726         const mnttab_node_t *mtn1 = arg1;
727         const mnttab_node_t *mtn2 = arg2;
728         int rv;
729
730         rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
731
732         if (rv == 0)
733                 return (0);
734         return (rv > 0 ? 1 : -1);
735 }
736
737 void
738 libzfs_mnttab_init(libzfs_handle_t *hdl)
739 {
740         assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
741         avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
742             sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
743 }
744
745 void
746 libzfs_mnttab_update(libzfs_handle_t *hdl)
747 {
748         struct mnttab entry;
749
750         rewind(hdl->libzfs_mnttab);
751         while (getmntent(hdl->libzfs_mnttab, &entry) == 0) {
752                 mnttab_node_t *mtn;
753
754                 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
755                         continue;
756                 mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
757                 mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
758                 mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
759                 mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
760                 mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
761                 avl_add(&hdl->libzfs_mnttab_cache, mtn);
762         }
763 }
764
765 void
766 libzfs_mnttab_fini(libzfs_handle_t *hdl)
767 {
768         void *cookie = NULL;
769         mnttab_node_t *mtn;
770
771         while (mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) {
772                 free(mtn->mtn_mt.mnt_special);
773                 free(mtn->mtn_mt.mnt_mountp);
774                 free(mtn->mtn_mt.mnt_fstype);
775                 free(mtn->mtn_mt.mnt_mntopts);
776                 free(mtn);
777         }
778         avl_destroy(&hdl->libzfs_mnttab_cache);
779 }
780
781 void
782 libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
783 {
784         hdl->libzfs_mnttab_enable = enable;
785 }
786
787 int
788 libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
789     struct mnttab *entry)
790 {
791         mnttab_node_t find;
792         mnttab_node_t *mtn;
793
794         if (!hdl->libzfs_mnttab_enable) {
795                 struct mnttab srch = { 0 };
796
797                 if (avl_numnodes(&hdl->libzfs_mnttab_cache))
798                         libzfs_mnttab_fini(hdl);
799                 rewind(hdl->libzfs_mnttab);
800                 srch.mnt_special = (char *)fsname;
801                 srch.mnt_fstype = MNTTYPE_ZFS;
802                 if (getmntany(hdl->libzfs_mnttab, entry, &srch) == 0)
803                         return (0);
804                 else
805                         return (ENOENT);
806         }
807
808         if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
809                 libzfs_mnttab_update(hdl);
810
811         find.mtn_mt.mnt_special = (char *)fsname;
812         mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
813         if (mtn) {
814                 *entry = mtn->mtn_mt;
815                 return (0);
816         }
817         return (ENOENT);
818 }
819
820 void
821 libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
822     const char *mountp, const char *mntopts)
823 {
824         mnttab_node_t *mtn;
825
826         if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
827                 return;
828         mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
829         mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
830         mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
831         mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
832         mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
833         avl_add(&hdl->libzfs_mnttab_cache, mtn);
834 }
835
836 void
837 libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
838 {
839         mnttab_node_t find;
840         mnttab_node_t *ret;
841
842         find.mtn_mt.mnt_special = (char *)fsname;
843         if (ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) {
844                 avl_remove(&hdl->libzfs_mnttab_cache, ret);
845                 free(ret->mtn_mt.mnt_special);
846                 free(ret->mtn_mt.mnt_mountp);
847                 free(ret->mtn_mt.mnt_fstype);
848                 free(ret->mtn_mt.mnt_mntopts);
849                 free(ret);
850         }
851 }
852
853 int
854 zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
855 {
856         zpool_handle_t *zpool_handle = zhp->zpool_hdl;
857
858         if (zpool_handle == NULL)
859                 return (-1);
860
861         *spa_version = zpool_get_prop_int(zpool_handle,
862             ZPOOL_PROP_VERSION, NULL);
863         return (0);
864 }
865
866 /*
867  * The choice of reservation property depends on the SPA version.
868  */
869 static int
870 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
871 {
872         int spa_version;
873
874         if (zfs_spa_version(zhp, &spa_version) < 0)
875                 return (-1);
876
877         if (spa_version >= SPA_VERSION_REFRESERVATION)
878                 *resv_prop = ZFS_PROP_REFRESERVATION;
879         else
880                 *resv_prop = ZFS_PROP_RESERVATION;
881
882         return (0);
883 }
884
885 /*
886  * Given an nvlist of properties to set, validates that they are correct, and
887  * parses any numeric properties (index, boolean, etc) if they are specified as
888  * strings.
889  */
890 nvlist_t *
891 zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
892     uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
893 {
894         nvpair_t *elem;
895         uint64_t intval;
896         char *strval;
897         zfs_prop_t prop;
898         nvlist_t *ret;
899         int chosen_normal = -1;
900         int chosen_utf = -1;
901
902         if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
903                 (void) no_memory(hdl);
904                 return (NULL);
905         }
906
907         /*
908          * Make sure this property is valid and applies to this type.
909          */
910
911         elem = NULL;
912         while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
913                 const char *propname = nvpair_name(elem);
914
915                 prop = zfs_name_to_prop(propname);
916                 if (prop == ZPROP_INVAL && zfs_prop_user(propname)) {
917                         /*
918                          * This is a user property: make sure it's a
919                          * string, and that it's less than ZAP_MAXNAMELEN.
920                          */
921                         if (nvpair_type(elem) != DATA_TYPE_STRING) {
922                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
923                                     "'%s' must be a string"), propname);
924                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
925                                 goto error;
926                         }
927
928                         if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
929                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
930                                     "property name '%s' is too long"),
931                                     propname);
932                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
933                                 goto error;
934                         }
935
936                         (void) nvpair_value_string(elem, &strval);
937                         if (nvlist_add_string(ret, propname, strval) != 0) {
938                                 (void) no_memory(hdl);
939                                 goto error;
940                         }
941                         continue;
942                 }
943
944                 /*
945                  * Currently, only user properties can be modified on
946                  * snapshots.
947                  */
948                 if (type == ZFS_TYPE_SNAPSHOT) {
949                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
950                             "this property can not be modified for snapshots"));
951                         (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
952                         goto error;
953                 }
954
955                 if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) {
956                         zfs_userquota_prop_t uqtype;
957                         char newpropname[128];
958                         char domain[128];
959                         uint64_t rid;
960                         uint64_t valary[3];
961
962                         if (userquota_propname_decode(propname, zoned,
963                             &uqtype, domain, sizeof (domain), &rid) != 0) {
964                                 zfs_error_aux(hdl,
965                                     dgettext(TEXT_DOMAIN,
966                                     "'%s' has an invalid user/group name"),
967                                     propname);
968                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
969                                 goto error;
970                         }
971
972                         if (uqtype != ZFS_PROP_USERQUOTA &&
973                             uqtype != ZFS_PROP_GROUPQUOTA) {
974                                 zfs_error_aux(hdl,
975                                     dgettext(TEXT_DOMAIN, "'%s' is readonly"),
976                                     propname);
977                                 (void) zfs_error(hdl, EZFS_PROPREADONLY,
978                                     errbuf);
979                                 goto error;
980                         }
981
982                         if (nvpair_type(elem) == DATA_TYPE_STRING) {
983                                 (void) nvpair_value_string(elem, &strval);
984                                 if (strcmp(strval, "none") == 0) {
985                                         intval = 0;
986                                 } else if (zfs_nicestrtonum(hdl,
987                                     strval, &intval) != 0) {
988                                         (void) zfs_error(hdl,
989                                             EZFS_BADPROP, errbuf);
990                                         goto error;
991                                 }
992                         } else if (nvpair_type(elem) ==
993                             DATA_TYPE_UINT64) {
994                                 (void) nvpair_value_uint64(elem, &intval);
995                                 if (intval == 0) {
996                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
997                                             "use 'none' to disable "
998                                             "userquota/groupquota"));
999                                         goto error;
1000                                 }
1001                         } else {
1002                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1003                                     "'%s' must be a number"), propname);
1004                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1005                                 goto error;
1006                         }
1007
1008                         /*
1009                          * Encode the prop name as
1010                          * userquota@<hex-rid>-domain, to make it easy
1011                          * for the kernel to decode.
1012                          */
1013                         (void) snprintf(newpropname, sizeof (newpropname),
1014                             "%s%llx-%s", zfs_userquota_prop_prefixes[uqtype],
1015                             (longlong_t)rid, domain);
1016                         valary[0] = uqtype;
1017                         valary[1] = rid;
1018                         valary[2] = intval;
1019                         if (nvlist_add_uint64_array(ret, newpropname,
1020                             valary, 3) != 0) {
1021                                 (void) no_memory(hdl);
1022                                 goto error;
1023                         }
1024                         continue;
1025                 } else if (prop == ZPROP_INVAL && zfs_prop_written(propname)) {
1026                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1027                             "'%s' is readonly"),
1028                             propname);
1029                         (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
1030                         goto error;
1031                 }
1032
1033                 if (prop == ZPROP_INVAL) {
1034                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1035                             "invalid property '%s'"), propname);
1036                         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1037                         goto error;
1038                 }
1039
1040                 if (!zfs_prop_valid_for_type(prop, type)) {
1041                         zfs_error_aux(hdl,
1042                             dgettext(TEXT_DOMAIN, "'%s' does not "
1043                             "apply to datasets of this type"), propname);
1044                         (void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
1045                         goto error;
1046                 }
1047
1048                 if (zfs_prop_readonly(prop) &&
1049                     (!zfs_prop_setonce(prop) || zhp != NULL)) {
1050                         zfs_error_aux(hdl,
1051                             dgettext(TEXT_DOMAIN, "'%s' is readonly"),
1052                             propname);
1053                         (void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
1054                         goto error;
1055                 }
1056
1057                 if (zprop_parse_value(hdl, elem, prop, type, ret,
1058                     &strval, &intval, errbuf) != 0)
1059                         goto error;
1060
1061                 /*
1062                  * Perform some additional checks for specific properties.
1063                  */
1064                 switch (prop) {
1065                 case ZFS_PROP_VERSION:
1066                 {
1067                         int version;
1068
1069                         if (zhp == NULL)
1070                                 break;
1071                         version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
1072                         if (intval < version) {
1073                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1074                                     "Can not downgrade; already at version %u"),
1075                                     version);
1076                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1077                                 goto error;
1078                         }
1079                         break;
1080                 }
1081
1082                 case ZFS_PROP_RECORDSIZE:
1083                 case ZFS_PROP_VOLBLOCKSIZE:
1084                         /* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
1085                         if (intval < SPA_MINBLOCKSIZE ||
1086                             intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) {
1087                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1088                                     "'%s' must be power of 2 from %u "
1089                                     "to %uk"), propname,
1090                                     (uint_t)SPA_MINBLOCKSIZE,
1091                                     (uint_t)SPA_MAXBLOCKSIZE >> 10);
1092                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1093                                 goto error;
1094                         }
1095                         break;
1096
1097                 case ZFS_PROP_MLSLABEL:
1098                 {
1099 #ifdef sun
1100                         /*
1101                          * Verify the mlslabel string and convert to
1102                          * internal hex label string.
1103                          */
1104
1105                         m_label_t *new_sl;
1106                         char *hex = NULL;       /* internal label string */
1107
1108                         /* Default value is already OK. */
1109                         if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
1110                                 break;
1111
1112                         /* Verify the label can be converted to binary form */
1113                         if (((new_sl = m_label_alloc(MAC_LABEL)) == NULL) ||
1114                             (str_to_label(strval, &new_sl, MAC_LABEL,
1115                             L_NO_CORRECTION, NULL) == -1)) {
1116                                 goto badlabel;
1117                         }
1118
1119                         /* Now translate to hex internal label string */
1120                         if (label_to_str(new_sl, &hex, M_INTERNAL,
1121                             DEF_NAMES) != 0) {
1122                                 if (hex)
1123                                         free(hex);
1124                                 goto badlabel;
1125                         }
1126                         m_label_free(new_sl);
1127
1128                         /* If string is already in internal form, we're done. */
1129                         if (strcmp(strval, hex) == 0) {
1130                                 free(hex);
1131                                 break;
1132                         }
1133
1134                         /* Replace the label string with the internal form. */
1135                         (void) nvlist_remove(ret, zfs_prop_to_name(prop),
1136                             DATA_TYPE_STRING);
1137                         verify(nvlist_add_string(ret, zfs_prop_to_name(prop),
1138                             hex) == 0);
1139                         free(hex);
1140
1141                         break;
1142
1143 badlabel:
1144                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1145                             "invalid mlslabel '%s'"), strval);
1146                         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1147                         m_label_free(new_sl);   /* OK if null */
1148 #else   /* !sun */
1149                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1150                             "mlslabel is not supported on FreeBSD"));
1151                         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1152 #endif  /* !sun */
1153                         goto error;
1154
1155                 }
1156
1157                 case ZFS_PROP_MOUNTPOINT:
1158                 {
1159                         namecheck_err_t why;
1160
1161                         if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
1162                             strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
1163                                 break;
1164
1165                         if (mountpoint_namecheck(strval, &why)) {
1166                                 switch (why) {
1167                                 case NAME_ERR_LEADING_SLASH:
1168                                         zfs_error_aux(hdl,
1169                                             dgettext(TEXT_DOMAIN,
1170                                             "'%s' must be an absolute path, "
1171                                             "'none', or 'legacy'"), propname);
1172                                         break;
1173                                 case NAME_ERR_TOOLONG:
1174                                         zfs_error_aux(hdl,
1175                                             dgettext(TEXT_DOMAIN,
1176                                             "component of '%s' is too long"),
1177                                             propname);
1178                                         break;
1179                                 }
1180                                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1181                                 goto error;
1182                         }
1183                 }
1184
1185                         /*FALLTHRU*/
1186
1187                 case ZFS_PROP_SHARESMB:
1188                 case ZFS_PROP_SHARENFS:
1189                         /*
1190                          * For the mountpoint and sharenfs or sharesmb
1191                          * properties, check if it can be set in a
1192                          * global/non-global zone based on
1193                          * the zoned property value:
1194                          *
1195                          *              global zone         non-global zone
1196                          * --------------------------------------------------
1197                          * zoned=on     mountpoint (no)     mountpoint (yes)
1198                          *              sharenfs (no)       sharenfs (no)
1199                          *              sharesmb (no)       sharesmb (no)
1200                          *
1201                          * zoned=off    mountpoint (yes)        N/A
1202                          *              sharenfs (yes)
1203                          *              sharesmb (yes)
1204                          */
1205                         if (zoned) {
1206                                 if (getzoneid() == GLOBAL_ZONEID) {
1207                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1208                                             "'%s' cannot be set on "
1209                                             "dataset in a non-global zone"),
1210                                             propname);
1211                                         (void) zfs_error(hdl, EZFS_ZONED,
1212                                             errbuf);
1213                                         goto error;
1214                                 } else if (prop == ZFS_PROP_SHARENFS ||
1215                                     prop == ZFS_PROP_SHARESMB) {
1216                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1217                                             "'%s' cannot be set in "
1218                                             "a non-global zone"), propname);
1219                                         (void) zfs_error(hdl, EZFS_ZONED,
1220                                             errbuf);
1221                                         goto error;
1222                                 }
1223                         } else if (getzoneid() != GLOBAL_ZONEID) {
1224                                 /*
1225                                  * If zoned property is 'off', this must be in
1226                                  * a global zone. If not, something is wrong.
1227                                  */
1228                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1229                                     "'%s' cannot be set while dataset "
1230                                     "'zoned' property is set"), propname);
1231                                 (void) zfs_error(hdl, EZFS_ZONED, errbuf);
1232                                 goto error;
1233                         }
1234
1235                         /*
1236                          * At this point, it is legitimate to set the
1237                          * property. Now we want to make sure that the
1238                          * property value is valid if it is sharenfs.
1239                          */
1240                         if ((prop == ZFS_PROP_SHARENFS ||
1241                             prop == ZFS_PROP_SHARESMB) &&
1242                             strcmp(strval, "on") != 0 &&
1243                             strcmp(strval, "off") != 0) {
1244                                 zfs_share_proto_t proto;
1245
1246                                 if (prop == ZFS_PROP_SHARESMB)
1247                                         proto = PROTO_SMB;
1248                                 else
1249                                         proto = PROTO_NFS;
1250
1251                                 /*
1252                                  * Must be an valid sharing protocol
1253                                  * option string so init the libshare
1254                                  * in order to enable the parser and
1255                                  * then parse the options. We use the
1256                                  * control API since we don't care about
1257                                  * the current configuration and don't
1258                                  * want the overhead of loading it
1259                                  * until we actually do something.
1260                                  */
1261
1262                                 if (zfs_init_libshare(hdl,
1263                                     SA_INIT_CONTROL_API) != SA_OK) {
1264                                         /*
1265                                          * An error occurred so we can't do
1266                                          * anything
1267                                          */
1268                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1269                                             "'%s' cannot be set: problem "
1270                                             "in share initialization"),
1271                                             propname);
1272                                         (void) zfs_error(hdl, EZFS_BADPROP,
1273                                             errbuf);
1274                                         goto error;
1275                                 }
1276
1277                                 if (zfs_parse_options(strval, proto) != SA_OK) {
1278                                         /*
1279                                          * There was an error in parsing so
1280                                          * deal with it by issuing an error
1281                                          * message and leaving after
1282                                          * uninitializing the the libshare
1283                                          * interface.
1284                                          */
1285                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1286                                             "'%s' cannot be set to invalid "
1287                                             "options"), propname);
1288                                         (void) zfs_error(hdl, EZFS_BADPROP,
1289                                             errbuf);
1290                                         zfs_uninit_libshare(hdl);
1291                                         goto error;
1292                                 }
1293                                 zfs_uninit_libshare(hdl);
1294                         }
1295
1296                         break;
1297                 case ZFS_PROP_UTF8ONLY:
1298                         chosen_utf = (int)intval;
1299                         break;
1300                 case ZFS_PROP_NORMALIZE:
1301                         chosen_normal = (int)intval;
1302                         break;
1303                 }
1304
1305                 /*
1306                  * For changes to existing volumes, we have some additional
1307                  * checks to enforce.
1308                  */
1309                 if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1310                         uint64_t volsize = zfs_prop_get_int(zhp,
1311                             ZFS_PROP_VOLSIZE);
1312                         uint64_t blocksize = zfs_prop_get_int(zhp,
1313                             ZFS_PROP_VOLBLOCKSIZE);
1314                         char buf[64];
1315
1316                         switch (prop) {
1317                         case ZFS_PROP_RESERVATION:
1318                         case ZFS_PROP_REFRESERVATION:
1319                                 if (intval > volsize) {
1320                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1321                                             "'%s' is greater than current "
1322                                             "volume size"), propname);
1323                                         (void) zfs_error(hdl, EZFS_BADPROP,
1324                                             errbuf);
1325                                         goto error;
1326                                 }
1327                                 break;
1328
1329                         case ZFS_PROP_VOLSIZE:
1330                                 if (intval % blocksize != 0) {
1331                                         zfs_nicenum(blocksize, buf,
1332                                             sizeof (buf));
1333                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1334                                             "'%s' must be a multiple of "
1335                                             "volume block size (%s)"),
1336                                             propname, buf);
1337                                         (void) zfs_error(hdl, EZFS_BADPROP,
1338                                             errbuf);
1339                                         goto error;
1340                                 }
1341
1342                                 if (intval == 0) {
1343                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1344                                             "'%s' cannot be zero"),
1345                                             propname);
1346                                         (void) zfs_error(hdl, EZFS_BADPROP,
1347                                             errbuf);
1348                                         goto error;
1349                                 }
1350                                 break;
1351                         }
1352                 }
1353         }
1354
1355         /*
1356          * If normalization was chosen, but no UTF8 choice was made,
1357          * enforce rejection of non-UTF8 names.
1358          *
1359          * If normalization was chosen, but rejecting non-UTF8 names
1360          * was explicitly not chosen, it is an error.
1361          */
1362         if (chosen_normal > 0 && chosen_utf < 0) {
1363                 if (nvlist_add_uint64(ret,
1364                     zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
1365                         (void) no_memory(hdl);
1366                         goto error;
1367                 }
1368         } else if (chosen_normal > 0 && chosen_utf == 0) {
1369                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1370                     "'%s' must be set 'on' if normalization chosen"),
1371                     zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
1372                 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1373                 goto error;
1374         }
1375         return (ret);
1376
1377 error:
1378         nvlist_free(ret);
1379         return (NULL);
1380 }
1381
1382 int
1383 zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1384 {
1385         uint64_t old_volsize;
1386         uint64_t new_volsize;
1387         uint64_t old_reservation;
1388         uint64_t new_reservation;
1389         zfs_prop_t resv_prop;
1390
1391         /*
1392          * If this is an existing volume, and someone is setting the volsize,
1393          * make sure that it matches the reservation, or add it if necessary.
1394          */
1395         old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1396         if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
1397                 return (-1);
1398         old_reservation = zfs_prop_get_int(zhp, resv_prop);
1399         if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) !=
1400             old_reservation) || nvlist_lookup_uint64(nvl,
1401             zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) {
1402                 return (0);
1403         }
1404         if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1405             &new_volsize) != 0)
1406                 return (-1);
1407         new_reservation = zvol_volsize_to_reservation(new_volsize,
1408             zhp->zfs_props);
1409         if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
1410             new_reservation) != 0) {
1411                 (void) no_memory(zhp->zfs_hdl);
1412                 return (-1);
1413         }
1414         return (1);
1415 }
1416
1417 void
1418 zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
1419     char *errbuf)
1420 {
1421         switch (err) {
1422
1423         case ENOSPC:
1424                 /*
1425                  * For quotas and reservations, ENOSPC indicates
1426                  * something different; setting a quota or reservation
1427                  * doesn't use any disk space.
1428                  */
1429                 switch (prop) {
1430                 case ZFS_PROP_QUOTA:
1431                 case ZFS_PROP_REFQUOTA:
1432                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1433                             "size is less than current used or "
1434                             "reserved space"));
1435                         (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1436                         break;
1437
1438                 case ZFS_PROP_RESERVATION:
1439                 case ZFS_PROP_REFRESERVATION:
1440                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1441                             "size is greater than available space"));
1442                         (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1443                         break;
1444
1445                 default:
1446                         (void) zfs_standard_error(hdl, err, errbuf);
1447                         break;
1448                 }
1449                 break;
1450
1451         case EBUSY:
1452                 (void) zfs_standard_error(hdl, EBUSY, errbuf);
1453                 break;
1454
1455         case EROFS:
1456                 (void) zfs_error(hdl, EZFS_DSREADONLY, errbuf);
1457                 break;
1458
1459         case ENOTSUP:
1460                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1461                     "pool and or dataset must be upgraded to set this "
1462                     "property or value"));
1463                 (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
1464                 break;
1465
1466         case ERANGE:
1467                 if (prop == ZFS_PROP_COMPRESSION) {
1468                         (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1469                             "property setting is not allowed on "
1470                             "bootable datasets"));
1471                         (void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
1472                 } else {
1473                         (void) zfs_standard_error(hdl, err, errbuf);
1474                 }
1475                 break;
1476
1477         case EINVAL:
1478                 if (prop == ZPROP_INVAL) {
1479                         (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1480                 } else {
1481                         (void) zfs_standard_error(hdl, err, errbuf);
1482                 }
1483                 break;
1484
1485         case EOVERFLOW:
1486                 /*
1487                  * This platform can't address a volume this big.
1488                  */
1489 #ifdef _ILP32
1490                 if (prop == ZFS_PROP_VOLSIZE) {
1491                         (void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf);
1492                         break;
1493                 }
1494 #endif
1495                 /* FALLTHROUGH */
1496         default:
1497                 (void) zfs_standard_error(hdl, err, errbuf);
1498         }
1499 }
1500
1501 /*
1502  * Given a property name and value, set the property for the given dataset.
1503  */
1504 int
1505 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1506 {
1507         zfs_cmd_t zc = { 0 };
1508         int ret = -1;
1509         prop_changelist_t *cl = NULL;
1510         char errbuf[1024];
1511         libzfs_handle_t *hdl = zhp->zfs_hdl;
1512         nvlist_t *nvl = NULL, *realprops;
1513         zfs_prop_t prop;
1514         boolean_t do_prefix = B_TRUE;
1515         int added_resv;
1516
1517         (void) snprintf(errbuf, sizeof (errbuf),
1518             dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1519             zhp->zfs_name);
1520
1521         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1522             nvlist_add_string(nvl, propname, propval) != 0) {
1523                 (void) no_memory(hdl);
1524                 goto error;
1525         }
1526
1527         if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1528             zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1529                 goto error;
1530
1531         nvlist_free(nvl);
1532         nvl = realprops;
1533
1534         prop = zfs_name_to_prop(propname);
1535
1536         /* We don't support those properties on FreeBSD. */
1537         switch (prop) {
1538         case ZFS_PROP_DEVICES:
1539         case ZFS_PROP_ISCSIOPTIONS:
1540         case ZFS_PROP_XATTR:
1541         case ZFS_PROP_VSCAN:
1542         case ZFS_PROP_NBMAND:
1543         case ZFS_PROP_MLSLABEL:
1544                 (void) snprintf(errbuf, sizeof (errbuf),
1545                     "property '%s' not supported on FreeBSD", propname);
1546                 ret = zfs_error(hdl, EZFS_PERM, errbuf);
1547                 goto error;
1548         }
1549
1550         if (prop == ZFS_PROP_VOLSIZE) {
1551                 if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
1552                         goto error;
1553         }
1554
1555         if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1556                 goto error;
1557
1558         if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1559                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1560                     "child dataset with inherited mountpoint is used "
1561                     "in a non-global zone"));
1562                 ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1563                 goto error;
1564         }
1565
1566         /*
1567          * We don't want to unmount & remount the dataset when changing
1568          * its canmount property to 'on' or 'noauto'.  We only use
1569          * the changelist logic to unmount when setting canmount=off.
1570          */
1571         if (prop == ZFS_PROP_CANMOUNT) {
1572                 uint64_t idx;
1573                 int err = zprop_string_to_index(prop, propval, &idx,
1574                     ZFS_TYPE_DATASET);
1575                 if (err == 0 && idx != ZFS_CANMOUNT_OFF)
1576                         do_prefix = B_FALSE;
1577         }
1578
1579         if (do_prefix && (ret = changelist_prefix(cl)) != 0)
1580                 goto error;
1581
1582         /*
1583          * Execute the corresponding ioctl() to set this property.
1584          */
1585         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1586
1587         if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1588                 goto error;
1589
1590         ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1591
1592         if (ret != 0) {
1593                 zfs_setprop_error(hdl, prop, errno, errbuf);
1594                 if (added_resv && errno == ENOSPC) {
1595                         /* clean up the volsize property we tried to set */
1596                         uint64_t old_volsize = zfs_prop_get_int(zhp,
1597                             ZFS_PROP_VOLSIZE);
1598                         nvlist_free(nvl);
1599                         zcmd_free_nvlists(&zc);
1600                         if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
1601                                 goto error;
1602                         if (nvlist_add_uint64(nvl,
1603                             zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1604                             old_volsize) != 0)
1605                                 goto error;
1606                         if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1607                                 goto error;
1608                         (void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1609                 }
1610         } else {
1611                 if (do_prefix)
1612                         ret = changelist_postfix(cl);
1613
1614                 /*
1615                  * Refresh the statistics so the new property value
1616                  * is reflected.
1617                  */
1618                 if (ret == 0)
1619                         (void) get_stats(zhp);
1620         }
1621
1622 error:
1623         nvlist_free(nvl);
1624         zcmd_free_nvlists(&zc);
1625         if (cl)
1626                 changelist_free(cl);
1627         return (ret);
1628 }
1629
1630 /*
1631  * Given a property, inherit the value from the parent dataset, or if received
1632  * is TRUE, revert to the received value, if any.
1633  */
1634 int
1635 zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
1636 {
1637         zfs_cmd_t zc = { 0 };
1638         int ret;
1639         prop_changelist_t *cl;
1640         libzfs_handle_t *hdl = zhp->zfs_hdl;
1641         char errbuf[1024];
1642         zfs_prop_t prop;
1643
1644         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1645             "cannot inherit %s for '%s'"), propname, zhp->zfs_name);
1646
1647         zc.zc_cookie = received;
1648         if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
1649                 /*
1650                  * For user properties, the amount of work we have to do is very
1651                  * small, so just do it here.
1652                  */
1653                 if (!zfs_prop_user(propname)) {
1654                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1655                             "invalid property"));
1656                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
1657                 }
1658
1659                 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1660                 (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1661
1662                 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0)
1663                         return (zfs_standard_error(hdl, errno, errbuf));
1664
1665                 return (0);
1666         }
1667
1668         /*
1669          * Verify that this property is inheritable.
1670          */
1671         if (zfs_prop_readonly(prop))
1672                 return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf));
1673
1674         if (!zfs_prop_inheritable(prop) && !received)
1675                 return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
1676
1677         /*
1678          * Check to see if the value applies to this type
1679          */
1680         if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1681                 return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
1682
1683         /*
1684          * Normalize the name, to get rid of shorthand abbreviations.
1685          */
1686         propname = zfs_prop_to_name(prop);
1687         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1688         (void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1689
1690         if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID &&
1691             zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
1692                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1693                     "dataset is used in a non-global zone"));
1694                 return (zfs_error(hdl, EZFS_ZONED, errbuf));
1695         }
1696
1697         /*
1698          * Determine datasets which will be affected by this change, if any.
1699          */
1700         if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1701                 return (-1);
1702
1703         if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1704                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1705                     "child dataset with inherited mountpoint is used "
1706                     "in a non-global zone"));
1707                 ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1708                 goto error;
1709         }
1710
1711         if ((ret = changelist_prefix(cl)) != 0)
1712                 goto error;
1713
1714         if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) {
1715                 return (zfs_standard_error(hdl, errno, errbuf));
1716         } else {
1717
1718                 if ((ret = changelist_postfix(cl)) != 0)
1719                         goto error;
1720
1721                 /*
1722                  * Refresh the statistics so the new property is reflected.
1723                  */
1724                 (void) get_stats(zhp);
1725         }
1726
1727 error:
1728         changelist_free(cl);
1729         return (ret);
1730 }
1731
1732 /*
1733  * True DSL properties are stored in an nvlist.  The following two functions
1734  * extract them appropriately.
1735  */
1736 static uint64_t
1737 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1738 {
1739         nvlist_t *nv;
1740         uint64_t value;
1741
1742         *source = NULL;
1743         if (nvlist_lookup_nvlist(zhp->zfs_props,
1744             zfs_prop_to_name(prop), &nv) == 0) {
1745                 verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
1746                 (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
1747         } else {
1748                 verify(!zhp->zfs_props_table ||
1749                     zhp->zfs_props_table[prop] == B_TRUE);
1750                 value = zfs_prop_default_numeric(prop);
1751                 *source = "";
1752         }
1753
1754         return (value);
1755 }
1756
1757 static char *
1758 getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1759 {
1760         nvlist_t *nv;
1761         char *value;
1762
1763         *source = NULL;
1764         if (nvlist_lookup_nvlist(zhp->zfs_props,
1765             zfs_prop_to_name(prop), &nv) == 0) {
1766                 verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
1767                 (void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
1768         } else {
1769                 verify(!zhp->zfs_props_table ||
1770                     zhp->zfs_props_table[prop] == B_TRUE);
1771                 if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
1772                         value = "";
1773                 *source = "";
1774         }
1775
1776         return (value);
1777 }
1778
1779 static boolean_t
1780 zfs_is_recvd_props_mode(zfs_handle_t *zhp)
1781 {
1782         return (zhp->zfs_props == zhp->zfs_recvd_props);
1783 }
1784
1785 static void
1786 zfs_set_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
1787 {
1788         *cookie = (uint64_t)(uintptr_t)zhp->zfs_props;
1789         zhp->zfs_props = zhp->zfs_recvd_props;
1790 }
1791
1792 static void
1793 zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
1794 {
1795         zhp->zfs_props = (nvlist_t *)(uintptr_t)*cookie;
1796         *cookie = 0;
1797 }
1798
1799 /*
1800  * Internal function for getting a numeric property.  Both zfs_prop_get() and
1801  * zfs_prop_get_int() are built using this interface.
1802  *
1803  * Certain properties can be overridden using 'mount -o'.  In this case, scan
1804  * the contents of the /etc/mnttab entry, searching for the appropriate options.
1805  * If they differ from the on-disk values, report the current values and mark
1806  * the source "temporary".
1807  */
1808 static int
1809 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
1810     char **source, uint64_t *val)
1811 {
1812         zfs_cmd_t zc = { 0 };
1813         nvlist_t *zplprops = NULL;
1814         struct mnttab mnt;
1815         char *mntopt_on = NULL;
1816         char *mntopt_off = NULL;
1817         boolean_t received = zfs_is_recvd_props_mode(zhp);
1818
1819         *source = NULL;
1820
1821         switch (prop) {
1822         case ZFS_PROP_ATIME:
1823                 mntopt_on = MNTOPT_ATIME;
1824                 mntopt_off = MNTOPT_NOATIME;
1825                 break;
1826
1827         case ZFS_PROP_DEVICES:
1828                 mntopt_on = MNTOPT_DEVICES;
1829                 mntopt_off = MNTOPT_NODEVICES;
1830                 break;
1831
1832         case ZFS_PROP_EXEC:
1833                 mntopt_on = MNTOPT_EXEC;
1834                 mntopt_off = MNTOPT_NOEXEC;
1835                 break;
1836
1837         case ZFS_PROP_READONLY:
1838                 mntopt_on = MNTOPT_RO;
1839                 mntopt_off = MNTOPT_RW;
1840                 break;
1841
1842         case ZFS_PROP_SETUID:
1843                 mntopt_on = MNTOPT_SETUID;
1844                 mntopt_off = MNTOPT_NOSETUID;
1845                 break;
1846
1847         case ZFS_PROP_XATTR:
1848                 mntopt_on = MNTOPT_XATTR;
1849                 mntopt_off = MNTOPT_NOXATTR;
1850                 break;
1851
1852         case ZFS_PROP_NBMAND:
1853                 mntopt_on = MNTOPT_NBMAND;
1854                 mntopt_off = MNTOPT_NONBMAND;
1855                 break;
1856         }
1857
1858         /*
1859          * Because looking up the mount options is potentially expensive
1860          * (iterating over all of /etc/mnttab), we defer its calculation until
1861          * we're looking up a property which requires its presence.
1862          */
1863         if (!zhp->zfs_mntcheck &&
1864             (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
1865                 libzfs_handle_t *hdl = zhp->zfs_hdl;
1866                 struct mnttab entry;
1867
1868                 if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) {
1869                         zhp->zfs_mntopts = zfs_strdup(hdl,
1870                             entry.mnt_mntopts);
1871                         if (zhp->zfs_mntopts == NULL)
1872                                 return (-1);
1873                 }
1874
1875                 zhp->zfs_mntcheck = B_TRUE;
1876         }
1877
1878         if (zhp->zfs_mntopts == NULL)
1879                 mnt.mnt_mntopts = "";
1880         else
1881                 mnt.mnt_mntopts = zhp->zfs_mntopts;
1882
1883         switch (prop) {
1884         case ZFS_PROP_ATIME:
1885         case ZFS_PROP_DEVICES:
1886         case ZFS_PROP_EXEC:
1887         case ZFS_PROP_READONLY:
1888         case ZFS_PROP_SETUID:
1889         case ZFS_PROP_XATTR:
1890         case ZFS_PROP_NBMAND:
1891                 *val = getprop_uint64(zhp, prop, source);
1892
1893                 if (received)
1894                         break;
1895
1896                 if (hasmntopt(&mnt, mntopt_on) && !*val) {
1897                         *val = B_TRUE;
1898                         if (src)
1899                                 *src = ZPROP_SRC_TEMPORARY;
1900                 } else if (hasmntopt(&mnt, mntopt_off) && *val) {
1901                         *val = B_FALSE;
1902                         if (src)
1903                                 *src = ZPROP_SRC_TEMPORARY;
1904                 }
1905                 break;
1906
1907         case ZFS_PROP_CANMOUNT:
1908         case ZFS_PROP_VOLSIZE:
1909         case ZFS_PROP_QUOTA:
1910         case ZFS_PROP_REFQUOTA:
1911         case ZFS_PROP_RESERVATION:
1912         case ZFS_PROP_REFRESERVATION:
1913                 *val = getprop_uint64(zhp, prop, source);
1914
1915                 if (*source == NULL) {
1916                         /* not default, must be local */
1917                         *source = zhp->zfs_name;
1918                 }
1919                 break;
1920
1921         case ZFS_PROP_MOUNTED:
1922                 *val = (zhp->zfs_mntopts != NULL);
1923                 break;
1924
1925         case ZFS_PROP_NUMCLONES:
1926                 *val = zhp->zfs_dmustats.dds_num_clones;
1927                 break;
1928
1929         case ZFS_PROP_VERSION:
1930         case ZFS_PROP_NORMALIZE:
1931         case ZFS_PROP_UTF8ONLY:
1932         case ZFS_PROP_CASE:
1933                 if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
1934                     zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
1935                         return (-1);
1936                 (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1937                 if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
1938                         zcmd_free_nvlists(&zc);
1939                         return (-1);
1940                 }
1941                 if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
1942                     nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
1943                     val) != 0) {
1944                         zcmd_free_nvlists(&zc);
1945                         return (-1);
1946                 }
1947                 if (zplprops)
1948                         nvlist_free(zplprops);
1949                 zcmd_free_nvlists(&zc);
1950                 break;
1951
1952         case ZFS_PROP_INCONSISTENT:
1953                 *val = zhp->zfs_dmustats.dds_inconsistent;
1954                 break;
1955
1956         default:
1957                 switch (zfs_prop_get_type(prop)) {
1958                 case PROP_TYPE_NUMBER:
1959                 case PROP_TYPE_INDEX:
1960                         *val = getprop_uint64(zhp, prop, source);
1961                         /*
1962                          * If we tried to use a default value for a
1963                          * readonly property, it means that it was not
1964                          * present.
1965                          */
1966                         if (zfs_prop_readonly(prop) &&
1967                             *source != NULL && (*source)[0] == '\0') {
1968                                 *source = NULL;
1969                         }
1970                         break;
1971
1972                 case PROP_TYPE_STRING:
1973                 default:
1974                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
1975                             "cannot get non-numeric property"));
1976                         return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
1977                             dgettext(TEXT_DOMAIN, "internal error")));
1978                 }
1979         }
1980
1981         return (0);
1982 }
1983
1984 /*
1985  * Calculate the source type, given the raw source string.
1986  */
1987 static void
1988 get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
1989     char *statbuf, size_t statlen)
1990 {
1991         if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY)
1992                 return;
1993
1994         if (source == NULL) {
1995                 *srctype = ZPROP_SRC_NONE;
1996         } else if (source[0] == '\0') {
1997                 *srctype = ZPROP_SRC_DEFAULT;
1998         } else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) {
1999                 *srctype = ZPROP_SRC_RECEIVED;
2000         } else {
2001                 if (strcmp(source, zhp->zfs_name) == 0) {
2002                         *srctype = ZPROP_SRC_LOCAL;
2003                 } else {
2004                         (void) strlcpy(statbuf, source, statlen);
2005                         *srctype = ZPROP_SRC_INHERITED;
2006                 }
2007         }
2008
2009 }
2010
2011 int
2012 zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
2013     size_t proplen, boolean_t literal)
2014 {
2015         zfs_prop_t prop;
2016         int err = 0;
2017
2018         if (zhp->zfs_recvd_props == NULL)
2019                 if (get_recvd_props_ioctl(zhp) != 0)
2020                         return (-1);
2021
2022         prop = zfs_name_to_prop(propname);
2023
2024         if (prop != ZPROP_INVAL) {
2025                 uint64_t cookie;
2026                 if (!nvlist_exists(zhp->zfs_recvd_props, propname))
2027                         return (-1);
2028                 zfs_set_recvd_props_mode(zhp, &cookie);
2029                 err = zfs_prop_get(zhp, prop, propbuf, proplen,
2030                     NULL, NULL, 0, literal);
2031                 zfs_unset_recvd_props_mode(zhp, &cookie);
2032         } else {
2033                 nvlist_t *propval;
2034                 char *recvdval;
2035                 if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
2036                     propname, &propval) != 0)
2037                         return (-1);
2038                 verify(nvlist_lookup_string(propval, ZPROP_VALUE,
2039                     &recvdval) == 0);
2040                 (void) strlcpy(propbuf, recvdval, proplen);
2041         }
2042
2043         return (err == 0 ? 0 : -1);
2044 }
2045
2046 static int
2047 get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
2048 {
2049         nvlist_t *value;
2050         nvpair_t *pair;
2051
2052         value = zfs_get_clones_nvl(zhp);
2053         if (value == NULL)
2054                 return (-1);
2055
2056         propbuf[0] = '\0';
2057         for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
2058             pair = nvlist_next_nvpair(value, pair)) {
2059                 if (propbuf[0] != '\0')
2060                         (void) strlcat(propbuf, ",", proplen);
2061                 (void) strlcat(propbuf, nvpair_name(pair), proplen);
2062         }
2063
2064         return (0);
2065 }
2066
2067 struct get_clones_arg {
2068         uint64_t numclones;
2069         nvlist_t *value;
2070         const char *origin;
2071         char buf[ZFS_MAXNAMELEN];
2072 };
2073
2074 int
2075 get_clones_cb(zfs_handle_t *zhp, void *arg)
2076 {
2077         struct get_clones_arg *gca = arg;
2078
2079         if (gca->numclones == 0) {
2080                 zfs_close(zhp);
2081                 return (0);
2082         }
2083
2084         if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
2085             NULL, NULL, 0, B_TRUE) != 0)
2086                 goto out;
2087         if (strcmp(gca->buf, gca->origin) == 0) {
2088                 fnvlist_add_boolean(gca->value, zfs_get_name(zhp));
2089                 gca->numclones--;
2090         }
2091
2092 out:
2093         (void) zfs_iter_children(zhp, get_clones_cb, gca);
2094         zfs_close(zhp);
2095         return (0);
2096 }
2097
2098 nvlist_t *
2099 zfs_get_clones_nvl(zfs_handle_t *zhp)
2100 {
2101         nvlist_t *nv, *value;
2102
2103         if (nvlist_lookup_nvlist(zhp->zfs_props,
2104             zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
2105                 struct get_clones_arg gca;
2106
2107                 /*
2108                  * if this is a snapshot, then the kernel wasn't able
2109                  * to get the clones.  Do it by slowly iterating.
2110                  */
2111                 if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
2112                         return (NULL);
2113                 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
2114                         return (NULL);
2115                 if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
2116                         nvlist_free(nv);
2117                         return (NULL);
2118                 }
2119
2120                 gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
2121                 gca.value = value;
2122                 gca.origin = zhp->zfs_name;
2123
2124                 if (gca.numclones != 0) {
2125                         zfs_handle_t *root;
2126                         char pool[ZFS_MAXNAMELEN];
2127                         char *cp = pool;
2128
2129                         /* get the pool name */
2130                         (void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
2131                         (void) strsep(&cp, "/@");
2132                         root = zfs_open(zhp->zfs_hdl, pool,
2133                             ZFS_TYPE_FILESYSTEM);
2134
2135                         (void) get_clones_cb(root, &gca);
2136                 }
2137
2138                 if (gca.numclones != 0 ||
2139                     nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
2140                     nvlist_add_nvlist(zhp->zfs_props,
2141                     zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
2142                         nvlist_free(nv);
2143                         nvlist_free(value);
2144                         return (NULL);
2145                 }
2146                 nvlist_free(nv);
2147                 nvlist_free(value);
2148                 verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
2149                     zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
2150         }
2151
2152         verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
2153
2154         return (value);
2155 }
2156
2157 /*
2158  * Retrieve a property from the given object.  If 'literal' is specified, then
2159  * numbers are left as exact values.  Otherwise, numbers are converted to a
2160  * human-readable form.
2161  *
2162  * Returns 0 on success, or -1 on error.
2163  */
2164 int
2165 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
2166     zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
2167 {
2168         char *source = NULL;
2169         uint64_t val;
2170         char *str;
2171         const char *strval;
2172         boolean_t received = zfs_is_recvd_props_mode(zhp);
2173
2174         /*
2175          * Check to see if this property applies to our object
2176          */
2177         if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
2178                 return (-1);
2179
2180         if (received && zfs_prop_readonly(prop))
2181                 return (-1);
2182
2183         if (src)
2184                 *src = ZPROP_SRC_NONE;
2185
2186         switch (prop) {
2187         case ZFS_PROP_CREATION:
2188                 /*
2189                  * 'creation' is a time_t stored in the statistics.  We convert
2190                  * this into a string unless 'literal' is specified.
2191                  */
2192                 {
2193                         val = getprop_uint64(zhp, prop, &source);
2194                         time_t time = (time_t)val;
2195                         struct tm t;
2196
2197                         if (literal ||
2198                             localtime_r(&time, &t) == NULL ||
2199                             strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
2200                             &t) == 0)
2201                                 (void) snprintf(propbuf, proplen, "%llu", val);
2202                 }
2203                 break;
2204
2205         case ZFS_PROP_MOUNTPOINT:
2206                 /*
2207                  * Getting the precise mountpoint can be tricky.
2208                  *
2209                  *  - for 'none' or 'legacy', return those values.
2210                  *  - for inherited mountpoints, we want to take everything
2211                  *    after our ancestor and append it to the inherited value.
2212                  *
2213                  * If the pool has an alternate root, we want to prepend that
2214                  * root to any values we return.
2215                  */
2216
2217                 str = getprop_string(zhp, prop, &source);
2218
2219                 if (str[0] == '/') {
2220                         char buf[MAXPATHLEN];
2221                         char *root = buf;
2222                         const char *relpath;
2223
2224                         /*
2225                          * If we inherit the mountpoint, even from a dataset
2226                          * with a received value, the source will be the path of
2227                          * the dataset we inherit from. If source is
2228                          * ZPROP_SOURCE_VAL_RECVD, the received value is not
2229                          * inherited.
2230                          */
2231                         if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2232                                 relpath = "";
2233                         } else {
2234                                 relpath = zhp->zfs_name + strlen(source);
2235                                 if (relpath[0] == '/')
2236                                         relpath++;
2237                         }
2238
2239                         if ((zpool_get_prop(zhp->zpool_hdl,
2240                             ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
2241                             (strcmp(root, "-") == 0))
2242                                 root[0] = '\0';
2243                         /*
2244                          * Special case an alternate root of '/'. This will
2245                          * avoid having multiple leading slashes in the
2246                          * mountpoint path.
2247                          */
2248                         if (strcmp(root, "/") == 0)
2249                                 root++;
2250
2251                         /*
2252                          * If the mountpoint is '/' then skip over this
2253                          * if we are obtaining either an alternate root or
2254                          * an inherited mountpoint.
2255                          */
2256                         if (str[1] == '\0' && (root[0] != '\0' ||
2257                             relpath[0] != '\0'))
2258                                 str++;
2259
2260                         if (relpath[0] == '\0')
2261                                 (void) snprintf(propbuf, proplen, "%s%s",
2262                                     root, str);
2263                         else
2264                                 (void) snprintf(propbuf, proplen, "%s%s%s%s",
2265                                     root, str, relpath[0] == '@' ? "" : "/",
2266                                     relpath);
2267                 } else {
2268                         /* 'legacy' or 'none' */
2269                         (void) strlcpy(propbuf, str, proplen);
2270                 }
2271
2272                 break;
2273
2274         case ZFS_PROP_ORIGIN:
2275                 (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
2276                     proplen);
2277                 /*
2278                  * If there is no parent at all, return failure to indicate that
2279                  * it doesn't apply to this dataset.
2280                  */
2281                 if (propbuf[0] == '\0')
2282                         return (-1);
2283                 break;
2284
2285         case ZFS_PROP_CLONES:
2286                 if (get_clones_string(zhp, propbuf, proplen) != 0)
2287                         return (-1);
2288                 break;
2289
2290         case ZFS_PROP_QUOTA:
2291         case ZFS_PROP_REFQUOTA:
2292         case ZFS_PROP_RESERVATION:
2293         case ZFS_PROP_REFRESERVATION:
2294
2295                 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2296                         return (-1);
2297
2298                 /*
2299                  * If quota or reservation is 0, we translate this into 'none'
2300                  * (unless literal is set), and indicate that it's the default
2301                  * value.  Otherwise, we print the number nicely and indicate
2302                  * that its set locally.
2303                  */
2304                 if (val == 0) {
2305                         if (literal)
2306                                 (void) strlcpy(propbuf, "0", proplen);
2307                         else
2308                                 (void) strlcpy(propbuf, "none", proplen);
2309                 } else {
2310                         if (literal)
2311                                 (void) snprintf(propbuf, proplen, "%llu",
2312                                     (u_longlong_t)val);
2313                         else
2314                                 zfs_nicenum(val, propbuf, proplen);
2315                 }
2316                 break;
2317
2318         case ZFS_PROP_REFRATIO:
2319         case ZFS_PROP_COMPRESSRATIO:
2320                 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2321                         return (-1);
2322                 (void) snprintf(propbuf, proplen, "%llu.%02llux",
2323                     (u_longlong_t)(val / 100),
2324                     (u_longlong_t)(val % 100));
2325                 break;
2326
2327         case ZFS_PROP_TYPE:
2328                 switch (zhp->zfs_type) {
2329                 case ZFS_TYPE_FILESYSTEM:
2330                         str = "filesystem";
2331                         break;
2332                 case ZFS_TYPE_VOLUME:
2333                         str = "volume";
2334                         break;
2335                 case ZFS_TYPE_SNAPSHOT:
2336                         str = "snapshot";
2337                         break;
2338                 case ZFS_TYPE_BOOKMARK:
2339                         str = "bookmark";
2340                         break;
2341                 default:
2342                         abort();
2343                 }
2344                 (void) snprintf(propbuf, proplen, "%s", str);
2345                 break;
2346
2347         case ZFS_PROP_MOUNTED:
2348                 /*
2349                  * The 'mounted' property is a pseudo-property that described
2350                  * whether the filesystem is currently mounted.  Even though
2351                  * it's a boolean value, the typical values of "on" and "off"
2352                  * don't make sense, so we translate to "yes" and "no".
2353                  */
2354                 if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
2355                     src, &source, &val) != 0)
2356                         return (-1);
2357                 if (val)
2358                         (void) strlcpy(propbuf, "yes", proplen);
2359                 else
2360                         (void) strlcpy(propbuf, "no", proplen);
2361                 break;
2362
2363         case ZFS_PROP_NAME:
2364                 /*
2365                  * The 'name' property is a pseudo-property derived from the
2366                  * dataset name.  It is presented as a real property to simplify
2367                  * consumers.
2368                  */
2369                 (void) strlcpy(propbuf, zhp->zfs_name, proplen);
2370                 break;
2371
2372         case ZFS_PROP_MLSLABEL:
2373                 {
2374 #ifdef sun
2375                         m_label_t *new_sl = NULL;
2376                         char *ascii = NULL;     /* human readable label */
2377
2378                         (void) strlcpy(propbuf,
2379                             getprop_string(zhp, prop, &source), proplen);
2380
2381                         if (literal || (strcasecmp(propbuf,
2382                             ZFS_MLSLABEL_DEFAULT) == 0))
2383                                 break;
2384
2385                         /*
2386                          * Try to translate the internal hex string to
2387                          * human-readable output.  If there are any
2388                          * problems just use the hex string.
2389                          */
2390
2391                         if (str_to_label(propbuf, &new_sl, MAC_LABEL,
2392                             L_NO_CORRECTION, NULL) == -1) {
2393                                 m_label_free(new_sl);
2394                                 break;
2395                         }
2396
2397                         if (label_to_str(new_sl, &ascii, M_LABEL,
2398                             DEF_NAMES) != 0) {
2399                                 if (ascii)
2400                                         free(ascii);
2401                                 m_label_free(new_sl);
2402                                 break;
2403                         }
2404                         m_label_free(new_sl);
2405
2406                         (void) strlcpy(propbuf, ascii, proplen);
2407                         free(ascii);
2408 #else   /* !sun */
2409                         propbuf[0] = '\0';
2410 #endif  /* !sun */
2411                 }
2412                 break;
2413
2414         case ZFS_PROP_GUID:
2415                 /*
2416                  * GUIDs are stored as numbers, but they are identifiers.
2417                  * We don't want them to be pretty printed, because pretty
2418                  * printing mangles the ID into a truncated and useless value.
2419                  */
2420                 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2421                         return (-1);
2422                 (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
2423                 break;
2424
2425         default:
2426                 switch (zfs_prop_get_type(prop)) {
2427                 case PROP_TYPE_NUMBER:
2428                         if (get_numeric_property(zhp, prop, src,
2429                             &source, &val) != 0)
2430                                 return (-1);
2431                         if (literal)
2432                                 (void) snprintf(propbuf, proplen, "%llu",
2433                                     (u_longlong_t)val);
2434                         else
2435                                 zfs_nicenum(val, propbuf, proplen);
2436                         break;
2437
2438                 case PROP_TYPE_STRING:
2439                         (void) strlcpy(propbuf,
2440                             getprop_string(zhp, prop, &source), proplen);
2441                         break;
2442
2443                 case PROP_TYPE_INDEX:
2444                         if (get_numeric_property(zhp, prop, src,
2445                             &source, &val) != 0)
2446                                 return (-1);
2447                         if (zfs_prop_index_to_string(prop, val, &strval) != 0)
2448                                 return (-1);
2449                         (void) strlcpy(propbuf, strval, proplen);
2450                         break;
2451
2452                 default:
2453                         abort();
2454                 }
2455         }
2456
2457         get_source(zhp, src, source, statbuf, statlen);
2458
2459         return (0);
2460 }
2461
2462 /*
2463  * Utility function to get the given numeric property.  Does no validation that
2464  * the given property is the appropriate type; should only be used with
2465  * hard-coded property types.
2466  */
2467 uint64_t
2468 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
2469 {
2470         char *source;
2471         uint64_t val;
2472
2473         (void) get_numeric_property(zhp, prop, NULL, &source, &val);
2474
2475         return (val);
2476 }
2477
2478 int
2479 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
2480 {
2481         char buf[64];
2482
2483         (void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
2484         return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
2485 }
2486
2487 /*
2488  * Similar to zfs_prop_get(), but returns the value as an integer.
2489  */
2490 int
2491 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
2492     zprop_source_t *src, char *statbuf, size_t statlen)
2493 {
2494         char *source;
2495
2496         /*
2497          * Check to see if this property applies to our object
2498          */
2499         if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
2500                 return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
2501                     dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
2502                     zfs_prop_to_name(prop)));
2503         }
2504
2505         if (src)
2506                 *src = ZPROP_SRC_NONE;
2507
2508         if (get_numeric_property(zhp, prop, src, &source, value) != 0)
2509                 return (-1);
2510
2511         get_source(zhp, src, source, statbuf, statlen);
2512
2513         return (0);
2514 }
2515
2516 static int
2517 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
2518     char **domainp, idmap_rid_t *ridp)
2519 {
2520 #ifdef sun
2521         idmap_get_handle_t *get_hdl = NULL;
2522         idmap_stat status;
2523         int err = EINVAL;
2524
2525         if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
2526                 goto out;
2527
2528         if (isuser) {
2529                 err = idmap_get_sidbyuid(get_hdl, id,
2530                     IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2531         } else {
2532                 err = idmap_get_sidbygid(get_hdl, id,
2533                     IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2534         }
2535         if (err == IDMAP_SUCCESS &&
2536             idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
2537             status == IDMAP_SUCCESS)
2538                 err = 0;
2539         else
2540                 err = EINVAL;
2541 out:
2542         if (get_hdl)
2543                 idmap_get_destroy(get_hdl);
2544         return (err);
2545 #else   /* !sun */
2546         assert(!"invalid code path");
2547 #endif  /* !sun */
2548 }
2549
2550 /*
2551  * convert the propname into parameters needed by kernel
2552  * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
2553  * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
2554  */
2555 static int
2556 userquota_propname_decode(const char *propname, boolean_t zoned,
2557     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
2558 {
2559         zfs_userquota_prop_t type;
2560         char *cp, *end;
2561         char *numericsid = NULL;
2562         boolean_t isuser;
2563
2564         domain[0] = '\0';
2565
2566         /* Figure out the property type ({user|group}{quota|space}) */
2567         for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
2568                 if (strncmp(propname, zfs_userquota_prop_prefixes[type],
2569                     strlen(zfs_userquota_prop_prefixes[type])) == 0)
2570                         break;
2571         }
2572         if (type == ZFS_NUM_USERQUOTA_PROPS)
2573                 return (EINVAL);
2574         *typep = type;
2575
2576         isuser = (type == ZFS_PROP_USERQUOTA ||
2577             type == ZFS_PROP_USERUSED);
2578
2579         cp = strchr(propname, '@') + 1;
2580
2581         if (strchr(cp, '@')) {
2582 #ifdef sun
2583                 /*
2584                  * It's a SID name (eg "user@domain") that needs to be
2585                  * turned into S-1-domainID-RID.
2586                  */
2587                 directory_error_t e;
2588                 if (zoned && getzoneid() == GLOBAL_ZONEID)
2589                         return (ENOENT);
2590                 if (isuser) {
2591                         e = directory_sid_from_user_name(NULL,
2592                             cp, &numericsid);
2593                 } else {
2594                         e = directory_sid_from_group_name(NULL,
2595                             cp, &numericsid);
2596                 }
2597                 if (e != NULL) {
2598                         directory_error_free(e);
2599                         return (ENOENT);
2600                 }
2601                 if (numericsid == NULL)
2602                         return (ENOENT);
2603                 cp = numericsid;
2604                 /* will be further decoded below */
2605 #else   /* !sun */
2606                 return (ENOENT);
2607 #endif  /* !sun */
2608         }
2609
2610         if (strncmp(cp, "S-1-", 4) == 0) {
2611                 /* It's a numeric SID (eg "S-1-234-567-89") */
2612                 (void) strlcpy(domain, cp, domainlen);
2613                 cp = strrchr(domain, '-');
2614                 *cp = '\0';
2615                 cp++;
2616
2617                 errno = 0;
2618                 *ridp = strtoull(cp, &end, 10);
2619                 if (numericsid) {
2620                         free(numericsid);
2621                         numericsid = NULL;
2622                 }
2623                 if (errno != 0 || *end != '\0')
2624                         return (EINVAL);
2625         } else if (!isdigit(*cp)) {
2626                 /*
2627                  * It's a user/group name (eg "user") that needs to be
2628                  * turned into a uid/gid
2629                  */
2630                 if (zoned && getzoneid() == GLOBAL_ZONEID)
2631                         return (ENOENT);
2632                 if (isuser) {
2633                         struct passwd *pw;
2634                         pw = getpwnam(cp);
2635                         if (pw == NULL)
2636                                 return (ENOENT);
2637                         *ridp = pw->pw_uid;
2638                 } else {
2639                         struct group *gr;
2640                         gr = getgrnam(cp);
2641                         if (gr == NULL)
2642                                 return (ENOENT);
2643                         *ridp = gr->gr_gid;
2644                 }
2645         } else {
2646                 /* It's a user/group ID (eg "12345"). */
2647                 uid_t id = strtoul(cp, &end, 10);
2648                 idmap_rid_t rid;
2649                 char *mapdomain;
2650
2651                 if (*end != '\0')
2652                         return (EINVAL);
2653                 if (id > MAXUID) {
2654                         /* It's an ephemeral ID. */
2655                         if (idmap_id_to_numeric_domain_rid(id, isuser,
2656                             &mapdomain, &rid) != 0)
2657                                 return (ENOENT);
2658                         (void) strlcpy(domain, mapdomain, domainlen);
2659                         *ridp = rid;
2660                 } else {
2661                         *ridp = id;
2662                 }
2663         }
2664
2665         ASSERT3P(numericsid, ==, NULL);
2666         return (0);
2667 }
2668
2669 static int
2670 zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
2671     uint64_t *propvalue, zfs_userquota_prop_t *typep)
2672 {
2673         int err;
2674         zfs_cmd_t zc = { 0 };
2675
2676         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2677
2678         err = userquota_propname_decode(propname,
2679             zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
2680             typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
2681         zc.zc_objset_type = *typep;
2682         if (err)
2683                 return (err);
2684
2685         err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
2686         if (err)
2687                 return (err);
2688
2689         *propvalue = zc.zc_cookie;
2690         return (0);
2691 }
2692
2693 int
2694 zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
2695     uint64_t *propvalue)
2696 {
2697         zfs_userquota_prop_t type;
2698
2699         return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
2700             &type));
2701 }
2702
2703 int
2704 zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
2705     char *propbuf, int proplen, boolean_t literal)
2706 {
2707         int err;
2708         uint64_t propvalue;
2709         zfs_userquota_prop_t type;
2710
2711         err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
2712             &type);
2713
2714         if (err)
2715                 return (err);
2716
2717         if (literal) {
2718                 (void) snprintf(propbuf, proplen, "%llu", propvalue);
2719         } else if (propvalue == 0 &&
2720             (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
2721                 (void) strlcpy(propbuf, "none", proplen);
2722         } else {
2723                 zfs_nicenum(propvalue, propbuf, proplen);
2724         }
2725         return (0);
2726 }
2727
2728 int
2729 zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
2730     uint64_t *propvalue)
2731 {
2732         int err;
2733         zfs_cmd_t zc = { 0 };
2734         const char *snapname;
2735
2736         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2737
2738         snapname = strchr(propname, '@') + 1;
2739         if (strchr(snapname, '@')) {
2740                 (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
2741         } else {
2742                 /* snapname is the short name, append it to zhp's fsname */
2743                 char *cp;
2744
2745                 (void) strlcpy(zc.zc_value, zhp->zfs_name,
2746                     sizeof (zc.zc_value));
2747                 cp = strchr(zc.zc_value, '@');
2748                 if (cp != NULL)
2749                         *cp = '\0';
2750                 (void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
2751                 (void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
2752         }
2753
2754         err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
2755         if (err)
2756                 return (err);
2757
2758         *propvalue = zc.zc_cookie;
2759         return (0);
2760 }
2761
2762 int
2763 zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
2764     char *propbuf, int proplen, boolean_t literal)
2765 {
2766         int err;
2767         uint64_t propvalue;
2768
2769         err = zfs_prop_get_written_int(zhp, propname, &propvalue);
2770
2771         if (err)
2772                 return (err);
2773
2774         if (literal) {
2775                 (void) snprintf(propbuf, proplen, "%llu", propvalue);
2776         } else {
2777                 zfs_nicenum(propvalue, propbuf, proplen);
2778         }
2779         return (0);
2780 }
2781
2782 /*
2783  * Returns the name of the given zfs handle.
2784  */
2785 const char *
2786 zfs_get_name(const zfs_handle_t *zhp)
2787 {
2788         return (zhp->zfs_name);
2789 }
2790
2791 /*
2792  * Returns the type of the given zfs handle.
2793  */
2794 zfs_type_t
2795 zfs_get_type(const zfs_handle_t *zhp)
2796 {
2797         return (zhp->zfs_type);
2798 }
2799
2800 /*
2801  * Is one dataset name a child dataset of another?
2802  *
2803  * Needs to handle these cases:
2804  * Dataset 1    "a/foo"         "a/foo"         "a/foo"         "a/foo"
2805  * Dataset 2    "a/fo"          "a/foobar"      "a/bar/baz"     "a/foo/bar"
2806  * Descendant?  No.             No.             No.             Yes.
2807  */
2808 static boolean_t
2809 is_descendant(const char *ds1, const char *ds2)
2810 {
2811         size_t d1len = strlen(ds1);
2812
2813         /* ds2 can't be a descendant if it's smaller */
2814         if (strlen(ds2) < d1len)
2815                 return (B_FALSE);
2816
2817         /* otherwise, compare strings and verify that there's a '/' char */
2818         return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0));
2819 }
2820
2821 /*
2822  * Given a complete name, return just the portion that refers to the parent.
2823  * Will return -1 if there is no parent (path is just the name of the
2824  * pool).
2825  */
2826 static int
2827 parent_name(const char *path, char *buf, size_t buflen)
2828 {
2829         char *slashp;
2830
2831         (void) strlcpy(buf, path, buflen);
2832
2833         if ((slashp = strrchr(buf, '/')) == NULL)
2834                 return (-1);
2835         *slashp = '\0';
2836
2837         return (0);
2838 }
2839
2840 /*
2841  * If accept_ancestor is false, then check to make sure that the given path has
2842  * a parent, and that it exists.  If accept_ancestor is true, then find the
2843  * closest existing ancestor for the given path.  In prefixlen return the
2844  * length of already existing prefix of the given path.  We also fetch the
2845  * 'zoned' property, which is used to validate property settings when creating
2846  * new datasets.
2847  */
2848 static int
2849 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
2850     boolean_t accept_ancestor, int *prefixlen)
2851 {
2852         zfs_cmd_t zc = { 0 };
2853         char parent[ZFS_MAXNAMELEN];
2854         char *slash;
2855         zfs_handle_t *zhp;
2856         char errbuf[1024];
2857         uint64_t is_zoned;
2858
2859         (void) snprintf(errbuf, sizeof (errbuf),
2860             dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
2861
2862         /* get parent, and check to see if this is just a pool */
2863         if (parent_name(path, parent, sizeof (parent)) != 0) {
2864                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2865                     "missing dataset name"));
2866                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2867         }
2868
2869         /* check to see if the pool exists */
2870         if ((slash = strchr(parent, '/')) == NULL)
2871                 slash = parent + strlen(parent);
2872         (void) strncpy(zc.zc_name, parent, slash - parent);
2873         zc.zc_name[slash - parent] = '\0';
2874         if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
2875             errno == ENOENT) {
2876                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2877                     "no such pool '%s'"), zc.zc_name);
2878                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
2879         }
2880
2881         /* check to see if the parent dataset exists */
2882         while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
2883                 if (errno == ENOENT && accept_ancestor) {
2884                         /*
2885                          * Go deeper to find an ancestor, give up on top level.
2886                          */
2887                         if (parent_name(parent, parent, sizeof (parent)) != 0) {
2888                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2889                                     "no such pool '%s'"), zc.zc_name);
2890                                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
2891                         }
2892                 } else if (errno == ENOENT) {
2893                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2894                             "parent does not exist"));
2895                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
2896                 } else
2897                         return (zfs_standard_error(hdl, errno, errbuf));
2898         }
2899
2900         is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
2901         if (zoned != NULL)
2902                 *zoned = is_zoned;
2903
2904         /* we are in a non-global zone, but parent is in the global zone */
2905         if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
2906                 (void) zfs_standard_error(hdl, EPERM, errbuf);
2907                 zfs_close(zhp);
2908                 return (-1);
2909         }
2910
2911         /* make sure parent is a filesystem */
2912         if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2913                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2914                     "parent is not a filesystem"));
2915                 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
2916                 zfs_close(zhp);
2917                 return (-1);
2918         }
2919
2920         zfs_close(zhp);
2921         if (prefixlen != NULL)
2922                 *prefixlen = strlen(parent);
2923         return (0);
2924 }
2925
2926 /*
2927  * Finds whether the dataset of the given type(s) exists.
2928  */
2929 boolean_t
2930 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
2931 {
2932         zfs_handle_t *zhp;
2933
2934         if (!zfs_validate_name(hdl, path, types, B_FALSE))
2935                 return (B_FALSE);
2936
2937         /*
2938          * Try to get stats for the dataset, which will tell us if it exists.
2939          */
2940         if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
2941                 int ds_type = zhp->zfs_type;
2942
2943                 zfs_close(zhp);
2944                 if (types & ds_type)
2945                         return (B_TRUE);
2946         }
2947         return (B_FALSE);
2948 }
2949
2950 /*
2951  * Given a path to 'target', create all the ancestors between
2952  * the prefixlen portion of the path, and the target itself.
2953  * Fail if the initial prefixlen-ancestor does not already exist.
2954  */
2955 int
2956 create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
2957 {
2958         zfs_handle_t *h;
2959         char *cp;
2960         const char *opname;
2961
2962         /* make sure prefix exists */
2963         cp = target + prefixlen;
2964         if (*cp != '/') {
2965                 assert(strchr(cp, '/') == NULL);
2966                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2967         } else {
2968                 *cp = '\0';
2969                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2970                 *cp = '/';
2971         }
2972         if (h == NULL)
2973                 return (-1);
2974         zfs_close(h);
2975
2976         /*
2977          * Attempt to create, mount, and share any ancestor filesystems,
2978          * up to the prefixlen-long one.
2979          */
2980         for (cp = target + prefixlen + 1;
2981             cp = strchr(cp, '/'); *cp = '/', cp++) {
2982
2983                 *cp = '\0';
2984
2985                 h = make_dataset_handle(hdl, target);
2986                 if (h) {
2987                         /* it already exists, nothing to do here */
2988                         zfs_close(h);
2989                         continue;
2990                 }
2991
2992                 if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
2993                     NULL) != 0) {
2994                         opname = dgettext(TEXT_DOMAIN, "create");
2995                         goto ancestorerr;
2996                 }
2997
2998                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2999                 if (h == NULL) {
3000                         opname = dgettext(TEXT_DOMAIN, "open");
3001                         goto ancestorerr;
3002                 }
3003
3004                 if (zfs_mount(h, NULL, 0) != 0) {
3005                         opname = dgettext(TEXT_DOMAIN, "mount");
3006                         goto ancestorerr;
3007                 }
3008
3009                 if (zfs_share(h) != 0) {
3010                         opname = dgettext(TEXT_DOMAIN, "share");
3011                         goto ancestorerr;
3012                 }
3013
3014                 zfs_close(h);
3015         }
3016
3017         return (0);
3018
3019 ancestorerr:
3020         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3021             "failed to %s ancestor '%s'"), opname, target);
3022         return (-1);
3023 }
3024
3025 /*
3026  * Creates non-existing ancestors of the given path.
3027  */
3028 int
3029 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
3030 {
3031         int prefix;
3032         char *path_copy;
3033         int rc;
3034
3035         if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
3036                 return (-1);
3037
3038         if ((path_copy = strdup(path)) != NULL) {
3039                 rc = create_parents(hdl, path_copy, prefix);
3040                 free(path_copy);
3041         }
3042         if (path_copy == NULL || rc != 0)
3043                 return (-1);
3044
3045         return (0);
3046 }
3047
3048 /*
3049  * Create a new filesystem or volume.
3050  */
3051 int
3052 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
3053     nvlist_t *props)
3054 {
3055         int ret;
3056         uint64_t size = 0;
3057         uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
3058         char errbuf[1024];
3059         uint64_t zoned;
3060         dmu_objset_type_t ost;
3061
3062         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3063             "cannot create '%s'"), path);
3064
3065         /* validate the path, taking care to note the extended error message */
3066         if (!zfs_validate_name(hdl, path, type, B_TRUE))
3067                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3068
3069         /* validate parents exist */
3070         if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
3071                 return (-1);
3072
3073         /*
3074          * The failure modes when creating a dataset of a different type over
3075          * one that already exists is a little strange.  In particular, if you
3076          * try to create a dataset on top of an existing dataset, the ioctl()
3077          * will return ENOENT, not EEXIST.  To prevent this from happening, we
3078          * first try to see if the dataset exists.
3079          */
3080         if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
3081                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3082                     "dataset already exists"));
3083                 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3084         }
3085
3086         if (type == ZFS_TYPE_VOLUME)
3087                 ost = DMU_OST_ZVOL;
3088         else
3089                 ost = DMU_OST_ZFS;
3090
3091         if (props && (props = zfs_valid_proplist(hdl, type, props,
3092             zoned, NULL, errbuf)) == 0)
3093                 return (-1);
3094
3095         if (type == ZFS_TYPE_VOLUME) {
3096                 /*
3097                  * If we are creating a volume, the size and block size must
3098                  * satisfy a few restraints.  First, the blocksize must be a
3099                  * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
3100                  * volsize must be a multiple of the block size, and cannot be
3101                  * zero.
3102                  */
3103                 if (props == NULL || nvlist_lookup_uint64(props,
3104                     zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
3105                         nvlist_free(props);
3106                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3107                             "missing volume size"));
3108                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3109                 }
3110
3111                 if ((ret = nvlist_lookup_uint64(props,
3112                     zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3113                     &blocksize)) != 0) {
3114                         if (ret == ENOENT) {
3115                                 blocksize = zfs_prop_default_numeric(
3116                                     ZFS_PROP_VOLBLOCKSIZE);
3117                         } else {
3118                                 nvlist_free(props);
3119                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3120                                     "missing volume block size"));
3121                                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3122                         }
3123                 }
3124
3125                 if (size == 0) {
3126                         nvlist_free(props);
3127                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3128                             "volume size cannot be zero"));
3129                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3130                 }
3131
3132                 if (size % blocksize != 0) {
3133                         nvlist_free(props);
3134                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3135                             "volume size must be a multiple of volume block "
3136                             "size"));
3137                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3138                 }
3139         }
3140
3141         /* create the dataset */
3142         ret = lzc_create(path, ost, props);
3143         nvlist_free(props);
3144
3145         /* check for failure */
3146         if (ret != 0) {
3147                 char parent[ZFS_MAXNAMELEN];
3148                 (void) parent_name(path, parent, sizeof (parent));
3149
3150                 switch (errno) {
3151                 case ENOENT:
3152                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3153                             "no such parent '%s'"), parent);
3154                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
3155
3156                 case EINVAL:
3157                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3158                             "parent '%s' is not a filesystem"), parent);
3159                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3160
3161                 case EDOM:
3162                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3163                             "volume block size must be power of 2 from "
3164                             "%u to %uk"),
3165                             (uint_t)SPA_MINBLOCKSIZE,
3166                             (uint_t)SPA_MAXBLOCKSIZE >> 10);
3167
3168                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3169
3170                 case ENOTSUP:
3171                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3172                             "pool must be upgraded to set this "
3173                             "property or value"));
3174                         return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
3175 #ifdef _ILP32
3176                 case EOVERFLOW:
3177                         /*
3178                          * This platform can't address a volume this big.
3179                          */
3180                         if (type == ZFS_TYPE_VOLUME)
3181                                 return (zfs_error(hdl, EZFS_VOLTOOBIG,
3182                                     errbuf));
3183 #endif
3184                         /* FALLTHROUGH */
3185                 default:
3186                         return (zfs_standard_error(hdl, errno, errbuf));
3187                 }
3188         }
3189
3190         return (0);
3191 }
3192
3193 /*
3194  * Destroys the given dataset.  The caller must make sure that the filesystem
3195  * isn't mounted, and that there are no active dependents. If the file system
3196  * does not exist this function does nothing.
3197  */
3198 int
3199 zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
3200 {
3201         zfs_cmd_t zc = { 0 };
3202
3203         if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
3204                 nvlist_t *nv = fnvlist_alloc();
3205                 fnvlist_add_boolean(nv, zhp->zfs_name);
3206                 int error = lzc_destroy_bookmarks(nv, NULL);
3207                 fnvlist_free(nv);
3208                 if (error != 0) {
3209                         return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3210                             dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3211                             zhp->zfs_name));
3212                 }
3213                 return (0);
3214         }
3215
3216         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3217
3218         if (ZFS_IS_VOLUME(zhp)) {
3219                 zc.zc_objset_type = DMU_OST_ZVOL;
3220         } else {
3221                 zc.zc_objset_type = DMU_OST_ZFS;
3222         }
3223
3224         zc.zc_defer_destroy = defer;
3225         if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
3226             errno != ENOENT) {
3227                 return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3228                     dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3229                     zhp->zfs_name));
3230         }
3231
3232         remove_mountpoint(zhp);
3233
3234         return (0);
3235 }
3236
3237 struct destroydata {
3238         nvlist_t *nvl;
3239         const char *snapname;
3240 };
3241
3242 static int
3243 zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
3244 {
3245         struct destroydata *dd = arg;
3246         char name[ZFS_MAXNAMELEN];
3247         int rv = 0;
3248
3249         (void) snprintf(name, sizeof (name),
3250             "%s@%s", zhp->zfs_name, dd->snapname);
3251
3252         if (lzc_exists(name))
3253                 verify(nvlist_add_boolean(dd->nvl, name) == 0);
3254
3255         rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
3256         zfs_close(zhp);
3257         return (rv);
3258 }
3259
3260 /*
3261  * Destroys all snapshots with the given name in zhp & descendants.
3262  */
3263 int
3264 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
3265 {
3266         int ret;
3267         struct destroydata dd = { 0 };
3268
3269         dd.snapname = snapname;
3270         verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
3271         (void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
3272
3273         if (nvlist_empty(dd.nvl)) {
3274                 ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3275                     dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3276                     zhp->zfs_name, snapname);
3277         } else {
3278                 ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer);
3279         }
3280         nvlist_free(dd.nvl);
3281         return (ret);
3282 }
3283
3284 /*
3285  * Destroys all the snapshots named in the nvlist.
3286  */
3287 int
3288 zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
3289 {
3290         int ret;
3291         nvlist_t *errlist;
3292
3293         ret = lzc_destroy_snaps(snaps, defer, &errlist);
3294
3295         if (ret == 0)
3296                 return (0);
3297
3298         if (nvlist_empty(errlist)) {
3299                 char errbuf[1024];
3300                 (void) snprintf(errbuf, sizeof (errbuf),
3301                     dgettext(TEXT_DOMAIN, "cannot destroy snapshots"));
3302
3303                 ret = zfs_standard_error(hdl, ret, errbuf);
3304         }
3305         for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
3306             pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
3307                 char errbuf[1024];
3308                 (void) snprintf(errbuf, sizeof (errbuf),
3309                     dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
3310                     nvpair_name(pair));
3311
3312                 switch (fnvpair_value_int32(pair)) {
3313                 case EEXIST:
3314                         zfs_error_aux(hdl,
3315                             dgettext(TEXT_DOMAIN, "snapshot is cloned"));
3316                         ret = zfs_error(hdl, EZFS_EXISTS, errbuf);
3317                         break;
3318                 default:
3319                         ret = zfs_standard_error(hdl, errno, errbuf);
3320                         break;
3321                 }
3322         }
3323
3324         return (ret);
3325 }
3326
3327 /*
3328  * Clones the given dataset.  The target must be of the same type as the source.
3329  */
3330 int
3331 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3332 {
3333         char parent[ZFS_MAXNAMELEN];
3334         int ret;
3335         char errbuf[1024];
3336         libzfs_handle_t *hdl = zhp->zfs_hdl;
3337         uint64_t zoned;
3338
3339         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3340
3341         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3342             "cannot create '%s'"), target);
3343
3344         /* validate the target/clone name */
3345         if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3346                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3347
3348         /* validate parents exist */
3349         if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3350                 return (-1);
3351
3352         (void) parent_name(target, parent, sizeof (parent));
3353
3354         /* do the clone */
3355
3356         if (props) {
3357                 zfs_type_t type;
3358                 if (ZFS_IS_VOLUME(zhp)) {
3359                         type = ZFS_TYPE_VOLUME;
3360                 } else {
3361                         type = ZFS_TYPE_FILESYSTEM;
3362                 }
3363                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3364                     zhp, errbuf)) == NULL)
3365                         return (-1);
3366         }
3367
3368         ret = lzc_clone(target, zhp->zfs_name, props);
3369         nvlist_free(props);
3370
3371         if (ret != 0) {
3372                 switch (errno) {
3373
3374                 case ENOENT:
3375                         /*
3376                          * The parent doesn't exist.  We should have caught this
3377                          * above, but there may a race condition that has since
3378                          * destroyed the parent.
3379                          *
3380                          * At this point, we don't know whether it's the source
3381                          * that doesn't exist anymore, or whether the target
3382                          * dataset doesn't exist.
3383                          */
3384                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3385                             "no such parent '%s'"), parent);
3386                         return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3387
3388                 case EXDEV:
3389                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3390                             "source and target pools differ"));
3391                         return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
3392                             errbuf));
3393
3394                 default:
3395                         return (zfs_standard_error(zhp->zfs_hdl, errno,
3396                             errbuf));
3397                 }
3398         }
3399
3400         return (ret);
3401 }
3402
3403 /*
3404  * Promotes the given clone fs to be the clone parent.
3405  */
3406 int
3407 zfs_promote(zfs_handle_t *zhp)
3408 {
3409         libzfs_handle_t *hdl = zhp->zfs_hdl;
3410         zfs_cmd_t zc = { 0 };
3411         char parent[MAXPATHLEN];
3412         int ret;
3413         char errbuf[1024];
3414
3415         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3416             "cannot promote '%s'"), zhp->zfs_name);
3417
3418         if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3419                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3420                     "snapshots can not be promoted"));
3421                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3422         }
3423
3424         (void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent));
3425         if (parent[0] == '\0') {
3426                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3427                     "not a cloned filesystem"));
3428                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3429         }
3430
3431         (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin,
3432             sizeof (zc.zc_value));
3433         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3434         ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
3435
3436         if (ret != 0) {
3437                 int save_errno = errno;
3438
3439                 switch (save_errno) {
3440                 case EEXIST:
3441                         /* There is a conflicting snapshot name. */
3442                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3443                             "conflicting snapshot '%s' from parent '%s'"),
3444                             zc.zc_string, parent);
3445                         return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3446
3447                 default:
3448                         return (zfs_standard_error(hdl, save_errno, errbuf));
3449                 }
3450         }
3451         return (ret);
3452 }
3453
3454 typedef struct snapdata {
3455         nvlist_t *sd_nvl;
3456         const char *sd_snapname;
3457 } snapdata_t;
3458
3459 static int
3460 zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
3461 {
3462         snapdata_t *sd = arg;
3463         char name[ZFS_MAXNAMELEN];
3464         int rv = 0;
3465
3466         if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
3467                 (void) snprintf(name, sizeof (name),
3468                     "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
3469
3470                 fnvlist_add_boolean(sd->sd_nvl, name);
3471
3472                 rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
3473         }
3474         zfs_close(zhp);
3475
3476         return (rv);
3477 }
3478
3479 /*
3480  * Creates snapshots.  The keys in the snaps nvlist are the snapshots to be
3481  * created.
3482  */
3483 int
3484 zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
3485 {
3486         int ret;
3487         char errbuf[1024];
3488         nvpair_t *elem;
3489         nvlist_t *errors;
3490
3491         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3492             "cannot create snapshots "));
3493
3494         elem = NULL;
3495         while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
3496                 const char *snapname = nvpair_name(elem);
3497
3498                 /* validate the target name */
3499                 if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
3500                     B_TRUE)) {
3501                         (void) snprintf(errbuf, sizeof (errbuf),
3502                             dgettext(TEXT_DOMAIN,
3503                             "cannot create snapshot '%s'"), snapname);
3504                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3505                 }
3506         }
3507
3508         if (props != NULL &&
3509             (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3510             props, B_FALSE, NULL, errbuf)) == NULL) {
3511                 return (-1);
3512         }
3513
3514         ret = lzc_snapshot(snaps, props, &errors);
3515
3516         if (ret != 0) {
3517                 boolean_t printed = B_FALSE;
3518                 for (elem = nvlist_next_nvpair(errors, NULL);
3519                     elem != NULL;
3520                     elem = nvlist_next_nvpair(errors, elem)) {
3521                         (void) snprintf(errbuf, sizeof (errbuf),
3522                             dgettext(TEXT_DOMAIN,
3523                             "cannot create snapshot '%s'"), nvpair_name(elem));
3524                         (void) zfs_standard_error(hdl,
3525                             fnvpair_value_int32(elem), errbuf);
3526                         printed = B_TRUE;
3527                 }
3528                 if (!printed) {
3529                         switch (ret) {
3530                         case EXDEV:
3531                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3532                                     "multiple snapshots of same "
3533                                     "fs not allowed"));
3534                                 (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3535
3536                                 break;
3537                         default:
3538                                 (void) zfs_standard_error(hdl, ret, errbuf);
3539                         }
3540                 }
3541         }
3542
3543         nvlist_free(props);
3544         nvlist_free(errors);
3545         return (ret);
3546 }
3547
3548 int
3549 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3550     nvlist_t *props)
3551 {
3552         int ret;
3553         snapdata_t sd = { 0 };
3554         char fsname[ZFS_MAXNAMELEN];
3555         char *cp;
3556         zfs_handle_t *zhp;
3557         char errbuf[1024];
3558
3559         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3560             "cannot snapshot %s"), path);
3561
3562         if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
3563                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3564
3565         (void) strlcpy(fsname, path, sizeof (fsname));
3566         cp = strchr(fsname, '@');
3567         *cp = '\0';
3568         sd.sd_snapname = cp + 1;
3569
3570         if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
3571             ZFS_TYPE_VOLUME)) == NULL) {
3572                 return (-1);
3573         }
3574
3575         verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
3576         if (recursive) {
3577                 (void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
3578         } else {
3579                 fnvlist_add_boolean(sd.sd_nvl, path);
3580         }
3581
3582         ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
3583         nvlist_free(sd.sd_nvl);
3584         zfs_close(zhp);
3585         return (ret);
3586 }
3587
3588 /*
3589  * Destroy any more recent snapshots.  We invoke this callback on any dependents
3590  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3591  * is a dependent and we should just destroy it without checking the transaction
3592  * group.
3593  */
3594 typedef struct rollback_data {
3595         const char      *cb_target;             /* the snapshot */
3596         uint64_t        cb_create;              /* creation time reference */
3597         boolean_t       cb_error;
3598         boolean_t       cb_force;
3599 } rollback_data_t;
3600
3601 static int
3602 rollback_destroy_dependent(zfs_handle_t *zhp, void *data)
3603 {
3604         rollback_data_t *cbp = data;
3605         prop_changelist_t *clp;
3606
3607         /* We must destroy this clone; first unmount it */
3608         clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3609             cbp->cb_force ? MS_FORCE: 0);
3610         if (clp == NULL || changelist_prefix(clp) != 0) {
3611                 cbp->cb_error = B_TRUE;
3612                 zfs_close(zhp);
3613                 return (0);
3614         }
3615         if (zfs_destroy(zhp, B_FALSE) != 0)
3616                 cbp->cb_error = B_TRUE;
3617         else
3618                 changelist_remove(clp, zhp->zfs_name);
3619         (void) changelist_postfix(clp);
3620         changelist_free(clp);
3621
3622         zfs_close(zhp);
3623         return (0);
3624 }
3625
3626 static int
3627 rollback_destroy(zfs_handle_t *zhp, void *data)
3628 {
3629         rollback_data_t *cbp = data;
3630
3631         if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
3632                 cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3633                     rollback_destroy_dependent, cbp);
3634
3635                 cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3636         }
3637
3638         zfs_close(zhp);
3639         return (0);
3640 }
3641
3642 /*
3643  * Given a dataset, rollback to a specific snapshot, discarding any
3644  * data changes since then and making it the active dataset.
3645  *
3646  * Any snapshots and bookmarks more recent than the target are
3647  * destroyed, along with their dependents (i.e. clones).
3648  */
3649 int
3650 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3651 {
3652         rollback_data_t cb = { 0 };
3653         int err;
3654         boolean_t restore_resv = 0;
3655         uint64_t old_volsize, new_volsize;
3656         zfs_prop_t resv_prop;
3657
3658         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3659             zhp->zfs_type == ZFS_TYPE_VOLUME);
3660
3661         /*
3662          * Destroy all recent snapshots and their dependents.
3663          */
3664         cb.cb_force = force;
3665         cb.cb_target = snap->zfs_name;
3666         cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3667         (void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
3668         (void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
3669
3670         if (cb.cb_error)
3671                 return (-1);
3672
3673         /*
3674          * Now that we have verified that the snapshot is the latest,
3675          * rollback to the given snapshot.
3676          */
3677
3678         if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
3679                 if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
3680                         return (-1);
3681                 old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3682                 restore_resv =
3683                     (old_volsize == zfs_prop_get_int(zhp, resv_prop));
3684         }
3685
3686         /*
3687          * We rely on zfs_iter_children() to verify that there are no
3688          * newer snapshots for the given dataset.  Therefore, we can
3689          * simply pass the name on to the ioctl() call.  There is still
3690          * an unlikely race condition where the user has taken a
3691          * snapshot since we verified that this was the most recent.
3692          */
3693         err = lzc_rollback(zhp->zfs_name, NULL, 0);
3694         if (err != 0) {
3695                 (void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3696                     dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
3697                     zhp->zfs_name);
3698                 return (err);
3699         }
3700
3701         /*
3702          * For volumes, if the pre-rollback volsize matched the pre-
3703          * rollback reservation and the volsize has changed then set
3704          * the reservation property to the post-rollback volsize.
3705          * Make a new handle since the rollback closed the dataset.
3706          */
3707         if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3708             (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3709                 if (restore_resv) {
3710                         new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3711                         if (old_volsize != new_volsize)
3712                                 err = zfs_prop_set_int(zhp, resv_prop,
3713                                     new_volsize);
3714                 }
3715                 zfs_close(zhp);
3716         }
3717         return (err);
3718 }
3719
3720 /*
3721  * Renames the given dataset.
3722  */
3723 int
3724 zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
3725     renameflags_t flags)
3726 {
3727         int ret;
3728         zfs_cmd_t zc = { 0 };
3729         char *delim;
3730         prop_changelist_t *cl = NULL;
3731         zfs_handle_t *zhrp = NULL;
3732         char *parentname = NULL;
3733         char parent[ZFS_MAXNAMELEN];
3734         char property[ZFS_MAXPROPLEN];
3735         libzfs_handle_t *hdl = zhp->zfs_hdl;
3736         char errbuf[1024];
3737
3738         /* if we have the same exact name, just return success */
3739         if (strcmp(zhp->zfs_name, target) == 0)
3740                 return (0);
3741
3742         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3743             "cannot rename to '%s'"), target);
3744
3745         if (source != NULL) {
3746                 /*
3747                  * This is recursive snapshots rename, put snapshot name
3748                  * (that might not exist) into zfs_name.
3749                  */
3750                 assert(flags.recurse);
3751
3752                 (void) strlcat(zhp->zfs_name, "@", sizeof(zhp->zfs_name));
3753                 (void) strlcat(zhp->zfs_name, source, sizeof(zhp->zfs_name));
3754                 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
3755         }
3756
3757         /*
3758          * Make sure the target name is valid
3759          */
3760         if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3761                 if ((strchr(target, '@') == NULL) ||
3762                     *target == '@') {
3763                         /*
3764                          * Snapshot target name is abbreviated,
3765                          * reconstruct full dataset name
3766                          */
3767                         (void) strlcpy(parent, zhp->zfs_name,
3768                             sizeof (parent));
3769                         delim = strchr(parent, '@');
3770                         if (strchr(target, '@') == NULL)
3771                                 *(++delim) = '\0';
3772                         else
3773                                 *delim = '\0';
3774                         (void) strlcat(parent, target, sizeof (parent));
3775                         target = parent;
3776                 } else {
3777                         /*
3778                          * Make sure we're renaming within the same dataset.
3779                          */
3780                         delim = strchr(target, '@');
3781                         if (strncmp(zhp->zfs_name, target, delim - target)
3782                             != 0 || zhp->zfs_name[delim - target] != '@') {
3783                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3784                                     "snapshots must be part of same "
3785                                     "dataset"));
3786                                 return (zfs_error(hdl, EZFS_CROSSTARGET,
3787                                     errbuf));
3788                         }
3789                 }
3790                 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3791                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3792         } else {
3793                 if (flags.recurse) {
3794                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3795                             "recursive rename must be a snapshot"));
3796                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3797                 }
3798
3799                 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3800                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3801
3802                 /* validate parents */
3803                 if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0)
3804                         return (-1);
3805
3806                 /* make sure we're in the same pool */
3807                 verify((delim = strchr(target, '/')) != NULL);
3808                 if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
3809                     zhp->zfs_name[delim - target] != '/') {
3810                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3811                             "datasets must be within same pool"));
3812                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
3813                 }
3814
3815                 /* new name cannot be a child of the current dataset name */
3816                 if (is_descendant(zhp->zfs_name, target)) {
3817                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3818                             "New dataset name cannot be a descendant of "
3819                             "current dataset name"));
3820                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3821                 }
3822         }
3823
3824         (void) snprintf(errbuf, sizeof (errbuf),
3825             dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
3826
3827         if (getzoneid() == GLOBAL_ZONEID &&
3828             zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
3829                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3830                     "dataset is used in a non-global zone"));
3831                 return (zfs_error(hdl, EZFS_ZONED, errbuf));
3832         }
3833
3834         /*
3835          * Avoid unmounting file systems with mountpoint property set to
3836          * 'legacy' or 'none' even if -u option is not given.
3837          */
3838         if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
3839             !flags.recurse && !flags.nounmount &&
3840             zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
3841             sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
3842             (strcmp(property, "legacy") == 0 ||
3843              strcmp(property, "none") == 0)) {
3844                 flags.nounmount = B_TRUE;
3845         }
3846
3847         if (flags.recurse) {
3848
3849                 parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
3850                 if (parentname == NULL) {
3851                         ret = -1;
3852                         goto error;
3853                 }
3854                 delim = strchr(parentname, '@');
3855                 *delim = '\0';
3856                 zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
3857                 if (zhrp == NULL) {
3858                         ret = -1;
3859                         goto error;
3860                 }
3861
3862         } else {
3863                 if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
3864                     flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
3865                     flags.forceunmount ? MS_FORCE : 0)) == NULL) {
3866                         return (-1);
3867                 }
3868
3869                 if (changelist_haszonedchild(cl)) {
3870                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3871                             "child dataset with inherited mountpoint is used "
3872                             "in a non-global zone"));
3873                         (void) zfs_error(hdl, EZFS_ZONED, errbuf);
3874                         goto error;
3875                 }
3876
3877                 if ((ret = changelist_prefix(cl)) != 0)
3878                         goto error;
3879         }
3880
3881         if (ZFS_IS_VOLUME(zhp))
3882                 zc.zc_objset_type = DMU_OST_ZVOL;
3883         else
3884                 zc.zc_objset_type = DMU_OST_ZFS;
3885
3886         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3887         (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
3888
3889         zc.zc_cookie = flags.recurse ? 1 : 0;
3890         if (flags.nounmount)
3891                 zc.zc_cookie |= 2;
3892
3893         if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
3894                 /*
3895                  * if it was recursive, the one that actually failed will
3896                  * be in zc.zc_name
3897                  */
3898                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3899                     "cannot rename '%s'"), zc.zc_name);
3900
3901                 if (flags.recurse && errno == EEXIST) {
3902                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3903                             "a child dataset already has a snapshot "
3904                             "with the new name"));
3905                         (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3906                 } else {
3907                         (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
3908                 }
3909
3910                 /*
3911                  * On failure, we still want to remount any filesystems that
3912                  * were previously mounted, so we don't alter the system state.
3913                  */
3914                 if (!flags.recurse)
3915                         (void) changelist_postfix(cl);
3916         } else {
3917                 if (!flags.recurse) {
3918                         changelist_rename(cl, zfs_get_name(zhp), target);
3919                         ret = changelist_postfix(cl);
3920                 }
3921         }
3922
3923 error:
3924         if (parentname) {
3925                 free(parentname);
3926         }
3927         if (zhrp) {
3928                 zfs_close(zhrp);
3929         }
3930         if (cl) {
3931                 changelist_free(cl);
3932         }
3933         return (ret);
3934 }
3935
3936 nvlist_t *
3937 zfs_get_user_props(zfs_handle_t *zhp)
3938 {
3939         return (zhp->zfs_user_props);
3940 }
3941
3942 nvlist_t *
3943 zfs_get_recvd_props(zfs_handle_t *zhp)
3944 {
3945         if (zhp->zfs_recvd_props == NULL)
3946                 if (get_recvd_props_ioctl(zhp) != 0)
3947                         return (NULL);
3948         return (zhp->zfs_recvd_props);
3949 }
3950
3951 /*
3952  * This function is used by 'zfs list' to determine the exact set of columns to
3953  * display, and their maximum widths.  This does two main things:
3954  *
3955  *      - If this is a list of all properties, then expand the list to include
3956  *        all native properties, and set a flag so that for each dataset we look
3957  *        for new unique user properties and add them to the list.
3958  *
3959  *      - For non fixed-width properties, keep track of the maximum width seen
3960  *        so that we can size the column appropriately. If the user has
3961  *        requested received property values, we also need to compute the width
3962  *        of the RECEIVED column.
3963  */
3964 int
3965 zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
3966     boolean_t literal)
3967 {
3968         libzfs_handle_t *hdl = zhp->zfs_hdl;
3969         zprop_list_t *entry;
3970         zprop_list_t **last, **start;
3971         nvlist_t *userprops, *propval;
3972         nvpair_t *elem;
3973         char *strval;
3974         char buf[ZFS_MAXPROPLEN];
3975
3976         if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
3977                 return (-1);
3978
3979         userprops = zfs_get_user_props(zhp);
3980
3981         entry = *plp;
3982         if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
3983                 /*
3984                  * Go through and add any user properties as necessary.  We
3985                  * start by incrementing our list pointer to the first
3986                  * non-native property.
3987                  */
3988                 start = plp;
3989                 while (*start != NULL) {
3990                         if ((*start)->pl_prop == ZPROP_INVAL)
3991                                 break;
3992                         start = &(*start)->pl_next;
3993                 }
3994
3995                 elem = NULL;
3996                 while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
3997                         /*
3998                          * See if we've already found this property in our list.
3999                          */
4000                         for (last = start; *last != NULL;
4001                             last = &(*last)->pl_next) {
4002                                 if (strcmp((*last)->pl_user_prop,
4003                                     nvpair_name(elem)) == 0)
4004                                         break;
4005                         }
4006
4007                         if (*last == NULL) {
4008                                 if ((entry = zfs_alloc(hdl,
4009                                     sizeof (zprop_list_t))) == NULL ||
4010                                     ((entry->pl_user_prop = zfs_strdup(hdl,
4011                                     nvpair_name(elem)))) == NULL) {
4012                                         free(entry);
4013                                         return (-1);
4014                                 }
4015
4016                                 entry->pl_prop = ZPROP_INVAL;
4017                                 entry->pl_width = strlen(nvpair_name(elem));
4018                                 entry->pl_all = B_TRUE;
4019                                 *last = entry;
4020                         }
4021                 }
4022         }
4023
4024         /*
4025          * Now go through and check the width of any non-fixed columns
4026          */
4027         for (entry = *plp; entry != NULL; entry = entry->pl_next) {
4028                 if (entry->pl_fixed && !literal)
4029                         continue;
4030
4031                 if (entry->pl_prop != ZPROP_INVAL) {
4032                         if (zfs_prop_get(zhp, entry->pl_prop,
4033                             buf, sizeof (buf), NULL, NULL, 0, literal) == 0) {
4034                                 if (strlen(buf) > entry->pl_width)
4035                                         entry->pl_width = strlen(buf);
4036                         }
4037                         if (received && zfs_prop_get_recvd(zhp,
4038                             zfs_prop_to_name(entry->pl_prop),
4039                             buf, sizeof (buf), literal) == 0)
4040                                 if (strlen(buf) > entry->pl_recvd_width)
4041                                         entry->pl_recvd_width = strlen(buf);
4042                 } else {
4043                         if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop,
4044                             &propval) == 0) {
4045                                 verify(nvlist_lookup_string(propval,
4046                                     ZPROP_VALUE, &strval) == 0);
4047                                 if (strlen(strval) > entry->pl_width)
4048                                         entry->pl_width = strlen(strval);
4049                         }
4050                         if (received && zfs_prop_get_recvd(zhp,
4051                             entry->pl_user_prop,
4052                             buf, sizeof (buf), literal) == 0)
4053                                 if (strlen(buf) > entry->pl_recvd_width)
4054                                         entry->pl_recvd_width = strlen(buf);
4055                 }
4056         }
4057
4058         return (0);
4059 }
4060
4061 int
4062 zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
4063     char *resource, void *export, void *sharetab,
4064     int sharemax, zfs_share_op_t operation)
4065 {
4066         zfs_cmd_t zc = { 0 };
4067         int error;
4068
4069         (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4070         (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4071         if (resource)
4072                 (void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
4073         zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
4074         zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
4075         zc.zc_share.z_sharetype = operation;
4076         zc.zc_share.z_sharemax = sharemax;
4077         error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
4078         return (error);
4079 }
4080
4081 void
4082 zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
4083 {
4084         nvpair_t *curr;
4085
4086         /*
4087          * Keep a reference to the props-table against which we prune the
4088          * properties.
4089          */
4090         zhp->zfs_props_table = props;
4091
4092         curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
4093
4094         while (curr) {
4095                 zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
4096                 nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
4097
4098                 /*
4099                  * User properties will result in ZPROP_INVAL, and since we
4100                  * only know how to prune standard ZFS properties, we always
4101                  * leave these in the list.  This can also happen if we
4102                  * encounter an unknown DSL property (when running older
4103                  * software, for example).
4104                  */
4105                 if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
4106                         (void) nvlist_remove(zhp->zfs_props,
4107                             nvpair_name(curr), nvpair_type(curr));
4108                 curr = next;
4109         }
4110 }
4111
4112 #ifdef sun
4113 static int
4114 zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
4115     zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
4116 {
4117         zfs_cmd_t zc = { 0 };
4118         nvlist_t *nvlist = NULL;
4119         int error;
4120
4121         (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4122         (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4123         zc.zc_cookie = (uint64_t)cmd;
4124
4125         if (cmd == ZFS_SMB_ACL_RENAME) {
4126                 if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
4127                         (void) no_memory(hdl);
4128                         return (NULL);
4129                 }
4130         }
4131
4132         switch (cmd) {
4133         case ZFS_SMB_ACL_ADD:
4134         case ZFS_SMB_ACL_REMOVE:
4135                 (void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
4136                 break;
4137         case ZFS_SMB_ACL_RENAME:
4138                 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
4139                     resource1) != 0) {
4140                                 (void) no_memory(hdl);
4141                                 return (-1);
4142                 }
4143                 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
4144                     resource2) != 0) {
4145                                 (void) no_memory(hdl);
4146                                 return (-1);
4147                 }
4148                 if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) {
4149                         nvlist_free(nvlist);
4150                         return (-1);
4151                 }
4152                 break;
4153         case ZFS_SMB_ACL_PURGE:
4154                 break;
4155         default:
4156                 return (-1);
4157         }
4158         error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
4159         if (nvlist)
4160                 nvlist_free(nvlist);
4161         return (error);
4162 }
4163
4164 int
4165 zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
4166     char *path, char *resource)
4167 {
4168         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
4169             resource, NULL));
4170 }
4171
4172 int
4173 zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
4174     char *path, char *resource)
4175 {
4176         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
4177             resource, NULL));
4178 }
4179
4180 int
4181 zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
4182 {
4183         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
4184             NULL, NULL));
4185 }
4186
4187 int
4188 zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
4189     char *oldname, char *newname)
4190 {
4191         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
4192             oldname, newname));
4193 }
4194 #endif  /* sun */
4195
4196 int
4197 zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4198     zfs_userspace_cb_t func, void *arg)
4199 {
4200         zfs_cmd_t zc = { 0 };
4201         zfs_useracct_t buf[100];
4202         libzfs_handle_t *hdl = zhp->zfs_hdl;
4203         int ret;
4204
4205         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4206
4207         zc.zc_objset_type = type;
4208         zc.zc_nvlist_dst = (uintptr_t)buf;
4209
4210         for (;;) {
4211                 zfs_useracct_t *zua = buf;
4212
4213                 zc.zc_nvlist_dst_size = sizeof (buf);
4214                 if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
4215                         char errbuf[1024];
4216
4217                         (void) snprintf(errbuf, sizeof (errbuf),
4218                             dgettext(TEXT_DOMAIN,
4219                             "cannot get used/quota for %s"), zc.zc_name);
4220                         return (zfs_standard_error_fmt(hdl, errno, errbuf));
4221                 }
4222                 if (zc.zc_nvlist_dst_size == 0)
4223                         break;
4224
4225                 while (zc.zc_nvlist_dst_size > 0) {
4226                         if ((ret = func(arg, zua->zu_domain, zua->zu_rid,
4227                             zua->zu_space)) != 0)
4228                                 return (ret);
4229                         zua++;
4230                         zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4231                 }
4232         }
4233
4234         return (0);
4235 }
4236
4237 struct holdarg {
4238         nvlist_t *nvl;
4239         const char *snapname;
4240         const char *tag;
4241         boolean_t recursive;
4242         int error;
4243 };
4244
4245 static int
4246 zfs_hold_one(zfs_handle_t *zhp, void *arg)
4247 {
4248         struct holdarg *ha = arg;
4249         char name[ZFS_MAXNAMELEN];
4250         int rv = 0;
4251
4252         (void) snprintf(name, sizeof (name),
4253             "%s@%s", zhp->zfs_name, ha->snapname);
4254
4255         if (lzc_exists(name))
4256                 fnvlist_add_string(ha->nvl, name, ha->tag);
4257
4258         if (ha->recursive)
4259                 rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
4260         zfs_close(zhp);
4261         return (rv);
4262 }
4263
4264 int
4265 zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4266     boolean_t recursive, int cleanup_fd)
4267 {
4268         int ret;
4269         struct holdarg ha;
4270
4271         ha.nvl = fnvlist_alloc();
4272         ha.snapname = snapname;
4273         ha.tag = tag;
4274         ha.recursive = recursive;
4275         (void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
4276
4277         if (nvlist_empty(ha.nvl)) {
4278                 char errbuf[1024];
4279
4280                 fnvlist_free(ha.nvl);
4281                 ret = ENOENT;
4282                 (void) snprintf(errbuf, sizeof (errbuf),
4283                     dgettext(TEXT_DOMAIN,
4284                     "cannot hold snapshot '%s@%s'"),
4285                     zhp->zfs_name, snapname);
4286                 (void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf);
4287                 return (ret);
4288         }
4289
4290         ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl);
4291         fnvlist_free(ha.nvl);
4292
4293         return (ret);
4294 }
4295
4296 int
4297 zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds)
4298 {
4299         int ret;
4300         nvlist_t *errors;
4301         libzfs_handle_t *hdl = zhp->zfs_hdl;
4302         char errbuf[1024];
4303         nvpair_t *elem;
4304
4305         errors = NULL;
4306         ret = lzc_hold(holds, cleanup_fd, &errors);
4307
4308         if (ret == 0) {
4309                 /* There may be errors even in the success case. */
4310                 fnvlist_free(errors);
4311                 return (0);
4312         }
4313
4314         if (nvlist_empty(errors)) {
4315                 /* no hold-specific errors */
4316                 (void) snprintf(errbuf, sizeof (errbuf),
4317                     dgettext(TEXT_DOMAIN, "cannot hold"));
4318                 switch (ret) {
4319                 case ENOTSUP:
4320                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4321                             "pool must be upgraded"));
4322                         (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4323                         break;
4324                 case EINVAL:
4325                         (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4326                         break;
4327                 default:
4328                         (void) zfs_standard_error(hdl, ret, errbuf);
4329                 }
4330         }
4331
4332         for (elem = nvlist_next_nvpair(errors, NULL);
4333             elem != NULL;
4334             elem = nvlist_next_nvpair(errors, elem)) {
4335                 (void) snprintf(errbuf, sizeof (errbuf),
4336                     dgettext(TEXT_DOMAIN,
4337                     "cannot hold snapshot '%s'"), nvpair_name(elem));
4338                 switch (fnvpair_value_int32(elem)) {
4339                 case E2BIG:
4340                         /*
4341                          * Temporary tags wind up having the ds object id
4342                          * prepended. So even if we passed the length check
4343                          * above, it's still possible for the tag to wind
4344                          * up being slightly too long.
4345                          */
4346                         (void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
4347                         break;
4348                 case EINVAL:
4349                         (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4350                         break;
4351                 case EEXIST:
4352                         (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
4353                         break;
4354                 default:
4355                         (void) zfs_standard_error(hdl,
4356                             fnvpair_value_int32(elem), errbuf);
4357                 }
4358         }
4359
4360         fnvlist_free(errors);
4361         return (ret);
4362 }
4363
4364 static int
4365 zfs_release_one(zfs_handle_t *zhp, void *arg)
4366 {
4367         struct holdarg *ha = arg;
4368         char name[ZFS_MAXNAMELEN];
4369         int rv = 0;
4370         nvlist_t *existing_holds;
4371
4372         (void) snprintf(name, sizeof (name),
4373             "%s@%s", zhp->zfs_name, ha->snapname);
4374
4375         if (lzc_get_holds(name, &existing_holds) != 0) {
4376                 ha->error = ENOENT;
4377         } else if (!nvlist_exists(existing_holds, ha->tag)) {
4378                 ha->error = ESRCH;
4379         } else {
4380                 nvlist_t *torelease = fnvlist_alloc();
4381                 fnvlist_add_boolean(torelease, ha->tag);
4382                 fnvlist_add_nvlist(ha->nvl, name, torelease);
4383                 fnvlist_free(torelease);
4384         }
4385
4386         if (ha->recursive)
4387                 rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
4388         zfs_close(zhp);
4389         return (rv);
4390 }
4391
4392 int
4393 zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
4394     boolean_t recursive)
4395 {
4396         int ret;
4397         struct holdarg ha;
4398         nvlist_t *errors = NULL;
4399         nvpair_t *elem;
4400         libzfs_handle_t *hdl = zhp->zfs_hdl;
4401         char errbuf[1024];
4402
4403         ha.nvl = fnvlist_alloc();
4404         ha.snapname = snapname;
4405         ha.tag = tag;
4406         ha.recursive = recursive;
4407         ha.error = 0;
4408         (void) zfs_release_one(zfs_handle_dup(zhp), &ha);
4409
4410         if (nvlist_empty(ha.nvl)) {
4411                 fnvlist_free(ha.nvl);
4412                 ret = ha.error;
4413                 (void) snprintf(errbuf, sizeof (errbuf),
4414                     dgettext(TEXT_DOMAIN,
4415                     "cannot release hold from snapshot '%s@%s'"),
4416                     zhp->zfs_name, snapname);
4417                 if (ret == ESRCH) {
4418                         (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4419                 } else {
4420                         (void) zfs_standard_error(hdl, ret, errbuf);
4421                 }
4422                 return (ret);
4423         }
4424
4425         ret = lzc_release(ha.nvl, &errors);
4426         fnvlist_free(ha.nvl);
4427
4428         if (ret == 0) {
4429                 /* There may be errors even in the success case. */
4430                 fnvlist_free(errors);
4431                 return (0);
4432         }
4433
4434         if (nvlist_empty(errors)) {
4435                 /* no hold-specific errors */
4436                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4437                     "cannot release"));
4438                 switch (errno) {
4439                 case ENOTSUP:
4440                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4441                             "pool must be upgraded"));
4442                         (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4443                         break;
4444                 default:
4445                         (void) zfs_standard_error_fmt(hdl, errno, errbuf);
4446                 }
4447         }
4448
4449         for (elem = nvlist_next_nvpair(errors, NULL);
4450             elem != NULL;
4451             elem = nvlist_next_nvpair(errors, elem)) {
4452                 (void) snprintf(errbuf, sizeof (errbuf),
4453                     dgettext(TEXT_DOMAIN,
4454                     "cannot release hold from snapshot '%s'"),
4455                     nvpair_name(elem));
4456                 switch (fnvpair_value_int32(elem)) {
4457                 case ESRCH:
4458                         (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4459                         break;
4460                 case EINVAL:
4461                         (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4462                         break;
4463                 default:
4464                         (void) zfs_standard_error_fmt(hdl,
4465                             fnvpair_value_int32(elem), errbuf);
4466                 }
4467         }
4468
4469         fnvlist_free(errors);
4470         return (ret);
4471 }
4472
4473 int
4474 zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
4475 {
4476         zfs_cmd_t zc = { 0 };
4477         libzfs_handle_t *hdl = zhp->zfs_hdl;
4478         int nvsz = 2048;
4479         void *nvbuf;
4480         int err = 0;
4481         char errbuf[1024];
4482
4483         assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4484             zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4485
4486 tryagain:
4487
4488         nvbuf = malloc(nvsz);
4489         if (nvbuf == NULL) {
4490                 err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
4491                 goto out;
4492         }
4493
4494         zc.zc_nvlist_dst_size = nvsz;
4495         zc.zc_nvlist_dst = (uintptr_t)nvbuf;
4496
4497         (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
4498
4499         if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
4500                 (void) snprintf(errbuf, sizeof (errbuf),
4501                     dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
4502                     zc.zc_name);
4503                 switch (errno) {
4504                 case ENOMEM:
4505                         free(nvbuf);
4506                         nvsz = zc.zc_nvlist_dst_size;
4507                         goto tryagain;
4508
4509                 case ENOTSUP:
4510                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4511                             "pool must be upgraded"));
4512                         err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4513                         break;
4514                 case EINVAL:
4515                         err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4516                         break;
4517                 case ENOENT:
4518                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
4519                         break;
4520                 default:
4521                         err = zfs_standard_error_fmt(hdl, errno, errbuf);
4522                         break;
4523                 }
4524         } else {
4525                 /* success */
4526                 int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
4527                 if (rc) {
4528                         (void) snprintf(errbuf, sizeof (errbuf), dgettext(
4529                             TEXT_DOMAIN, "cannot get permissions on '%s'"),
4530                             zc.zc_name);
4531                         err = zfs_standard_error_fmt(hdl, rc, errbuf);
4532                 }
4533         }
4534
4535         free(nvbuf);
4536 out:
4537         return (err);
4538 }
4539
4540 int
4541 zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
4542 {
4543         zfs_cmd_t zc = { 0 };
4544         libzfs_handle_t *hdl = zhp->zfs_hdl;
4545         char *nvbuf;
4546         char errbuf[1024];
4547         size_t nvsz;
4548         int err;
4549
4550         assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4551             zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4552
4553         err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
4554         assert(err == 0);
4555
4556         nvbuf = malloc(nvsz);
4557
4558         err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
4559         assert(err == 0);
4560
4561         zc.zc_nvlist_src_size = nvsz;
4562         zc.zc_nvlist_src = (uintptr_t)nvbuf;
4563         zc.zc_perm_action = un;
4564
4565         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4566
4567         if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
4568                 (void) snprintf(errbuf, sizeof (errbuf),
4569                     dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
4570                     zc.zc_name);
4571                 switch (errno) {
4572                 case ENOTSUP:
4573                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4574                             "pool must be upgraded"));
4575                         err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4576                         break;
4577                 case EINVAL:
4578                         err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4579                         break;
4580                 case ENOENT:
4581                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
4582                         break;
4583                 default:
4584                         err = zfs_standard_error_fmt(hdl, errno, errbuf);
4585                         break;
4586                 }
4587         }
4588
4589         free(nvbuf);
4590
4591         return (err);
4592 }
4593
4594 int
4595 zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
4596 {
4597         int err;
4598         char errbuf[1024];
4599
4600         err = lzc_get_holds(zhp->zfs_name, nvl);
4601
4602         if (err != 0) {
4603                 libzfs_handle_t *hdl = zhp->zfs_hdl;
4604
4605                 (void) snprintf(errbuf, sizeof (errbuf),
4606                     dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
4607                     zhp->zfs_name);
4608                 switch (err) {
4609                 case ENOTSUP:
4610                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4611                             "pool must be upgraded"));
4612                         err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4613                         break;
4614                 case EINVAL:
4615                         err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4616                         break;
4617                 case ENOENT:
4618                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
4619                         break;
4620                 default:
4621                         err = zfs_standard_error_fmt(hdl, errno, errbuf);
4622                         break;
4623                 }
4624         }
4625
4626         return (err);
4627 }
4628
4629 /*
4630  * Convert the zvol's volume size to an appropriate reservation.
4631  * Note: If this routine is updated, it is necessary to update the ZFS test
4632  * suite's shell version in reservation.kshlib.
4633  */
4634 uint64_t
4635 zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
4636 {
4637         uint64_t numdb;
4638         uint64_t nblocks, volblocksize;
4639         int ncopies;
4640         char *strval;
4641
4642         if (nvlist_lookup_string(props,
4643             zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
4644                 ncopies = atoi(strval);
4645         else
4646                 ncopies = 1;
4647         if (nvlist_lookup_uint64(props,
4648             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
4649             &volblocksize) != 0)
4650                 volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
4651         nblocks = volsize/volblocksize;
4652         /* start with metadnode L0-L6 */
4653         numdb = 7;
4654         /* calculate number of indirects */
4655         while (nblocks > 1) {
4656                 nblocks += DNODES_PER_LEVEL - 1;
4657                 nblocks /= DNODES_PER_LEVEL;
4658                 numdb += nblocks;
4659         }
4660         numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1);
4661         volsize *= ncopies;
4662         /*
4663          * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't
4664          * compressed, but in practice they compress down to about
4665          * 1100 bytes
4666          */
4667         numdb *= 1ULL << DN_MAX_INDBLKSHIFT;
4668         volsize += numdb;
4669         return (volsize);
4670 }
4671
4672 /*
4673  * Attach/detach the given filesystem to/from the given jail.
4674  */
4675 int
4676 zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
4677 {
4678         libzfs_handle_t *hdl = zhp->zfs_hdl;
4679         zfs_cmd_t zc = { 0 };
4680         char errbuf[1024];
4681         unsigned long cmd;
4682         int ret;
4683
4684         if (attach) {
4685                 (void) snprintf(errbuf, sizeof (errbuf),
4686                     dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
4687         } else {
4688                 (void) snprintf(errbuf, sizeof (errbuf),
4689                     dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
4690         }
4691
4692         switch (zhp->zfs_type) {
4693         case ZFS_TYPE_VOLUME:
4694                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4695                     "volumes can not be jailed"));
4696                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4697         case ZFS_TYPE_SNAPSHOT:
4698                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4699                     "snapshots can not be jailed"));
4700                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4701         }
4702         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4703
4704         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4705         zc.zc_objset_type = DMU_OST_ZFS;
4706         zc.zc_jailid = jailid;
4707
4708         cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL;
4709         if ((ret = ioctl(hdl->libzfs_fd, cmd, &zc)) != 0)
4710                 zfs_standard_error(hdl, errno, errbuf);
4711
4712         return (ret);
4713 }