1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (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>
45 #include <sys/mnttab.h>
46 #include <sys/mntent.h>
47 #include <sys/types.h>
48 #include <libcmdutils.h>
49
50 #include <libzfs.h>
51 #include <libzfs_core.h>
52
53 #include "libzfs_impl.h"
54 #include "zfs_prop.h"
55 #include "zfeature_common.h"
56
57 int
58 libzfs_errno(libzfs_handle_t *hdl)
59 {
60 return (hdl->libzfs_error);
61 }
62
63 const char *
64 libzfs_error_action(libzfs_handle_t *hdl)
65 {
66 return (hdl->libzfs_action);
67 }
68
69 const char *
70 libzfs_error_description(libzfs_handle_t *hdl)
71 {
72 if (hdl->libzfs_desc[0] != '\0')
73 return (hdl->libzfs_desc);
74
75 switch (hdl->libzfs_error) {
76 case EZFS_NOMEM:
77 return (dgettext(TEXT_DOMAIN, "out of memory"));
78 case EZFS_BADPROP:
79 return (dgettext(TEXT_DOMAIN, "invalid property value"));
80 case EZFS_PROPREADONLY:
81 return (dgettext(TEXT_DOMAIN, "read-only property"));
82 case EZFS_PROPTYPE:
83 return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
84 "datasets of this type"));
85 case EZFS_PROPNONINHERIT:
86 return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
87 case EZFS_PROPSPACE:
88 return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
89 case EZFS_BADTYPE:
90 return (dgettext(TEXT_DOMAIN, "operation not applicable to "
91 "datasets of this type"));
92 case EZFS_BUSY:
93 return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
94 case EZFS_EXISTS:
95 return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
96 case EZFS_NOENT:
97 return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
98 case EZFS_BADSTREAM:
99 return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
100 case EZFS_DSREADONLY:
101 return (dgettext(TEXT_DOMAIN, "dataset is read-only"));
102 case EZFS_VOLTOOBIG:
103 return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
104 "this system"));
105 case EZFS_INVALIDNAME:
106 return (dgettext(TEXT_DOMAIN, "invalid name"));
107 case EZFS_BADRESTORE:
108 return (dgettext(TEXT_DOMAIN, "unable to restore to "
109 "destination"));
110 case EZFS_BADBACKUP:
111 return (dgettext(TEXT_DOMAIN, "backup failed"));
112 case EZFS_BADTARGET:
113 return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
114 case EZFS_NODEVICE:
115 return (dgettext(TEXT_DOMAIN, "no such device in pool"));
116 case EZFS_BADDEV:
117 return (dgettext(TEXT_DOMAIN, "invalid device"));
118 case EZFS_NOREPLICAS:
119 return (dgettext(TEXT_DOMAIN, "no valid replicas"));
120 case EZFS_RESILVERING:
121 return (dgettext(TEXT_DOMAIN, "currently resilvering"));
122 case EZFS_BADVERSION:
123 return (dgettext(TEXT_DOMAIN, "unsupported version or "
124 "feature"));
125 case EZFS_POOLUNAVAIL:
126 return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
127 case EZFS_DEVOVERFLOW:
128 return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
129 case EZFS_BADPATH:
130 return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
131 case EZFS_CROSSTARGET:
132 return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
133 "pools"));
134 case EZFS_ZONED:
135 return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
136 case EZFS_MOUNTFAILED:
137 return (dgettext(TEXT_DOMAIN, "mount failed"));
138 case EZFS_UMOUNTFAILED:
139 return (dgettext(TEXT_DOMAIN, "umount failed"));
140 case EZFS_UNSHARENFSFAILED:
141 return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
142 case EZFS_SHARENFSFAILED:
143 return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
144 case EZFS_UNSHARESMBFAILED:
145 return (dgettext(TEXT_DOMAIN, "smb remove share failed"));
146 case EZFS_SHARESMBFAILED:
147 return (dgettext(TEXT_DOMAIN, "smb add share failed"));
148 case EZFS_PERM:
149 return (dgettext(TEXT_DOMAIN, "permission denied"));
150 case EZFS_NOSPC:
151 return (dgettext(TEXT_DOMAIN, "out of space"));
152 case EZFS_FAULT:
153 return (dgettext(TEXT_DOMAIN, "bad address"));
154 case EZFS_IO:
155 return (dgettext(TEXT_DOMAIN, "I/O error"));
156 case EZFS_INTR:
157 return (dgettext(TEXT_DOMAIN, "signal received"));
158 case EZFS_ISSPARE:
159 return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
160 "spare"));
161 case EZFS_INVALCONFIG:
162 return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
163 case EZFS_RECURSIVE:
164 return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
165 case EZFS_NOHISTORY:
166 return (dgettext(TEXT_DOMAIN, "no history available"));
167 case EZFS_POOLPROPS:
168 return (dgettext(TEXT_DOMAIN, "failed to retrieve "
169 "pool properties"));
170 case EZFS_POOL_NOTSUP:
171 return (dgettext(TEXT_DOMAIN, "operation not supported "
172 "on this type of pool"));
173 case EZFS_POOL_INVALARG:
174 return (dgettext(TEXT_DOMAIN, "invalid argument for "
175 "this pool operation"));
176 case EZFS_NAMETOOLONG:
177 return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
178 case EZFS_OPENFAILED:
179 return (dgettext(TEXT_DOMAIN, "open failed"));
180 case EZFS_NOCAP:
181 return (dgettext(TEXT_DOMAIN,
182 "disk capacity information could not be retrieved"));
183 case EZFS_LABELFAILED:
184 return (dgettext(TEXT_DOMAIN, "write of label failed"));
185 case EZFS_BADWHO:
186 return (dgettext(TEXT_DOMAIN, "invalid user/group"));
187 case EZFS_BADPERM:
188 return (dgettext(TEXT_DOMAIN, "invalid permission"));
189 case EZFS_BADPERMSET:
190 return (dgettext(TEXT_DOMAIN, "invalid permission set name"));
191 case EZFS_NODELEGATION:
192 return (dgettext(TEXT_DOMAIN, "delegated administration is "
193 "disabled on pool"));
194 case EZFS_BADCACHE:
195 return (dgettext(TEXT_DOMAIN, "invalid or missing cache file"));
196 case EZFS_ISL2CACHE:
197 return (dgettext(TEXT_DOMAIN, "device is in use as a cache"));
198 case EZFS_VDEVNOTSUP:
199 return (dgettext(TEXT_DOMAIN, "vdev specification is not "
200 "supported"));
201 case EZFS_NOTSUP:
202 return (dgettext(TEXT_DOMAIN, "operation not supported "
203 "on this dataset"));
204 case EZFS_ACTIVE_SPARE:
205 return (dgettext(TEXT_DOMAIN, "pool has active shared spare "
206 "device"));
207 case EZFS_UNPLAYED_LOGS:
208 return (dgettext(TEXT_DOMAIN, "log device has unplayed intent "
209 "logs"));
210 case EZFS_REFTAG_RELE:
211 return (dgettext(TEXT_DOMAIN, "no such tag on this dataset"));
212 case EZFS_REFTAG_HOLD:
213 return (dgettext(TEXT_DOMAIN, "tag already exists on this "
214 "dataset"));
215 case EZFS_TAGTOOLONG:
216 return (dgettext(TEXT_DOMAIN, "tag too long"));
217 case EZFS_PIPEFAILED:
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
261 va_end(ap);
262 }
263
264 static void
265 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
266 {
267 (void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
268 fmt, ap);
269 hdl->libzfs_error = error;
270
271 if (hdl->libzfs_desc_active)
272 hdl->libzfs_desc_active = 0;
273 else
274 hdl->libzfs_desc[0] = '\0';
275
276 if (hdl->libzfs_printerr) {
277 if (error == EZFS_UNKNOWN) {
278 (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
279 "error: %s\n"), libzfs_error_description(hdl));
280 abort();
281 }
282
283 (void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
284 libzfs_error_description(hdl));
285 if (error == EZFS_NOMEM)
286 exit(1);
287 }
288 }
289
290 int
291 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
292 {
293 return (zfs_error_fmt(hdl, error, "%s", msg));
294 }
295
296 /*PRINTFLIKE3*/
297 int
298 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
299 {
300 va_list ap;
301
302 va_start(ap, fmt);
303
304 zfs_verror(hdl, error, fmt, ap);
305
306 va_end(ap);
307
308 return (-1);
309 }
310
311 static int
312 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
313 va_list ap)
314 {
315 switch (error) {
316 case EPERM:
317 case EACCES:
318 zfs_verror(hdl, EZFS_PERM, fmt, ap);
319 return (-1);
320
321 case ECANCELED:
322 zfs_verror(hdl, EZFS_NODELEGATION, fmt, ap);
323 return (-1);
324
325 case EIO:
326 zfs_verror(hdl, EZFS_IO, fmt, ap);
327 return (-1);
328
329 case EFAULT:
330 zfs_verror(hdl, EZFS_FAULT, fmt, ap);
331 return (-1);
332
333 case EINTR:
334 zfs_verror(hdl, EZFS_INTR, fmt, ap);
335 return (-1);
336 }
337
338 return (0);
339 }
340
341 int
342 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
343 {
344 return (zfs_standard_error_fmt(hdl, error, "%s", msg));
345 }
346
347 /*PRINTFLIKE3*/
348 int
349 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
350 {
351 va_list ap;
352
353 va_start(ap, fmt);
354
355 if (zfs_common_error(hdl, error, fmt, ap) != 0) {
356 va_end(ap);
357 return (-1);
358 }
359
360 switch (error) {
361 case ENXIO:
362 case ENODEV:
363 case EPIPE:
364 zfs_verror(hdl, EZFS_IO, fmt, ap);
365 break;
366
367 case ENOENT:
368 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
369 "dataset does not exist"));
370 zfs_verror(hdl, EZFS_NOENT, fmt, ap);
371 break;
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 /*
510 * A safe form of malloc() which will die if the allocation fails.
511 */
512 void *
513 zfs_alloc(libzfs_handle_t *hdl, size_t size)
514 {
515 void *data;
516
517 if ((data = calloc(1, size)) == NULL)
518 (void) no_memory(hdl);
519
520 return (data);
521 }
522
523 /*
524 * A safe form of asprintf() which will die if the allocation fails.
525 */
526 /*PRINTFLIKE2*/
527 char *
528 zfs_asprintf(libzfs_handle_t *hdl, const char *fmt, ...)
529 {
530 va_list ap;
531 char *ret;
532 int err;
533
534 va_start(ap, fmt);
535
536 err = vasprintf(&ret, fmt, ap);
537
538 va_end(ap);
539
540 if (err < 0)
541 (void) no_memory(hdl);
542
543 return (ret);
544 }
545
546 /*
547 * A safe form of realloc(), which also zeroes newly allocated space.
548 */
549 void *
550 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
551 {
552 void *ret;
553
554 if ((ret = realloc(ptr, newsize)) == NULL) {
555 (void) no_memory(hdl);
556 return (NULL);
557 }
558
559 bzero((char *)ret + oldsize, (newsize - oldsize));
560 return (ret);
561 }
562
563 /*
564 * A safe form of strdup() which will die if the allocation fails.
565 */
566 char *
567 zfs_strdup(libzfs_handle_t *hdl, const char *str)
568 {
569 char *ret;
570
571 if ((ret = strdup(str)) == NULL)
572 (void) no_memory(hdl);
573
574 return (ret);
575 }
576
577 /*
578 * Convert a number to an appropriately human-readable output.
579 */
580 void
581 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
582 {
583 nicenum(num, buf, buflen);
584 }
585
586 void
587 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
588 {
589 hdl->libzfs_printerr = printerr;
590 }
591
592 libzfs_handle_t *
593 libzfs_init(void)
594 {
595 libzfs_handle_t *hdl;
596
597 if ((hdl = calloc(1, sizeof (libzfs_handle_t))) == NULL) {
598 return (NULL);
599 }
600
601 if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
602 free(hdl);
603 return (NULL);
604 }
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 }
662
663 zpool_handle_t *
664 zfs_get_pool_handle(const zfs_handle_t *zhp)
665 {
666 return (zhp->zpool_hdl);
667 }
668
669 /*
670 * Given a name, determine whether or not it's a valid path
671 * (starts with '/' or "./"). If so, walk the mnttab trying
672 * to match the device number. If not, treat the path as an
673 * fs/vol/snap/bkmark name.
674 */
675 zfs_handle_t *
676 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
677 {
678 struct stat64 statbuf;
679 struct extmnttab entry;
680 int ret;
681
682 if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
683 /*
684 * It's not a valid path, assume it's a name of type 'argtype'.
685 */
686 return (zfs_open(hdl, path, argtype));
687 }
688
689 if (stat64(path, &statbuf) != 0) {
690 (void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
691 return (NULL);
692 }
693
694 rewind(hdl->libzfs_mnttab);
695 while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
696 if (makedevice(entry.mnt_major, entry.mnt_minor) ==
697 statbuf.st_dev) {
698 break;
699 }
700 }
701 if (ret != 0) {
702 return (NULL);
703 }
704
705 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
706 (void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
707 path);
708 return (NULL);
709 }
710
711 return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
712 }
713
714 /*
715 * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
716 * an ioctl().
717 */
718 int
719 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
720 {
721 if (len == 0)
722 len = 16 * 1024;
723 zc->zc_nvlist_dst_size = len;
724 zc->zc_nvlist_dst =
725 (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
726 if (zc->zc_nvlist_dst == 0)
727 return (-1);
728
729 return (0);
730 }
731
732 /*
733 * Called when an ioctl() which returns an nvlist fails with ENOMEM. This will
734 * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
735 * filled in by the kernel to indicate the actual required size.
736 */
737 int
738 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
739 {
740 free((void *)(uintptr_t)zc->zc_nvlist_dst);
741 zc->zc_nvlist_dst =
742 (uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
743 if (zc->zc_nvlist_dst == 0)
744 return (-1);
745
746 return (0);
747 }
748
749 /*
750 * Called to free the src and dst nvlists stored in the command structure.
751 */
752 void
753 zcmd_free_nvlists(zfs_cmd_t *zc)
754 {
755 free((void *)(uintptr_t)zc->zc_nvlist_conf);
756 free((void *)(uintptr_t)zc->zc_nvlist_src);
757 free((void *)(uintptr_t)zc->zc_nvlist_dst);
758 zc->zc_nvlist_conf = NULL;
759 zc->zc_nvlist_src = NULL;
760 zc->zc_nvlist_dst = NULL;
761 }
762
763 static int
764 zcmd_write_nvlist_com(libzfs_handle_t *hdl, uint64_t *outnv, uint64_t *outlen,
765 nvlist_t *nvl)
766 {
767 char *packed;
768 size_t len;
769
770 verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
771
772 if ((packed = zfs_alloc(hdl, len)) == NULL)
773 return (-1);
774
775 verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
776
777 *outnv = (uint64_t)(uintptr_t)packed;
778 *outlen = len;
779
780 return (0);
781 }
782
783 int
784 zcmd_write_conf_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl)
785 {
786 return (zcmd_write_nvlist_com(hdl, &zc->zc_nvlist_conf,
787 &zc->zc_nvlist_conf_size, nvl));
788 }
789
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
834 /*
835 * Start with the length of the column headers.
836 */
837 cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
838 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
839 "PROPERTY"));
840 cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
841 "VALUE"));
842 cbp->cb_colwidths[GET_COL_RECVD] = strlen(dgettext(TEXT_DOMAIN,
843 "RECEIVED"));
844 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
845 "SOURCE"));
846
847 /* first property is always NAME */
848 assert(cbp->cb_proplist->pl_prop ==
849 ((type == ZFS_TYPE_POOL) ? ZPOOL_PROP_NAME : ZFS_PROP_NAME));
850
851 /*
852 * Go through and calculate the widths for each column. For the
853 * 'source' column, we kludge it up by taking the worst-case scenario of
854 * inheriting from the longest name. This is acceptable because in the
855 * majority of cases 'SOURCE' is the last column displayed, and we don't
856 * use the width anyway. Note that the 'VALUE' column can be oversized,
857 * if the name of the property is much longer than any values we find.
858 */
859 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
860 /*
861 * 'PROPERTY' column
862 */
863 if (pl->pl_prop != ZPROP_INVAL) {
864 const char *propname = (type == ZFS_TYPE_POOL) ?
865 zpool_prop_to_name(pl->pl_prop) :
866 zfs_prop_to_name(pl->pl_prop);
867
868 len = strlen(propname);
869 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
870 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
871 } else {
872 len = strlen(pl->pl_user_prop);
873 if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
874 cbp->cb_colwidths[GET_COL_PROPERTY] = len;
875 }
876
877 /*
878 * 'VALUE' column. The first property is always the 'name'
879 * property that was tacked on either by /sbin/zfs's
880 * zfs_do_get() or when calling zprop_expand_list(), so we
881 * ignore its width. If the user specified the name property
882 * to display, then it will be later in the list in any case.
883 */
884 if (pl != cbp->cb_proplist &&
885 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
886 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
887
888 /* 'RECEIVED' column. */
889 if (pl != cbp->cb_proplist &&
890 pl->pl_recvd_width > cbp->cb_colwidths[GET_COL_RECVD])
891 cbp->cb_colwidths[GET_COL_RECVD] = pl->pl_recvd_width;
892
893 /*
894 * 'NAME' and 'SOURCE' columns
895 */
896 if (pl->pl_prop == (type == ZFS_TYPE_POOL ? ZPOOL_PROP_NAME :
897 ZFS_PROP_NAME) &&
898 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
899 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
900 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
901 strlen(dgettext(TEXT_DOMAIN, "inherited from"));
902 }
903 }
904
905 /*
906 * Now go through and print the headers.
907 */
908 for (i = 0; i < ZFS_GET_NCOLS; i++) {
909 switch (cbp->cb_columns[i]) {
910 case GET_COL_NAME:
911 title = dgettext(TEXT_DOMAIN, "NAME");
912 break;
913 case GET_COL_PROPERTY:
914 title = dgettext(TEXT_DOMAIN, "PROPERTY");
915 break;
916 case GET_COL_VALUE:
917 title = dgettext(TEXT_DOMAIN, "VALUE");
918 break;
919 case GET_COL_RECVD:
920 title = dgettext(TEXT_DOMAIN, "RECEIVED");
921 break;
922 case GET_COL_SOURCE:
923 title = dgettext(TEXT_DOMAIN, "SOURCE");
924 break;
925 default:
926 title = NULL;
927 }
928
929 if (title != NULL) {
930 if (i == (ZFS_GET_NCOLS - 1) ||
931 cbp->cb_columns[i + 1] == GET_COL_NONE)
932 (void) printf("%s", title);
933 else
934 (void) printf("%-*s ",
935 cbp->cb_colwidths[cbp->cb_columns[i]],
936 title);
937 }
938 }
939 (void) printf("\n");
940 }
941
942 /*
943 * Display a single line of output, according to the settings in the callback
944 * structure.
945 */
946 void
947 zprop_print_one_property(const char *name, zprop_get_cbdata_t *cbp,
948 const char *propname, const char *value, zprop_source_t sourcetype,
949 const char *source, const char *recvd_value)
950 {
951 int i;
952 const char *str = NULL;
953 char buf[128];
954
955 /*
956 * Ignore those source types that the user has chosen to ignore.
957 */
958 if ((sourcetype & cbp->cb_sources) == 0)
959 return;
960
961 if (cbp->cb_first)
962 zprop_print_headers(cbp, cbp->cb_type);
963
964 for (i = 0; i < ZFS_GET_NCOLS; i++) {
965 switch (cbp->cb_columns[i]) {
966 case GET_COL_NAME:
967 str = name;
968 break;
969
970 case GET_COL_PROPERTY:
971 str = propname;
972 break;
973
974 case GET_COL_VALUE:
975 str = value;
976 break;
977
978 case GET_COL_SOURCE:
979 switch (sourcetype) {
980 case ZPROP_SRC_NONE:
981 str = "-";
982 break;
983
984 case ZPROP_SRC_DEFAULT:
985 str = "default";
986 break;
987
988 case ZPROP_SRC_LOCAL:
989 str = "local";
990 break;
991
992 case ZPROP_SRC_TEMPORARY:
993 str = "temporary";
994 break;
995
996 case ZPROP_SRC_INHERITED:
997 (void) snprintf(buf, sizeof (buf),
998 "inherited from %s", source);
999 str = buf;
1000 break;
1001 case ZPROP_SRC_RECEIVED:
1002 str = "received";
1003 break;
1004
1005 default:
1006 str = NULL;
1007 assert(!"unhandled zprop_source_t");
1008 }
1009 break;
1010
1011 case GET_COL_RECVD:
1012 str = (recvd_value == NULL ? "-" : recvd_value);
1013 break;
1014
1015 default:
1016 continue;
1017 }
1018
1019 if (cbp->cb_columns[i + 1] == GET_COL_NONE)
1020 (void) printf("%s", str);
1021 else if (cbp->cb_scripted)
1022 (void) printf("%s\t", str);
1023 else
1024 (void) printf("%-*s ",
1025 cbp->cb_colwidths[cbp->cb_columns[i]],
1026 str);
1027 }
1028
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] != '.') {
1082 if (hdl)
1083 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1084 "bad numeric value '%s'"), value);
1085 return (-1);
1086 }
1087
1088 /* Rely on strtoull() to process the numeric portion. */
1089 errno = 0;
1090 *num = strtoull(value, &end, 10);
1091
1092 /*
1093 * Check for ERANGE, which indicates that the value is too large to fit
1094 * in a 64-bit value.
1095 */
1096 if (errno == ERANGE) {
1097 if (hdl)
1098 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1099 "numeric value is too large"));
1100 return (-1);
1101 }
1102
1103 /*
1104 * If we have a decimal value, then do the computation with floating
1105 * point arithmetic. Otherwise, use standard arithmetic.
1106 */
1107 if (*end == '.') {
1108 double fval = strtod(value, &end);
1109
1110 if ((shift = str2shift(hdl, end)) == -1)
1111 return (-1);
1112
1113 fval *= pow(2, shift);
1114
1115 if (fval > UINT64_MAX) {
1116 if (hdl)
1117 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1118 "numeric value is too large"));
1119 return (-1);
1120 }
1121
1122 *num = (uint64_t)fval;
1123 } else {
1124 if ((shift = str2shift(hdl, end)) == -1)
1125 return (-1);
1126
1127 /* Check for overflow */
1128 if (shift >= 64 || (*num << shift) >> shift != *num) {
1129 if (hdl)
1130 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1131 "numeric value is too large"));
1132 return (-1);
1133 }
1134
1135 *num <<= shift;
1136 }
1137
1138 return (0);
1139 }
1140
1141 /*
1142 * Given a propname=value nvpair to set, parse any numeric properties
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,
1187 "'%s' is too long"), nvpair_name(elem));
1188 goto error;
1189 }
1190 break;
1191
1192 case PROP_TYPE_NUMBER:
1193 if (datatype == DATA_TYPE_STRING) {
1194 (void) nvpair_value_string(elem, &value);
1195 if (strcmp(value, "none") == 0) {
1196 isnone = B_TRUE;
1197 } else if (zfs_nicestrtonum(hdl, value, ivalp)
1198 != 0) {
1199 goto error;
1200 }
1201 } else if (datatype == DATA_TYPE_UINT64) {
1202 (void) nvpair_value_uint64(elem, ivalp);
1203 } else {
1204 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1205 "'%s' must be a number"), nvpair_name(elem));
1206 goto error;
1207 }
1208
1209 /*
1210 * Quota special: force 'none' and don't allow 0.
1211 */
1212 if ((type & ZFS_TYPE_DATASET) && *ivalp == 0 && !isnone &&
1213 (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_REFQUOTA)) {
1214 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1215 "use 'none' to disable quota/refquota"));
1216 goto error;
1217 }
1218
1219 /*
1220 * Special handling for "*_limit=none". In this case it's not
1221 * 0 but UINT64_MAX.
1222 */
1223 if ((type & ZFS_TYPE_DATASET) && isnone &&
1224 (prop == ZFS_PROP_FILESYSTEM_LIMIT ||
1225 prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
1226 *ivalp = UINT64_MAX;
1227 }
1228 break;
1229
1230 case PROP_TYPE_INDEX:
1231 if (datatype != DATA_TYPE_STRING) {
1232 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1233 "'%s' must be a string"), nvpair_name(elem));
1234 goto error;
1235 }
1236
1237 (void) nvpair_value_string(elem, &value);
1238
1239 if (zprop_string_to_index(prop, value, ivalp, type) != 0) {
1240 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1241 "'%s' must be one of '%s'"), propname,
1242 zprop_values(prop, type));
1243 goto error;
1244 }
1245 break;
1246
1247 default:
1248 abort();
1249 }
1250
1251 /*
1252 * Add the result to our return set of properties.
1253 */
1254 if (*svalp != NULL) {
1255 if (nvlist_add_string(ret, propname, *svalp) != 0) {
1256 (void) no_memory(hdl);
1257 return (-1);
1258 }
1259 } else {
1260 if (nvlist_add_uint64(ret, propname, *ivalp) != 0) {
1261 (void) no_memory(hdl);
1262 return (-1);
1263 }
1264 }
1265
1266 return (0);
1267 error:
1268 (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1269 return (-1);
1270 }
1271
1272 static int
1273 addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
1274 zfs_type_t type)
1275 {
1276 int prop;
1277 zprop_list_t *entry;
1278
1279 prop = zprop_name_to_prop(propname, type);
1280
1281 if (prop != ZPROP_INVAL && !zprop_valid_for_type(prop, type))
1282 prop = ZPROP_INVAL;
1283
1284 /*
1285 * When no property table entry can be found, return failure if
1286 * this is a pool property or if this isn't a user-defined
1287 * dataset property,
1288 */
1289 if (prop == ZPROP_INVAL && ((type == ZFS_TYPE_POOL &&
1290 !zpool_prop_feature(propname) &&
1291 !zpool_prop_unsupported(propname)) ||
1292 (type == ZFS_TYPE_DATASET && !zfs_prop_user(propname) &&
1293 !zfs_prop_userquota(propname) && !zfs_prop_written(propname)))) {
1294 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1295 "invalid property '%s'"), propname);
1296 return (zfs_error(hdl, EZFS_BADPROP,
1297 dgettext(TEXT_DOMAIN, "bad property list")));
1298 }
1299
1300 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
1301 return (-1);
1302
1303 entry->pl_prop = prop;
1304 if (prop == ZPROP_INVAL) {
1305 if ((entry->pl_user_prop = zfs_strdup(hdl, propname)) ==
1306 NULL) {
1307 free(entry);
1308 return (-1);
1309 }
1310 entry->pl_width = strlen(propname);
1311 } else {
1312 entry->pl_width = zprop_width(prop, &entry->pl_fixed,
1313 type);
1314 }
1315
1316 *listp = entry;
1317
1318 return (0);
1319 }
1320
1321 /*
1322 * Given a comma-separated list of properties, construct a property list
1323 * containing both user-defined and native properties. This function will
1324 * return a NULL list if 'all' is specified, which can later be expanded
1325 * by zprop_expand_list().
1326 */
1327 int
1328 zprop_get_list(libzfs_handle_t *hdl, char *props, zprop_list_t **listp,
1329 zfs_type_t type)
1330 {
1331 *listp = NULL;
1332
1333 /*
1334 * If 'all' is specified, return a NULL list.
1335 */
1336 if (strcmp(props, "all") == 0)
1337 return (0);
1338
1339 /*
1340 * If no props were specified, return an error.
1341 */
1342 if (props[0] == '\0') {
1343 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1344 "no properties specified"));
1345 return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1346 "bad property list")));
1347 }
1348
1349 /*
1350 * It would be nice to use getsubopt() here, but the inclusion of column
1351 * aliases makes this more effort than it's worth.
1352 */
1353 while (*props != '\0') {
1354 size_t len;
1355 char *p;
1356 char c;
1357
1358 if ((p = strchr(props, ',')) == NULL) {
1359 len = strlen(props);
1360 p = props + len;
1361 } else {
1362 len = p - props;
1363 }
1364
1365 /*
1366 * Check for empty options.
1367 */
1368 if (len == 0) {
1369 zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1370 "empty property name"));
1371 return (zfs_error(hdl, EZFS_BADPROP,
1372 dgettext(TEXT_DOMAIN, "bad property list")));
1373 }
1374
1375 /*
1376 * Check all regular property names.
1377 */
1378 c = props[len];
1379 props[len] = '\0';
1380
1381 if (strcmp(props, "space") == 0) {
1382 static char *spaceprops[] = {
1383 "name", "avail", "used", "usedbysnapshots",
1384 "usedbydataset", "usedbyrefreservation",
1385 "usedbychildren", NULL
1386 };
1387 int i;
1388
1389 for (i = 0; spaceprops[i]; i++) {
1390 if (addlist(hdl, spaceprops[i], listp, type))
1391 return (-1);
1392 listp = &(*listp)->pl_next;
1393 }
1394 } else {
1395 if (addlist(hdl, props, listp, type))
1396 return (-1);
1397 listp = &(*listp)->pl_next;
1398 }
1399
1400 props = p;
1401 if (c == ',')
1402 props++;
1403 }
1404
1405 return (0);
1406 }
1407
1408 void
1409 zprop_free_list(zprop_list_t *pl)
1410 {
1411 zprop_list_t *next;
1412
1413 while (pl != NULL) {
1414 next = pl->pl_next;
1415 free(pl->pl_user_prop);
1416 free(pl);
1417 pl = next;
1418 }
1419 }
1420
1421 typedef struct expand_data {
1422 zprop_list_t **last;
1423 libzfs_handle_t *hdl;
1424 zfs_type_t type;
1425 } expand_data_t;
1426
1427 int
1428 zprop_expand_list_cb(int prop, void *cb)
1429 {
1430 zprop_list_t *entry;
1431 expand_data_t *edp = cb;
1432
1433 if ((entry = zfs_alloc(edp->hdl, sizeof (zprop_list_t))) == NULL)
1434 return (ZPROP_INVAL);
1435
1436 entry->pl_prop = prop;
1437 entry->pl_width = zprop_width(prop, &entry->pl_fixed, edp->type);
1438 entry->pl_all = B_TRUE;
1439
1440 *(edp->last) = entry;
1441 edp->last = &entry->pl_next;
1442
1443 return (ZPROP_CONT);
1444 }
1445
1446 int
1447 zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp, zfs_type_t type)
1448 {
1449 zprop_list_t *entry;
1450 zprop_list_t **last;
1451 expand_data_t exp;
1452
1453 if (*plp == NULL) {
1454 /*
1455 * If this is the very first time we've been called for an 'all'
1456 * specification, expand the list to include all native
1457 * properties.
1458 */
1459 last = plp;
1460
1461 exp.last = last;
1462 exp.hdl = hdl;
1463 exp.type = type;
1464
1465 if (zprop_iter_common(zprop_expand_list_cb, &exp, B_FALSE,
1466 B_FALSE, type) == ZPROP_INVAL)
1467 return (-1);
1468
1469 /*
1470 * Add 'name' to the beginning of the list, which is handled
1471 * specially.
1472 */
1473 if ((entry = zfs_alloc(hdl, sizeof (zprop_list_t))) == NULL)
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);
1514 if (fd == -1)
1515 return (errno);
1516
1517 if (ioctl(fd, _FIO_COUNT_FILLED, &fill) == -1) {
1518 err = errno;
1519 (void) close(fd);
1520 return (err);
1521 }
1522
1523 if (fstat64(fd, &ss) == -1) {
1524 err = errno;
1525 (void) close(fd);
1526 return (err);
1527 }
1528
1529 *count = (ss.st_size + ss.st_blksize - 1) / ss.st_blksize - fill;
1530 VERIFY3S(*count, >=, 0);
1531 if (bs != NULL) {
1532 *bs = ss.st_blksize;
1533 }
1534
1535 if (close(fd) == -1) {
1536 return (errno);
1537 }
1538 return (0);
1539 }