1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock  * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
21fa9e4066Sahrens /*
225aba80dbSck  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23fa9e4066Sahrens  * Use is subject to license terms.
24fa9e4066Sahrens  */
25fa9e4066Sahrens 
26fa9e4066Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27fa9e4066Sahrens 
28fa9e4066Sahrens /*
29fa9e4066Sahrens  * Internal utility routines for the ZFS library.
30fa9e4066Sahrens  */
31fa9e4066Sahrens 
32fa9e4066Sahrens #include <errno.h>
33fa9e4066Sahrens #include <fcntl.h>
34fa9e4066Sahrens #include <libintl.h>
35fa9e4066Sahrens #include <stdarg.h>
36fa9e4066Sahrens #include <stdio.h>
37fa9e4066Sahrens #include <stdlib.h>
38fa9e4066Sahrens #include <strings.h>
39fa9e4066Sahrens #include <unistd.h>
40fa9e4066Sahrens #include <sys/mnttab.h>
415aba80dbSck #include <sys/mntent.h>
425aba80dbSck #include <sys/types.h>
43fa9e4066Sahrens 
44fa9e4066Sahrens #include <libzfs.h>
45fa9e4066Sahrens 
46fa9e4066Sahrens #include "libzfs_impl.h"
47fa9e4066Sahrens 
4899653d4eSeschrock int
4999653d4eSeschrock libzfs_errno(libzfs_handle_t *hdl)
5099653d4eSeschrock {
5199653d4eSeschrock 	return (hdl->libzfs_error);
5299653d4eSeschrock }
53fa9e4066Sahrens 
5499653d4eSeschrock const char *
5599653d4eSeschrock libzfs_error_action(libzfs_handle_t *hdl)
5699653d4eSeschrock {
5799653d4eSeschrock 	return (hdl->libzfs_action);
5899653d4eSeschrock }
59fa9e4066Sahrens 
6099653d4eSeschrock const char *
6199653d4eSeschrock libzfs_error_description(libzfs_handle_t *hdl)
6299653d4eSeschrock {
6399653d4eSeschrock 	if (hdl->libzfs_desc[0] != '\0')
6499653d4eSeschrock 		return (hdl->libzfs_desc);
6599653d4eSeschrock 
6699653d4eSeschrock 	switch (hdl->libzfs_error) {
6799653d4eSeschrock 	case EZFS_NOMEM:
6899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "out of memory"));
6999653d4eSeschrock 	case EZFS_BADPROP:
7099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid property value"));
7199653d4eSeschrock 	case EZFS_PROPREADONLY:
7299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "read only property"));
7399653d4eSeschrock 	case EZFS_PROPTYPE:
7499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
7599653d4eSeschrock 		    "datasets of this type"));
7699653d4eSeschrock 	case EZFS_PROPNONINHERIT:
7799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
7899653d4eSeschrock 	case EZFS_PROPSPACE:
7999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
8099653d4eSeschrock 	case EZFS_BADTYPE:
8199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "operation not applicable to "
8299653d4eSeschrock 		    "datasets of this type"));
8399653d4eSeschrock 	case EZFS_BUSY:
8499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
8599653d4eSeschrock 	case EZFS_EXISTS:
8699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
8799653d4eSeschrock 	case EZFS_NOENT:
8899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
8999653d4eSeschrock 	case EZFS_BADSTREAM:
9099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
9199653d4eSeschrock 	case EZFS_DSREADONLY:
9299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "dataset is read only"));
9399653d4eSeschrock 	case EZFS_VOLTOOBIG:
9499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
9599653d4eSeschrock 		    "this system"));
9699653d4eSeschrock 	case EZFS_VOLHASDATA:
9799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "volume has data"));
9899653d4eSeschrock 	case EZFS_INVALIDNAME:
9999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid name"));
10099653d4eSeschrock 	case EZFS_BADRESTORE:
10199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unable to restore to "
10299653d4eSeschrock 		    "destination"));
10399653d4eSeschrock 	case EZFS_BADBACKUP:
10499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "backup failed"));
10599653d4eSeschrock 	case EZFS_BADTARGET:
10699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
10799653d4eSeschrock 	case EZFS_NODEVICE:
10899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "no such device in pool"));
10999653d4eSeschrock 	case EZFS_BADDEV:
11099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid device"));
11199653d4eSeschrock 	case EZFS_NOREPLICAS:
11299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "no valid replicas"));
11399653d4eSeschrock 	case EZFS_RESILVERING:
11499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "currently resilvering"));
11599653d4eSeschrock 	case EZFS_BADVERSION:
11699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unsupported version"));
11799653d4eSeschrock 	case EZFS_POOLUNAVAIL:
11899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
11999653d4eSeschrock 	case EZFS_DEVOVERFLOW:
12099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
12199653d4eSeschrock 	case EZFS_BADPATH:
12299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
12399653d4eSeschrock 	case EZFS_CROSSTARGET:
12499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
12599653d4eSeschrock 		    "pools"));
12699653d4eSeschrock 	case EZFS_ZONED:
12799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
12899653d4eSeschrock 	case EZFS_MOUNTFAILED:
12999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "mount failed"));
13099653d4eSeschrock 	case EZFS_UMOUNTFAILED:
13199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "umount failed"));
132f3861e1aSahl 	case EZFS_UNSHARENFSFAILED:
13399653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
134f3861e1aSahl 	case EZFS_SHARENFSFAILED:
13599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
13699653d4eSeschrock 	case EZFS_DEVLINKS:
13799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "failed to create /dev links"));
13899653d4eSeschrock 	case EZFS_PERM:
13999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "permission denied"));
14099653d4eSeschrock 	case EZFS_NOSPC:
14199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "out of space"));
14299653d4eSeschrock 	case EZFS_IO:
14399653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "I/O error"));
14499653d4eSeschrock 	case EZFS_INTR:
14599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "signal received"));
14699653d4eSeschrock 	case EZFS_ISSPARE:
14799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
14899653d4eSeschrock 		    "spare"));
14999653d4eSeschrock 	case EZFS_INVALCONFIG:
15099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
1513bb79becSeschrock 	case EZFS_RECURSIVE:
1523bb79becSeschrock 		return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
15306eeb2adSek 	case EZFS_NOHISTORY:
15406eeb2adSek 		return (dgettext(TEXT_DOMAIN, "no history available"));
155f3861e1aSahl 	case EZFS_UNSHAREISCSIFAILED:
156f3861e1aSahl 		return (dgettext(TEXT_DOMAIN,
157f3861e1aSahl 		    "iscsitgtd failed request to unshare"));
158f3861e1aSahl 	case EZFS_SHAREISCSIFAILED:
159f3861e1aSahl 		return (dgettext(TEXT_DOMAIN,
160f3861e1aSahl 		    "iscsitgtd failed request to share"));
161b1b8ab34Slling 	case EZFS_POOLPROPS:
162b1b8ab34Slling 		return (dgettext(TEXT_DOMAIN, "failed to retrieve "
163b1b8ab34Slling 		    "pool properties"));
164b1b8ab34Slling 	case EZFS_POOL_NOTSUP:
165b1b8ab34Slling 		return (dgettext(TEXT_DOMAIN, "operation not supported "
166b1b8ab34Slling 		    "on this type of pool"));
167b1b8ab34Slling 	case EZFS_POOL_INVALARG:
168b1b8ab34Slling 		return (dgettext(TEXT_DOMAIN, "invalid argument for "
169b1b8ab34Slling 		    "this pool operation"));
170*b7661cccSmmusante 	case EZFS_NAMETOOLONG:
171*b7661cccSmmusante 		return (dgettext(TEXT_DOMAIN, "dataset name is too long"));
17299653d4eSeschrock 	case EZFS_UNKNOWN:
17399653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unknown error"));
17499653d4eSeschrock 	default:
175c08432ebSeschrock 		assert(hdl->libzfs_error == 0);
176c08432ebSeschrock 		return (dgettext(TEXT_DOMAIN, "no error"));
17799653d4eSeschrock 	}
17899653d4eSeschrock }
17999653d4eSeschrock 
18099653d4eSeschrock /*PRINTFLIKE2*/
181fa9e4066Sahrens void
18299653d4eSeschrock zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
183fa9e4066Sahrens {
184fa9e4066Sahrens 	va_list ap;
185fa9e4066Sahrens 
186fa9e4066Sahrens 	va_start(ap, fmt);
187fa9e4066Sahrens 
18899653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
18999653d4eSeschrock 	    fmt, ap);
19099653d4eSeschrock 	hdl->libzfs_desc_active = 1;
19199653d4eSeschrock 
19299653d4eSeschrock 	va_end(ap);
19399653d4eSeschrock }
19499653d4eSeschrock 
19599653d4eSeschrock static void
19699653d4eSeschrock zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
19799653d4eSeschrock {
19899653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
19999653d4eSeschrock 	    fmt, ap);
20099653d4eSeschrock 	hdl->libzfs_error = error;
20199653d4eSeschrock 
20299653d4eSeschrock 	if (hdl->libzfs_desc_active)
20399653d4eSeschrock 		hdl->libzfs_desc_active = 0;
20499653d4eSeschrock 	else
20599653d4eSeschrock 		hdl->libzfs_desc[0] = '\0';
20699653d4eSeschrock 
20799653d4eSeschrock 	if (hdl->libzfs_printerr) {
20899653d4eSeschrock 		if (error == EZFS_UNKNOWN) {
20999653d4eSeschrock 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
21099653d4eSeschrock 			    "error: %s\n"), libzfs_error_description(hdl));
21199653d4eSeschrock 			abort();
21299653d4eSeschrock 		}
21399653d4eSeschrock 
21499653d4eSeschrock 		(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
215b1b8ab34Slling 		    libzfs_error_description(hdl));
21699653d4eSeschrock 		if (error == EZFS_NOMEM)
21799653d4eSeschrock 			exit(1);
218fa9e4066Sahrens 	}
21999653d4eSeschrock }
22099653d4eSeschrock 
221ece3d9b3Slling int
222ece3d9b3Slling zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
223ece3d9b3Slling {
224ece3d9b3Slling 	return (zfs_error_fmt(hdl, error, "%s", msg));
225ece3d9b3Slling }
226ece3d9b3Slling 
22799653d4eSeschrock /*PRINTFLIKE3*/
22899653d4eSeschrock int
229ece3d9b3Slling zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
23099653d4eSeschrock {
23199653d4eSeschrock 	va_list ap;
23299653d4eSeschrock 
23399653d4eSeschrock 	va_start(ap, fmt);
23499653d4eSeschrock 
23599653d4eSeschrock 	zfs_verror(hdl, error, fmt, ap);
236fa9e4066Sahrens 
237fa9e4066Sahrens 	va_end(ap);
23899653d4eSeschrock 
23999653d4eSeschrock 	return (-1);
240fa9e4066Sahrens }
241fa9e4066Sahrens 
24299653d4eSeschrock static int
24399653d4eSeschrock zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
24499653d4eSeschrock     va_list ap)
24599653d4eSeschrock {
24699653d4eSeschrock 	switch (error) {
24799653d4eSeschrock 	case EPERM:
24899653d4eSeschrock 	case EACCES:
24999653d4eSeschrock 		zfs_verror(hdl, EZFS_PERM, fmt, ap);
25099653d4eSeschrock 		return (-1);
25199653d4eSeschrock 
25299653d4eSeschrock 	case EIO:
25399653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
25499653d4eSeschrock 		return (-1);
25599653d4eSeschrock 
25699653d4eSeschrock 	case EINTR:
25799653d4eSeschrock 		zfs_verror(hdl, EZFS_INTR, fmt, ap);
25899653d4eSeschrock 		return (-1);
25999653d4eSeschrock 	}
26099653d4eSeschrock 
26199653d4eSeschrock 	return (0);
26299653d4eSeschrock }
26399653d4eSeschrock 
264ece3d9b3Slling int
265ece3d9b3Slling zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
266ece3d9b3Slling {
267ece3d9b3Slling 	return (zfs_standard_error_fmt(hdl, error, "%s", msg));
268ece3d9b3Slling }
269ece3d9b3Slling 
27099653d4eSeschrock /*PRINTFLIKE3*/
27199653d4eSeschrock int
272ece3d9b3Slling zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
273fa9e4066Sahrens {
274fa9e4066Sahrens 	va_list ap;
275fa9e4066Sahrens 
276fa9e4066Sahrens 	va_start(ap, fmt);
277fa9e4066Sahrens 
27899653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
27999653d4eSeschrock 		va_end(ap);
28099653d4eSeschrock 		return (-1);
281fa9e4066Sahrens 	}
282fa9e4066Sahrens 
283fa9e4066Sahrens 
28499653d4eSeschrock 	switch (error) {
28599653d4eSeschrock 	case ENXIO:
28699653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
28799653d4eSeschrock 		break;
28899653d4eSeschrock 
28999653d4eSeschrock 	case ENOENT:
29099653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
29199653d4eSeschrock 		    "dataset does not exist"));
29299653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
29399653d4eSeschrock 		break;
29499653d4eSeschrock 
29599653d4eSeschrock 	case ENOSPC:
29699653d4eSeschrock 	case EDQUOT:
29799653d4eSeschrock 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
29899653d4eSeschrock 		return (-1);
29999653d4eSeschrock 
30099653d4eSeschrock 	case EEXIST:
30199653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
30299653d4eSeschrock 		    "dataset already exists"));
30399653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
30499653d4eSeschrock 		break;
30599653d4eSeschrock 
30699653d4eSeschrock 	case EBUSY:
30799653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
30899653d4eSeschrock 		    "dataset is busy"));
30999653d4eSeschrock 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
31099653d4eSeschrock 		break;
311*b7661cccSmmusante 
312*b7661cccSmmusante 	case ENAMETOOLONG:
313*b7661cccSmmusante 		zfs_verror(hdl, EZFS_NAMETOOLONG, fmt, ap);
314*b7661cccSmmusante 		break;
315*b7661cccSmmusante 
31699653d4eSeschrock 	default:
31799653d4eSeschrock 		zfs_error_aux(hdl, strerror(errno));
31899653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
31999653d4eSeschrock 		break;
32099653d4eSeschrock 	}
32199653d4eSeschrock 
32299653d4eSeschrock 	va_end(ap);
32399653d4eSeschrock 	return (-1);
324fa9e4066Sahrens }
325fa9e4066Sahrens 
326ece3d9b3Slling int
327ece3d9b3Slling zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
328ece3d9b3Slling {
329ece3d9b3Slling 	return (zpool_standard_error_fmt(hdl, error, "%s", msg));
330ece3d9b3Slling }
331ece3d9b3Slling 
33299653d4eSeschrock /*PRINTFLIKE3*/
33399653d4eSeschrock int
334ece3d9b3Slling zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
335fa9e4066Sahrens {
33699653d4eSeschrock 	va_list ap;
33799653d4eSeschrock 
33899653d4eSeschrock 	va_start(ap, fmt);
33999653d4eSeschrock 
34099653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
34199653d4eSeschrock 		va_end(ap);
34299653d4eSeschrock 		return (-1);
34399653d4eSeschrock 	}
34499653d4eSeschrock 
34599653d4eSeschrock 	switch (error) {
34699653d4eSeschrock 	case ENODEV:
34799653d4eSeschrock 		zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
34899653d4eSeschrock 		break;
34999653d4eSeschrock 
35099653d4eSeschrock 	case ENOENT:
351b1b8ab34Slling 		zfs_error_aux(hdl,
352b1b8ab34Slling 		    dgettext(TEXT_DOMAIN, "no such pool or dataset"));
35399653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
35499653d4eSeschrock 		break;
35599653d4eSeschrock 
35699653d4eSeschrock 	case EEXIST:
35799653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
35899653d4eSeschrock 		    "pool already exists"));
35999653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
36099653d4eSeschrock 		break;
36199653d4eSeschrock 
36299653d4eSeschrock 	case EBUSY:
36399653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
36499653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
36599653d4eSeschrock 		break;
36699653d4eSeschrock 
36799653d4eSeschrock 	case ENXIO:
36899653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
36999653d4eSeschrock 		    "one or more devices is currently unavailable"));
37099653d4eSeschrock 		zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
37199653d4eSeschrock 		break;
37299653d4eSeschrock 
37399653d4eSeschrock 	case ENAMETOOLONG:
37499653d4eSeschrock 		zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
37599653d4eSeschrock 		break;
37699653d4eSeschrock 
377b1b8ab34Slling 	case ENOTSUP:
378b1b8ab34Slling 		zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
379b1b8ab34Slling 		break;
380b1b8ab34Slling 
381b1b8ab34Slling 	case EINVAL:
382b1b8ab34Slling 		zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
383b1b8ab34Slling 		break;
384b1b8ab34Slling 
38599653d4eSeschrock 	default:
38699653d4eSeschrock 		zfs_error_aux(hdl, strerror(error));
38799653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
38899653d4eSeschrock 	}
38999653d4eSeschrock 
39099653d4eSeschrock 	va_end(ap);
39199653d4eSeschrock 	return (-1);
392fa9e4066Sahrens }
393fa9e4066Sahrens 
394fa9e4066Sahrens /*
395fa9e4066Sahrens  * Display an out of memory error message and abort the current program.
396fa9e4066Sahrens  */
39799653d4eSeschrock int
39899653d4eSeschrock no_memory(libzfs_handle_t *hdl)
399fa9e4066Sahrens {
40099653d4eSeschrock 	return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
401fa9e4066Sahrens }
402fa9e4066Sahrens 
403fa9e4066Sahrens /*
404fa9e4066Sahrens  * A safe form of malloc() which will die if the allocation fails.
405fa9e4066Sahrens  */
406fa9e4066Sahrens void *
40799653d4eSeschrock zfs_alloc(libzfs_handle_t *hdl, size_t size)
408fa9e4066Sahrens {
409fa9e4066Sahrens 	void *data;
410fa9e4066Sahrens 
411fa9e4066Sahrens 	if ((data = calloc(1, size)) == NULL)
41299653d4eSeschrock 		(void) no_memory(hdl);
413fa9e4066Sahrens 
414fa9e4066Sahrens 	return (data);
415fa9e4066Sahrens }
416fa9e4066Sahrens 
417e9dbad6fSeschrock /*
418e9dbad6fSeschrock  * A safe form of realloc(), which also zeroes newly allocated space.
419e9dbad6fSeschrock  */
420e9dbad6fSeschrock void *
421e9dbad6fSeschrock zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
422e9dbad6fSeschrock {
423e9dbad6fSeschrock 	void *ret;
424e9dbad6fSeschrock 
425e9dbad6fSeschrock 	if ((ret = realloc(ptr, newsize)) == NULL) {
426e9dbad6fSeschrock 		(void) no_memory(hdl);
427e9dbad6fSeschrock 		free(ptr);
428e9dbad6fSeschrock 		return (NULL);
429e9dbad6fSeschrock 	}
430e9dbad6fSeschrock 
431e9dbad6fSeschrock 	bzero((char *)ret + oldsize, (newsize - oldsize));
432e9dbad6fSeschrock 	return (ret);
433e9dbad6fSeschrock }
434e9dbad6fSeschrock 
435fa9e4066Sahrens /*
436fa9e4066Sahrens  * A safe form of strdup() which will die if the allocation fails.
437fa9e4066Sahrens  */
438fa9e4066Sahrens char *
43999653d4eSeschrock zfs_strdup(libzfs_handle_t *hdl, const char *str)
440fa9e4066Sahrens {
441fa9e4066Sahrens 	char *ret;
442fa9e4066Sahrens 
443fa9e4066Sahrens 	if ((ret = strdup(str)) == NULL)
44499653d4eSeschrock 		(void) no_memory(hdl);
445fa9e4066Sahrens 
446fa9e4066Sahrens 	return (ret);
447fa9e4066Sahrens }
448fa9e4066Sahrens 
449fa9e4066Sahrens /*
450fa9e4066Sahrens  * Convert a number to an appropriately human-readable output.
451fa9e4066Sahrens  */
452fa9e4066Sahrens void
453fa9e4066Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen)
454fa9e4066Sahrens {
455fa9e4066Sahrens 	uint64_t n = num;
456fa9e4066Sahrens 	int index = 0;
457fa9e4066Sahrens 	char u;
458fa9e4066Sahrens 
459fa9e4066Sahrens 	while (n >= 1024) {
4605c709891Seschrock 		n /= 1024;
461fa9e4066Sahrens 		index++;
462fa9e4066Sahrens 	}
463fa9e4066Sahrens 
464fa9e4066Sahrens 	u = " KMGTPE"[index];
465fa9e4066Sahrens 
4665c709891Seschrock 	if (index == 0) {
467fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu", n);
4685c709891Seschrock 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
4695c709891Seschrock 		/*
4705c709891Seschrock 		 * If this is an even multiple of the base, always display
4715c709891Seschrock 		 * without any decimal precision.
4725c709891Seschrock 		 */
473fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu%c", n, u);
4745c709891Seschrock 	} else {
4755c709891Seschrock 		/*
4765c709891Seschrock 		 * We want to choose a precision that reflects the best choice
4775c709891Seschrock 		 * for fitting in 5 characters.  This can get rather tricky when
4785c709891Seschrock 		 * we have numbers that are very close to an order of magnitude.
4795c709891Seschrock 		 * For example, when displaying 10239 (which is really 9.999K),
4805c709891Seschrock 		 * we want only a single place of precision for 10.0K.  We could
4815c709891Seschrock 		 * develop some complex heuristics for this, but it's much
4825c709891Seschrock 		 * easier just to try each combination in turn.
4835c709891Seschrock 		 */
4845c709891Seschrock 		int i;
4855c709891Seschrock 		for (i = 2; i >= 0; i--) {
4865c709891Seschrock 			(void) snprintf(buf, buflen, "%.*f%c", i,
4875c709891Seschrock 			    (double)num / (1ULL << 10 * index), u);
4885c709891Seschrock 			if (strlen(buf) <= 5)
4895c709891Seschrock 				break;
4905c709891Seschrock 		}
4915c709891Seschrock 	}
492fa9e4066Sahrens }
49399653d4eSeschrock 
49499653d4eSeschrock void
49599653d4eSeschrock libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
49699653d4eSeschrock {
49799653d4eSeschrock 	hdl->libzfs_printerr = printerr;
49899653d4eSeschrock }
49999653d4eSeschrock 
50099653d4eSeschrock libzfs_handle_t *
50199653d4eSeschrock libzfs_init(void)
50299653d4eSeschrock {
50399653d4eSeschrock 	libzfs_handle_t *hdl;
50499653d4eSeschrock 
50599653d4eSeschrock 	if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
50699653d4eSeschrock 		return (NULL);
50799653d4eSeschrock 	}
50899653d4eSeschrock 
509c08432ebSeschrock 	if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
51099653d4eSeschrock 		free(hdl);
51199653d4eSeschrock 		return (NULL);
51299653d4eSeschrock 	}
51399653d4eSeschrock 
51499653d4eSeschrock 	if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
51599653d4eSeschrock 		(void) close(hdl->libzfs_fd);
51699653d4eSeschrock 		free(hdl);
51799653d4eSeschrock 		return (NULL);
51899653d4eSeschrock 	}
51999653d4eSeschrock 
52099653d4eSeschrock 	hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
52199653d4eSeschrock 
52299653d4eSeschrock 	return (hdl);
52399653d4eSeschrock }
52499653d4eSeschrock 
52599653d4eSeschrock void
52699653d4eSeschrock libzfs_fini(libzfs_handle_t *hdl)
52799653d4eSeschrock {
52899653d4eSeschrock 	(void) close(hdl->libzfs_fd);
52999653d4eSeschrock 	if (hdl->libzfs_mnttab)
53099653d4eSeschrock 		(void) fclose(hdl->libzfs_mnttab);
53199653d4eSeschrock 	if (hdl->libzfs_sharetab)
53299653d4eSeschrock 		(void) fclose(hdl->libzfs_sharetab);
53399653d4eSeschrock 	namespace_clear(hdl);
53499653d4eSeschrock 	free(hdl);
53599653d4eSeschrock }
53699653d4eSeschrock 
53799653d4eSeschrock libzfs_handle_t *
53899653d4eSeschrock zpool_get_handle(zpool_handle_t *zhp)
53999653d4eSeschrock {
54099653d4eSeschrock 	return (zhp->zpool_hdl);
54199653d4eSeschrock }
54299653d4eSeschrock 
54399653d4eSeschrock libzfs_handle_t *
54499653d4eSeschrock zfs_get_handle(zfs_handle_t *zhp)
54599653d4eSeschrock {
54699653d4eSeschrock 	return (zhp->zfs_hdl);
54799653d4eSeschrock }
548e9dbad6fSeschrock 
5495aba80dbSck /*
5505aba80dbSck  * Given a name, determine whether or not it's a valid path
5515aba80dbSck  * (starts with '/' or "./").  If so, walk the mnttab trying
5525aba80dbSck  * to match the device number.  If not, treat the path as an
5535aba80dbSck  * fs/vol/snap name.
5545aba80dbSck  */
5555aba80dbSck zfs_handle_t *
5565aba80dbSck zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
5575aba80dbSck {
5585aba80dbSck 	struct stat64 statbuf;
5595aba80dbSck 	struct extmnttab entry;
5605aba80dbSck 	int ret;
5615aba80dbSck 
5625aba80dbSck 	if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
5635aba80dbSck 		/*
5645aba80dbSck 		 * It's not a valid path, assume it's a name of type 'argtype'.
5655aba80dbSck 		 */
5665aba80dbSck 		return (zfs_open(hdl, path, argtype));
5675aba80dbSck 	}
5685aba80dbSck 
5695aba80dbSck 	if (stat64(path, &statbuf) != 0) {
5705aba80dbSck 		(void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
5715aba80dbSck 		return (NULL);
5725aba80dbSck 	}
5735aba80dbSck 
5745aba80dbSck 	rewind(hdl->libzfs_mnttab);
5755aba80dbSck 	while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
5765aba80dbSck 		if (makedevice(entry.mnt_major, entry.mnt_minor) ==
5775aba80dbSck 		    statbuf.st_dev) {
5785aba80dbSck 			break;
5795aba80dbSck 		}
5805aba80dbSck 	}
5815aba80dbSck 	if (ret != 0) {
5825aba80dbSck 		return (NULL);
5835aba80dbSck 	}
5845aba80dbSck 
5855aba80dbSck 	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
5865aba80dbSck 		(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
5875aba80dbSck 		    path);
5885aba80dbSck 		return (NULL);
5895aba80dbSck 	}
5905aba80dbSck 
5915aba80dbSck 	return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
5925aba80dbSck }
5935aba80dbSck 
594e9dbad6fSeschrock /*
595e9dbad6fSeschrock  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
596e9dbad6fSeschrock  * an ioctl().
597e9dbad6fSeschrock  */
598e9dbad6fSeschrock int
599e9dbad6fSeschrock zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
600e9dbad6fSeschrock {
601e9dbad6fSeschrock 	if (len == 0)
602a2eea2e1Sahrens 		len = 2048;
603e9dbad6fSeschrock 	zc->zc_nvlist_dst_size = len;
604e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
605e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
606e9dbad6fSeschrock 		return (-1);
607e9dbad6fSeschrock 
608e9dbad6fSeschrock 	return (0);
609e9dbad6fSeschrock }
610e9dbad6fSeschrock 
611e9dbad6fSeschrock /*
612e9dbad6fSeschrock  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
613e9dbad6fSeschrock  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
614e9dbad6fSeschrock  * filled in by the kernel to indicate the actual required size.
615e9dbad6fSeschrock  */
616e9dbad6fSeschrock int
617e9dbad6fSeschrock zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
618e9dbad6fSeschrock {
619e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
620e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
621e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size))
622e9dbad6fSeschrock 	    == NULL)
623e9dbad6fSeschrock 		return (-1);
624e9dbad6fSeschrock 
625e9dbad6fSeschrock 	return (0);
626e9dbad6fSeschrock }
627e9dbad6fSeschrock 
628e9dbad6fSeschrock /*
629a2eea2e1Sahrens  * Called to free the src and dst nvlists stored in the command structure.
630e9dbad6fSeschrock  */
631e9dbad6fSeschrock void
632e9dbad6fSeschrock zcmd_free_nvlists(zfs_cmd_t *zc)
633e9dbad6fSeschrock {
634e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_src);
635e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
636e9dbad6fSeschrock }
637e9dbad6fSeschrock 
638e9dbad6fSeschrock int
639e9dbad6fSeschrock zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
640e9dbad6fSeschrock     size_t *size)
641e9dbad6fSeschrock {
642e9dbad6fSeschrock 	char *packed;
643e9dbad6fSeschrock 	size_t len;
644e9dbad6fSeschrock 
645e9dbad6fSeschrock 	verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
646e9dbad6fSeschrock 
647e9dbad6fSeschrock 	if ((packed = zfs_alloc(hdl, len)) == NULL)
648e9dbad6fSeschrock 		return (-1);
649e9dbad6fSeschrock 
650e9dbad6fSeschrock 	verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
651e9dbad6fSeschrock 
652e9dbad6fSeschrock 	zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
653e9dbad6fSeschrock 	zc->zc_nvlist_src_size = len;
654e9dbad6fSeschrock 
655e9dbad6fSeschrock 	if (size)
656e9dbad6fSeschrock 		*size = len;
657e9dbad6fSeschrock 	return (0);
658e9dbad6fSeschrock }
659e9dbad6fSeschrock 
660e9dbad6fSeschrock /*
661e9dbad6fSeschrock  * Unpacks an nvlist from the ZFS ioctl command structure.
662e9dbad6fSeschrock  */
663e9dbad6fSeschrock int
664e9dbad6fSeschrock zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
665e9dbad6fSeschrock {
666e9dbad6fSeschrock 	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
667e9dbad6fSeschrock 	    zc->zc_nvlist_dst_size, nvlp, 0) != 0)
668e9dbad6fSeschrock 		return (no_memory(hdl));
669e9dbad6fSeschrock 
670e9dbad6fSeschrock 	return (0);
671e9dbad6fSeschrock }
672b1b8ab34Slling 
673b1b8ab34Slling static void
674b1b8ab34Slling zfs_print_prop_headers(libzfs_get_cbdata_t *cbp)
675b1b8ab34Slling {
676b1b8ab34Slling 	zfs_proplist_t *pl = cbp->cb_proplist;
677b1b8ab34Slling 	int i;
678b1b8ab34Slling 	char *title;
679b1b8ab34Slling 	size_t len;
680b1b8ab34Slling 
681b1b8ab34Slling 	cbp->cb_first = B_FALSE;
682b1b8ab34Slling 	if (cbp->cb_scripted)
683b1b8ab34Slling 		return;
684b1b8ab34Slling 
685b1b8ab34Slling 	/*
686b1b8ab34Slling 	 * Start with the length of the column headers.
687b1b8ab34Slling 	 */
688b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
689b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
690b1b8ab34Slling 	    "PROPERTY"));
691b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
692b1b8ab34Slling 	    "VALUE"));
693b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
694b1b8ab34Slling 	    "SOURCE"));
695b1b8ab34Slling 
696b1b8ab34Slling 	/*
697b1b8ab34Slling 	 * Go through and calculate the widths for each column.  For the
698b1b8ab34Slling 	 * 'source' column, we kludge it up by taking the worst-case scenario of
699b1b8ab34Slling 	 * inheriting from the longest name.  This is acceptable because in the
700b1b8ab34Slling 	 * majority of cases 'SOURCE' is the last column displayed, and we don't
701b1b8ab34Slling 	 * use the width anyway.  Note that the 'VALUE' column can be oversized,
702b1b8ab34Slling 	 * if the name of the property is much longer the any values we find.
703b1b8ab34Slling 	 */
704b1b8ab34Slling 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
705b1b8ab34Slling 		/*
706b1b8ab34Slling 		 * 'PROPERTY' column
707b1b8ab34Slling 		 */
708b1b8ab34Slling 		if (pl->pl_prop != ZFS_PROP_INVAL) {
709b1b8ab34Slling 			len = strlen(zfs_prop_to_name(pl->pl_prop));
710b1b8ab34Slling 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
711b1b8ab34Slling 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
712b1b8ab34Slling 		} else {
713b1b8ab34Slling 			len = strlen(pl->pl_user_prop);
714b1b8ab34Slling 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
715b1b8ab34Slling 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
716b1b8ab34Slling 		}
717b1b8ab34Slling 
718b1b8ab34Slling 		/*
719b1b8ab34Slling 		 * 'VALUE' column
720b1b8ab34Slling 		 */
721b1b8ab34Slling 		if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) &&
722b1b8ab34Slling 		    pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
723b1b8ab34Slling 			cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
724b1b8ab34Slling 
725b1b8ab34Slling 		/*
726b1b8ab34Slling 		 * 'NAME' and 'SOURCE' columns
727b1b8ab34Slling 		 */
728b1b8ab34Slling 		if (pl->pl_prop == ZFS_PROP_NAME &&
729b1b8ab34Slling 		    pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
730b1b8ab34Slling 			cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
731b1b8ab34Slling 			cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
732b1b8ab34Slling 			    strlen(dgettext(TEXT_DOMAIN, "inherited from"));
733b1b8ab34Slling 		}
734b1b8ab34Slling 	}
735b1b8ab34Slling 
736b1b8ab34Slling 	/*
737b1b8ab34Slling 	 * Now go through and print the headers.
738b1b8ab34Slling 	 */
739b1b8ab34Slling 	for (i = 0; i < 4; i++) {
740b1b8ab34Slling 		switch (cbp->cb_columns[i]) {
741b1b8ab34Slling 		case GET_COL_NAME:
742b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "NAME");
743b1b8ab34Slling 			break;
744b1b8ab34Slling 		case GET_COL_PROPERTY:
745b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "PROPERTY");
746b1b8ab34Slling 			break;
747b1b8ab34Slling 		case GET_COL_VALUE:
748b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "VALUE");
749b1b8ab34Slling 			break;
750b1b8ab34Slling 		case GET_COL_SOURCE:
751b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "SOURCE");
752b1b8ab34Slling 			break;
753b1b8ab34Slling 		default:
754b1b8ab34Slling 			title = NULL;
755b1b8ab34Slling 		}
756b1b8ab34Slling 
757b1b8ab34Slling 		if (title != NULL) {
758b1b8ab34Slling 			if (i == 3 || cbp->cb_columns[i + 1] == 0)
759b1b8ab34Slling 				(void) printf("%s", title);
760b1b8ab34Slling 			else
761b1b8ab34Slling 				(void) printf("%-*s  ",
762b1b8ab34Slling 				    cbp->cb_colwidths[cbp->cb_columns[i]],
763b1b8ab34Slling 				    title);
764b1b8ab34Slling 		}
765b1b8ab34Slling 	}
766b1b8ab34Slling 	(void) printf("\n");
767b1b8ab34Slling }
768b1b8ab34Slling 
769b1b8ab34Slling /*
770b1b8ab34Slling  * Display a single line of output, according to the settings in the callback
771b1b8ab34Slling  * structure.
772b1b8ab34Slling  */
773b1b8ab34Slling void
774b1b8ab34Slling libzfs_print_one_property(const char *name, libzfs_get_cbdata_t *cbp,
775b1b8ab34Slling     const char *propname, const char *value, zfs_source_t sourcetype,
776b1b8ab34Slling     const char *source)
777b1b8ab34Slling {
778b1b8ab34Slling 	int i;
779b1b8ab34Slling 	const char *str;
780b1b8ab34Slling 	char buf[128];
781b1b8ab34Slling 
782b1b8ab34Slling 	/*
783b1b8ab34Slling 	 * Ignore those source types that the user has chosen to ignore.
784b1b8ab34Slling 	 */
785b1b8ab34Slling 	if ((sourcetype & cbp->cb_sources) == 0)
786b1b8ab34Slling 		return;
787b1b8ab34Slling 
788b1b8ab34Slling 	if (cbp->cb_first)
789b1b8ab34Slling 		zfs_print_prop_headers(cbp);
790b1b8ab34Slling 
791b1b8ab34Slling 	for (i = 0; i < 4; i++) {
792b1b8ab34Slling 		switch (cbp->cb_columns[i]) {
793b1b8ab34Slling 		case GET_COL_NAME:
794b1b8ab34Slling 			str = name;
795b1b8ab34Slling 			break;
796b1b8ab34Slling 
797b1b8ab34Slling 		case GET_COL_PROPERTY:
798b1b8ab34Slling 			str = propname;
799b1b8ab34Slling 			break;
800b1b8ab34Slling 
801b1b8ab34Slling 		case GET_COL_VALUE:
802b1b8ab34Slling 			str = value;
803b1b8ab34Slling 			break;
804b1b8ab34Slling 
805b1b8ab34Slling 		case GET_COL_SOURCE:
806b1b8ab34Slling 			switch (sourcetype) {
807b1b8ab34Slling 			case ZFS_SRC_NONE:
808b1b8ab34Slling 				str = "-";
809b1b8ab34Slling 				break;
810b1b8ab34Slling 
811b1b8ab34Slling 			case ZFS_SRC_DEFAULT:
812b1b8ab34Slling 				str = "default";
813b1b8ab34Slling 				break;
814b1b8ab34Slling 
815b1b8ab34Slling 			case ZFS_SRC_LOCAL:
816b1b8ab34Slling 				str = "local";
817b1b8ab34Slling 				break;
818b1b8ab34Slling 
819b1b8ab34Slling 			case ZFS_SRC_TEMPORARY:
820b1b8ab34Slling 				str = "temporary";
821b1b8ab34Slling 				break;
822b1b8ab34Slling 
823b1b8ab34Slling 			case ZFS_SRC_INHERITED:
824b1b8ab34Slling 				(void) snprintf(buf, sizeof (buf),
825b1b8ab34Slling 				    "inherited from %s", source);
826b1b8ab34Slling 				str = buf;
827b1b8ab34Slling 				break;
828b1b8ab34Slling 			}
829b1b8ab34Slling 			break;
830b1b8ab34Slling 
831b1b8ab34Slling 		default:
832b1b8ab34Slling 			continue;
833b1b8ab34Slling 		}
834b1b8ab34Slling 
835b1b8ab34Slling 		if (cbp->cb_columns[i + 1] == 0)
836b1b8ab34Slling 			(void) printf("%s", str);
837b1b8ab34Slling 		else if (cbp->cb_scripted)
838b1b8ab34Slling 			(void) printf("%s\t", str);
839b1b8ab34Slling 		else
840b1b8ab34Slling 			(void) printf("%-*s  ",
841b1b8ab34Slling 			    cbp->cb_colwidths[cbp->cb_columns[i]],
842b1b8ab34Slling 			    str);
843b1b8ab34Slling 
844b1b8ab34Slling 	}
845b1b8ab34Slling 
846b1b8ab34Slling 	(void) printf("\n");
847b1b8ab34Slling }
848