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