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