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