5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (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>
27 * Copyright (c) 2017 Datto Inc.
28 */
29
30 /*
31 * Internal utility routines for the ZFS library.
32 */
33
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <libintl.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <strings.h>
41 #include <unistd.h>
42 #include <ctype.h>
43 #include <math.h>
44 #include <sys/filio.h>
218 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
219 case EZFS_THREADCREATEFAILED:
220 return (dgettext(TEXT_DOMAIN, "thread create failed"));
221 case EZFS_POSTSPLIT_ONLINE:
222 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
223 "into a new one"));
224 case EZFS_SCRUB_PAUSED:
225 return (dgettext(TEXT_DOMAIN, "scrub is paused; "
226 "use 'zpool scrub' to resume"));
227 case EZFS_SCRUBBING:
228 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
229 "use 'zpool scrub -s' to cancel current scrub"));
230 case EZFS_NO_SCRUB:
231 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
232 case EZFS_DIFF:
233 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
234 case EZFS_DIFFDATA:
235 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
236 case EZFS_POOLREADONLY:
237 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
238 case EZFS_NO_PENDING:
239 return (dgettext(TEXT_DOMAIN, "operation is not "
240 "in progress"));
241 case EZFS_UNKNOWN:
242 return (dgettext(TEXT_DOMAIN, "unknown error"));
243 default:
244 assert(hdl->libzfs_error == 0);
245 return (dgettext(TEXT_DOMAIN, "no error"));
246 }
247 }
248
249 /*PRINTFLIKE2*/
250 void
251 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
252 {
253 va_list ap;
254
255 va_start(ap, fmt);
256
257 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
258 fmt, ap);
259 hdl->libzfs_desc_active = 1;
260
372
373 case ENOSPC:
374 case EDQUOT:
375 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
376 return (-1);
377
378 case EEXIST:
379 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
380 "dataset already exists"));
381 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
382 break;
383
384 case EBUSY:
385 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
386 "dataset is busy"));
387 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
388 break;
389 case EROFS:
390 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
391 break;
392 case ENAMETOOLONG:
393 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
394 break;
395 case ENOTSUP:
396 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
397 break;
398 case EAGAIN:
399 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
400 "pool I/O is currently suspended"));
401 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
402 break;
403 default:
404 zfs_error_aux(hdl, strerror(error));
405 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
406 break;
407 }
408
409 va_end(ap);
410 return (-1);
411 }
412
413 int
414 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
415 {
416 return (zpool_standard_error_fmt(hdl, error, "%s", msg));
417 }
418
419 /*PRINTFLIKE3*/
420 int
421 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
422 {
423 va_list ap;
424
425 va_start(ap, fmt);
426
427 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
428 va_end(ap);
429 return (-1);
430 }
431
432 switch (error) {
433 case ENODEV:
434 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
435 break;
436
437 case ENOENT:
438 zfs_error_aux(hdl,
439 dgettext(TEXT_DOMAIN, "no such pool or dataset"));
440 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
441 break;
442
443 case EEXIST:
444 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
445 "pool already exists"));
446 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
447 break;
448
449 case EBUSY:
450 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
451 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
452 break;
453
454 case ENXIO:
455 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
456 "one or more devices is currently unavailable"));
457 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
458 break;
459
460 case ENAMETOOLONG:
461 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
462 break;
463
464 case ENOTSUP:
465 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
466 break;
467
468 case EINVAL:
469 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
470 break;
471
472 case ENOSPC:
473 case EDQUOT:
474 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
475 return (-1);
476
477 case EAGAIN:
478 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
479 "pool I/O is currently suspended"));
480 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
481 break;
482
483 case EROFS:
484 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
485 break;
486 /* There is no pending operation to cancel */
487 case ENOTACTIVE:
488 zfs_verror(hdl, EZFS_NO_PENDING, fmt, ap);
489 break;
490
491 default:
492 zfs_error_aux(hdl, strerror(error));
493 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
494 }
495
496 va_end(ap);
497 return (-1);
498 }
499
500 /*
501 * Display an out of memory error message and abort the current program.
502 */
503 int
504 no_memory(libzfs_handle_t *hdl)
505 {
506 return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
507 }
508
509 /*
605
606 if ((hdl->libzfs_mnttab = fopen(MNTTAB, "rF")) == NULL) {
607 (void) close(hdl->libzfs_fd);
608 free(hdl);
609 return (NULL);
610 }
611
612 hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "rF");
613
614 if (libzfs_core_init() != 0) {
615 (void) close(hdl->libzfs_fd);
616 (void) fclose(hdl->libzfs_mnttab);
617 (void) fclose(hdl->libzfs_sharetab);
618 free(hdl);
619 return (NULL);
620 }
621
622 zfs_prop_init();
623 zpool_prop_init();
624 zpool_feature_init();
625 libzfs_mnttab_init(hdl);
626
627 if (getenv("ZFS_PROP_DEBUG") != NULL) {
628 hdl->libzfs_prop_debug = B_TRUE;
629 }
630
631 return (hdl);
632 }
633
634 void
635 libzfs_fini(libzfs_handle_t *hdl)
636 {
637 (void) close(hdl->libzfs_fd);
638 if (hdl->libzfs_mnttab)
639 (void) fclose(hdl->libzfs_mnttab);
640 if (hdl->libzfs_sharetab)
641 (void) fclose(hdl->libzfs_sharetab);
642 zfs_uninit_libshare(hdl);
643 zpool_free_handles(hdl);
644 libzfs_fru_clear(hdl, B_TRUE);
645 namespace_clear(hdl);
646 libzfs_mnttab_fini(hdl);
647 libzfs_core_fini();
648 free(hdl);
649 }
650
651 libzfs_handle_t *
652 zpool_get_handle(zpool_handle_t *zhp)
653 {
654 return (zhp->zpool_hdl);
655 }
656
657 libzfs_handle_t *
658 zfs_get_handle(zfs_handle_t *zhp)
659 {
660 return (zhp->zfs_hdl);
661 }
790 int
791 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
792 {
793 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
794 &zc->zc_nvlist_src_size, nvl));
795 }
796
797 /*
798 * Unpacks an nvlist from the ZFS ioctl command structure.
799 */
800 int
801 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
802 {
803 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
804 zc->zc_nvlist_dst_size, nvlp, 0) != 0)
805 return (no_memory(hdl));
806
807 return (0);
808 }
809
810 int
811 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
812 {
813 return (ioctl(hdl->libzfs_fd, request, zc));
814 }
815
816 /*
817 * ================================================================
818 * API shared by zfs and zpool property management
819 * ================================================================
820 */
821
822 static void
823 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
824 {
825 zprop_list_t *pl = cbp->cb_proplist;
826 int i;
827 char *title;
828 size_t len;
829
830 cbp->cb_first = B_FALSE;
831 if (cbp->cb_scripted)
832 return;
833
1029 (void) printf("\n");
1030 }
1031
1032 /*
1033 * Given a numeric suffix, convert the value into a number of bits that the
1034 * resulting value must be shifted.
1035 */
1036 static int
1037 str2shift(libzfs_handle_t *hdl, const char *buf)
1038 {
1039 const char *ends = "BKMGTPEZ";
1040 int i;
1041
1042 if (buf[0] == '\0')
1043 return (0);
1044 for (i = 0; i < strlen(ends); i++) {
1045 if (toupper(buf[0]) == ends[i])
1046 break;
1047 }
1048 if (i == strlen(ends)) {
1049 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1050 "invalid numeric suffix '%s'"), buf);
1051 return (-1);
1052 }
1053
1054 /*
1055 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
1056 * allow 'BB' - that's just weird.
1057 */
1058 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1059 toupper(buf[0]) != 'B'))
1060 return (10*i);
1061
1062 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1063 "invalid numeric suffix '%s'"), buf);
1064 return (-1);
1065 }
1066
1067 /*
1068 * Convert a string of the form '100G' into a real number. Used when setting
1069 * properties or creating a volume. 'buf' is used to place an extended error
1070 * message for the caller to use.
1071 */
1072 int
1073 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1074 {
1075 char *end;
1076 int shift;
1077
1078 *num = 0;
1079
1080 /* Check to see if this looks like a number. */
1081 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1143 * (index, boolean, etc) if they are specified as strings and add the
1144 * resulting nvpair to the returned nvlist.
1145 *
1146 * At the DSL layer, all properties are either 64-bit numbers or strings.
1147 * We want the user to be able to ignore this fact and specify properties
1148 * as native values (numbers, for example) or as strings (to simplify
1149 * command line utilities). This also handles converting index types
1150 * (compression, checksum, etc) from strings to their on-disk index.
1151 */
1152 int
1153 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1154 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1155 const char *errbuf)
1156 {
1157 data_type_t datatype = nvpair_type(elem);
1158 zprop_type_t proptype;
1159 const char *propname;
1160 char *value;
1161 boolean_t isnone = B_FALSE;
1162
1163 if (type == ZFS_TYPE_POOL) {
1164 proptype = zpool_prop_get_type(prop);
1165 propname = zpool_prop_to_name(prop);
1166 } else {
1167 proptype = zfs_prop_get_type(prop);
1168 propname = zfs_prop_to_name(prop);
1169 }
1170
1171 /*
1172 * Convert any properties to the internal DSL value types.
1173 */
1174 *svalp = NULL;
1175 *ivalp = 0;
1176
1177 switch (proptype) {
1178 case PROP_TYPE_STRING:
1179 if (datatype != DATA_TYPE_STRING) {
1180 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1181 "'%s' must be a string"), nvpair_name(elem));
1182 goto error;
1183 }
1184 (void) nvpair_value_string(elem, svalp);
1185 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1186 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1474 return (-1);
1475
1476 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
1477 ZFS_PROP_NAME;
1478 entry->pl_width = zprop_width(entry->pl_prop,
1479 &entry->pl_fixed, type);
1480 entry->pl_all = B_TRUE;
1481 entry->pl_next = *plp;
1482 *plp = entry;
1483 }
1484 return (0);
1485 }
1486
1487 int
1488 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1489 zfs_type_t type)
1490 {
1491 return (zprop_iter_common(func, cb, show_all, ordered, type));
1492 }
1493
1494 /*
1495 * zfs_get_hole_count retrieves the number of holes (blocks which are
1496 * zero-filled) in the specified file using the _FIO_COUNT_FILLED ioctl. It
1497 * also optionally fetches the block size when bs is non-NULL. With hole count
1498 * and block size the full space consumed by the holes of a file can be
1499 * calculated.
1500 *
1501 * On success, zero is returned, the count argument is set to the
1502 * number of holes, and the bs argument is set to the block size (if it is
1503 * not NULL). On error, a non-zero errno is returned and the values in count
1504 * and bs are undefined.
1505 */
1506 int
1507 zfs_get_hole_count(const char *path, uint64_t *count, uint64_t *bs)
1508 {
1509 int fd, err;
1510 struct stat64 ss;
1511 uint64_t fill;
1512
1513 fd = open(path, O_RDONLY | O_LARGEFILE);
|
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
25 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26 * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
27 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
28 * Copyright (c) 2017 Datto Inc.
29 */
30
31 /*
32 * Internal utility routines for the ZFS library.
33 */
34
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <libintl.h>
38 #include <stdarg.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <strings.h>
42 #include <unistd.h>
43 #include <ctype.h>
44 #include <math.h>
45 #include <sys/filio.h>
219 return (dgettext(TEXT_DOMAIN, "pipe create failed"));
220 case EZFS_THREADCREATEFAILED:
221 return (dgettext(TEXT_DOMAIN, "thread create failed"));
222 case EZFS_POSTSPLIT_ONLINE:
223 return (dgettext(TEXT_DOMAIN, "disk was split from this pool "
224 "into a new one"));
225 case EZFS_SCRUB_PAUSED:
226 return (dgettext(TEXT_DOMAIN, "scrub is paused; "
227 "use 'zpool scrub' to resume"));
228 case EZFS_SCRUBBING:
229 return (dgettext(TEXT_DOMAIN, "currently scrubbing; "
230 "use 'zpool scrub -s' to cancel current scrub"));
231 case EZFS_NO_SCRUB:
232 return (dgettext(TEXT_DOMAIN, "there is no active scrub"));
233 case EZFS_DIFF:
234 return (dgettext(TEXT_DOMAIN, "unable to generate diffs"));
235 case EZFS_DIFFDATA:
236 return (dgettext(TEXT_DOMAIN, "invalid diff data"));
237 case EZFS_POOLREADONLY:
238 return (dgettext(TEXT_DOMAIN, "pool is read-only"));
239 case EZFS_PROPNOTSUP:
240 return (dgettext(TEXT_DOMAIN, "property is not supported"));
241 case EZFS_COSNOTFOUND:
242 return (dgettext(TEXT_DOMAIN, "CoS descriptor not found"));
243 case EZFS_COSEXIST:
244 return (dgettext(TEXT_DOMAIN, "CoS descriptor already exists"));
245 case EZFS_COSREF:
246 return (dgettext(TEXT_DOMAIN,
247 "CoS descriptor is still referenced"));
248 case EZFS_UNKNOWN:
249 return (dgettext(TEXT_DOMAIN, "unknown error"));
250 default:
251 assert(hdl->libzfs_error == 0);
252 return (dgettext(TEXT_DOMAIN, "no error"));
253 }
254 }
255
256 /*PRINTFLIKE2*/
257 void
258 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
259 {
260 va_list ap;
261
262 va_start(ap, fmt);
263
264 (void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
265 fmt, ap);
266 hdl->libzfs_desc_active = 1;
267
379
380 case ENOSPC:
381 case EDQUOT:
382 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
383 return (-1);
384
385 case EEXIST:
386 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
387 "dataset already exists"));
388 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
389 break;
390
391 case EBUSY:
392 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
393 "dataset is busy"));
394 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
395 break;
396 case EROFS:
397 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
398 break;
399 case EINVAL:
400 zfs_verror(hdl, EZFS_INVALIDNAME, fmt, ap);
401 break;
402 case ENAMETOOLONG:
403 zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
404 break;
405 case ENOTSUP:
406 zfs_verror(hdl, EZFS_BADVERSION, fmt, ap);
407 break;
408 case EAGAIN:
409 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
410 "pool I/O is currently suspended"));
411 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
412 break;
413 default:
414 zfs_error_aux(hdl, strerror(error));
415 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
416 break;
417 }
418
419 va_end(ap);
420 return (-1);
421 }
422
423 int
424 zpool_vprop_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
425 {
426 return (zpool_vprop_standard_error_fmt(hdl, error, "%s", msg));
427 }
428
429 /*PRINTFLIKE3*/
430 int
431 zpool_vprop_standard_error_fmt(libzfs_handle_t *hdl, int error,
432 const char *fmt, ...)
433 {
434 va_list ap;
435
436 va_start(ap, fmt);
437
438 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
439 va_end(ap);
440 return (-1);
441 }
442
443 switch (error) {
444 case ENOENT:
445 zfs_verror(hdl, EZFS_COSNOTFOUND, fmt, ap);
446 break;
447 case ENOTSUP:
448 zfs_verror(hdl, EZFS_PROPNOTSUP, fmt, ap);
449 break;
450
451 case EEXIST:
452 zfs_verror(hdl, EZFS_COSEXIST, fmt, ap);
453 break;
454 case EBUSY:
455 zfs_verror(hdl, EZFS_COSREF, fmt, ap);
456 break;
457 default:
458 zfs_error_aux(hdl, strerror(error));
459 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
460 break;
461 }
462
463 va_end(ap);
464 return (-1);
465 }
466
467 int
468 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
469 {
470 return (zpool_standard_error_fmt(hdl, error, "%s", msg));
471 }
472
473 /*PRINTFLIKE3*/
474 int
475 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
476 {
477 va_list ap;
478
479 va_start(ap, fmt);
480
481 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
482 va_end(ap);
483 return (-1);
484 }
485
486 switch (error) {
487 case ENODEV:
488 zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
489 break;
490
491 case ENOENT:
492 zfs_error_aux(hdl,
493 dgettext(TEXT_DOMAIN, "no such pool or dataset"));
494 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
495 break;
496
497 case EEXIST:
498 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
499 "pool already exists"));
500 zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
501 break;
502
503 case EBUSY:
504 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
505 "pool or device is busy"));
506 zfs_verror(hdl, EZFS_BUSY, fmt, ap);
507 break;
508
509 case ENXIO:
510 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
511 "one or more devices is currently unavailable"));
512 zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
513 break;
514
515 case ENAMETOOLONG:
516 zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
517 break;
518
519 case ENOTSUP:
520 zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
521 break;
522
523 case EINVAL:
524 zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
525 break;
526
527 case ENOSPC:
528 case EDQUOT:
529 zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
530 return (-1);
531
532 case EAGAIN:
533 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
534 "pool I/O is currently suspended"));
535 zfs_verror(hdl, EZFS_POOLUNAVAIL, fmt, ap);
536 break;
537
538 case EROFS:
539 zfs_verror(hdl, EZFS_POOLREADONLY, fmt, ap);
540 break;
541
542 default:
543 zfs_error_aux(hdl, strerror(error));
544 zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
545 }
546
547 va_end(ap);
548 return (-1);
549 }
550
551 /*
552 * Display an out of memory error message and abort the current program.
553 */
554 int
555 no_memory(libzfs_handle_t *hdl)
556 {
557 return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
558 }
559
560 /*
656
657 if ((hdl->libzfs_mnttab = fopen(MNTTAB, "rF")) == NULL) {
658 (void) close(hdl->libzfs_fd);
659 free(hdl);
660 return (NULL);
661 }
662
663 hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "rF");
664
665 if (libzfs_core_init() != 0) {
666 (void) close(hdl->libzfs_fd);
667 (void) fclose(hdl->libzfs_mnttab);
668 (void) fclose(hdl->libzfs_sharetab);
669 free(hdl);
670 return (NULL);
671 }
672
673 zfs_prop_init();
674 zpool_prop_init();
675 zpool_feature_init();
676 vdev_prop_init();
677 cos_prop_init();
678 libzfs_mnttab_init(hdl);
679
680 if (getenv("ZFS_PROP_DEBUG") != NULL) {
681 hdl->libzfs_prop_debug = B_TRUE;
682 }
683
684 return (hdl);
685 }
686
687 void
688 libzfs_fini(libzfs_handle_t *hdl)
689 {
690 (void) close(hdl->libzfs_fd);
691 if (hdl->libzfs_mnttab)
692 (void) fclose(hdl->libzfs_mnttab);
693 if (hdl->libzfs_sharetab)
694 (void) fclose(hdl->libzfs_sharetab);
695 if (hdl->libzfs_log_str)
696 free(hdl->libzfs_log_str);
697 zfs_uninit_libshare(hdl);
698 zpool_free_handles(hdl);
699 libzfs_fru_clear(hdl, B_TRUE);
700 namespace_clear(hdl);
701 libzfs_mnttab_fini(hdl);
702 libzfs_core_fini();
703 free(hdl);
704 }
705
706 libzfs_handle_t *
707 zpool_get_handle(zpool_handle_t *zhp)
708 {
709 return (zhp->zpool_hdl);
710 }
711
712 libzfs_handle_t *
713 zfs_get_handle(zfs_handle_t *zhp)
714 {
715 return (zhp->zfs_hdl);
716 }
845 int
846 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
847 {
848 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_src,
849 &zc->zc_nvlist_src_size, nvl));
850 }
851
852 /*
853 * Unpacks an nvlist from the ZFS ioctl command structure.
854 */
855 int
856 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
857 {
858 if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
859 zc->zc_nvlist_dst_size, nvlp, 0) != 0)
860 return (no_memory(hdl));
861
862 return (0);
863 }
864
865 #pragma weak libzfs_log_event = libzfs_log_event_stub
866
867 /* ARGSUSED hdl zc */
868 void
869 libzfs_log_event_stub(libzfs_handle_t *hdl, const char *zc)
870 {
871 }
872
873 int
874 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
875 {
876 int error;
877
878 error = ioctl(hdl->libzfs_fd, request, zc);
879 if (error == 0)
880 libzfs_log_event(hdl, zc->zc_name);
881
882 return (error);
883 }
884
885 /*
886 * ================================================================
887 * API shared by zfs and zpool property management
888 * ================================================================
889 */
890
891 static void
892 zprop_print_headers(zprop_get_cbdata_t *cbp, zfs_type_t type)
893 {
894 zprop_list_t *pl = cbp->cb_proplist;
895 int i;
896 char *title;
897 size_t len;
898
899 cbp->cb_first = B_FALSE;
900 if (cbp->cb_scripted)
901 return;
902
1098 (void) printf("\n");
1099 }
1100
1101 /*
1102 * Given a numeric suffix, convert the value into a number of bits that the
1103 * resulting value must be shifted.
1104 */
1105 static int
1106 str2shift(libzfs_handle_t *hdl, const char *buf)
1107 {
1108 const char *ends = "BKMGTPEZ";
1109 int i;
1110
1111 if (buf[0] == '\0')
1112 return (0);
1113 for (i = 0; i < strlen(ends); i++) {
1114 if (toupper(buf[0]) == ends[i])
1115 break;
1116 }
1117 if (i == strlen(ends)) {
1118 if (hdl)
1119 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1120 "invalid numeric suffix '%s'"), buf);
1121 return (-1);
1122 }
1123
1124 /*
1125 * We want to allow trailing 'b' characters for 'GB' or 'Mb'. But don't
1126 * allow 'BB' - that's just weird.
1127 */
1128 if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
1129 toupper(buf[0]) != 'B'))
1130 return (10*i);
1131
1132 if (hdl)
1133 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1134 "invalid numeric suffix '%s'"), buf);
1135 return (-1);
1136 }
1137
1138 /*
1139 * Convert a string of the form '100G' into a real number. Used when setting
1140 * properties or creating a volume. 'buf' is used to place an extended error
1141 * message for the caller to use.
1142 */
1143 int
1144 zfs_nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
1145 {
1146 char *end;
1147 int shift;
1148
1149 *num = 0;
1150
1151 /* Check to see if this looks like a number. */
1152 if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
1214 * (index, boolean, etc) if they are specified as strings and add the
1215 * resulting nvpair to the returned nvlist.
1216 *
1217 * At the DSL layer, all properties are either 64-bit numbers or strings.
1218 * We want the user to be able to ignore this fact and specify properties
1219 * as native values (numbers, for example) or as strings (to simplify
1220 * command line utilities). This also handles converting index types
1221 * (compression, checksum, etc) from strings to their on-disk index.
1222 */
1223 int
1224 zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
1225 zfs_type_t type, nvlist_t *ret, char **svalp, uint64_t *ivalp,
1226 const char *errbuf)
1227 {
1228 data_type_t datatype = nvpair_type(elem);
1229 zprop_type_t proptype;
1230 const char *propname;
1231 char *value;
1232 boolean_t isnone = B_FALSE;
1233
1234 switch (type) {
1235 case ZFS_TYPE_POOL:
1236 proptype = zpool_prop_get_type(prop);
1237 propname = zpool_prop_to_name(prop);
1238 break;
1239 case ZFS_TYPE_VDEV:
1240 proptype = vdev_prop_get_type(prop);
1241 propname = vdev_prop_to_name(prop);
1242 break;
1243 case ZFS_TYPE_COS:
1244 proptype = cos_prop_get_type(prop);
1245 propname = cos_prop_to_name(prop);
1246 break;
1247 default:
1248 proptype = zfs_prop_get_type(prop);
1249 propname = zfs_prop_to_name(prop);
1250 }
1251
1252 /*
1253 * Convert any properties to the internal DSL value types.
1254 */
1255 *svalp = NULL;
1256 *ivalp = 0;
1257
1258 switch (proptype) {
1259 case PROP_TYPE_STRING:
1260 if (datatype != DATA_TYPE_STRING) {
1261 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1262 "'%s' must be a string"), nvpair_name(elem));
1263 goto error;
1264 }
1265 (void) nvpair_value_string(elem, svalp);
1266 if (strlen(*svalp) >= ZFS_MAXPROPLEN) {
1267 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1555 return (-1);
1556
1557 entry->pl_prop = (type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME :
1558 ZFS_PROP_NAME;
1559 entry->pl_width = zprop_width(entry->pl_prop,
1560 &entry->pl_fixed, type);
1561 entry->pl_all = B_TRUE;
1562 entry->pl_next = *plp;
1563 *plp = entry;
1564 }
1565 return (0);
1566 }
1567
1568 int
1569 zprop_iter(zprop_func func, void *cb, boolean_t show_all, boolean_t ordered,
1570 zfs_type_t type)
1571 {
1572 return (zprop_iter_common(func, cb, show_all, ordered, type));
1573 }
1574
1575 int
1576 vdev_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp)
1577 {
1578 *listp = NULL;
1579
1580 /*
1581 * If 'all' is specified, return a NULL list.
1582 */
1583 if (strcmp(props, "all") == 0) {
1584 vdev_prop_t prop;
1585 for (prop = VDEV_PROP_PATH; prop < VDEV_NUM_PROPS; prop++) {
1586 const char *propname = vdev_prop_to_name(prop);
1587 if (addlist(hdl, (char *)propname, listp,
1588 ZFS_TYPE_VDEV))
1589 return (-1);
1590 listp = &(*listp)->pl_next;
1591 }
1592
1593 return (0);
1594 }
1595
1596 /*
1597 * If no props were specified, return an error.
1598 */
1599 if (props[0] == '\0') {
1600 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1601 "no properties specified"));
1602 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1603 "bad property list")));
1604 }
1605
1606 /*
1607 * It would be nice to use getsubopt() here, but the inclusion of column
1608 * aliases makes this more effort than it's worth.
1609 */
1610 while (*props != '\0') {
1611 size_t len;
1612 char *p;
1613 char c;
1614
1615 if ((p = strchr(props, ',')) == NULL) {
1616 len = strlen(props);
1617 p = props + len;
1618 } else {
1619 len = p - props;
1620 }
1621
1622 /*
1623 * Check for empty options.
1624 */
1625 if (len == 0) {
1626 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1627 "empty property name"));
1628 return (zfs_error(hdl, EZFS_BADPROP,
1629 dgettext(TEXT_DOMAIN, "bad property list")));
1630 }
1631
1632 /*
1633 * Check all regular property names.
1634 */
1635 c = props[len];
1636 props[len] = '\0';
1637
1638 /*
1639 * Make sure we're looking at a valid prop.
1640 */
1641 if (vdev_name_to_prop(props) == ZPROP_INVAL) {
1642 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1643 "invalid property '%s'"), props);
1644 return (zfs_error(hdl, EZFS_BADPROP,
1645 dgettext(TEXT_DOMAIN, "bad property list")));
1646 }
1647
1648 if (addlist(hdl, props, listp, ZFS_TYPE_VDEV))
1649 return (-1);
1650 listp = &(*listp)->pl_next;
1651
1652 props = p;
1653 if (c == ',')
1654 props++;
1655 }
1656
1657 return (0);
1658 }
1659
1660 int
1661 cos_get_proplist(libzfs_handle_t *hdl, char *props, zprop_list_t **listp)
1662 {
1663 *listp = NULL;
1664
1665 /*
1666 * If 'all' is specified, return a NULL list.
1667 */
1668 if (strcmp(props, "all") == 0) {
1669 cos_prop_t prop;
1670 for (prop = COS_PROP_GUID; prop < COS_NUM_PROPS; prop++) {
1671 const char *propname = cos_prop_to_name(prop);
1672 if (addlist(hdl, (char *)propname, listp,
1673 ZFS_TYPE_COS))
1674 return (-1);
1675 listp = &(*listp)->pl_next;
1676 }
1677
1678 return (0);
1679 }
1680
1681 /*
1682 * If no props were specified, return an error.
1683 */
1684 if (props[0] == '\0') {
1685 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1686 "no properties specified"));
1687 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1688 "bad property list")));
1689 }
1690
1691 /*
1692 * It would be nice to use getsubopt() here, but the inclusion of column
1693 * aliases makes this more effort than it's worth.
1694 */
1695 while (*props != '\0') {
1696 size_t len;
1697 char *p;
1698 char c;
1699
1700 if ((p = strchr(props, ',')) == NULL) {
1701 len = strlen(props);
1702 p = props + len;
1703 } else {
1704 len = p - props;
1705 }
1706
1707 /*
1708 * Check for empty options.
1709 */
1710 if (len == 0) {
1711 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1712 "empty property name"));
1713 return (zfs_error(hdl, EZFS_BADPROP,
1714 dgettext(TEXT_DOMAIN, "bad property list")));
1715 }
1716
1717 /*
1718 * Check all regular property names.
1719 */
1720 c = props[len];
1721 props[len] = '\0';
1722
1723 if (addlist(hdl, props, listp, ZFS_TYPE_COS))
1724 return (-1);
1725 listp = &(*listp)->pl_next;
1726
1727 props = p;
1728 if (c == ',')
1729 props++;
1730 }
1731
1732 return (0);
1733 }
1734
1735 void
1736 vdev_print_headers(zprop_get_cbdata_t *cbp)
1737 {
1738 zprop_list_t *pl = cbp->cb_proplist;
1739 int i;
1740 char *title;
1741 size_t len;
1742
1743 cbp->cb_first = B_FALSE;
1744 if (cbp->cb_scripted)
1745 return;
1746
1747 /*
1748 * Start with the length of the column headers.
1749 */
1750 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN,
1751 "POOLNAME"));
1752 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
1753 "c0t0d0s0"));
1754 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
1755 "PROPERTY"));
1756 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
1757 "VALUE"));
1758
1759 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
1760 /*
1761 * 'PROPERTY' column
1762 */
1763 const char *propname = vdev_prop_to_name(pl->pl_prop);
1764
1765 len = strlen(propname);
1766 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
1767 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
1768
1769 /*
1770 * 'VALUE' column.
1771 */
1772 if (pl != cbp->cb_proplist &&
1773 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
1774 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
1775
1776 /*
1777 * 'NAME'
1778 */
1779 if (pl->pl_prop == 0 &&
1780 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
1781 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
1782 }
1783 /*
1784 * 'SOURCE'
1785 */
1786 if (pl->pl_prop == 0 &&
1787 pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) {
1788 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width;
1789 }
1790 }
1791
1792 /*
1793 * Now go through and print the headers.
1794 */
1795 for (i = 0; i < ZFS_GET_NCOLS-1; i++) {
1796 switch (cbp->cb_columns[i]) {
1797 case GET_COL_NAME:
1798 title = dgettext(TEXT_DOMAIN, "POOLNAME");
1799 break;
1800 case GET_COL_SOURCE:
1801 title = dgettext(TEXT_DOMAIN, "VDEV");
1802 break;
1803 case GET_COL_PROPERTY:
1804 title = dgettext(TEXT_DOMAIN, "PROPERTY");
1805 break;
1806 case GET_COL_VALUE:
1807 title = dgettext(TEXT_DOMAIN, "VALUE");
1808 break;
1809 default:
1810 title = NULL;
1811 }
1812
1813 if (title != NULL) {
1814 if (i == (ZFS_GET_NCOLS - 1) ||
1815 cbp->cb_columns[i + 1] == GET_COL_NONE)
1816 (void) printf("%s", title);
1817 else
1818 (void) printf("%-*s ",
1819 cbp->cb_colwidths[cbp->cb_columns[i]],
1820 title);
1821 }
1822 }
1823 (void) printf("\n");
1824 }
1825
1826 void
1827 cos_print_headers(zprop_get_cbdata_t *cbp)
1828 {
1829 zprop_list_t *pl = cbp->cb_proplist;
1830 int i;
1831 char *title;
1832 size_t len;
1833
1834 cbp->cb_first = B_FALSE;
1835 if (cbp->cb_scripted)
1836 return;
1837
1838 /*
1839 * Start with the length of the column headers.
1840 */
1841 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN,
1842 "POOLNAME"));
1843 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
1844 "c0t0d0s0"));
1845 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
1846 "PROPERTY"));
1847 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
1848 "VALUE"));
1849
1850 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
1851 /*
1852 * 'PROPERTY' column
1853 */
1854 const char *propname = cos_prop_to_name(pl->pl_prop);
1855
1856 len = strlen(propname);
1857 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
1858 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
1859
1860 /*
1861 * 'VALUE' column.
1862 */
1863 if (pl != cbp->cb_proplist &&
1864 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
1865 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
1866
1867 /*
1868 * 'NAME'
1869 */
1870 if (pl->pl_prop == 0 &&
1871 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
1872 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
1873 }
1874 /*
1875 * 'SOURCE'
1876 */
1877 if (pl->pl_prop == 0 &&
1878 pl->pl_width > cbp->cb_colwidths[GET_COL_SOURCE]) {
1879 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width;
1880 }
1881 }
1882
1883 /*
1884 * Now go through and print the headers.
1885 */
1886 for (i = 0; i < ZFS_GET_NCOLS-1; i++) {
1887 switch (cbp->cb_columns[i]) {
1888 case GET_COL_NAME:
1889 title = dgettext(TEXT_DOMAIN, "POOLNAME");
1890 break;
1891 case GET_COL_SOURCE:
1892 title = dgettext(TEXT_DOMAIN, "COS");
1893 break;
1894 case GET_COL_PROPERTY:
1895 title = dgettext(TEXT_DOMAIN, "PROPERTY");
1896 break;
1897 case GET_COL_VALUE:
1898 title = dgettext(TEXT_DOMAIN, "VALUE");
1899 break;
1900 default:
1901 title = NULL;
1902 }
1903
1904 if (title != NULL) {
1905 if (i == (ZFS_GET_NCOLS - 1) ||
1906 cbp->cb_columns[i + 1] == GET_COL_NONE)
1907 (void) printf("%s", title);
1908 else
1909 (void) printf("%-*s ",
1910 cbp->cb_colwidths[cbp->cb_columns[i]],
1911 title);
1912 }
1913 }
1914 (void) printf("\n");
1915 }
1916
1917 void
1918 vdev_print_one_property(const char *poolname, const char *vdevname,
1919 zprop_get_cbdata_t *cbp, const char *propname, const char *value)
1920 {
1921 int i;
1922 const char *str;
1923
1924 if (cbp->cb_first)
1925 vdev_print_headers(cbp);
1926
1927 for (i = 0; i < ZFS_GET_NCOLS; i++) {
1928 switch (cbp->cb_columns[i]) {
1929 case GET_COL_NAME:
1930 str = poolname;
1931 break;
1932
1933 case GET_COL_SOURCE:
1934 str = vdevname;
1935 break;
1936
1937 case GET_COL_PROPERTY:
1938 str = propname;
1939 break;
1940
1941 case GET_COL_VALUE:
1942 str = value;
1943 break;
1944
1945 default:
1946 continue;
1947 }
1948
1949 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1950 (void) printf("%s", str);
1951 else if (cbp->cb_scripted)
1952 (void) printf("%s\t", str);
1953 else
1954 (void) printf("%-*s ",
1955 cbp->cb_colwidths[cbp->cb_columns[i]],
1956 str);
1957 }
1958
1959 (void) printf("\n");
1960 }
1961
1962 void
1963 cos_print_one_property(const char *poolname, const char *cosname,
1964 zprop_get_cbdata_t *cbp, const char *propname, const char *value)
1965 {
1966 int i;
1967 const char *str;
1968
1969 if (cbp->cb_first)
1970 cos_print_headers(cbp);
1971
1972 for (i = 0; i < ZFS_GET_NCOLS; i++) {
1973 switch (cbp->cb_columns[i]) {
1974 case GET_COL_NAME:
1975 str = poolname;
1976 break;
1977
1978 case GET_COL_SOURCE:
1979 str = cosname;
1980 break;
1981
1982 case GET_COL_PROPERTY:
1983 str = propname;
1984 break;
1985
1986 case GET_COL_VALUE:
1987 str = value;
1988 break;
1989
1990 default:
1991 continue;
1992 }
1993
1994 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1995 (void) printf("%s", str);
1996 else if (cbp->cb_scripted)
1997 (void) printf("%s\t", str);
1998 else
1999 (void) printf("%-*s ",
2000 cbp->cb_colwidths[cbp->cb_columns[i]],
2001 str);
2002 }
2003
2004 (void) printf("\n");
2005 }
2006
2007 /*
2008 * zfs_get_hole_count retrieves the number of holes (blocks which are
2009 * zero-filled) in the specified file using the _FIO_COUNT_FILLED ioctl. It
2010 * also optionally fetches the block size when bs is non-NULL. With hole count
2011 * and block size the full space consumed by the holes of a file can be
2012 * calculated.
2013 *
2014 * On success, zero is returned, the count argument is set to the
2015 * number of holes, and the bs argument is set to the block size (if it is
2016 * not NULL). On error, a non-zero errno is returned and the values in count
2017 * and bs are undefined.
2018 */
2019 int
2020 zfs_get_hole_count(const char *path, uint64_t *count, uint64_t *bs)
2021 {
2022 int fd, err;
2023 struct stat64 ss;
2024 uint64_t fill;
2025
2026 fd = open(path, O_RDONLY | O_LARGEFILE);
|