8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libzfs / common / libzfs_util.c
blobb8a16a08d454c751e81427b67d62db234cf7648d
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
26 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
30 * Internal utility routines for the ZFS library.
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <libintl.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <unistd.h>
41 #include <ctype.h>
42 #include <math.h>
43 #include <sys/filio.h>
44 #include <sys/mnttab.h>
45 #include <sys/mntent.h>
46 #include <sys/types.h>
48 #include <libzfs.h>
49 #include <libzfs_core.h>
51 #include "libzfs_impl.h"
52 #include "zfs_prop.h"
53 #include "zfeature_common.h"
55 int
56 libzfs_errno(libzfs_handle_t *hdl)
58 return (hdl->libzfs_error);
61 const char *
62 libzfs_error_action(libzfs_handle_t *hdl)
64 return (hdl->libzfs_action);
67 const char *
68 libzfs_error_description(libzfs_handle_t *hdl)
70 if (hdl->libzfs_desc[0] != '\0')
71 return (hdl->libzfs_desc);
73 switch (hdl->libzfs_error) {
74 case EZFS_NOMEM:
75 return (dgettext(TEXT_DOMAIN, "out of memory"));
76 case EZFS_BADPROP:
77 return (dgettext(TEXT_DOMAIN, "invalid property value"));
78 case EZFS_PROPREADONLY:
79 return (dgettext(TEXT_DOMAIN, "read-only property"));
80 case EZFS_PROPTYPE:
81 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
82 "datasets of this type"));
83 case EZFS_PROPNONINHERIT:
84 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
85 case EZFS_PROPSPACE:
86 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
87 case EZFS_BADTYPE:
88 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
89 "datasets of this type"));
90 case EZFS_BUSY:
91 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
92 case EZFS_EXISTS:
93 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
94 case EZFS_NOENT:
95 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
96 case EZFS_BADSTREAM:
97 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
98 case EZFS_DSREADONLY:
99 return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
100 case EZFS_VOLTOOBIG:
101 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
102 "this system"));
103 case EZFS_INVALIDNAME:
104 return (dgettext(TEXT_DOMAIN, "invalid name"));
105 case EZFS_BADRESTORE:
106 return (dgettext(TEXT_DOMAIN, "unable to restore to "
107 "destination"));
108 case EZFS_BADBACKUP:
109 return (dgettext(TEXT_DOMAIN, "backup failed"));
110 case EZFS_BADTARGET:
111 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
112 case EZFS_NODEVICE:
113 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
114 case EZFS_BADDEV:
115 return (dgettext(TEXT_DOMAIN, "invalid device"));
116 case EZFS_NOREPLICAS:
117 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
118 case EZFS_RESILVERING:
119 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
120 case EZFS_BADVERSION:
121 return (dgettext(TEXT_DOMAIN, "unsupported version or "
122 "feature"));
123 case EZFS_POOLUNAVAIL:
124 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
125 case EZFS_DEVOVERFLOW:
126 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
127 case EZFS_BADPATH:
128 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
129 case EZFS_CROSSTARGET:
130 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
131 "pools"));
132 case EZFS_ZONED:
133 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
134 case EZFS_MOUNTFAILED:
135 return (dgettext(TEXT_DOMAIN, "mount failed"));
136 case EZFS_UMOUNTFAILED:
137 return (dgettext(TEXT_DOMAIN, "umount failed"));
138 case EZFS_UNSHARENFSFAILED:
139 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
140 case EZFS_SHARENFSFAILED:
141 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
142 case EZFS_UNSHARESMBFAILED:
143 return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
144 case EZFS_SHARESMBFAILED:
145 return (dgettext(TEXT_DOMAIN, "smb add share failed"));
146 case EZFS_PERM:
147 return (dgettext(TEXT_DOMAIN, "permission denied"));
148 case EZFS_NOSPC:
149 return (dgettext(TEXT_DOMAIN, "out of space"));
150 case EZFS_FAULT:
151 return (dgettext(TEXT_DOMAIN, "bad address"));
152 case EZFS_IO:
153 return (dgettext(TEXT_DOMAIN, "I/O error"));
154 case EZFS_INTR:
155 return (dgettext(TEXT_DOMAIN, "signal received"));
156 case EZFS_ISSPARE:
157 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
158 "spare"));
159 case EZFS_INVALCONFIG:
160 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
161 case EZFS_RECURSIVE:
162 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
163 case EZFS_NOHISTORY:
164 return (dgettext(TEXT_DOMAIN, "no history available"));
165 case EZFS_POOLPROPS:
166 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
167 "pool properties"));
168 case EZFS_POOL_NOTSUP:
169 return (dgettext(TEXT_DOMAIN, "operation not supported "
170 "on this type of pool"));
171 case EZFS_POOL_INVALARG:
172 return (dgettext(TEXT_DOMAIN, "invalid argument for "
173 "this pool operation"));
174 case EZFS_NAMETOOLONG:
175 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
176 case EZFS_OPENFAILED:
177 return (dgettext(TEXT_DOMAIN, "open failed"));
178 case EZFS_NOCAP:
179 return (dgettext(TEXT_DOMAIN,
180 "disk capacity information could not be retrieved"));
181 case EZFS_LABELFAILED:
182 return (dgettext(TEXT_DOMAIN, "write of label failed"));
183 case EZFS_BADWHO:
184 return (dgettext(TEXT_DOMAIN, "invalid user/group"));
185 case EZFS_BADPERM:
186 return (dgettext(TEXT_DOMAIN, "invalid permission"));
187 case EZFS_BADPERMSET:
188 return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
189 case EZFS_NODELEGATION:
190 return (dgettext(TEXT_DOMAIN, "delegated administration is "
191 "disabled on pool"));
192 case EZFS_BADCACHE:
193 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
194 case EZFS_ISL2CACHE:
195 return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
196 case EZFS_VDEVNOTSUP:
197 return (dgettext(TEXT_DOMAIN, "vdev specification is not "
198 "supported"));
199 case EZFS_NOTSUP:
200 return (dgettext(TEXT_DOMAIN, "operation not supported "
201 "on this dataset"));
202 case EZFS_ACTIVE_SPARE:
203 return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
204 "device"));
205 case EZFS_UNPLAYED_LOGS:
206 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
207 "logs"));
208 case EZFS_REFTAG_RELE:
209 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
210 case EZFS_REFTAG_HOLD:
211 return (dgettext(TEXT_DOMAIN, "tag already exists on this "
212 "dataset"));
213 case EZFS_TAGTOOLONG:
214 return (dgettext(TEXT_DOMAIN, "tag too long"));
215 case EZFS_PIPEFAILED:
216 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
217 case EZFS_THREADCREATEFAILED:
218 return (dgettext(TEXT_DOMAIN, "thread create failed"));
219 case EZFS_POSTSPLIT_ONLINE:
220 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
221 "into a new one"));
222 case EZFS_SCRUBBING:
223 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
224 "use 'zpool scrub -s' to cancel current scrub"));
225 case EZFS_NO_SCRUB:
226 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
227 case EZFS_DIFF:
228 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
229 case EZFS_DIFFDATA:
230 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
231 case EZFS_POOLREADONLY:
232 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
233 case EZFS_UNKNOWN:
234 return (dgettext(TEXT_DOMAIN, "unknown error"));
235 default:
236 assert(hdl->libzfs_error == 0);
237 return (dgettext(TEXT_DOMAIN, "no error"));
241 /*PRINTFLIKE2*/
242 void
243 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
245 va_list ap;
247 va_start(ap, fmt);
249 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
250 fmt, ap);
251 hdl->libzfs_desc_active = 1;
253 va_end(ap);
256 static void
257 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
259 (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
260 fmt, ap);
261 hdl->libzfs_error = error;
263 if (hdl->libzfs_desc_active)
264 hdl->libzfs_desc_active = 0;
265 else
266 hdl->libzfs_desc[0] = '\0';
268 if (hdl->libzfs_printerr) {
269 if (error == EZFS_UNKNOWN) {
270 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
271 "error: %s\n"), libzfs_error_description(hdl));
272 abort();
275 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
276 libzfs_error_description(hdl));
277 if (error == EZFS_NOMEM)
278 exit(1);
283 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
285 return (zfs_error_fmt(hdl, error, "%s", msg));
288 /*PRINTFLIKE3*/
290 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
292 va_list ap;
294 va_start(ap, fmt);
296 zfs_verror(hdl, error, fmt, ap);
298 va_end(ap);
300 return (-1);
303 static int
304 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
305 va_list ap)
307 switch (error) {
308 case EPERM:
309 case EACCES:
310 zfs_verror(hdl, EZFS_PERM, fmt, ap);
311 return (-1);
313 case ECANCELED:
314 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
315 return (-1);
317 case EIO:
318 zfs_verror(hdl, EZFS_IO, fmt, ap);
319 return (-1);
321 case EFAULT:
322 zfs_verror(hdl, EZFS_FAULT, fmt, ap);
323 return (-1);
325 case EINTR:
326 zfs_verror(hdl, EZFS_INTR, fmt, ap);
327 return (-1);
330 return (0);
334 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
336 return (zfs_standard_error_fmt(hdl, error, "%s", msg));
339 /*PRINTFLIKE3*/
341 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
343 va_list ap;
345 va_start(ap, fmt);
347 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
348 va_end(ap);
349 return (-1);
352 switch (error) {
353 case ENXIO:
354 case ENODEV:
355 case EPIPE:
356 zfs_verror(hdl, EZFS_IO, fmt, ap);
357 break;
359 case ENOENT:
360 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
361 "dataset does not exist"));
362 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
363 break;
365 case ENOSPC:
366 case EDQUOT:
367 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
368 return (-1);
370 case EEXIST:
371 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
372 "dataset already exists"));
373 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
374 break;
376 case EBUSY:
377 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
378 "dataset is busy"));
379 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
380 break;
381 case EROFS:
382 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
383 break;
384 case ENAMETOOLONG:
385 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
386 break;
387 case ENOTSUP:
388 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
389 break;
390 case EAGAIN:
391 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
392 "pool I/O is currently suspended"));
393 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
394 break;
395 default:
396 zfs_error_aux(hdl, strerror(error));
397 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
398 break;
401 va_end(ap);
402 return (-1);
406 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
408 return (zpool_standard_error_fmt(hdl, error, "%s", msg));
411 /*PRINTFLIKE3*/
413 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
415 va_list ap;
417 va_start(ap, fmt);
419 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
420 va_end(ap);
421 return (-1);
424 switch (error) {
425 case ENODEV:
426 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
427 break;
429 case ENOENT:
430 zfs_error_aux(hdl,
431 dgettext(TEXT_DOMAIN, "no such pool or dataset"));
432 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
433 break;
435 case EEXIST:
436 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
437 "pool already exists"));
438 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
439 break;
441 case EBUSY:
442 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
443 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
444 break;
446 case ENXIO:
447 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
448 "one or more devices is currently unavailable"));
449 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
450 break;
452 case ENAMETOOLONG:
453 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
454 break;
456 case ENOTSUP:
457 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
458 break;
460 case EINVAL:
461 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
462 break;
464 case ENOSPC:
465 case EDQUOT:
466 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
467 return (-1);
469 case EAGAIN:
470 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
471 "pool I/O is currently suspended"));
472 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
473 break;
475 case EROFS:
476 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
477 break;
479 default:
480 zfs_error_aux(hdl, strerror(error));
481 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
484 va_end(ap);
485 return (-1);
489 * Display an out of memory error message and abort the current program.
492 no_memory(libzfs_handle_t *hdl)
494 return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
498 * A safe form of malloc() which will die if the allocation fails.
500 void *
501 zfs_alloc(libzfs_handle_t *hdl, size_t size)
503 void *data;
505 if ((data = calloc(1, size)) == NULL)
506 (void) no_memory(hdl);
508 return (data);
512 * A safe form of asprintf() which will die if the allocation fails.
514 /*PRINTFLIKE2*/
515 char *
516 zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
518 va_list ap;
519 char *ret;
520 int err;
522 va_start(ap, fmt);
524 err = vasprintf(&ret, fmt, ap);
526 va_end(ap);
528 if (err < 0)
529 (void) no_memory(hdl);
531 return (ret);
535 * A safe form of realloc(), which also zeroes newly allocated space.
537 void *
538 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
540 void *ret;
542 if ((ret = realloc(ptr, newsize)) == NULL) {
543 (void) no_memory(hdl);
544 return (NULL);
547 bzero((char *)ret + oldsize, (newsize - oldsize));
548 return (ret);
552 * A safe form of strdup() which will die if the allocation fails.
554 char *
555 zfs_strdup(libzfs_handle_t *hdl, const char *str)
557 char *ret;
559 if ((ret = strdup(str)) == NULL)
560 (void) no_memory(hdl);
562 return (ret);
566 * Convert a number to an appropriately human-readable output.
568 void
569 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
571 uint64_t n = num;
572 int index = 0;
573 char u;
575 while (n >= 1024) {
576 n /= 1024;
577 index++;
580 u = " KMGTPE"[index];
582 if (index == 0) {
583 (void) snprintf(buf, buflen, "%llu", n);
584 } else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
586 * If this is an even multiple of the base, always display
587 * without any decimal precision.
589 (void) snprintf(buf, buflen, "%llu%c", n, u);
590 } else {
592 * We want to choose a precision that reflects the best choice
593 * for fitting in 5 characters. This can get rather tricky when
594 * we have numbers that are very close to an order of magnitude.
595 * For example, when displaying 10239 (which is really 9.999K),
596 * we want only a single place of precision for 10.0K. We could
597 * develop some complex heuristics for this, but it's much
598 * easier just to try each combination in turn.
600 int i;
601 for (i = 2; i >= 0; i--) {
602 if (snprintf(buf, buflen, "%.*f%c", i,
603 (double)num / (1ULL << 10 * index), u) <= 5)
604 break;
609 void
610 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
612 hdl->libzfs_printerr = printerr;
615 libzfs_handle_t *
616 libzfs_init(void)
618 libzfs_handle_t *hdl;
620 if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
621 return (NULL);
624 if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
625 free(hdl);
626 return (NULL);
629 if ((hdl->libzfs_mnttab = fopen(MNTTAB, "rF")) == NULL) {
630 (void) close(hdl->libzfs_fd);
631 free(hdl);
632 return (NULL);
635 hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "rF");
637 if (libzfs_core_init() != 0) {
638 (void) close(hdl->libzfs_fd);
639 (void) fclose(hdl->libzfs_mnttab);
640 (void) fclose(hdl->libzfs_sharetab);
641 free(hdl);
642 return (NULL);
645 zfs_prop_init();
646 zpool_prop_init();
647 zpool_feature_init();
648 libzfs_mnttab_init(hdl);
650 return (hdl);
653 void
654 libzfs_fini(libzfs_handle_t *hdl)
656 (void) close(hdl->libzfs_fd);
657 if (hdl->libzfs_mnttab)
658 (void) fclose(hdl->libzfs_mnttab);
659 if (hdl->libzfs_sharetab)
660 (void) fclose(hdl->libzfs_sharetab);
661 zfs_uninit_libshare(hdl);
662 zpool_free_handles(hdl);
663 libzfs_fru_clear(hdl, B_TRUE);
664 namespace_clear(hdl);
665 libzfs_mnttab_fini(hdl);
666 libzfs_core_fini();
667 free(hdl);
670 libzfs_handle_t *
671 zpool_get_handle(zpool_handle_t *zhp)
673 return (zhp->zpool_hdl);
676 libzfs_handle_t *
677 zfs_get_handle(zfs_handle_t *zhp)
679 return (zhp->zfs_hdl);
682 zpool_handle_t *
683 zfs_get_pool_handle(const zfs_handle_t *zhp)
685 return (zhp->zpool_hdl);
689 * Given a name, determine whether or not it's a valid path
690 * (starts with '/' or "./"). If so, walk the mnttab trying
691 * to match the device number. If not, treat the path as an
692 * fs/vol/snap/bkmark name.
694 zfs_handle_t *
695 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
697 struct stat64 statbuf;
698 struct extmnttab entry;
699 int ret;
701 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
703 * It's not a valid path, assume it's a name of type 'argtype'.
705 return (zfs_open(hdl, path, argtype));
708 if (stat64(path, &statbuf) != 0) {
709 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
710 return (NULL);
713 rewind(hdl->libzfs_mnttab);
714 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
715 if (makedevice(entry.mnt_major, entry.mnt_minor) ==
716 statbuf.st_dev) {
717 break;
720 if (ret != 0) {
721 return (NULL);
724 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
725 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
726 path);
727 return (NULL);
730 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
734 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
735 * an ioctl().
738 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
740 if (len == 0)
741 len = 16 * 1024;
742 zc->zc_nvlist_dst_size = len;
743 zc->zc_nvlist_dst =
744 (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
745 if (zc->zc_nvlist_dst == 0)
746 return (-1);
748 return (0);
752 * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will
753 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
754 * filled in by the kernel to indicate the actual required size.
757 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
759 free((void *)(uintptr_t)zc->zc_nvlist_dst);
760 zc->zc_nvlist_dst =
761 (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
762 if (zc->zc_nvlist_dst == 0)
763 return (-1);
765 return (0);
769 * Called to free the src and dst nvlists stored in the command structure.
771 void
772 zcmd_free_nvlists(zfs_cmd_t *zc)
774 free((void *)(uintptr_t)zc->zc_nvlist_conf);
775 free((void *)(uintptr_t)zc->zc_nvlist_src);
776 free((void *)(uintptr_t)zc->zc_nvlist_dst);
777 zc->zc_nvlist_conf = NULL;
778 zc->zc_nvlist_src = NULL;
779 zc->zc_nvlist_dst = NULL;
782 static int
783 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
784 nvlist_t *nvl)
786 char *packed;
787 size_t len;
789 verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
791 if ((packed = zfs_alloc(hdl, len)) == NULL)
792 return (-1);
794 verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
796 *outnv = (uint64_t)(uintptr_t)packed;
797 *outlen = len;
799 return (0);
803 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
805 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
806 &zc->zc_nvlist_conf_size, nvl));
810 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
812 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
813 &zc->zc_nvlist_src_size, nvl));
817 * Unpacks an nvlist from the ZFS ioctl command structure.
820 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
822 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
823 zc->zc_nvlist_dst_size, nvlp, 0) != 0)
824 return (no_memory(hdl));
826 return (0);
830 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
832 return (ioctl(hdl->libzfs_fd, request, zc));
836 * ================================================================
837 * API shared by zfs and zpool property management
838 * ================================================================
841 static void
842 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
844 zprop_list_t *pl = cbp->cb_proplist;
845 int i;
846 char *title;
847 size_t len;
849 cbp->cb_first = B_FALSE;
850 if (cbp->cb_scripted)
851 return;
854 * Start with the length of the column headers.
856 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
857 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
858 "PROPERTY"));
859 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
860 "VALUE"));
861 cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
862 "RECEIVED"));
863 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
864 "SOURCE"));
866 /* first property is always NAME */
867 assert(cbp->cb_proplist->pl_prop ==
868 ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME));
871 * Go through and calculate the widths for each column. For the
872 * 'source' column, we kludge it up by taking the worst-case scenario of
873 * inheriting from the longest name. This is acceptable because in the
874 * majority of cases 'SOURCE' is the last column displayed, and we don't
875 * use the width anyway. Note that the 'VALUE' column can be oversized,
876 * if the name of the property is much longer than any values we find.
878 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
880 * 'PROPERTY' column
882 if (pl->pl_prop != ZPROP_INVAL) {
883 const char *propname = (type == ZFS_TYPE_POOL) ?
884 zpool_prop_to_name(pl->pl_prop) :
885 zfs_prop_to_name(pl->pl_prop);
887 len = strlen(propname);
888 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
889 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
890 } else {
891 len = strlen(pl->pl_user_prop);
892 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
893 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
897 * 'VALUE' column. The first property is always the 'name'
898 * property that was tacked on either by /sbin/zfs's
899 * zfs_do_get() or when calling zprop_expand_list(), so we
900 * ignore its width. If the user specified the name property
901 * to display, then it will be later in the list in any case.
903 if (pl != cbp->cb_proplist &&
904 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
905 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
907 /* 'RECEIVED' column. */
908 if (pl != cbp->cb_proplist &&
909 pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
910 cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
913 * 'NAME' and 'SOURCE' columns
915 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
916 ZFS_PROP_NAME) &&
917 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
918 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
919 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
920 strlen(dgettext(TEXT_DOMAIN, "inherited from"));
925 * Now go through and print the headers.
927 for (i = 0; i < ZFS_GET_NCOLS; i++) {
928 switch (cbp->cb_columns[i]) {
929 case GET_COL_NAME:
930 title = dgettext(TEXT_DOMAIN, "NAME");
931 break;
932 case GET_COL_PROPERTY:
933 title = dgettext(TEXT_DOMAIN, "PROPERTY");
934 break;
935 case GET_COL_VALUE:
936 title = dgettext(TEXT_DOMAIN, "VALUE");
937 break;
938 case GET_COL_RECVD:
939 title = dgettext(TEXT_DOMAIN, "RECEIVED");
940 break;
941 case GET_COL_SOURCE:
942 title = dgettext(TEXT_DOMAIN, "SOURCE");
943 break;
944 default:
945 title = NULL;
948 if (title != NULL) {
949 if (i == (ZFS_GET_NCOLS - 1) ||
950 cbp->cb_columns[i + 1] == GET_COL_NONE)
951 (void) printf("%s", title);
952 else
953 (void) printf("%-*s ",
954 cbp->cb_colwidths[cbp->cb_columns[i]],
955 title);
958 (void) printf("\n");
962 * Display a single line of output, according to the settings in the callback
963 * structure.
965 void
966 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
967 const char *propname, const char *value, zprop_source_t sourcetype,
968 const char *source, const char *recvd_value)
970 int i;
971 const char *str = NULL;
972 char buf[128];
975 * Ignore those source types that the user has chosen to ignore.
977 if ((sourcetype & cbp->cb_sources) == 0)
978 return;
980 if (cbp->cb_first)
981 zprop_print_headers(cbp, cbp->cb_type);
983 for (i = 0; i < ZFS_GET_NCOLS; i++) {
984 switch (cbp->cb_columns[i]) {
985 case GET_COL_NAME:
986 str = name;
987 break;
989 case GET_COL_PROPERTY:
990 str = propname;
991 break;
993 case GET_COL_VALUE:
994 str = value;
995 break;
997 case GET_COL_SOURCE:
998 switch (sourcetype) {
999 case ZPROP_SRC_NONE:
1000 str = "-";
1001 break;
1003 case ZPROP_SRC_DEFAULT:
1004 str = "default";
1005 break;
1007 case ZPROP_SRC_LOCAL:
1008 str = "local";
1009 break;
1011 case ZPROP_SRC_TEMPORARY:
1012 str = "temporary";
1013 break;
1015 case ZPROP_SRC_INHERITED:
1016 (void) snprintf(buf, sizeof (buf),
1017 "inherited from %s", source);
1018 str = buf;
1019 break;
1020 case ZPROP_SRC_RECEIVED:
1021 str = "received";
1022 break;
1024 default:
1025 str = NULL;
1026 assert(!"unhandled zprop_source_t");
1028 break;
1030 case GET_COL_RECVD:
1031 str = (recvd_value == NULL ? "-" : recvd_value);
1032 break;
1034 default:
1035 continue;
1038 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1039 (void) printf("%s", str);
1040 else if (cbp->cb_scripted)
1041 (void) printf("%s\t", str);
1042 else
1043 (void) printf("%-*s ",
1044 cbp->cb_colwidths[cbp->cb_columns[i]],
1045 str);
1048 (void) printf("\n");
1052 * Given a numeric suffix, convert the value into a number of bits that the
1053 * resulting value must be shifted.
1055 static int
1056 str2shift(libzfs_handle_t *hdl, const char *buf)
1058 const char *ends = "BKMGTPEZ";
1059 int i;
1061 if (buf[0] == '\0')
1062 return (0);
1063 for (i = 0; i < strlen(ends); i++) {
1064 if (toupper(buf[0]) == ends[i])
1065 break;
1067 if (i == strlen(ends)) {
1068 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1069 "invalid numeric suffix '%s'"), buf);
1070 return (-1);
1074 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
1075 * allow 'BB' - that's just weird.
1077 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1078 toupper(buf[0]) != 'B'))
1079 return (10*i);
1081 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1082 "invalid numeric suffix '%s'"), buf);
1083 return (-1);
1087 * Convert a string of the form '100G' into a real number. Used when setting
1088 * properties or creating a volume. 'buf' is used to place an extended error
1089 * message for the caller to use.
1092 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1094 char *end;
1095 int shift;
1097 *num = 0;
1099 /* Check to see if this looks like a number. */
1100 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1101 if (hdl)
1102 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1103 "bad numeric value '%s'"), value);
1104 return (-1);
1107 /* Rely on strtoull() to process the numeric portion. */
1108 errno = 0;
1109 *num = strtoull(value, &end, 10);
1112 * Check for ERANGE, which indicates that the value is too large to fit
1113 * in a 64-bit value.
1115 if (errno == ERANGE) {
1116 if (hdl)
1117 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1118 "numeric value is too large"));
1119 return (-1);
1123 * If we have a decimal value, then do the computation with floating
1124 * point arithmetic. Otherwise, use standard arithmetic.
1126 if (*end == '.') {
1127 double fval = strtod(value, &end);
1129 if ((shift = str2shift(hdl, end)) == -1)
1130 return (-1);
1132 fval *= pow(2, shift);
1134 if (fval > UINT64_MAX) {
1135 if (hdl)
1136 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1137 "numeric value is too large"));
1138 return (-1);
1141 *num = (uint64_t)fval;
1142 } else {
1143 if ((shift = str2shift(hdl, end)) == -1)
1144 return (-1);
1146 /* Check for overflow */
1147 if (shift >= 64 || (*num << shift) >> shift != *num) {
1148 if (hdl)
1149 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1150 "numeric value is too large"));
1151 return (-1);
1154 *num <<= shift;
1157 return (0);
1161 * Given a propname=value nvpair to set, parse any numeric properties
1162 * (index, boolean, etc) if they are specified as strings and add the
1163 * resulting nvpair to the returned nvlist.
1165 * At the DSL layer, all properties are either 64-bit numbers or strings.
1166 * We want the user to be able to ignore this fact and specify properties
1167 * as native values (numbers, for example) or as strings (to simplify
1168 * command line utilities). This also handles converting index types
1169 * (compression, checksum, etc) from strings to their on-disk index.
1172 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1173 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1174 const char *errbuf)
1176 data_type_t datatype = nvpair_type(elem);
1177 zprop_type_t proptype;
1178 const char *propname;
1179 char *value;
1180 boolean_t isnone = B_FALSE;
1182 if (type == ZFS_TYPE_POOL) {
1183 proptype = zpool_prop_get_type(prop);
1184 propname = zpool_prop_to_name(prop);
1185 } else {
1186 proptype = zfs_prop_get_type(prop);
1187 propname = zfs_prop_to_name(prop);
1191 * Convert any properties to the internal DSL value types.
1193 *svalp = NULL;
1194 *ivalp = 0;
1196 switch (proptype) {
1197 case PROP_TYPE_STRING:
1198 if (datatype != DATA_TYPE_STRING) {
1199 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1200 "'%s' must be a string"), nvpair_name(elem));
1201 goto error;
1203 (void) nvpair_value_string(elem, svalp);
1204 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1205 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1206 "'%s' is too long"), nvpair_name(elem));
1207 goto error;
1209 break;
1211 case PROP_TYPE_NUMBER:
1212 if (datatype == DATA_TYPE_STRING) {
1213 (void) nvpair_value_string(elem, &value);
1214 if (strcmp(value, "none") == 0) {
1215 isnone = B_TRUE;
1216 } else if (zfs_nicestrtonum(hdl, value, ivalp)
1217 != 0) {
1218 goto error;
1220 } else if (datatype == DATA_TYPE_UINT64) {
1221 (void) nvpair_value_uint64(elem, ivalp);
1222 } else {
1223 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1224 "'%s' must be a number"), nvpair_name(elem));
1225 goto error;
1229 * Quota special: force 'none' and don't allow 0.
1231 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1232 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1233 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1234 "use 'none' to disable quota/refquota"));
1235 goto error;
1239 * Special handling for "*_limit=none". In this case it's not
1240 * 0 but UINT64_MAX.
1242 if ((type & ZFS_TYPE_DATASET) && isnone &&
1243 (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
1244 prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
1245 *ivalp = UINT64_MAX;
1247 break;
1249 case PROP_TYPE_INDEX:
1250 if (datatype != DATA_TYPE_STRING) {
1251 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1252 "'%s' must be a string"), nvpair_name(elem));
1253 goto error;
1256 (void) nvpair_value_string(elem, &value);
1258 if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1259 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1260 "'%s' must be one of '%s'"), propname,
1261 zprop_values(prop, type));
1262 goto error;
1264 break;
1266 default:
1267 abort();
1271 * Add the result to our return set of properties.
1273 if (*svalp != NULL) {
1274 if (nvlist_add_string(ret, propname, *svalp) != 0) {
1275 (void) no_memory(hdl);
1276 return (-1);
1278 } else {
1279 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1280 (void) no_memory(hdl);
1281 return (-1);
1285 return (0);
1286 error:
1287 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1288 return (-1);
1291 static int
1292 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1293 zfs_type_t type)
1295 int prop;
1296 zprop_list_t *entry;
1298 prop = zprop_name_to_prop(propname, type);
1300 if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1301 prop = ZPROP_INVAL;
1304 * When no property table entry can be found, return failure if
1305 * this is a pool property or if this isn't a user-defined
1306 * dataset property,
1308 if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1309 !zpool_prop_feature(propname) &&
1310 !zpool_prop_unsupported(propname)) ||
1311 (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
1312 !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1313 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1314 "invalid property '%s'"), propname);
1315 return (zfs_error(hdl, EZFS_BADPROP,
1316 dgettext(TEXT_DOMAIN, "bad property list")));
1319 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1320 return (-1);
1322 entry->pl_prop = prop;
1323 if (prop == ZPROP_INVAL) {
1324 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
1325 NULL) {
1326 free(entry);
1327 return (-1);
1329 entry->pl_width = strlen(propname);
1330 } else {
1331 entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1332 type);
1335 *listp = entry;
1337 return (0);
1341 * Given a comma-separated list of properties, construct a property list
1342 * containing both user-defined and native properties. This function will
1343 * return a NULL list if 'all' is specified, which can later be expanded
1344 * by zprop_expand_list().
1347 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1348 zfs_type_t type)
1350 *listp = NULL;
1353 * If 'all' is specified, return a NULL list.
1355 if (strcmp(props, "all") == 0)
1356 return (0);
1359 * If no props were specified, return an error.
1361 if (props[0] == '\0') {
1362 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1363 "no properties specified"));
1364 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1365 "bad property list")));
1369 * It would be nice to use getsubopt() here, but the inclusion of column
1370 * aliases makes this more effort than it's worth.
1372 while (*props != '\0') {
1373 size_t len;
1374 char *p;
1375 char c;
1377 if ((p = strchr(props, ',')) == NULL) {
1378 len = strlen(props);
1379 p = props + len;
1380 } else {
1381 len = p - props;
1385 * Check for empty options.
1387 if (len == 0) {
1388 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1389 "empty property name"));
1390 return (zfs_error(hdl, EZFS_BADPROP,
1391 dgettext(TEXT_DOMAIN, "bad property list")));
1395 * Check all regular property names.
1397 c = props[len];
1398 props[len] = '\0';
1400 if (strcmp(props, "space") == 0) {
1401 static char *spaceprops[] = {
1402 "name", "avail", "used", "usedbysnapshots",
1403 "usedbydataset", "usedbyrefreservation",
1404 "usedbychildren", NULL
1406 int i;
1408 for (i = 0; spaceprops[i]; i++) {
1409 if (addlist(hdl, spaceprops[i], listp, type))
1410 return (-1);
1411 listp = &(*listp)->pl_next;
1413 } else {
1414 if (addlist(hdl, props, listp, type))
1415 return (-1);
1416 listp = &(*listp)->pl_next;
1419 props = p;
1420 if (c == ',')
1421 props++;
1424 return (0);
1427 void
1428 zprop_free_list(zprop_list_t *pl)
1430 zprop_list_t *next;
1432 while (pl != NULL) {
1433 next = pl->pl_next;
1434 free(pl->pl_user_prop);
1435 free(pl);
1436 pl = next;
1440 typedef struct expand_data {
1441 zprop_list_t **last;
1442 libzfs_handle_t *hdl;
1443 zfs_type_t type;
1444 } expand_data_t;
1447 zprop_expand_list_cb(int prop, void *cb)
1449 zprop_list_t *entry;
1450 expand_data_t *edp = cb;
1452 if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1453 return (ZPROP_INVAL);
1455 entry->pl_prop = prop;
1456 entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1457 entry->pl_all = B_TRUE;
1459 *(edp->last) = entry;
1460 edp->last = &entry->pl_next;
1462 return (ZPROP_CONT);
1466 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1468 zprop_list_t *entry;
1469 zprop_list_t **last;
1470 expand_data_t exp;
1472 if (*plp == NULL) {
1474 * If this is the very first time we've been called for an 'all'
1475 * specification, expand the list to include all native
1476 * properties.
1478 last = plp;
1480 exp.last = last;
1481 exp.hdl = hdl;
1482 exp.type = type;
1484 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1485 B_FALSE, type) == ZPROP_INVAL)
1486 return (-1);
1489 * Add 'name' to the beginning of the list, which is handled
1490 * specially.
1492 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1493 return (-1);
1495 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
1496 ZFS_PROP_NAME;
1497 entry->pl_width = zprop_width(entry->pl_prop,
1498 &entry->pl_fixed, type);
1499 entry->pl_all = B_TRUE;
1500 entry->pl_next = *plp;
1501 *plp = entry;
1503 return (0);
1507 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1508 zfs_type_t type)
1510 return (zprop_iter_common(func, cb, show_all, ordered, type));
1514 * zfs_get_hole_count retrieves the number of holes (blocks which are
1515 * zero-filled) in the specified file using the _FIO_COUNT_FILLED ioctl. It
1516 * also optionally fetches the block size when bs is non-NULL. With hole count
1517 * and block size the full space consumed by the holes of a file can be
1518 * calculated.
1520 * On success, zero is returned, the count argument is set to the
1521 * number of holes, and the bs argument is set to the block size (if it is
1522 * not NULL). On error, a non-zero errno is returned and the values in count
1523 * and bs are undefined.
1526 zfs_get_hole_count(const char *path, uint64_t *count, uint64_t *bs)
1528 int fd, err;
1529 struct stat64 ss;
1530 uint64_t fill;
1532 fd = open(path, O_RDONLY | O_LARGEFILE);
1533 if (fd == -1)
1534 return (errno);
1536 if (ioctl(fd, _FIO_COUNT_FILLED, &fill) == -1) {
1537 err = errno;
1538 (void) close(fd);
1539 return (err);
1542 if (fstat64(fd, &ss) == -1) {
1543 err = errno;
1544 (void) close(fd);
1545 return (err);
1548 *count = (ss.st_size + ss.st_blksize - 1) / ss.st_blksize - fill;
1549 VERIFY3S(*count, >=, 0);
1550 if (bs != NULL) {
1551 *bs = ss.st_blksize;
1554 if (close(fd) == -1) {
1555 return (errno);
1557 return (0);