xref: /titanic_44/usr/src/lib/libzfs/common/libzfs_util.c (revision a237e38e9161f0acd6451439d4a7dd597e66291d)
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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Internal utility routines for the ZFS library.
30  */
31 
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <libintl.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <strings.h>
39 #include <unistd.h>
40 #include <sys/mnttab.h>
41 #include <sys/mntent.h>
42 #include <sys/types.h>
43 
44 #include <libzfs.h>
45 
46 #include "libzfs_impl.h"
47 
48 int
49 libzfs_errno(libzfs_handle_t *hdl)
50 {
51 	return (hdl->libzfs_error);
52 }
53 
54 const char *
55 libzfs_error_action(libzfs_handle_t *hdl)
56 {
57 	return (hdl->libzfs_action);
58 }
59 
60 const char *
61 libzfs_error_description(libzfs_handle_t *hdl)
62 {
63 	if (hdl->libzfs_desc[0] != '\0')
64 		return (hdl->libzfs_desc);
65 
66 	switch (hdl->libzfs_error) {
67 	case EZFS_NOMEM:
68 		return (dgettext(TEXT_DOMAIN, "out of memory"));
69 	case EZFS_BADPROP:
70 		return (dgettext(TEXT_DOMAIN, "invalid property value"));
71 	case EZFS_PROPREADONLY:
72 		return (dgettext(TEXT_DOMAIN, "read only property"));
73 	case EZFS_PROPTYPE:
74 		return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
75 		    "datasets of this type"));
76 	case EZFS_PROPNONINHERIT:
77 		return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
78 	case EZFS_PROPSPACE:
79 		return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
80 	case EZFS_BADTYPE:
81 		return (dgettext(TEXT_DOMAIN, "operation not applicable to "
82 		    "datasets of this type"));
83 	case EZFS_BUSY:
84 		return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
85 	case EZFS_EXISTS:
86 		return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
87 	case EZFS_NOENT:
88 		return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
89 	case EZFS_BADSTREAM:
90 		return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
91 	case EZFS_DSREADONLY:
92 		return (dgettext(TEXT_DOMAIN, "dataset is read only"));
93 	case EZFS_VOLTOOBIG:
94 		return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
95 		    "this system"));
96 	case EZFS_VOLHASDATA:
97 		return (dgettext(TEXT_DOMAIN, "volume has data"));
98 	case EZFS_INVALIDNAME:
99 		return (dgettext(TEXT_DOMAIN, "invalid name"));
100 	case EZFS_BADRESTORE:
101 		return (dgettext(TEXT_DOMAIN, "unable to restore to "
102 		    "destination"));
103 	case EZFS_BADBACKUP:
104 		return (dgettext(TEXT_DOMAIN, "backup failed"));
105 	case EZFS_BADTARGET:
106 		return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
107 	case EZFS_NODEVICE:
108 		return (dgettext(TEXT_DOMAIN, "no such device in pool"));
109 	case EZFS_BADDEV:
110 		return (dgettext(TEXT_DOMAIN, "invalid device"));
111 	case EZFS_NOREPLICAS:
112 		return (dgettext(TEXT_DOMAIN, "no valid replicas"));
113 	case EZFS_RESILVERING:
114 		return (dgettext(TEXT_DOMAIN, "currently resilvering"));
115 	case EZFS_BADVERSION:
116 		return (dgettext(TEXT_DOMAIN, "unsupported version"));
117 	case EZFS_POOLUNAVAIL:
118 		return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
119 	case EZFS_DEVOVERFLOW:
120 		return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
121 	case EZFS_BADPATH:
122 		return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
123 	case EZFS_CROSSTARGET:
124 		return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
125 		    "pools"));
126 	case EZFS_ZONED:
127 		return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
128 	case EZFS_MOUNTFAILED:
129 		return (dgettext(TEXT_DOMAIN, "mount failed"));
130 	case EZFS_UMOUNTFAILED:
131 		return (dgettext(TEXT_DOMAIN, "umount failed"));
132 	case EZFS_UNSHARENFSFAILED:
133 		return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
134 	case EZFS_SHARENFSFAILED:
135 		return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
136 	case EZFS_DEVLINKS:
137 		return (dgettext(TEXT_DOMAIN, "failed to create /dev links"));
138 	case EZFS_PERM:
139 		return (dgettext(TEXT_DOMAIN, "permission denied"));
140 	case EZFS_NOSPC:
141 		return (dgettext(TEXT_DOMAIN, "out of space"));
142 	case EZFS_IO:
143 		return (dgettext(TEXT_DOMAIN, "I/O error"));
144 	case EZFS_INTR:
145 		return (dgettext(TEXT_DOMAIN, "signal received"));
146 	case EZFS_ISSPARE:
147 		return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
148 		    "spare"));
149 	case EZFS_INVALCONFIG:
150 		return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
151 	case EZFS_RECURSIVE:
152 		return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
153 	case EZFS_NOHISTORY:
154 		return (dgettext(TEXT_DOMAIN, "no history available"));
155 	case EZFS_UNSHAREISCSIFAILED:
156 		return (dgettext(TEXT_DOMAIN,
157 		    "iscsitgtd failed request to unshare"));
158 	case EZFS_SHAREISCSIFAILED:
159 		return (dgettext(TEXT_DOMAIN,
160 		    "iscsitgtd failed request to share"));
161 	case EZFS_POOLPROPS:
162 		return (dgettext(TEXT_DOMAIN, "failed to retrieve "
163 		    "pool properties"));
164 	case EZFS_POOL_NOTSUP:
165 		return (dgettext(TEXT_DOMAIN, "operation not supported "
166 		    "on this type of pool"));
167 	case EZFS_POOL_INVALARG:
168 		return (dgettext(TEXT_DOMAIN, "invalid argument for "
169 		    "this pool operation"));
170 	case EZFS_UNKNOWN:
171 		return (dgettext(TEXT_DOMAIN, "unknown error"));
172 	default:
173 		assert(hdl->libzfs_error == 0);
174 		return (dgettext(TEXT_DOMAIN, "no error"));
175 	}
176 }
177 
178 /*PRINTFLIKE2*/
179 void
180 zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
181 {
182 	va_list ap;
183 
184 	va_start(ap, fmt);
185 
186 	(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
187 	    fmt, ap);
188 	hdl->libzfs_desc_active = 1;
189 
190 	va_end(ap);
191 }
192 
193 static void
194 zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
195 {
196 	(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
197 	    fmt, ap);
198 	hdl->libzfs_error = error;
199 
200 	if (hdl->libzfs_desc_active)
201 		hdl->libzfs_desc_active = 0;
202 	else
203 		hdl->libzfs_desc[0] = '\0';
204 
205 	if (hdl->libzfs_printerr) {
206 		if (error == EZFS_UNKNOWN) {
207 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
208 			    "error: %s\n"), libzfs_error_description(hdl));
209 			abort();
210 		}
211 
212 		(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
213 		    libzfs_error_description(hdl));
214 		if (error == EZFS_NOMEM)
215 			exit(1);
216 	}
217 }
218 
219 int
220 zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
221 {
222 	return (zfs_error_fmt(hdl, error, "%s", msg));
223 }
224 
225 /*PRINTFLIKE3*/
226 int
227 zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
228 {
229 	va_list ap;
230 
231 	va_start(ap, fmt);
232 
233 	zfs_verror(hdl, error, fmt, ap);
234 
235 	va_end(ap);
236 
237 	return (-1);
238 }
239 
240 static int
241 zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
242     va_list ap)
243 {
244 	switch (error) {
245 	case EPERM:
246 	case EACCES:
247 		zfs_verror(hdl, EZFS_PERM, fmt, ap);
248 		return (-1);
249 
250 	case EIO:
251 		zfs_verror(hdl, EZFS_IO, fmt, ap);
252 		return (-1);
253 
254 	case EINTR:
255 		zfs_verror(hdl, EZFS_INTR, fmt, ap);
256 		return (-1);
257 	}
258 
259 	return (0);
260 }
261 
262 int
263 zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
264 {
265 	return (zfs_standard_error_fmt(hdl, error, "%s", msg));
266 }
267 
268 /*PRINTFLIKE3*/
269 int
270 zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
271 {
272 	va_list ap;
273 
274 	va_start(ap, fmt);
275 
276 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
277 		va_end(ap);
278 		return (-1);
279 	}
280 
281 
282 	switch (error) {
283 	case ENXIO:
284 		zfs_verror(hdl, EZFS_IO, fmt, ap);
285 		break;
286 
287 	case ENOENT:
288 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
289 		    "dataset does not exist"));
290 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
291 		break;
292 
293 	case ENOSPC:
294 	case EDQUOT:
295 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
296 		return (-1);
297 
298 	case EEXIST:
299 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
300 		    "dataset already exists"));
301 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
302 		break;
303 
304 	case EBUSY:
305 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
306 		    "dataset is busy"));
307 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
308 		break;
309 	default:
310 		zfs_error_aux(hdl, strerror(errno));
311 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
312 		break;
313 	}
314 
315 	va_end(ap);
316 	return (-1);
317 }
318 
319 int
320 zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
321 {
322 	return (zpool_standard_error_fmt(hdl, error, "%s", msg));
323 }
324 
325 /*PRINTFLIKE3*/
326 int
327 zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
328 {
329 	va_list ap;
330 
331 	va_start(ap, fmt);
332 
333 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
334 		va_end(ap);
335 		return (-1);
336 	}
337 
338 	switch (error) {
339 	case ENODEV:
340 		zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
341 		break;
342 
343 	case ENOENT:
344 		zfs_error_aux(hdl,
345 		    dgettext(TEXT_DOMAIN, "no such pool or dataset"));
346 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
347 		break;
348 
349 	case EEXIST:
350 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
351 		    "pool already exists"));
352 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
353 		break;
354 
355 	case EBUSY:
356 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
357 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
358 		break;
359 
360 	case ENXIO:
361 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
362 		    "one or more devices is currently unavailable"));
363 		zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
364 		break;
365 
366 	case ENAMETOOLONG:
367 		zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
368 		break;
369 
370 	case ENOTSUP:
371 		zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
372 		break;
373 
374 	case EINVAL:
375 		zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
376 		break;
377 
378 	default:
379 		zfs_error_aux(hdl, strerror(error));
380 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
381 	}
382 
383 	va_end(ap);
384 	return (-1);
385 }
386 
387 /*
388  * Display an out of memory error message and abort the current program.
389  */
390 int
391 no_memory(libzfs_handle_t *hdl)
392 {
393 	return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
394 }
395 
396 /*
397  * A safe form of malloc() which will die if the allocation fails.
398  */
399 void *
400 zfs_alloc(libzfs_handle_t *hdl, size_t size)
401 {
402 	void *data;
403 
404 	if ((data = calloc(1, size)) == NULL)
405 		(void) no_memory(hdl);
406 
407 	return (data);
408 }
409 
410 /*
411  * A safe form of realloc(), which also zeroes newly allocated space.
412  */
413 void *
414 zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
415 {
416 	void *ret;
417 
418 	if ((ret = realloc(ptr, newsize)) == NULL) {
419 		(void) no_memory(hdl);
420 		free(ptr);
421 		return (NULL);
422 	}
423 
424 	bzero((char *)ret + oldsize, (newsize - oldsize));
425 	return (ret);
426 }
427 
428 /*
429  * A safe form of strdup() which will die if the allocation fails.
430  */
431 char *
432 zfs_strdup(libzfs_handle_t *hdl, const char *str)
433 {
434 	char *ret;
435 
436 	if ((ret = strdup(str)) == NULL)
437 		(void) no_memory(hdl);
438 
439 	return (ret);
440 }
441 
442 /*
443  * Convert a number to an appropriately human-readable output.
444  */
445 void
446 zfs_nicenum(uint64_t num, char *buf, size_t buflen)
447 {
448 	uint64_t n = num;
449 	int index = 0;
450 	char u;
451 
452 	while (n >= 1024) {
453 		n /= 1024;
454 		index++;
455 	}
456 
457 	u = " KMGTPE"[index];
458 
459 	if (index == 0) {
460 		(void) snprintf(buf, buflen, "%llu", n);
461 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
462 		/*
463 		 * If this is an even multiple of the base, always display
464 		 * without any decimal precision.
465 		 */
466 		(void) snprintf(buf, buflen, "%llu%c", n, u);
467 	} else {
468 		/*
469 		 * We want to choose a precision that reflects the best choice
470 		 * for fitting in 5 characters.  This can get rather tricky when
471 		 * we have numbers that are very close to an order of magnitude.
472 		 * For example, when displaying 10239 (which is really 9.999K),
473 		 * we want only a single place of precision for 10.0K.  We could
474 		 * develop some complex heuristics for this, but it's much
475 		 * easier just to try each combination in turn.
476 		 */
477 		int i;
478 		for (i = 2; i >= 0; i--) {
479 			(void) snprintf(buf, buflen, "%.*f%c", i,
480 			    (double)num / (1ULL << 10 * index), u);
481 			if (strlen(buf) <= 5)
482 				break;
483 		}
484 	}
485 }
486 
487 void
488 libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
489 {
490 	hdl->libzfs_printerr = printerr;
491 }
492 
493 libzfs_handle_t *
494 libzfs_init(void)
495 {
496 	libzfs_handle_t *hdl;
497 
498 	if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
499 		return (NULL);
500 	}
501 
502 	if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
503 		free(hdl);
504 		return (NULL);
505 	}
506 
507 	if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
508 		(void) close(hdl->libzfs_fd);
509 		free(hdl);
510 		return (NULL);
511 	}
512 
513 	hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
514 
515 	return (hdl);
516 }
517 
518 void
519 libzfs_fini(libzfs_handle_t *hdl)
520 {
521 	(void) close(hdl->libzfs_fd);
522 	if (hdl->libzfs_mnttab)
523 		(void) fclose(hdl->libzfs_mnttab);
524 	if (hdl->libzfs_sharetab)
525 		(void) fclose(hdl->libzfs_sharetab);
526 	namespace_clear(hdl);
527 	free(hdl);
528 }
529 
530 libzfs_handle_t *
531 zpool_get_handle(zpool_handle_t *zhp)
532 {
533 	return (zhp->zpool_hdl);
534 }
535 
536 libzfs_handle_t *
537 zfs_get_handle(zfs_handle_t *zhp)
538 {
539 	return (zhp->zfs_hdl);
540 }
541 
542 /*
543  * Given a name, determine whether or not it's a valid path
544  * (starts with '/' or "./").  If so, walk the mnttab trying
545  * to match the device number.  If not, treat the path as an
546  * fs/vol/snap name.
547  */
548 zfs_handle_t *
549 zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
550 {
551 	struct stat64 statbuf;
552 	struct extmnttab entry;
553 	int ret;
554 
555 	if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
556 		/*
557 		 * It's not a valid path, assume it's a name of type 'argtype'.
558 		 */
559 		return (zfs_open(hdl, path, argtype));
560 	}
561 
562 	if (stat64(path, &statbuf) != 0) {
563 		(void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
564 		return (NULL);
565 	}
566 
567 	rewind(hdl->libzfs_mnttab);
568 	while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
569 		if (makedevice(entry.mnt_major, entry.mnt_minor) ==
570 		    statbuf.st_dev) {
571 			break;
572 		}
573 	}
574 	if (ret != 0) {
575 		return (NULL);
576 	}
577 
578 	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
579 		(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
580 		    path);
581 		return (NULL);
582 	}
583 
584 	return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
585 }
586 
587 /*
588  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
589  * an ioctl().
590  */
591 int
592 zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
593 {
594 	if (len == 0)
595 		len = 2048;
596 	zc->zc_nvlist_dst_size = len;
597 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
598 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
599 		return (-1);
600 
601 	return (0);
602 }
603 
604 /*
605  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
606  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
607  * filled in by the kernel to indicate the actual required size.
608  */
609 int
610 zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
611 {
612 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
613 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
614 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size))
615 	    == NULL)
616 		return (-1);
617 
618 	return (0);
619 }
620 
621 /*
622  * Called to free the src and dst nvlists stored in the command structure.
623  */
624 void
625 zcmd_free_nvlists(zfs_cmd_t *zc)
626 {
627 	free((void *)(uintptr_t)zc->zc_nvlist_src);
628 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
629 }
630 
631 int
632 zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
633     size_t *size)
634 {
635 	char *packed;
636 	size_t len;
637 
638 	verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
639 
640 	if ((packed = zfs_alloc(hdl, len)) == NULL)
641 		return (-1);
642 
643 	verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
644 
645 	zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
646 	zc->zc_nvlist_src_size = len;
647 
648 	if (size)
649 		*size = len;
650 	return (0);
651 }
652 
653 /*
654  * Unpacks an nvlist from the ZFS ioctl command structure.
655  */
656 int
657 zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
658 {
659 	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
660 	    zc->zc_nvlist_dst_size, nvlp, 0) != 0)
661 		return (no_memory(hdl));
662 
663 	return (0);
664 }
665 
666 static void
667 zfs_print_prop_headers(libzfs_get_cbdata_t *cbp)
668 {
669 	zfs_proplist_t *pl = cbp->cb_proplist;
670 	int i;
671 	char *title;
672 	size_t len;
673 
674 	cbp->cb_first = B_FALSE;
675 	if (cbp->cb_scripted)
676 		return;
677 
678 	/*
679 	 * Start with the length of the column headers.
680 	 */
681 	cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
682 	cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
683 	    "PROPERTY"));
684 	cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
685 	    "VALUE"));
686 	cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
687 	    "SOURCE"));
688 
689 	/*
690 	 * Go through and calculate the widths for each column.  For the
691 	 * 'source' column, we kludge it up by taking the worst-case scenario of
692 	 * inheriting from the longest name.  This is acceptable because in the
693 	 * majority of cases 'SOURCE' is the last column displayed, and we don't
694 	 * use the width anyway.  Note that the 'VALUE' column can be oversized,
695 	 * if the name of the property is much longer the any values we find.
696 	 */
697 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
698 		/*
699 		 * 'PROPERTY' column
700 		 */
701 		if (pl->pl_prop != ZFS_PROP_INVAL) {
702 			len = strlen(zfs_prop_to_name(pl->pl_prop));
703 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
704 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
705 		} else {
706 			len = strlen(pl->pl_user_prop);
707 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
708 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
709 		}
710 
711 		/*
712 		 * 'VALUE' column
713 		 */
714 		if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) &&
715 		    pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
716 			cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
717 
718 		/*
719 		 * 'NAME' and 'SOURCE' columns
720 		 */
721 		if (pl->pl_prop == ZFS_PROP_NAME &&
722 		    pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
723 			cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
724 			cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
725 			    strlen(dgettext(TEXT_DOMAIN, "inherited from"));
726 		}
727 	}
728 
729 	/*
730 	 * Now go through and print the headers.
731 	 */
732 	for (i = 0; i < 4; i++) {
733 		switch (cbp->cb_columns[i]) {
734 		case GET_COL_NAME:
735 			title = dgettext(TEXT_DOMAIN, "NAME");
736 			break;
737 		case GET_COL_PROPERTY:
738 			title = dgettext(TEXT_DOMAIN, "PROPERTY");
739 			break;
740 		case GET_COL_VALUE:
741 			title = dgettext(TEXT_DOMAIN, "VALUE");
742 			break;
743 		case GET_COL_SOURCE:
744 			title = dgettext(TEXT_DOMAIN, "SOURCE");
745 			break;
746 		default:
747 			title = NULL;
748 		}
749 
750 		if (title != NULL) {
751 			if (i == 3 || cbp->cb_columns[i + 1] == 0)
752 				(void) printf("%s", title);
753 			else
754 				(void) printf("%-*s  ",
755 				    cbp->cb_colwidths[cbp->cb_columns[i]],
756 				    title);
757 		}
758 	}
759 	(void) printf("\n");
760 }
761 
762 /*
763  * Display a single line of output, according to the settings in the callback
764  * structure.
765  */
766 void
767 libzfs_print_one_property(const char *name, libzfs_get_cbdata_t *cbp,
768     const char *propname, const char *value, zfs_source_t sourcetype,
769     const char *source)
770 {
771 	int i;
772 	const char *str;
773 	char buf[128];
774 
775 	/*
776 	 * Ignore those source types that the user has chosen to ignore.
777 	 */
778 	if ((sourcetype & cbp->cb_sources) == 0)
779 		return;
780 
781 	if (cbp->cb_first)
782 		zfs_print_prop_headers(cbp);
783 
784 	for (i = 0; i < 4; i++) {
785 		switch (cbp->cb_columns[i]) {
786 		case GET_COL_NAME:
787 			str = name;
788 			break;
789 
790 		case GET_COL_PROPERTY:
791 			str = propname;
792 			break;
793 
794 		case GET_COL_VALUE:
795 			str = value;
796 			break;
797 
798 		case GET_COL_SOURCE:
799 			switch (sourcetype) {
800 			case ZFS_SRC_NONE:
801 				str = "-";
802 				break;
803 
804 			case ZFS_SRC_DEFAULT:
805 				str = "default";
806 				break;
807 
808 			case ZFS_SRC_LOCAL:
809 				str = "local";
810 				break;
811 
812 			case ZFS_SRC_TEMPORARY:
813 				str = "temporary";
814 				break;
815 
816 			case ZFS_SRC_INHERITED:
817 				(void) snprintf(buf, sizeof (buf),
818 				    "inherited from %s", source);
819 				str = buf;
820 				break;
821 			}
822 			break;
823 
824 		default:
825 			continue;
826 		}
827 
828 		if (cbp->cb_columns[i + 1] == 0)
829 			(void) printf("%s", str);
830 		else if (cbp->cb_scripted)
831 			(void) printf("%s\t", str);
832 		else
833 			(void) printf("%-*s  ",
834 			    cbp->cb_colwidths[cbp->cb_columns[i]],
835 			    str);
836 
837 	}
838 
839 	(void) printf("\n");
840 }
841