]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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         case ZFS_PROP_INCONSISTENT:
1889                 *val = zhp->zfs_dmustats.dds_inconsistent;
1890                 break;
1891
1892         default:
1893                 switch (zfs_prop_get_type(prop)) {
1894                 case PROP_TYPE_NUMBER:
1895                 case PROP_TYPE_INDEX:
1896                         *val = getprop_uint64(zhp, prop, source);
1897                         /*
1898                          * If we tried to use a default value for a
1899                          * readonly property, it means that it was not
1900                          * present.
1901                          */
1902                         if (zfs_prop_readonly(prop) &&
1903                             *source != NULL && (*source)[0] == '\0') {
1904                                 *source = NULL;
1905                         }
1906                         break;
1907
1908                 case PROP_TYPE_STRING:
1909                 default:
1910                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
1911                             "cannot get non-numeric property"));
1912                         return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
1913                             dgettext(TEXT_DOMAIN, "internal error")));
1914                 }
1915         }
1916
1917         return (0);
1918 }
1919
1920 /*
1921  * Calculate the source type, given the raw source string.
1922  */
1923 static void
1924 get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
1925     char *statbuf, size_t statlen)
1926 {
1927         if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY)
1928                 return;
1929
1930         if (source == NULL) {
1931                 *srctype = ZPROP_SRC_NONE;
1932         } else if (source[0] == '\0') {
1933                 *srctype = ZPROP_SRC_DEFAULT;
1934         } else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) {
1935                 *srctype = ZPROP_SRC_RECEIVED;
1936         } else {
1937                 if (strcmp(source, zhp->zfs_name) == 0) {
1938                         *srctype = ZPROP_SRC_LOCAL;
1939                 } else {
1940                         (void) strlcpy(statbuf, source, statlen);
1941                         *srctype = ZPROP_SRC_INHERITED;
1942                 }
1943         }
1944
1945 }
1946
1947 int
1948 zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
1949     size_t proplen, boolean_t literal)
1950 {
1951         zfs_prop_t prop;
1952         int err = 0;
1953
1954         if (zhp->zfs_recvd_props == NULL)
1955                 if (get_recvd_props_ioctl(zhp) != 0)
1956                         return (-1);
1957
1958         prop = zfs_name_to_prop(propname);
1959
1960         if (prop != ZPROP_INVAL) {
1961                 uint64_t cookie;
1962                 if (!nvlist_exists(zhp->zfs_recvd_props, propname))
1963                         return (-1);
1964                 zfs_set_recvd_props_mode(zhp, &cookie);
1965                 err = zfs_prop_get(zhp, prop, propbuf, proplen,
1966                     NULL, NULL, 0, literal);
1967                 zfs_unset_recvd_props_mode(zhp, &cookie);
1968         } else {
1969                 nvlist_t *propval;
1970                 char *recvdval;
1971                 if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
1972                     propname, &propval) != 0)
1973                         return (-1);
1974                 verify(nvlist_lookup_string(propval, ZPROP_VALUE,
1975                     &recvdval) == 0);
1976                 (void) strlcpy(propbuf, recvdval, proplen);
1977         }
1978
1979         return (err == 0 ? 0 : -1);
1980 }
1981
1982 static int
1983 get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
1984 {
1985         nvlist_t *value;
1986         nvpair_t *pair;
1987
1988         value = zfs_get_clones_nvl(zhp);
1989         if (value == NULL)
1990                 return (-1);
1991
1992         propbuf[0] = '\0';
1993         for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
1994             pair = nvlist_next_nvpair(value, pair)) {
1995                 if (propbuf[0] != '\0')
1996                         (void) strlcat(propbuf, ",", proplen);
1997                 (void) strlcat(propbuf, nvpair_name(pair), proplen);
1998         }
1999
2000         return (0);
2001 }
2002
2003 struct get_clones_arg {
2004         uint64_t numclones;
2005         nvlist_t *value;
2006         const char *origin;
2007         char buf[ZFS_MAXNAMELEN];
2008 };
2009
2010 int
2011 get_clones_cb(zfs_handle_t *zhp, void *arg)
2012 {
2013         struct get_clones_arg *gca = arg;
2014
2015         if (gca->numclones == 0) {
2016                 zfs_close(zhp);
2017                 return (0);
2018         }
2019
2020         if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
2021             NULL, NULL, 0, B_TRUE) != 0)
2022                 goto out;
2023         if (strcmp(gca->buf, gca->origin) == 0) {
2024                 fnvlist_add_boolean(gca->value, zfs_get_name(zhp));
2025                 gca->numclones--;
2026         }
2027
2028 out:
2029         (void) zfs_iter_children(zhp, get_clones_cb, gca);
2030         zfs_close(zhp);
2031         return (0);
2032 }
2033
2034 nvlist_t *
2035 zfs_get_clones_nvl(zfs_handle_t *zhp)
2036 {
2037         nvlist_t *nv, *value;
2038
2039         if (nvlist_lookup_nvlist(zhp->zfs_props,
2040             zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
2041                 struct get_clones_arg gca;
2042
2043                 /*
2044                  * if this is a snapshot, then the kernel wasn't able
2045                  * to get the clones.  Do it by slowly iterating.
2046                  */
2047                 if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
2048                         return (NULL);
2049                 if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
2050                         return (NULL);
2051                 if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
2052                         nvlist_free(nv);
2053                         return (NULL);
2054                 }
2055
2056                 gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
2057                 gca.value = value;
2058                 gca.origin = zhp->zfs_name;
2059
2060                 if (gca.numclones != 0) {
2061                         zfs_handle_t *root;
2062                         char pool[ZFS_MAXNAMELEN];
2063                         char *cp = pool;
2064
2065                         /* get the pool name */
2066                         (void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
2067                         (void) strsep(&cp, "/@");
2068                         root = zfs_open(zhp->zfs_hdl, pool,
2069                             ZFS_TYPE_FILESYSTEM);
2070
2071                         (void) get_clones_cb(root, &gca);
2072                 }
2073
2074                 if (gca.numclones != 0 ||
2075                     nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
2076                     nvlist_add_nvlist(zhp->zfs_props,
2077                     zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
2078                         nvlist_free(nv);
2079                         nvlist_free(value);
2080                         return (NULL);
2081                 }
2082                 nvlist_free(nv);
2083                 nvlist_free(value);
2084                 verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
2085                     zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
2086         }
2087
2088         verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
2089
2090         return (value);
2091 }
2092
2093 /*
2094  * Retrieve a property from the given object.  If 'literal' is specified, then
2095  * numbers are left as exact values.  Otherwise, numbers are converted to a
2096  * human-readable form.
2097  *
2098  * Returns 0 on success, or -1 on error.
2099  */
2100 int
2101 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
2102     zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
2103 {
2104         char *source = NULL;
2105         uint64_t val;
2106         char *str;
2107         const char *strval;
2108         boolean_t received = zfs_is_recvd_props_mode(zhp);
2109
2110         /*
2111          * Check to see if this property applies to our object
2112          */
2113         if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
2114                 return (-1);
2115
2116         if (received && zfs_prop_readonly(prop))
2117                 return (-1);
2118
2119         if (src)
2120                 *src = ZPROP_SRC_NONE;
2121
2122         switch (prop) {
2123         case ZFS_PROP_CREATION:
2124                 /*
2125                  * 'creation' is a time_t stored in the statistics.  We convert
2126                  * this into a string unless 'literal' is specified.
2127                  */
2128                 {
2129                         val = getprop_uint64(zhp, prop, &source);
2130                         time_t time = (time_t)val;
2131                         struct tm t;
2132
2133                         if (literal ||
2134                             localtime_r(&time, &t) == NULL ||
2135                             strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
2136                             &t) == 0)
2137                                 (void) snprintf(propbuf, proplen, "%llu", val);
2138                 }
2139                 break;
2140
2141         case ZFS_PROP_MOUNTPOINT:
2142                 /*
2143                  * Getting the precise mountpoint can be tricky.
2144                  *
2145                  *  - for 'none' or 'legacy', return those values.
2146                  *  - for inherited mountpoints, we want to take everything
2147                  *    after our ancestor and append it to the inherited value.
2148                  *
2149                  * If the pool has an alternate root, we want to prepend that
2150                  * root to any values we return.
2151                  */
2152
2153                 str = getprop_string(zhp, prop, &source);
2154
2155                 if (str[0] == '/') {
2156                         char buf[MAXPATHLEN];
2157                         char *root = buf;
2158                         const char *relpath;
2159
2160                         /*
2161                          * If we inherit the mountpoint, even from a dataset
2162                          * with a received value, the source will be the path of
2163                          * the dataset we inherit from. If source is
2164                          * ZPROP_SOURCE_VAL_RECVD, the received value is not
2165                          * inherited.
2166                          */
2167                         if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2168                                 relpath = "";
2169                         } else {
2170                                 relpath = zhp->zfs_name + strlen(source);
2171                                 if (relpath[0] == '/')
2172                                         relpath++;
2173                         }
2174
2175                         if ((zpool_get_prop(zhp->zpool_hdl,
2176                             ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
2177                             (strcmp(root, "-") == 0))
2178                                 root[0] = '\0';
2179                         /*
2180                          * Special case an alternate root of '/'. This will
2181                          * avoid having multiple leading slashes in the
2182                          * mountpoint path.
2183                          */
2184                         if (strcmp(root, "/") == 0)
2185                                 root++;
2186
2187                         /*
2188                          * If the mountpoint is '/' then skip over this
2189                          * if we are obtaining either an alternate root or
2190                          * an inherited mountpoint.
2191                          */
2192                         if (str[1] == '\0' && (root[0] != '\0' ||
2193                             relpath[0] != '\0'))
2194                                 str++;
2195
2196                         if (relpath[0] == '\0')
2197                                 (void) snprintf(propbuf, proplen, "%s%s",
2198                                     root, str);
2199                         else
2200                                 (void) snprintf(propbuf, proplen, "%s%s%s%s",
2201                                     root, str, relpath[0] == '@' ? "" : "/",
2202                                     relpath);
2203                 } else {
2204                         /* 'legacy' or 'none' */
2205                         (void) strlcpy(propbuf, str, proplen);
2206                 }
2207
2208                 break;
2209
2210         case ZFS_PROP_ORIGIN:
2211                 (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
2212                     proplen);
2213                 /*
2214                  * If there is no parent at all, return failure to indicate that
2215                  * it doesn't apply to this dataset.
2216                  */
2217                 if (propbuf[0] == '\0')
2218                         return (-1);
2219                 break;
2220
2221         case ZFS_PROP_CLONES:
2222                 if (get_clones_string(zhp, propbuf, proplen) != 0)
2223                         return (-1);
2224                 break;
2225
2226         case ZFS_PROP_QUOTA:
2227         case ZFS_PROP_REFQUOTA:
2228         case ZFS_PROP_RESERVATION:
2229         case ZFS_PROP_REFRESERVATION:
2230
2231                 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2232                         return (-1);
2233
2234                 /*
2235                  * If quota or reservation is 0, we translate this into 'none'
2236                  * (unless literal is set), and indicate that it's the default
2237                  * value.  Otherwise, we print the number nicely and indicate
2238                  * that its set locally.
2239                  */
2240                 if (val == 0) {
2241                         if (literal)
2242                                 (void) strlcpy(propbuf, "0", proplen);
2243                         else
2244                                 (void) strlcpy(propbuf, "none", proplen);
2245                 } else {
2246                         if (literal)
2247                                 (void) snprintf(propbuf, proplen, "%llu",
2248                                     (u_longlong_t)val);
2249                         else
2250                                 zfs_nicenum(val, propbuf, proplen);
2251                 }
2252                 break;
2253
2254         case ZFS_PROP_REFRATIO:
2255         case ZFS_PROP_COMPRESSRATIO:
2256                 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2257                         return (-1);
2258                 (void) snprintf(propbuf, proplen, "%llu.%02llux",
2259                     (u_longlong_t)(val / 100),
2260                     (u_longlong_t)(val % 100));
2261                 break;
2262
2263         case ZFS_PROP_TYPE:
2264                 switch (zhp->zfs_type) {
2265                 case ZFS_TYPE_FILESYSTEM:
2266                         str = "filesystem";
2267                         break;
2268                 case ZFS_TYPE_VOLUME:
2269                         str = "volume";
2270                         break;
2271                 case ZFS_TYPE_SNAPSHOT:
2272                         str = "snapshot";
2273                         break;
2274                 default:
2275                         abort();
2276                 }
2277                 (void) snprintf(propbuf, proplen, "%s", str);
2278                 break;
2279
2280         case ZFS_PROP_MOUNTED:
2281                 /*
2282                  * The 'mounted' property is a pseudo-property that described
2283                  * whether the filesystem is currently mounted.  Even though
2284                  * it's a boolean value, the typical values of "on" and "off"
2285                  * don't make sense, so we translate to "yes" and "no".
2286                  */
2287                 if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
2288                     src, &source, &val) != 0)
2289                         return (-1);
2290                 if (val)
2291                         (void) strlcpy(propbuf, "yes", proplen);
2292                 else
2293                         (void) strlcpy(propbuf, "no", proplen);
2294                 break;
2295
2296         case ZFS_PROP_NAME:
2297                 /*
2298                  * The 'name' property is a pseudo-property derived from the
2299                  * dataset name.  It is presented as a real property to simplify
2300                  * consumers.
2301                  */
2302                 (void) strlcpy(propbuf, zhp->zfs_name, proplen);
2303                 break;
2304
2305         case ZFS_PROP_MLSLABEL:
2306                 {
2307 #ifdef sun
2308                         m_label_t *new_sl = NULL;
2309                         char *ascii = NULL;     /* human readable label */
2310
2311                         (void) strlcpy(propbuf,
2312                             getprop_string(zhp, prop, &source), proplen);
2313
2314                         if (literal || (strcasecmp(propbuf,
2315                             ZFS_MLSLABEL_DEFAULT) == 0))
2316                                 break;
2317
2318                         /*
2319                          * Try to translate the internal hex string to
2320                          * human-readable output.  If there are any
2321                          * problems just use the hex string.
2322                          */
2323
2324                         if (str_to_label(propbuf, &new_sl, MAC_LABEL,
2325                             L_NO_CORRECTION, NULL) == -1) {
2326                                 m_label_free(new_sl);
2327                                 break;
2328                         }
2329
2330                         if (label_to_str(new_sl, &ascii, M_LABEL,
2331                             DEF_NAMES) != 0) {
2332                                 if (ascii)
2333                                         free(ascii);
2334                                 m_label_free(new_sl);
2335                                 break;
2336                         }
2337                         m_label_free(new_sl);
2338
2339                         (void) strlcpy(propbuf, ascii, proplen);
2340                         free(ascii);
2341 #else   /* !sun */
2342                         propbuf[0] = '\0';
2343 #endif  /* !sun */
2344                 }
2345                 break;
2346
2347         case ZFS_PROP_GUID:
2348                 /*
2349                  * GUIDs are stored as numbers, but they are identifiers.
2350                  * We don't want them to be pretty printed, because pretty
2351                  * printing mangles the ID into a truncated and useless value.
2352                  */
2353                 if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2354                         return (-1);
2355                 (void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
2356                 break;
2357
2358         default:
2359                 switch (zfs_prop_get_type(prop)) {
2360                 case PROP_TYPE_NUMBER:
2361                         if (get_numeric_property(zhp, prop, src,
2362                             &source, &val) != 0)
2363                                 return (-1);
2364                         if (literal)
2365                                 (void) snprintf(propbuf, proplen, "%llu",
2366                                     (u_longlong_t)val);
2367                         else
2368                                 zfs_nicenum(val, propbuf, proplen);
2369                         break;
2370
2371                 case PROP_TYPE_STRING:
2372                         (void) strlcpy(propbuf,
2373                             getprop_string(zhp, prop, &source), proplen);
2374                         break;
2375
2376                 case PROP_TYPE_INDEX:
2377                         if (get_numeric_property(zhp, prop, src,
2378                             &source, &val) != 0)
2379                                 return (-1);
2380                         if (zfs_prop_index_to_string(prop, val, &strval) != 0)
2381                                 return (-1);
2382                         (void) strlcpy(propbuf, strval, proplen);
2383                         break;
2384
2385                 default:
2386                         abort();
2387                 }
2388         }
2389
2390         get_source(zhp, src, source, statbuf, statlen);
2391
2392         return (0);
2393 }
2394
2395 /*
2396  * Utility function to get the given numeric property.  Does no validation that
2397  * the given property is the appropriate type; should only be used with
2398  * hard-coded property types.
2399  */
2400 uint64_t
2401 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
2402 {
2403         char *source;
2404         uint64_t val;
2405
2406         (void) get_numeric_property(zhp, prop, NULL, &source, &val);
2407
2408         return (val);
2409 }
2410
2411 int
2412 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
2413 {
2414         char buf[64];
2415
2416         (void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
2417         return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
2418 }
2419
2420 /*
2421  * Similar to zfs_prop_get(), but returns the value as an integer.
2422  */
2423 int
2424 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
2425     zprop_source_t *src, char *statbuf, size_t statlen)
2426 {
2427         char *source;
2428
2429         /*
2430          * Check to see if this property applies to our object
2431          */
2432         if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
2433                 return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
2434                     dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
2435                     zfs_prop_to_name(prop)));
2436         }
2437
2438         if (src)
2439                 *src = ZPROP_SRC_NONE;
2440
2441         if (get_numeric_property(zhp, prop, src, &source, value) != 0)
2442                 return (-1);
2443
2444         get_source(zhp, src, source, statbuf, statlen);
2445
2446         return (0);
2447 }
2448
2449 static int
2450 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
2451     char **domainp, idmap_rid_t *ridp)
2452 {
2453 #ifdef sun
2454         idmap_get_handle_t *get_hdl = NULL;
2455         idmap_stat status;
2456         int err = EINVAL;
2457
2458         if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
2459                 goto out;
2460
2461         if (isuser) {
2462                 err = idmap_get_sidbyuid(get_hdl, id,
2463                     IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2464         } else {
2465                 err = idmap_get_sidbygid(get_hdl, id,
2466                     IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2467         }
2468         if (err == IDMAP_SUCCESS &&
2469             idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
2470             status == IDMAP_SUCCESS)
2471                 err = 0;
2472         else
2473                 err = EINVAL;
2474 out:
2475         if (get_hdl)
2476                 idmap_get_destroy(get_hdl);
2477         return (err);
2478 #else   /* !sun */
2479         assert(!"invalid code path");
2480 #endif  /* !sun */
2481 }
2482
2483 /*
2484  * convert the propname into parameters needed by kernel
2485  * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
2486  * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
2487  */
2488 static int
2489 userquota_propname_decode(const char *propname, boolean_t zoned,
2490     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
2491 {
2492         zfs_userquota_prop_t type;
2493         char *cp, *end;
2494         char *numericsid = NULL;
2495         boolean_t isuser;
2496
2497         domain[0] = '\0';
2498
2499         /* Figure out the property type ({user|group}{quota|space}) */
2500         for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
2501                 if (strncmp(propname, zfs_userquota_prop_prefixes[type],
2502                     strlen(zfs_userquota_prop_prefixes[type])) == 0)
2503                         break;
2504         }
2505         if (type == ZFS_NUM_USERQUOTA_PROPS)
2506                 return (EINVAL);
2507         *typep = type;
2508
2509         isuser = (type == ZFS_PROP_USERQUOTA ||
2510             type == ZFS_PROP_USERUSED);
2511
2512         cp = strchr(propname, '@') + 1;
2513
2514         if (strchr(cp, '@')) {
2515 #ifdef sun
2516                 /*
2517                  * It's a SID name (eg "user@domain") that needs to be
2518                  * turned into S-1-domainID-RID.
2519                  */
2520                 directory_error_t e;
2521                 if (zoned && getzoneid() == GLOBAL_ZONEID)
2522                         return (ENOENT);
2523                 if (isuser) {
2524                         e = directory_sid_from_user_name(NULL,
2525                             cp, &numericsid);
2526                 } else {
2527                         e = directory_sid_from_group_name(NULL,
2528                             cp, &numericsid);
2529                 }
2530                 if (e != NULL) {
2531                         directory_error_free(e);
2532                         return (ENOENT);
2533                 }
2534                 if (numericsid == NULL)
2535                         return (ENOENT);
2536                 cp = numericsid;
2537                 /* will be further decoded below */
2538 #else   /* !sun */
2539                 return (ENOENT);
2540 #endif  /* !sun */
2541         }
2542
2543         if (strncmp(cp, "S-1-", 4) == 0) {
2544                 /* It's a numeric SID (eg "S-1-234-567-89") */
2545                 (void) strlcpy(domain, cp, domainlen);
2546                 cp = strrchr(domain, '-');
2547                 *cp = '\0';
2548                 cp++;
2549
2550                 errno = 0;
2551                 *ridp = strtoull(cp, &end, 10);
2552                 if (numericsid) {
2553                         free(numericsid);
2554                         numericsid = NULL;
2555                 }
2556                 if (errno != 0 || *end != '\0')
2557                         return (EINVAL);
2558         } else if (!isdigit(*cp)) {
2559                 /*
2560                  * It's a user/group name (eg "user") that needs to be
2561                  * turned into a uid/gid
2562                  */
2563                 if (zoned && getzoneid() == GLOBAL_ZONEID)
2564                         return (ENOENT);
2565                 if (isuser) {
2566                         struct passwd *pw;
2567                         pw = getpwnam(cp);
2568                         if (pw == NULL)
2569                                 return (ENOENT);
2570                         *ridp = pw->pw_uid;
2571                 } else {
2572                         struct group *gr;
2573                         gr = getgrnam(cp);
2574                         if (gr == NULL)
2575                                 return (ENOENT);
2576                         *ridp = gr->gr_gid;
2577                 }
2578         } else {
2579                 /* It's a user/group ID (eg "12345"). */
2580                 uid_t id = strtoul(cp, &end, 10);
2581                 idmap_rid_t rid;
2582                 char *mapdomain;
2583
2584                 if (*end != '\0')
2585                         return (EINVAL);
2586                 if (id > MAXUID) {
2587                         /* It's an ephemeral ID. */
2588                         if (idmap_id_to_numeric_domain_rid(id, isuser,
2589                             &mapdomain, &rid) != 0)
2590                                 return (ENOENT);
2591                         (void) strlcpy(domain, mapdomain, domainlen);
2592                         *ridp = rid;
2593                 } else {
2594                         *ridp = id;
2595                 }
2596         }
2597
2598         ASSERT3P(numericsid, ==, NULL);
2599         return (0);
2600 }
2601
2602 static int
2603 zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
2604     uint64_t *propvalue, zfs_userquota_prop_t *typep)
2605 {
2606         int err;
2607         zfs_cmd_t zc = { 0 };
2608
2609         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2610
2611         err = userquota_propname_decode(propname,
2612             zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
2613             typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
2614         zc.zc_objset_type = *typep;
2615         if (err)
2616                 return (err);
2617
2618         err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
2619         if (err)
2620                 return (err);
2621
2622         *propvalue = zc.zc_cookie;
2623         return (0);
2624 }
2625
2626 int
2627 zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
2628     uint64_t *propvalue)
2629 {
2630         zfs_userquota_prop_t type;
2631
2632         return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
2633             &type));
2634 }
2635
2636 int
2637 zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
2638     char *propbuf, int proplen, boolean_t literal)
2639 {
2640         int err;
2641         uint64_t propvalue;
2642         zfs_userquota_prop_t type;
2643
2644         err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
2645             &type);
2646
2647         if (err)
2648                 return (err);
2649
2650         if (literal) {
2651                 (void) snprintf(propbuf, proplen, "%llu", propvalue);
2652         } else if (propvalue == 0 &&
2653             (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
2654                 (void) strlcpy(propbuf, "none", proplen);
2655         } else {
2656                 zfs_nicenum(propvalue, propbuf, proplen);
2657         }
2658         return (0);
2659 }
2660
2661 int
2662 zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
2663     uint64_t *propvalue)
2664 {
2665         int err;
2666         zfs_cmd_t zc = { 0 };
2667         const char *snapname;
2668
2669         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2670
2671         snapname = strchr(propname, '@') + 1;
2672         if (strchr(snapname, '@')) {
2673                 (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
2674         } else {
2675                 /* snapname is the short name, append it to zhp's fsname */
2676                 char *cp;
2677
2678                 (void) strlcpy(zc.zc_value, zhp->zfs_name,
2679                     sizeof (zc.zc_value));
2680                 cp = strchr(zc.zc_value, '@');
2681                 if (cp != NULL)
2682                         *cp = '\0';
2683                 (void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
2684                 (void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
2685         }
2686
2687         err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
2688         if (err)
2689                 return (err);
2690
2691         *propvalue = zc.zc_cookie;
2692         return (0);
2693 }
2694
2695 int
2696 zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
2697     char *propbuf, int proplen, boolean_t literal)
2698 {
2699         int err;
2700         uint64_t propvalue;
2701
2702         err = zfs_prop_get_written_int(zhp, propname, &propvalue);
2703
2704         if (err)
2705                 return (err);
2706
2707         if (literal) {
2708                 (void) snprintf(propbuf, proplen, "%llu", propvalue);
2709         } else {
2710                 zfs_nicenum(propvalue, propbuf, proplen);
2711         }
2712         return (0);
2713 }
2714
2715 /*
2716  * Returns the name of the given zfs handle.
2717  */
2718 const char *
2719 zfs_get_name(const zfs_handle_t *zhp)
2720 {
2721         return (zhp->zfs_name);
2722 }
2723
2724 /*
2725  * Returns the type of the given zfs handle.
2726  */
2727 zfs_type_t
2728 zfs_get_type(const zfs_handle_t *zhp)
2729 {
2730         return (zhp->zfs_type);
2731 }
2732
2733 /*
2734  * Is one dataset name a child dataset of another?
2735  *
2736  * Needs to handle these cases:
2737  * Dataset 1    "a/foo"         "a/foo"         "a/foo"         "a/foo"
2738  * Dataset 2    "a/fo"          "a/foobar"      "a/bar/baz"     "a/foo/bar"
2739  * Descendant?  No.             No.             No.             Yes.
2740  */
2741 static boolean_t
2742 is_descendant(const char *ds1, const char *ds2)
2743 {
2744         size_t d1len = strlen(ds1);
2745
2746         /* ds2 can't be a descendant if it's smaller */
2747         if (strlen(ds2) < d1len)
2748                 return (B_FALSE);
2749
2750         /* otherwise, compare strings and verify that there's a '/' char */
2751         return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0));
2752 }
2753
2754 /*
2755  * Given a complete name, return just the portion that refers to the parent.
2756  * Will return -1 if there is no parent (path is just the name of the
2757  * pool).
2758  */
2759 static int
2760 parent_name(const char *path, char *buf, size_t buflen)
2761 {
2762         char *slashp;
2763
2764         (void) strlcpy(buf, path, buflen);
2765
2766         if ((slashp = strrchr(buf, '/')) == NULL)
2767                 return (-1);
2768         *slashp = '\0';
2769
2770         return (0);
2771 }
2772
2773 /*
2774  * If accept_ancestor is false, then check to make sure that the given path has
2775  * a parent, and that it exists.  If accept_ancestor is true, then find the
2776  * closest existing ancestor for the given path.  In prefixlen return the
2777  * length of already existing prefix of the given path.  We also fetch the
2778  * 'zoned' property, which is used to validate property settings when creating
2779  * new datasets.
2780  */
2781 static int
2782 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
2783     boolean_t accept_ancestor, int *prefixlen)
2784 {
2785         zfs_cmd_t zc = { 0 };
2786         char parent[ZFS_MAXNAMELEN];
2787         char *slash;
2788         zfs_handle_t *zhp;
2789         char errbuf[1024];
2790         uint64_t is_zoned;
2791
2792         (void) snprintf(errbuf, sizeof (errbuf),
2793             dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
2794
2795         /* get parent, and check to see if this is just a pool */
2796         if (parent_name(path, parent, sizeof (parent)) != 0) {
2797                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2798                     "missing dataset name"));
2799                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2800         }
2801
2802         /* check to see if the pool exists */
2803         if ((slash = strchr(parent, '/')) == NULL)
2804                 slash = parent + strlen(parent);
2805         (void) strncpy(zc.zc_name, parent, slash - parent);
2806         zc.zc_name[slash - parent] = '\0';
2807         if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
2808             errno == ENOENT) {
2809                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2810                     "no such pool '%s'"), zc.zc_name);
2811                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
2812         }
2813
2814         /* check to see if the parent dataset exists */
2815         while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
2816                 if (errno == ENOENT && accept_ancestor) {
2817                         /*
2818                          * Go deeper to find an ancestor, give up on top level.
2819                          */
2820                         if (parent_name(parent, parent, sizeof (parent)) != 0) {
2821                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2822                                     "no such pool '%s'"), zc.zc_name);
2823                                 return (zfs_error(hdl, EZFS_NOENT, errbuf));
2824                         }
2825                 } else if (errno == ENOENT) {
2826                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2827                             "parent does not exist"));
2828                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
2829                 } else
2830                         return (zfs_standard_error(hdl, errno, errbuf));
2831         }
2832
2833         is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
2834         if (zoned != NULL)
2835                 *zoned = is_zoned;
2836
2837         /* we are in a non-global zone, but parent is in the global zone */
2838         if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
2839                 (void) zfs_standard_error(hdl, EPERM, errbuf);
2840                 zfs_close(zhp);
2841                 return (-1);
2842         }
2843
2844         /* make sure parent is a filesystem */
2845         if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2846                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2847                     "parent is not a filesystem"));
2848                 (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
2849                 zfs_close(zhp);
2850                 return (-1);
2851         }
2852
2853         zfs_close(zhp);
2854         if (prefixlen != NULL)
2855                 *prefixlen = strlen(parent);
2856         return (0);
2857 }
2858
2859 /*
2860  * Finds whether the dataset of the given type(s) exists.
2861  */
2862 boolean_t
2863 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
2864 {
2865         zfs_handle_t *zhp;
2866
2867         if (!zfs_validate_name(hdl, path, types, B_FALSE))
2868                 return (B_FALSE);
2869
2870         /*
2871          * Try to get stats for the dataset, which will tell us if it exists.
2872          */
2873         if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
2874                 int ds_type = zhp->zfs_type;
2875
2876                 zfs_close(zhp);
2877                 if (types & ds_type)
2878                         return (B_TRUE);
2879         }
2880         return (B_FALSE);
2881 }
2882
2883 /*
2884  * Given a path to 'target', create all the ancestors between
2885  * the prefixlen portion of the path, and the target itself.
2886  * Fail if the initial prefixlen-ancestor does not already exist.
2887  */
2888 int
2889 create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
2890 {
2891         zfs_handle_t *h;
2892         char *cp;
2893         const char *opname;
2894
2895         /* make sure prefix exists */
2896         cp = target + prefixlen;
2897         if (*cp != '/') {
2898                 assert(strchr(cp, '/') == NULL);
2899                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2900         } else {
2901                 *cp = '\0';
2902                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2903                 *cp = '/';
2904         }
2905         if (h == NULL)
2906                 return (-1);
2907         zfs_close(h);
2908
2909         /*
2910          * Attempt to create, mount, and share any ancestor filesystems,
2911          * up to the prefixlen-long one.
2912          */
2913         for (cp = target + prefixlen + 1;
2914             cp = strchr(cp, '/'); *cp = '/', cp++) {
2915
2916                 *cp = '\0';
2917
2918                 h = make_dataset_handle(hdl, target);
2919                 if (h) {
2920                         /* it already exists, nothing to do here */
2921                         zfs_close(h);
2922                         continue;
2923                 }
2924
2925                 if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
2926                     NULL) != 0) {
2927                         opname = dgettext(TEXT_DOMAIN, "create");
2928                         goto ancestorerr;
2929                 }
2930
2931                 h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2932                 if (h == NULL) {
2933                         opname = dgettext(TEXT_DOMAIN, "open");
2934                         goto ancestorerr;
2935                 }
2936
2937                 if (zfs_mount(h, NULL, 0) != 0) {
2938                         opname = dgettext(TEXT_DOMAIN, "mount");
2939                         goto ancestorerr;
2940                 }
2941
2942                 if (zfs_share(h) != 0) {
2943                         opname = dgettext(TEXT_DOMAIN, "share");
2944                         goto ancestorerr;
2945                 }
2946
2947                 zfs_close(h);
2948         }
2949
2950         return (0);
2951
2952 ancestorerr:
2953         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2954             "failed to %s ancestor '%s'"), opname, target);
2955         return (-1);
2956 }
2957
2958 /*
2959  * Creates non-existing ancestors of the given path.
2960  */
2961 int
2962 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
2963 {
2964         int prefix;
2965         char *path_copy;
2966         int rc;
2967
2968         if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
2969                 return (-1);
2970
2971         if ((path_copy = strdup(path)) != NULL) {
2972                 rc = create_parents(hdl, path_copy, prefix);
2973                 free(path_copy);
2974         }
2975         if (path_copy == NULL || rc != 0)
2976                 return (-1);
2977
2978         return (0);
2979 }
2980
2981 /*
2982  * Create a new filesystem or volume.
2983  */
2984 int
2985 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
2986     nvlist_t *props)
2987 {
2988         int ret;
2989         uint64_t size = 0;
2990         uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
2991         char errbuf[1024];
2992         uint64_t zoned;
2993         dmu_objset_type_t ost;
2994
2995         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2996             "cannot create '%s'"), path);
2997
2998         /* validate the path, taking care to note the extended error message */
2999         if (!zfs_validate_name(hdl, path, type, B_TRUE))
3000                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3001
3002         /* validate parents exist */
3003         if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
3004                 return (-1);
3005
3006         /*
3007          * The failure modes when creating a dataset of a different type over
3008          * one that already exists is a little strange.  In particular, if you
3009          * try to create a dataset on top of an existing dataset, the ioctl()
3010          * will return ENOENT, not EEXIST.  To prevent this from happening, we
3011          * first try to see if the dataset exists.
3012          */
3013         if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
3014                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3015                     "dataset already exists"));
3016                 return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3017         }
3018
3019         if (type == ZFS_TYPE_VOLUME)
3020                 ost = DMU_OST_ZVOL;
3021         else
3022                 ost = DMU_OST_ZFS;
3023
3024         if (props && (props = zfs_valid_proplist(hdl, type, props,
3025             zoned, NULL, errbuf)) == 0)
3026                 return (-1);
3027
3028         if (type == ZFS_TYPE_VOLUME) {
3029                 /*
3030                  * If we are creating a volume, the size and block size must
3031                  * satisfy a few restraints.  First, the blocksize must be a
3032                  * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
3033                  * volsize must be a multiple of the block size, and cannot be
3034                  * zero.
3035                  */
3036                 if (props == NULL || nvlist_lookup_uint64(props,
3037                     zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
3038                         nvlist_free(props);
3039                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3040                             "missing volume size"));
3041                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3042                 }
3043
3044                 if ((ret = nvlist_lookup_uint64(props,
3045                     zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3046                     &blocksize)) != 0) {
3047                         if (ret == ENOENT) {
3048                                 blocksize = zfs_prop_default_numeric(
3049                                     ZFS_PROP_VOLBLOCKSIZE);
3050                         } else {
3051                                 nvlist_free(props);
3052                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3053                                     "missing volume block size"));
3054                                 return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3055                         }
3056                 }
3057
3058                 if (size == 0) {
3059                         nvlist_free(props);
3060                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3061                             "volume size cannot be zero"));
3062                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3063                 }
3064
3065                 if (size % blocksize != 0) {
3066                         nvlist_free(props);
3067                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3068                             "volume size must be a multiple of volume block "
3069                             "size"));
3070                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3071                 }
3072         }
3073
3074         /* create the dataset */
3075         ret = lzc_create(path, ost, props);
3076         nvlist_free(props);
3077
3078         /* check for failure */
3079         if (ret != 0) {
3080                 char parent[ZFS_MAXNAMELEN];
3081                 (void) parent_name(path, parent, sizeof (parent));
3082
3083                 switch (errno) {
3084                 case ENOENT:
3085                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3086                             "no such parent '%s'"), parent);
3087                         return (zfs_error(hdl, EZFS_NOENT, errbuf));
3088
3089                 case EINVAL:
3090                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3091                             "parent '%s' is not a filesystem"), parent);
3092                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3093
3094                 case EDOM:
3095                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3096                             "volume block size must be power of 2 from "
3097                             "%u to %uk"),
3098                             (uint_t)SPA_MINBLOCKSIZE,
3099                             (uint_t)SPA_MAXBLOCKSIZE >> 10);
3100
3101                         return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3102
3103                 case ENOTSUP:
3104                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3105                             "pool must be upgraded to set this "
3106                             "property or value"));
3107                         return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
3108 #ifdef _ILP32
3109                 case EOVERFLOW:
3110                         /*
3111                          * This platform can't address a volume this big.
3112                          */
3113                         if (type == ZFS_TYPE_VOLUME)
3114                                 return (zfs_error(hdl, EZFS_VOLTOOBIG,
3115                                     errbuf));
3116 #endif
3117                         /* FALLTHROUGH */
3118                 default:
3119                         return (zfs_standard_error(hdl, errno, errbuf));
3120                 }
3121         }
3122
3123         return (0);
3124 }
3125
3126 /*
3127  * Destroys the given dataset.  The caller must make sure that the filesystem
3128  * isn't mounted, and that there are no active dependents. If the file system
3129  * does not exist this function does nothing.
3130  */
3131 int
3132 zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
3133 {
3134         zfs_cmd_t zc = { 0 };
3135
3136         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3137
3138         if (ZFS_IS_VOLUME(zhp)) {
3139                 zc.zc_objset_type = DMU_OST_ZVOL;
3140         } else {
3141                 zc.zc_objset_type = DMU_OST_ZFS;
3142         }
3143
3144         zc.zc_defer_destroy = defer;
3145         if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
3146             errno != ENOENT) {
3147                 return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3148                     dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3149                     zhp->zfs_name));
3150         }
3151
3152         remove_mountpoint(zhp);
3153
3154         return (0);
3155 }
3156
3157 struct destroydata {
3158         nvlist_t *nvl;
3159         const char *snapname;
3160 };
3161
3162 static int
3163 zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
3164 {
3165         struct destroydata *dd = arg;
3166         char name[ZFS_MAXNAMELEN];
3167         int rv = 0;
3168
3169         (void) snprintf(name, sizeof (name),
3170             "%s@%s", zhp->zfs_name, dd->snapname);
3171
3172         if (lzc_exists(name))
3173                 verify(nvlist_add_boolean(dd->nvl, name) == 0);
3174
3175         rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
3176         zfs_close(zhp);
3177         return (rv);
3178 }
3179
3180 /*
3181  * Destroys all snapshots with the given name in zhp & descendants.
3182  */
3183 int
3184 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
3185 {
3186         int ret;
3187         struct destroydata dd = { 0 };
3188
3189         dd.snapname = snapname;
3190         verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
3191         (void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
3192
3193         if (nvlist_empty(dd.nvl)) {
3194                 ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3195                     dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3196                     zhp->zfs_name, snapname);
3197         } else {
3198                 ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer);
3199         }
3200         nvlist_free(dd.nvl);
3201         return (ret);
3202 }
3203
3204 /*
3205  * Destroys all the snapshots named in the nvlist.
3206  */
3207 int
3208 zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
3209 {
3210         int ret;
3211         nvlist_t *errlist;
3212
3213         ret = lzc_destroy_snaps(snaps, defer, &errlist);
3214
3215         if (ret == 0)
3216                 return (0);
3217
3218         if (nvlist_empty(errlist)) {
3219                 char errbuf[1024];
3220                 (void) snprintf(errbuf, sizeof (errbuf),
3221                     dgettext(TEXT_DOMAIN, "cannot destroy snapshots"));
3222
3223                 ret = zfs_standard_error(hdl, ret, errbuf);
3224         }
3225         for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
3226             pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
3227                 char errbuf[1024];
3228                 (void) snprintf(errbuf, sizeof (errbuf),
3229                     dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
3230                     nvpair_name(pair));
3231
3232                 switch (fnvpair_value_int32(pair)) {
3233                 case EEXIST:
3234                         zfs_error_aux(hdl,
3235                             dgettext(TEXT_DOMAIN, "snapshot is cloned"));
3236                         ret = zfs_error(hdl, EZFS_EXISTS, errbuf);
3237                         break;
3238                 default:
3239                         ret = zfs_standard_error(hdl, errno, errbuf);
3240                         break;
3241                 }
3242         }
3243
3244         return (ret);
3245 }
3246
3247 /*
3248  * Clones the given dataset.  The target must be of the same type as the source.
3249  */
3250 int
3251 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3252 {
3253         char parent[ZFS_MAXNAMELEN];
3254         int ret;
3255         char errbuf[1024];
3256         libzfs_handle_t *hdl = zhp->zfs_hdl;
3257         uint64_t zoned;
3258
3259         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3260
3261         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3262             "cannot create '%s'"), target);
3263
3264         /* validate the target/clone name */
3265         if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3266                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3267
3268         /* validate parents exist */
3269         if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3270                 return (-1);
3271
3272         (void) parent_name(target, parent, sizeof (parent));
3273
3274         /* do the clone */
3275
3276         if (props) {
3277                 zfs_type_t type;
3278                 if (ZFS_IS_VOLUME(zhp)) {
3279                         type = ZFS_TYPE_VOLUME;
3280                 } else {
3281                         type = ZFS_TYPE_FILESYSTEM;
3282                 }
3283                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3284                     zhp, errbuf)) == NULL)
3285                         return (-1);
3286         }
3287
3288         ret = lzc_clone(target, zhp->zfs_name, props);
3289         nvlist_free(props);
3290
3291         if (ret != 0) {
3292                 switch (errno) {
3293
3294                 case ENOENT:
3295                         /*
3296                          * The parent doesn't exist.  We should have caught this
3297                          * above, but there may a race condition that has since
3298                          * destroyed the parent.
3299                          *
3300                          * At this point, we don't know whether it's the source
3301                          * that doesn't exist anymore, or whether the target
3302                          * dataset doesn't exist.
3303                          */
3304                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3305                             "no such parent '%s'"), parent);
3306                         return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3307
3308                 case EXDEV:
3309                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3310                             "source and target pools differ"));
3311                         return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
3312                             errbuf));
3313
3314                 default:
3315                         return (zfs_standard_error(zhp->zfs_hdl, errno,
3316                             errbuf));
3317                 }
3318         }
3319
3320         return (ret);
3321 }
3322
3323 /*
3324  * Promotes the given clone fs to be the clone parent.
3325  */
3326 int
3327 zfs_promote(zfs_handle_t *zhp)
3328 {
3329         libzfs_handle_t *hdl = zhp->zfs_hdl;
3330         zfs_cmd_t zc = { 0 };
3331         char parent[MAXPATHLEN];
3332         int ret;
3333         char errbuf[1024];
3334
3335         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3336             "cannot promote '%s'"), zhp->zfs_name);
3337
3338         if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3339                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3340                     "snapshots can not be promoted"));
3341                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3342         }
3343
3344         (void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent));
3345         if (parent[0] == '\0') {
3346                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3347                     "not a cloned filesystem"));
3348                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3349         }
3350
3351         (void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin,
3352             sizeof (zc.zc_value));
3353         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3354         ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
3355
3356         if (ret != 0) {
3357                 int save_errno = errno;
3358
3359                 switch (save_errno) {
3360                 case EEXIST:
3361                         /* There is a conflicting snapshot name. */
3362                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3363                             "conflicting snapshot '%s' from parent '%s'"),
3364                             zc.zc_string, parent);
3365                         return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3366
3367                 default:
3368                         return (zfs_standard_error(hdl, save_errno, errbuf));
3369                 }
3370         }
3371         return (ret);
3372 }
3373
3374 typedef struct snapdata {
3375         nvlist_t *sd_nvl;
3376         const char *sd_snapname;
3377 } snapdata_t;
3378
3379 static int
3380 zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
3381 {
3382         snapdata_t *sd = arg;
3383         char name[ZFS_MAXNAMELEN];
3384         int rv = 0;
3385
3386         if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
3387                 (void) snprintf(name, sizeof (name),
3388                     "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
3389
3390                 fnvlist_add_boolean(sd->sd_nvl, name);
3391
3392                 rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
3393         }
3394         zfs_close(zhp);
3395
3396         return (rv);
3397 }
3398
3399 /*
3400  * Creates snapshots.  The keys in the snaps nvlist are the snapshots to be
3401  * created.
3402  */
3403 int
3404 zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
3405 {
3406         int ret;
3407         char errbuf[1024];
3408         nvpair_t *elem;
3409         nvlist_t *errors;
3410
3411         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3412             "cannot create snapshots "));
3413
3414         elem = NULL;
3415         while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
3416                 const char *snapname = nvpair_name(elem);
3417
3418                 /* validate the target name */
3419                 if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
3420                     B_TRUE)) {
3421                         (void) snprintf(errbuf, sizeof (errbuf),
3422                             dgettext(TEXT_DOMAIN,
3423                             "cannot create snapshot '%s'"), snapname);
3424                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3425                 }
3426         }
3427
3428         if (props != NULL &&
3429             (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3430             props, B_FALSE, NULL, errbuf)) == NULL) {
3431                 return (-1);
3432         }
3433
3434         ret = lzc_snapshot(snaps, props, &errors);
3435
3436         if (ret != 0) {
3437                 boolean_t printed = B_FALSE;
3438                 for (elem = nvlist_next_nvpair(errors, NULL);
3439                     elem != NULL;
3440                     elem = nvlist_next_nvpair(errors, elem)) {
3441                         (void) snprintf(errbuf, sizeof (errbuf),
3442                             dgettext(TEXT_DOMAIN,
3443                             "cannot create snapshot '%s'"), nvpair_name(elem));
3444                         (void) zfs_standard_error(hdl,
3445                             fnvpair_value_int32(elem), errbuf);
3446                         printed = B_TRUE;
3447                 }
3448                 if (!printed) {
3449                         switch (ret) {
3450                         case EXDEV:
3451                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3452                                     "multiple snapshots of same "
3453                                     "fs not allowed"));
3454                                 (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3455
3456                                 break;
3457                         default:
3458                                 (void) zfs_standard_error(hdl, ret, errbuf);
3459                         }
3460                 }
3461         }
3462
3463         nvlist_free(props);
3464         nvlist_free(errors);
3465         return (ret);
3466 }
3467
3468 int
3469 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3470     nvlist_t *props)
3471 {
3472         int ret;
3473         snapdata_t sd = { 0 };
3474         char fsname[ZFS_MAXNAMELEN];
3475         char *cp;
3476         zfs_handle_t *zhp;
3477         char errbuf[1024];
3478
3479         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3480             "cannot snapshot %s"), path);
3481
3482         if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
3483                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3484
3485         (void) strlcpy(fsname, path, sizeof (fsname));
3486         cp = strchr(fsname, '@');
3487         *cp = '\0';
3488         sd.sd_snapname = cp + 1;
3489
3490         if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
3491             ZFS_TYPE_VOLUME)) == NULL) {
3492                 return (-1);
3493         }
3494
3495         verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
3496         if (recursive) {
3497                 (void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
3498         } else {
3499                 fnvlist_add_boolean(sd.sd_nvl, path);
3500         }
3501
3502         ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
3503         nvlist_free(sd.sd_nvl);
3504         zfs_close(zhp);
3505         return (ret);
3506 }
3507
3508 /*
3509  * Destroy any more recent snapshots.  We invoke this callback on any dependents
3510  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3511  * is a dependent and we should just destroy it without checking the transaction
3512  * group.
3513  */
3514 typedef struct rollback_data {
3515         const char      *cb_target;             /* the snapshot */
3516         uint64_t        cb_create;              /* creation time reference */
3517         boolean_t       cb_error;
3518         boolean_t       cb_dependent;
3519         boolean_t       cb_force;
3520 } rollback_data_t;
3521
3522 static int
3523 rollback_destroy(zfs_handle_t *zhp, void *data)
3524 {
3525         rollback_data_t *cbp = data;
3526
3527         if (!cbp->cb_dependent) {
3528                 if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
3529                     zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
3530                     zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
3531                     cbp->cb_create) {
3532
3533                         cbp->cb_dependent = B_TRUE;
3534                         cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3535                             rollback_destroy, cbp);
3536                         cbp->cb_dependent = B_FALSE;
3537
3538                         cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3539                 }
3540         } else {
3541                 /* We must destroy this clone; first unmount it */
3542                 prop_changelist_t *clp;
3543
3544                 clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3545                     cbp->cb_force ? MS_FORCE: 0);
3546                 if (clp == NULL || changelist_prefix(clp) != 0) {
3547                         cbp->cb_error = B_TRUE;
3548                         zfs_close(zhp);
3549                         return (0);
3550                 }
3551                 if (zfs_destroy(zhp, B_FALSE) != 0)
3552                         cbp->cb_error = B_TRUE;
3553                 else
3554                         changelist_remove(clp, zhp->zfs_name);
3555                 (void) changelist_postfix(clp);
3556                 changelist_free(clp);
3557         }
3558
3559         zfs_close(zhp);
3560         return (0);
3561 }
3562
3563 /*
3564  * Given a dataset, rollback to a specific snapshot, discarding any
3565  * data changes since then and making it the active dataset.
3566  *
3567  * Any snapshots more recent than the target are destroyed, along with
3568  * their dependents.
3569  */
3570 int
3571 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3572 {
3573         rollback_data_t cb = { 0 };
3574         int err;
3575         boolean_t restore_resv = 0;
3576         uint64_t old_volsize, new_volsize;
3577         zfs_prop_t resv_prop;
3578
3579         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3580             zhp->zfs_type == ZFS_TYPE_VOLUME);
3581
3582         /*
3583          * Destroy all recent snapshots and their dependents.
3584          */
3585         cb.cb_force = force;
3586         cb.cb_target = snap->zfs_name;
3587         cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3588         (void) zfs_iter_children(zhp, rollback_destroy, &cb);
3589
3590         if (cb.cb_error)
3591                 return (-1);
3592
3593         /*
3594          * Now that we have verified that the snapshot is the latest,
3595          * rollback to the given snapshot.
3596          */
3597
3598         if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
3599                 if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
3600                         return (-1);
3601                 old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3602                 restore_resv =
3603                     (old_volsize == zfs_prop_get_int(zhp, resv_prop));
3604         }
3605
3606         /*
3607          * We rely on zfs_iter_children() to verify that there are no
3608          * newer snapshots for the given dataset.  Therefore, we can
3609          * simply pass the name on to the ioctl() call.  There is still
3610          * an unlikely race condition where the user has taken a
3611          * snapshot since we verified that this was the most recent.
3612          */
3613         err = lzc_rollback(zhp->zfs_name, NULL, 0);
3614         if (err != 0) {
3615                 (void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3616                     dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
3617                     zhp->zfs_name);
3618                 return (err);
3619         }
3620
3621         /*
3622          * For volumes, if the pre-rollback volsize matched the pre-
3623          * rollback reservation and the volsize has changed then set
3624          * the reservation property to the post-rollback volsize.
3625          * Make a new handle since the rollback closed the dataset.
3626          */
3627         if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3628             (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3629                 if (restore_resv) {
3630                         new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3631                         if (old_volsize != new_volsize)
3632                                 err = zfs_prop_set_int(zhp, resv_prop,
3633                                     new_volsize);
3634                 }
3635                 zfs_close(zhp);
3636         }
3637         return (err);
3638 }
3639
3640 /*
3641  * Renames the given dataset.
3642  */
3643 int
3644 zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
3645     renameflags_t flags)
3646 {
3647         int ret;
3648         zfs_cmd_t zc = { 0 };
3649         char *delim;
3650         prop_changelist_t *cl = NULL;
3651         zfs_handle_t *zhrp = NULL;
3652         char *parentname = NULL;
3653         char parent[ZFS_MAXNAMELEN];
3654         char property[ZFS_MAXPROPLEN];
3655         libzfs_handle_t *hdl = zhp->zfs_hdl;
3656         char errbuf[1024];
3657
3658         /* if we have the same exact name, just return success */
3659         if (strcmp(zhp->zfs_name, target) == 0)
3660                 return (0);
3661
3662         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3663             "cannot rename to '%s'"), target);
3664
3665         if (source != NULL) {
3666                 /*
3667                  * This is recursive snapshots rename, put snapshot name
3668                  * (that might not exist) into zfs_name.
3669                  */
3670                 assert(flags.recurse);
3671
3672                 (void) strlcat(zhp->zfs_name, "@", sizeof(zhp->zfs_name));
3673                 (void) strlcat(zhp->zfs_name, source, sizeof(zhp->zfs_name));
3674                 zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
3675         }
3676
3677         /*
3678          * Make sure the target name is valid
3679          */
3680         if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3681                 if ((strchr(target, '@') == NULL) ||
3682                     *target == '@') {
3683                         /*
3684                          * Snapshot target name is abbreviated,
3685                          * reconstruct full dataset name
3686                          */
3687                         (void) strlcpy(parent, zhp->zfs_name,
3688                             sizeof (parent));
3689                         delim = strchr(parent, '@');
3690                         if (strchr(target, '@') == NULL)
3691                                 *(++delim) = '\0';
3692                         else
3693                                 *delim = '\0';
3694                         (void) strlcat(parent, target, sizeof (parent));
3695                         target = parent;
3696                 } else {
3697                         /*
3698                          * Make sure we're renaming within the same dataset.
3699                          */
3700                         delim = strchr(target, '@');
3701                         if (strncmp(zhp->zfs_name, target, delim - target)
3702                             != 0 || zhp->zfs_name[delim - target] != '@') {
3703                                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3704                                     "snapshots must be part of same "
3705                                     "dataset"));
3706                                 return (zfs_error(hdl, EZFS_CROSSTARGET,
3707                                     errbuf));
3708                         }
3709                 }
3710                 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3711                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3712         } else {
3713                 if (flags.recurse) {
3714                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3715                             "recursive rename must be a snapshot"));
3716                         return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3717                 }
3718
3719                 if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3720                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3721
3722                 /* validate parents */
3723                 if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0)
3724                         return (-1);
3725
3726                 /* make sure we're in the same pool */
3727                 verify((delim = strchr(target, '/')) != NULL);
3728                 if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
3729                     zhp->zfs_name[delim - target] != '/') {
3730                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3731                             "datasets must be within same pool"));
3732                         return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
3733                 }
3734
3735                 /* new name cannot be a child of the current dataset name */
3736                 if (is_descendant(zhp->zfs_name, target)) {
3737                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3738                             "New dataset name cannot be a descendant of "
3739                             "current dataset name"));
3740                         return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3741                 }
3742         }
3743
3744         (void) snprintf(errbuf, sizeof (errbuf),
3745             dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
3746
3747         if (getzoneid() == GLOBAL_ZONEID &&
3748             zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
3749                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3750                     "dataset is used in a non-global zone"));
3751                 return (zfs_error(hdl, EZFS_ZONED, errbuf));
3752         }
3753
3754         /*
3755          * Avoid unmounting file systems with mountpoint property set to
3756          * 'legacy' or 'none' even if -u option is not given.
3757          */
3758         if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
3759             !flags.recurse && !flags.nounmount &&
3760             zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
3761             sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
3762             (strcmp(property, "legacy") == 0 ||
3763              strcmp(property, "none") == 0)) {
3764                 flags.nounmount = B_TRUE;
3765         }
3766
3767         if (flags.recurse) {
3768
3769                 parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
3770                 if (parentname == NULL) {
3771                         ret = -1;
3772                         goto error;
3773                 }
3774                 delim = strchr(parentname, '@');
3775                 *delim = '\0';
3776                 zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
3777                 if (zhrp == NULL) {
3778                         ret = -1;
3779                         goto error;
3780                 }
3781
3782         } else {
3783                 if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
3784                     flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
3785                     flags.forceunmount ? MS_FORCE : 0)) == NULL) {
3786                         return (-1);
3787                 }
3788
3789                 if (changelist_haszonedchild(cl)) {
3790                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3791                             "child dataset with inherited mountpoint is used "
3792                             "in a non-global zone"));
3793                         (void) zfs_error(hdl, EZFS_ZONED, errbuf);
3794                         goto error;
3795                 }
3796
3797                 if ((ret = changelist_prefix(cl)) != 0)
3798                         goto error;
3799         }
3800
3801         if (ZFS_IS_VOLUME(zhp))
3802                 zc.zc_objset_type = DMU_OST_ZVOL;
3803         else
3804                 zc.zc_objset_type = DMU_OST_ZFS;
3805
3806         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3807         (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
3808
3809         zc.zc_cookie = flags.recurse ? 1 : 0;
3810         if (flags.nounmount)
3811                 zc.zc_cookie |= 2;
3812
3813         if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
3814                 /*
3815                  * if it was recursive, the one that actually failed will
3816                  * be in zc.zc_name
3817                  */
3818                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3819                     "cannot rename '%s'"), zc.zc_name);
3820
3821                 if (flags.recurse && errno == EEXIST) {
3822                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3823                             "a child dataset already has a snapshot "
3824                             "with the new name"));
3825                         (void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3826                 } else {
3827                         (void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
3828                 }
3829
3830                 /*
3831                  * On failure, we still want to remount any filesystems that
3832                  * were previously mounted, so we don't alter the system state.
3833                  */
3834                 if (!flags.recurse)
3835                         (void) changelist_postfix(cl);
3836         } else {
3837                 if (!flags.recurse) {
3838                         changelist_rename(cl, zfs_get_name(zhp), target);
3839                         ret = changelist_postfix(cl);
3840                 }
3841         }
3842
3843 error:
3844         if (parentname) {
3845                 free(parentname);
3846         }
3847         if (zhrp) {
3848                 zfs_close(zhrp);
3849         }
3850         if (cl) {
3851                 changelist_free(cl);
3852         }
3853         return (ret);
3854 }
3855
3856 nvlist_t *
3857 zfs_get_user_props(zfs_handle_t *zhp)
3858 {
3859         return (zhp->zfs_user_props);
3860 }
3861
3862 nvlist_t *
3863 zfs_get_recvd_props(zfs_handle_t *zhp)
3864 {
3865         if (zhp->zfs_recvd_props == NULL)
3866                 if (get_recvd_props_ioctl(zhp) != 0)
3867                         return (NULL);
3868         return (zhp->zfs_recvd_props);
3869 }
3870
3871 /*
3872  * This function is used by 'zfs list' to determine the exact set of columns to
3873  * display, and their maximum widths.  This does two main things:
3874  *
3875  *      - If this is a list of all properties, then expand the list to include
3876  *        all native properties, and set a flag so that for each dataset we look
3877  *        for new unique user properties and add them to the list.
3878  *
3879  *      - For non fixed-width properties, keep track of the maximum width seen
3880  *        so that we can size the column appropriately. If the user has
3881  *        requested received property values, we also need to compute the width
3882  *        of the RECEIVED column.
3883  */
3884 int
3885 zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received)
3886 {
3887         libzfs_handle_t *hdl = zhp->zfs_hdl;
3888         zprop_list_t *entry;
3889         zprop_list_t **last, **start;
3890         nvlist_t *userprops, *propval;
3891         nvpair_t *elem;
3892         char *strval;
3893         char buf[ZFS_MAXPROPLEN];
3894
3895         if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
3896                 return (-1);
3897
3898         userprops = zfs_get_user_props(zhp);
3899
3900         entry = *plp;
3901         if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
3902                 /*
3903                  * Go through and add any user properties as necessary.  We
3904                  * start by incrementing our list pointer to the first
3905                  * non-native property.
3906                  */
3907                 start = plp;
3908                 while (*start != NULL) {
3909                         if ((*start)->pl_prop == ZPROP_INVAL)
3910                                 break;
3911                         start = &(*start)->pl_next;
3912                 }
3913
3914                 elem = NULL;
3915                 while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
3916                         /*
3917                          * See if we've already found this property in our list.
3918                          */
3919                         for (last = start; *last != NULL;
3920                             last = &(*last)->pl_next) {
3921                                 if (strcmp((*last)->pl_user_prop,
3922                                     nvpair_name(elem)) == 0)
3923                                         break;
3924                         }
3925
3926                         if (*last == NULL) {
3927                                 if ((entry = zfs_alloc(hdl,
3928                                     sizeof (zprop_list_t))) == NULL ||
3929                                     ((entry->pl_user_prop = zfs_strdup(hdl,
3930                                     nvpair_name(elem)))) == NULL) {
3931                                         free(entry);
3932                                         return (-1);
3933                                 }
3934
3935                                 entry->pl_prop = ZPROP_INVAL;
3936                                 entry->pl_width = strlen(nvpair_name(elem));
3937                                 entry->pl_all = B_TRUE;
3938                                 *last = entry;
3939                         }
3940                 }
3941         }
3942
3943         /*
3944          * Now go through and check the width of any non-fixed columns
3945          */
3946         for (entry = *plp; entry != NULL; entry = entry->pl_next) {
3947                 if (entry->pl_fixed)
3948                         continue;
3949
3950                 if (entry->pl_prop != ZPROP_INVAL) {
3951                         if (zfs_prop_get(zhp, entry->pl_prop,
3952                             buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) {
3953                                 if (strlen(buf) > entry->pl_width)
3954                                         entry->pl_width = strlen(buf);
3955                         }
3956                         if (received && zfs_prop_get_recvd(zhp,
3957                             zfs_prop_to_name(entry->pl_prop),
3958                             buf, sizeof (buf), B_FALSE) == 0)
3959                                 if (strlen(buf) > entry->pl_recvd_width)
3960                                         entry->pl_recvd_width = strlen(buf);
3961                 } else {
3962                         if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop,
3963                             &propval) == 0) {
3964                                 verify(nvlist_lookup_string(propval,
3965                                     ZPROP_VALUE, &strval) == 0);
3966                                 if (strlen(strval) > entry->pl_width)
3967                                         entry->pl_width = strlen(strval);
3968                         }
3969                         if (received && zfs_prop_get_recvd(zhp,
3970                             entry->pl_user_prop,
3971                             buf, sizeof (buf), B_FALSE) == 0)
3972                                 if (strlen(buf) > entry->pl_recvd_width)
3973                                         entry->pl_recvd_width = strlen(buf);
3974                 }
3975         }
3976
3977         return (0);
3978 }
3979
3980 int
3981 zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
3982     char *resource, void *export, void *sharetab,
3983     int sharemax, zfs_share_op_t operation)
3984 {
3985         zfs_cmd_t zc = { 0 };
3986         int error;
3987
3988         (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3989         (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
3990         if (resource)
3991                 (void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
3992         zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
3993         zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
3994         zc.zc_share.z_sharetype = operation;
3995         zc.zc_share.z_sharemax = sharemax;
3996         error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
3997         return (error);
3998 }
3999
4000 void
4001 zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
4002 {
4003         nvpair_t *curr;
4004
4005         /*
4006          * Keep a reference to the props-table against which we prune the
4007          * properties.
4008          */
4009         zhp->zfs_props_table = props;
4010
4011         curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
4012
4013         while (curr) {
4014                 zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
4015                 nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
4016
4017                 /*
4018                  * User properties will result in ZPROP_INVAL, and since we
4019                  * only know how to prune standard ZFS properties, we always
4020                  * leave these in the list.  This can also happen if we
4021                  * encounter an unknown DSL property (when running older
4022                  * software, for example).
4023                  */
4024                 if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
4025                         (void) nvlist_remove(zhp->zfs_props,
4026                             nvpair_name(curr), nvpair_type(curr));
4027                 curr = next;
4028         }
4029 }
4030
4031 #ifdef sun
4032 static int
4033 zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
4034     zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
4035 {
4036         zfs_cmd_t zc = { 0 };
4037         nvlist_t *nvlist = NULL;
4038         int error;
4039
4040         (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4041         (void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4042         zc.zc_cookie = (uint64_t)cmd;
4043
4044         if (cmd == ZFS_SMB_ACL_RENAME) {
4045                 if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
4046                         (void) no_memory(hdl);
4047                         return (NULL);
4048                 }
4049         }
4050
4051         switch (cmd) {
4052         case ZFS_SMB_ACL_ADD:
4053         case ZFS_SMB_ACL_REMOVE:
4054                 (void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
4055                 break;
4056         case ZFS_SMB_ACL_RENAME:
4057                 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
4058                     resource1) != 0) {
4059                                 (void) no_memory(hdl);
4060                                 return (-1);
4061                 }
4062                 if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
4063                     resource2) != 0) {
4064                                 (void) no_memory(hdl);
4065                                 return (-1);
4066                 }
4067                 if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) {
4068                         nvlist_free(nvlist);
4069                         return (-1);
4070                 }
4071                 break;
4072         case ZFS_SMB_ACL_PURGE:
4073                 break;
4074         default:
4075                 return (-1);
4076         }
4077         error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
4078         if (nvlist)
4079                 nvlist_free(nvlist);
4080         return (error);
4081 }
4082
4083 int
4084 zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
4085     char *path, char *resource)
4086 {
4087         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
4088             resource, NULL));
4089 }
4090
4091 int
4092 zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
4093     char *path, char *resource)
4094 {
4095         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
4096             resource, NULL));
4097 }
4098
4099 int
4100 zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
4101 {
4102         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
4103             NULL, NULL));
4104 }
4105
4106 int
4107 zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
4108     char *oldname, char *newname)
4109 {
4110         return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
4111             oldname, newname));
4112 }
4113 #endif  /* sun */
4114
4115 int
4116 zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4117     zfs_userspace_cb_t func, void *arg)
4118 {
4119         zfs_cmd_t zc = { 0 };
4120         zfs_useracct_t buf[100];
4121         libzfs_handle_t *hdl = zhp->zfs_hdl;
4122         int ret;
4123
4124         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4125
4126         zc.zc_objset_type = type;
4127         zc.zc_nvlist_dst = (uintptr_t)buf;
4128
4129         for (;;) {
4130                 zfs_useracct_t *zua = buf;
4131
4132                 zc.zc_nvlist_dst_size = sizeof (buf);
4133                 if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
4134                         char errbuf[1024];
4135
4136                         (void) snprintf(errbuf, sizeof (errbuf),
4137                             dgettext(TEXT_DOMAIN,
4138                             "cannot get used/quota for %s"), zc.zc_name);
4139                         return (zfs_standard_error_fmt(hdl, errno, errbuf));
4140                 }
4141                 if (zc.zc_nvlist_dst_size == 0)
4142                         break;
4143
4144                 while (zc.zc_nvlist_dst_size > 0) {
4145                         if ((ret = func(arg, zua->zu_domain, zua->zu_rid,
4146                             zua->zu_space)) != 0)
4147                                 return (ret);
4148                         zua++;
4149                         zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4150                 }
4151         }
4152
4153         return (0);
4154 }
4155
4156 struct holdarg {
4157         nvlist_t *nvl;
4158         const char *snapname;
4159         const char *tag;
4160         boolean_t recursive;
4161         int error;
4162 };
4163
4164 static int
4165 zfs_hold_one(zfs_handle_t *zhp, void *arg)
4166 {
4167         struct holdarg *ha = arg;
4168         char name[ZFS_MAXNAMELEN];
4169         int rv = 0;
4170
4171         (void) snprintf(name, sizeof (name),
4172             "%s@%s", zhp->zfs_name, ha->snapname);
4173
4174         if (lzc_exists(name))
4175                 fnvlist_add_string(ha->nvl, name, ha->tag);
4176
4177         if (ha->recursive)
4178                 rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
4179         zfs_close(zhp);
4180         return (rv);
4181 }
4182
4183 int
4184 zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4185     boolean_t recursive, int cleanup_fd)
4186 {
4187         int ret;
4188         struct holdarg ha;
4189
4190         ha.nvl = fnvlist_alloc();
4191         ha.snapname = snapname;
4192         ha.tag = tag;
4193         ha.recursive = recursive;
4194         (void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
4195
4196         if (nvlist_empty(ha.nvl)) {
4197                 char errbuf[1024];
4198
4199                 fnvlist_free(ha.nvl);
4200                 ret = ENOENT;
4201                 (void) snprintf(errbuf, sizeof (errbuf),
4202                     dgettext(TEXT_DOMAIN,
4203                     "cannot hold snapshot '%s@%s'"),
4204                     zhp->zfs_name, snapname);
4205                 (void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf);
4206                 return (ret);
4207         }
4208
4209         ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl);
4210         fnvlist_free(ha.nvl);
4211
4212         return (ret);
4213 }
4214
4215 int
4216 zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds)
4217 {
4218         int ret;
4219         nvlist_t *errors;
4220         libzfs_handle_t *hdl = zhp->zfs_hdl;
4221         char errbuf[1024];
4222         nvpair_t *elem;
4223
4224         errors = NULL;
4225         ret = lzc_hold(holds, cleanup_fd, &errors);
4226
4227         if (ret == 0) {
4228                 /* There may be errors even in the success case. */
4229                 fnvlist_free(errors);
4230                 return (0);
4231         }
4232
4233         if (nvlist_empty(errors)) {
4234                 /* no hold-specific errors */
4235                 (void) snprintf(errbuf, sizeof (errbuf),
4236                     dgettext(TEXT_DOMAIN, "cannot hold"));
4237                 switch (ret) {
4238                 case ENOTSUP:
4239                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4240                             "pool must be upgraded"));
4241                         (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4242                         break;
4243                 case EINVAL:
4244                         (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4245                         break;
4246                 default:
4247                         (void) zfs_standard_error(hdl, ret, errbuf);
4248                 }
4249         }
4250
4251         for (elem = nvlist_next_nvpair(errors, NULL);
4252             elem != NULL;
4253             elem = nvlist_next_nvpair(errors, elem)) {
4254                 (void) snprintf(errbuf, sizeof (errbuf),
4255                     dgettext(TEXT_DOMAIN,
4256                     "cannot hold snapshot '%s'"), nvpair_name(elem));
4257                 switch (fnvpair_value_int32(elem)) {
4258                 case E2BIG:
4259                         /*
4260                          * Temporary tags wind up having the ds object id
4261                          * prepended. So even if we passed the length check
4262                          * above, it's still possible for the tag to wind
4263                          * up being slightly too long.
4264                          */
4265                         (void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
4266                         break;
4267                 case EINVAL:
4268                         (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4269                         break;
4270                 case EEXIST:
4271                         (void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
4272                         break;
4273                 default:
4274                         (void) zfs_standard_error(hdl,
4275                             fnvpair_value_int32(elem), errbuf);
4276                 }
4277         }
4278
4279         fnvlist_free(errors);
4280         return (ret);
4281 }
4282
4283 static int
4284 zfs_release_one(zfs_handle_t *zhp, void *arg)
4285 {
4286         struct holdarg *ha = arg;
4287         char name[ZFS_MAXNAMELEN];
4288         int rv = 0;
4289         nvlist_t *existing_holds;
4290
4291         (void) snprintf(name, sizeof (name),
4292             "%s@%s", zhp->zfs_name, ha->snapname);
4293
4294         if (lzc_get_holds(name, &existing_holds) != 0) {
4295                 ha->error = ENOENT;
4296         } else if (!nvlist_exists(existing_holds, ha->tag)) {
4297                 ha->error = ESRCH;
4298         } else {
4299                 nvlist_t *torelease = fnvlist_alloc();
4300                 fnvlist_add_boolean(torelease, ha->tag);
4301                 fnvlist_add_nvlist(ha->nvl, name, torelease);
4302                 fnvlist_free(torelease);
4303         }
4304
4305         if (ha->recursive)
4306                 rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
4307         zfs_close(zhp);
4308         return (rv);
4309 }
4310
4311 int
4312 zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
4313     boolean_t recursive)
4314 {
4315         int ret;
4316         struct holdarg ha;
4317         nvlist_t *errors = NULL;
4318         nvpair_t *elem;
4319         libzfs_handle_t *hdl = zhp->zfs_hdl;
4320         char errbuf[1024];
4321
4322         ha.nvl = fnvlist_alloc();
4323         ha.snapname = snapname;
4324         ha.tag = tag;
4325         ha.recursive = recursive;
4326         ha.error = 0;
4327         (void) zfs_release_one(zfs_handle_dup(zhp), &ha);
4328
4329         if (nvlist_empty(ha.nvl)) {
4330                 fnvlist_free(ha.nvl);
4331                 ret = ha.error;
4332                 (void) snprintf(errbuf, sizeof (errbuf),
4333                     dgettext(TEXT_DOMAIN,
4334                     "cannot release hold from snapshot '%s@%s'"),
4335                     zhp->zfs_name, snapname);
4336                 if (ret == ESRCH) {
4337                         (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4338                 } else {
4339                         (void) zfs_standard_error(hdl, ret, errbuf);
4340                 }
4341                 return (ret);
4342         }
4343
4344         ret = lzc_release(ha.nvl, &errors);
4345         fnvlist_free(ha.nvl);
4346
4347         if (ret == 0) {
4348                 /* There may be errors even in the success case. */
4349                 fnvlist_free(errors);
4350                 return (0);
4351         }
4352
4353         if (nvlist_empty(errors)) {
4354                 /* no hold-specific errors */
4355                 (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4356                     "cannot release"));
4357                 switch (errno) {
4358                 case ENOTSUP:
4359                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4360                             "pool must be upgraded"));
4361                         (void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4362                         break;
4363                 default:
4364                         (void) zfs_standard_error_fmt(hdl, errno, errbuf);
4365                 }
4366         }
4367
4368         for (elem = nvlist_next_nvpair(errors, NULL);
4369             elem != NULL;
4370             elem = nvlist_next_nvpair(errors, elem)) {
4371                 (void) snprintf(errbuf, sizeof (errbuf),
4372                     dgettext(TEXT_DOMAIN,
4373                     "cannot release hold from snapshot '%s'"),
4374                     nvpair_name(elem));
4375                 switch (fnvpair_value_int32(elem)) {
4376                 case ESRCH:
4377                         (void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4378                         break;
4379                 case EINVAL:
4380                         (void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4381                         break;
4382                 default:
4383                         (void) zfs_standard_error_fmt(hdl,
4384                             fnvpair_value_int32(elem), errbuf);
4385                 }
4386         }
4387
4388         fnvlist_free(errors);
4389         return (ret);
4390 }
4391
4392 int
4393 zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
4394 {
4395         zfs_cmd_t zc = { 0 };
4396         libzfs_handle_t *hdl = zhp->zfs_hdl;
4397         int nvsz = 2048;
4398         void *nvbuf;
4399         int err = 0;
4400         char errbuf[1024];
4401
4402         assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4403             zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4404
4405 tryagain:
4406
4407         nvbuf = malloc(nvsz);
4408         if (nvbuf == NULL) {
4409                 err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
4410                 goto out;
4411         }
4412
4413         zc.zc_nvlist_dst_size = nvsz;
4414         zc.zc_nvlist_dst = (uintptr_t)nvbuf;
4415
4416         (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
4417
4418         if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
4419                 (void) snprintf(errbuf, sizeof (errbuf),
4420                     dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
4421                     zc.zc_name);
4422                 switch (errno) {
4423                 case ENOMEM:
4424                         free(nvbuf);
4425                         nvsz = zc.zc_nvlist_dst_size;
4426                         goto tryagain;
4427
4428                 case ENOTSUP:
4429                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4430                             "pool must be upgraded"));
4431                         err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4432                         break;
4433                 case EINVAL:
4434                         err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4435                         break;
4436                 case ENOENT:
4437                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
4438                         break;
4439                 default:
4440                         err = zfs_standard_error_fmt(hdl, errno, errbuf);
4441                         break;
4442                 }
4443         } else {
4444                 /* success */
4445                 int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
4446                 if (rc) {
4447                         (void) snprintf(errbuf, sizeof (errbuf), dgettext(
4448                             TEXT_DOMAIN, "cannot get permissions on '%s'"),
4449                             zc.zc_name);
4450                         err = zfs_standard_error_fmt(hdl, rc, errbuf);
4451                 }
4452         }
4453
4454         free(nvbuf);
4455 out:
4456         return (err);
4457 }
4458
4459 int
4460 zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
4461 {
4462         zfs_cmd_t zc = { 0 };
4463         libzfs_handle_t *hdl = zhp->zfs_hdl;
4464         char *nvbuf;
4465         char errbuf[1024];
4466         size_t nvsz;
4467         int err;
4468
4469         assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4470             zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4471
4472         err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
4473         assert(err == 0);
4474
4475         nvbuf = malloc(nvsz);
4476
4477         err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
4478         assert(err == 0);
4479
4480         zc.zc_nvlist_src_size = nvsz;
4481         zc.zc_nvlist_src = (uintptr_t)nvbuf;
4482         zc.zc_perm_action = un;
4483
4484         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4485
4486         if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
4487                 (void) snprintf(errbuf, sizeof (errbuf),
4488                     dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
4489                     zc.zc_name);
4490                 switch (errno) {
4491                 case ENOTSUP:
4492                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4493                             "pool must be upgraded"));
4494                         err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4495                         break;
4496                 case EINVAL:
4497                         err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4498                         break;
4499                 case ENOENT:
4500                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
4501                         break;
4502                 default:
4503                         err = zfs_standard_error_fmt(hdl, errno, errbuf);
4504                         break;
4505                 }
4506         }
4507
4508         free(nvbuf);
4509
4510         return (err);
4511 }
4512
4513 int
4514 zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
4515 {
4516         int err;
4517         char errbuf[1024];
4518
4519         err = lzc_get_holds(zhp->zfs_name, nvl);
4520
4521         if (err != 0) {
4522                 libzfs_handle_t *hdl = zhp->zfs_hdl;
4523
4524                 (void) snprintf(errbuf, sizeof (errbuf),
4525                     dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
4526                     zhp->zfs_name);
4527                 switch (err) {
4528                 case ENOTSUP:
4529                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4530                             "pool must be upgraded"));
4531                         err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4532                         break;
4533                 case EINVAL:
4534                         err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4535                         break;
4536                 case ENOENT:
4537                         err = zfs_error(hdl, EZFS_NOENT, errbuf);
4538                         break;
4539                 default:
4540                         err = zfs_standard_error_fmt(hdl, errno, errbuf);
4541                         break;
4542                 }
4543         }
4544
4545         return (err);
4546 }
4547
4548 /*
4549  * Convert the zvol's volume size to an appropriate reservation.
4550  * Note: If this routine is updated, it is necessary to update the ZFS test
4551  * suite's shell version in reservation.kshlib.
4552  */
4553 uint64_t
4554 zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
4555 {
4556         uint64_t numdb;
4557         uint64_t nblocks, volblocksize;
4558         int ncopies;
4559         char *strval;
4560
4561         if (nvlist_lookup_string(props,
4562             zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
4563                 ncopies = atoi(strval);
4564         else
4565                 ncopies = 1;
4566         if (nvlist_lookup_uint64(props,
4567             zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
4568             &volblocksize) != 0)
4569                 volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
4570         nblocks = volsize/volblocksize;
4571         /* start with metadnode L0-L6 */
4572         numdb = 7;
4573         /* calculate number of indirects */
4574         while (nblocks > 1) {
4575                 nblocks += DNODES_PER_LEVEL - 1;
4576                 nblocks /= DNODES_PER_LEVEL;
4577                 numdb += nblocks;
4578         }
4579         numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1);
4580         volsize *= ncopies;
4581         /*
4582          * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't
4583          * compressed, but in practice they compress down to about
4584          * 1100 bytes
4585          */
4586         numdb *= 1ULL << DN_MAX_INDBLKSHIFT;
4587         volsize += numdb;
4588         return (volsize);
4589 }
4590
4591 /*
4592  * Attach/detach the given filesystem to/from the given jail.
4593  */
4594 int
4595 zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
4596 {
4597         libzfs_handle_t *hdl = zhp->zfs_hdl;
4598         zfs_cmd_t zc = { 0 };
4599         char errbuf[1024];
4600         unsigned long cmd;
4601         int ret;
4602
4603         if (attach) {
4604                 (void) snprintf(errbuf, sizeof (errbuf),
4605                     dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
4606         } else {
4607                 (void) snprintf(errbuf, sizeof (errbuf),
4608                     dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name);
4609         }
4610
4611         switch (zhp->zfs_type) {
4612         case ZFS_TYPE_VOLUME:
4613                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4614                     "volumes can not be jailed"));
4615                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4616         case ZFS_TYPE_SNAPSHOT:
4617                 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4618                     "snapshots can not be jailed"));
4619                 return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4620         }
4621         assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4622
4623         (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4624         zc.zc_objset_type = DMU_OST_ZFS;
4625         zc.zc_jailid = jailid;
4626
4627         cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL;
4628         if ((ret = ioctl(hdl->libzfs_fd, cmd, &zc)) != 0)
4629                 zfs_standard_error(hdl, errno, errbuf);
4630
4631         return (ret);
4632 }