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