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