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