xref: /illumos-gate/usr/src/lib/libzfs/common/libzfs_util.c (revision b1b8ab34de515a5e83206da22c3d7e563241b021)
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"));
161*b1b8ab34Slling 	case EZFS_POOLPROPS:
162*b1b8ab34Slling 		return (dgettext(TEXT_DOMAIN, "failed to retrieve "
163*b1b8ab34Slling 		    "pool properties"));
164*b1b8ab34Slling 	case EZFS_POOL_NOTSUP:
165*b1b8ab34Slling 		return (dgettext(TEXT_DOMAIN, "operation not supported "
166*b1b8ab34Slling 		    "on this type of pool"));
167*b1b8ab34Slling 	case EZFS_POOL_INVALARG:
168*b1b8ab34Slling 		return (dgettext(TEXT_DOMAIN, "invalid argument for "
169*b1b8ab34Slling 		    "this pool operation"));
17099653d4eSeschrock 	case EZFS_UNKNOWN:
17199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unknown error"));
17299653d4eSeschrock 	default:
173c08432ebSeschrock 		assert(hdl->libzfs_error == 0);
174c08432ebSeschrock 		return (dgettext(TEXT_DOMAIN, "no error"));
17599653d4eSeschrock 	}
17699653d4eSeschrock }
17799653d4eSeschrock 
17899653d4eSeschrock /*PRINTFLIKE2*/
179fa9e4066Sahrens void
18099653d4eSeschrock zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
181fa9e4066Sahrens {
182fa9e4066Sahrens 	va_list ap;
183fa9e4066Sahrens 
184fa9e4066Sahrens 	va_start(ap, fmt);
185fa9e4066Sahrens 
18699653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
18799653d4eSeschrock 	    fmt, ap);
18899653d4eSeschrock 	hdl->libzfs_desc_active = 1;
18999653d4eSeschrock 
19099653d4eSeschrock 	va_end(ap);
19199653d4eSeschrock }
19299653d4eSeschrock 
19399653d4eSeschrock static void
19499653d4eSeschrock zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
19599653d4eSeschrock {
19699653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
19799653d4eSeschrock 	    fmt, ap);
19899653d4eSeschrock 	hdl->libzfs_error = error;
19999653d4eSeschrock 
20099653d4eSeschrock 	if (hdl->libzfs_desc_active)
20199653d4eSeschrock 		hdl->libzfs_desc_active = 0;
20299653d4eSeschrock 	else
20399653d4eSeschrock 		hdl->libzfs_desc[0] = '\0';
20499653d4eSeschrock 
20599653d4eSeschrock 	if (hdl->libzfs_printerr) {
20699653d4eSeschrock 		if (error == EZFS_UNKNOWN) {
20799653d4eSeschrock 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
20899653d4eSeschrock 			    "error: %s\n"), libzfs_error_description(hdl));
20999653d4eSeschrock 			abort();
21099653d4eSeschrock 		}
21199653d4eSeschrock 
21299653d4eSeschrock 		(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
213*b1b8ab34Slling 		    libzfs_error_description(hdl));
21499653d4eSeschrock 		if (error == EZFS_NOMEM)
21599653d4eSeschrock 			exit(1);
216fa9e4066Sahrens 	}
21799653d4eSeschrock }
21899653d4eSeschrock 
219ece3d9b3Slling int
220ece3d9b3Slling zfs_error(libzfs_handle_t *hdl, int error, const char *msg)
221ece3d9b3Slling {
222ece3d9b3Slling 	return (zfs_error_fmt(hdl, error, "%s", msg));
223ece3d9b3Slling }
224ece3d9b3Slling 
22599653d4eSeschrock /*PRINTFLIKE3*/
22699653d4eSeschrock int
227ece3d9b3Slling zfs_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
22899653d4eSeschrock {
22999653d4eSeschrock 	va_list ap;
23099653d4eSeschrock 
23199653d4eSeschrock 	va_start(ap, fmt);
23299653d4eSeschrock 
23399653d4eSeschrock 	zfs_verror(hdl, error, fmt, ap);
234fa9e4066Sahrens 
235fa9e4066Sahrens 	va_end(ap);
23699653d4eSeschrock 
23799653d4eSeschrock 	return (-1);
238fa9e4066Sahrens }
239fa9e4066Sahrens 
24099653d4eSeschrock static int
24199653d4eSeschrock zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
24299653d4eSeschrock     va_list ap)
24399653d4eSeschrock {
24499653d4eSeschrock 	switch (error) {
24599653d4eSeschrock 	case EPERM:
24699653d4eSeschrock 	case EACCES:
24799653d4eSeschrock 		zfs_verror(hdl, EZFS_PERM, fmt, ap);
24899653d4eSeschrock 		return (-1);
24999653d4eSeschrock 
25099653d4eSeschrock 	case EIO:
25199653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
25299653d4eSeschrock 		return (-1);
25399653d4eSeschrock 
25499653d4eSeschrock 	case EINTR:
25599653d4eSeschrock 		zfs_verror(hdl, EZFS_INTR, fmt, ap);
25699653d4eSeschrock 		return (-1);
25799653d4eSeschrock 	}
25899653d4eSeschrock 
25999653d4eSeschrock 	return (0);
26099653d4eSeschrock }
26199653d4eSeschrock 
262ece3d9b3Slling int
263ece3d9b3Slling zfs_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
264ece3d9b3Slling {
265ece3d9b3Slling 	return (zfs_standard_error_fmt(hdl, error, "%s", msg));
266ece3d9b3Slling }
267ece3d9b3Slling 
26899653d4eSeschrock /*PRINTFLIKE3*/
26999653d4eSeschrock int
270ece3d9b3Slling zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
271fa9e4066Sahrens {
272fa9e4066Sahrens 	va_list ap;
273fa9e4066Sahrens 
274fa9e4066Sahrens 	va_start(ap, fmt);
275fa9e4066Sahrens 
27699653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
27799653d4eSeschrock 		va_end(ap);
27899653d4eSeschrock 		return (-1);
279fa9e4066Sahrens 	}
280fa9e4066Sahrens 
281fa9e4066Sahrens 
28299653d4eSeschrock 	switch (error) {
28399653d4eSeschrock 	case ENXIO:
28499653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
28599653d4eSeschrock 		break;
28699653d4eSeschrock 
28799653d4eSeschrock 	case ENOENT:
28899653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
28999653d4eSeschrock 		    "dataset does not exist"));
29099653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
29199653d4eSeschrock 		break;
29299653d4eSeschrock 
29399653d4eSeschrock 	case ENOSPC:
29499653d4eSeschrock 	case EDQUOT:
29599653d4eSeschrock 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
29699653d4eSeschrock 		return (-1);
29799653d4eSeschrock 
29899653d4eSeschrock 	case EEXIST:
29999653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
30099653d4eSeschrock 		    "dataset already exists"));
30199653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
30299653d4eSeschrock 		break;
30399653d4eSeschrock 
30499653d4eSeschrock 	case EBUSY:
30599653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
30699653d4eSeschrock 		    "dataset is busy"));
30799653d4eSeschrock 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
30899653d4eSeschrock 		break;
30999653d4eSeschrock 	default:
31099653d4eSeschrock 		zfs_error_aux(hdl, strerror(errno));
31199653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
31299653d4eSeschrock 		break;
31399653d4eSeschrock 	}
31499653d4eSeschrock 
31599653d4eSeschrock 	va_end(ap);
31699653d4eSeschrock 	return (-1);
317fa9e4066Sahrens }
318fa9e4066Sahrens 
319ece3d9b3Slling int
320ece3d9b3Slling zpool_standard_error(libzfs_handle_t *hdl, int error, const char *msg)
321ece3d9b3Slling {
322ece3d9b3Slling 	return (zpool_standard_error_fmt(hdl, error, "%s", msg));
323ece3d9b3Slling }
324ece3d9b3Slling 
32599653d4eSeschrock /*PRINTFLIKE3*/
32699653d4eSeschrock int
327ece3d9b3Slling zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
328fa9e4066Sahrens {
32999653d4eSeschrock 	va_list ap;
33099653d4eSeschrock 
33199653d4eSeschrock 	va_start(ap, fmt);
33299653d4eSeschrock 
33399653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
33499653d4eSeschrock 		va_end(ap);
33599653d4eSeschrock 		return (-1);
33699653d4eSeschrock 	}
33799653d4eSeschrock 
33899653d4eSeschrock 	switch (error) {
33999653d4eSeschrock 	case ENODEV:
34099653d4eSeschrock 		zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
34199653d4eSeschrock 		break;
34299653d4eSeschrock 
34399653d4eSeschrock 	case ENOENT:
344*b1b8ab34Slling 		zfs_error_aux(hdl,
345*b1b8ab34Slling 		    dgettext(TEXT_DOMAIN, "no such pool or dataset"));
34699653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
34799653d4eSeschrock 		break;
34899653d4eSeschrock 
34999653d4eSeschrock 	case EEXIST:
35099653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
35199653d4eSeschrock 		    "pool already exists"));
35299653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
35399653d4eSeschrock 		break;
35499653d4eSeschrock 
35599653d4eSeschrock 	case EBUSY:
35699653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
35799653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
35899653d4eSeschrock 		break;
35999653d4eSeschrock 
36099653d4eSeschrock 	case ENXIO:
36199653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
36299653d4eSeschrock 		    "one or more devices is currently unavailable"));
36399653d4eSeschrock 		zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
36499653d4eSeschrock 		break;
36599653d4eSeschrock 
36699653d4eSeschrock 	case ENAMETOOLONG:
36799653d4eSeschrock 		zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
36899653d4eSeschrock 		break;
36999653d4eSeschrock 
370*b1b8ab34Slling 	case ENOTSUP:
371*b1b8ab34Slling 		zfs_verror(hdl, EZFS_POOL_NOTSUP, fmt, ap);
372*b1b8ab34Slling 		break;
373*b1b8ab34Slling 
374*b1b8ab34Slling 	case EINVAL:
375*b1b8ab34Slling 		zfs_verror(hdl, EZFS_POOL_INVALARG, fmt, ap);
376*b1b8ab34Slling 		break;
377*b1b8ab34Slling 
37899653d4eSeschrock 	default:
37999653d4eSeschrock 		zfs_error_aux(hdl, strerror(error));
38099653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
38199653d4eSeschrock 	}
38299653d4eSeschrock 
38399653d4eSeschrock 	va_end(ap);
38499653d4eSeschrock 	return (-1);
385fa9e4066Sahrens }
386fa9e4066Sahrens 
387fa9e4066Sahrens /*
388fa9e4066Sahrens  * Display an out of memory error message and abort the current program.
389fa9e4066Sahrens  */
39099653d4eSeschrock int
39199653d4eSeschrock no_memory(libzfs_handle_t *hdl)
392fa9e4066Sahrens {
39399653d4eSeschrock 	return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
394fa9e4066Sahrens }
395fa9e4066Sahrens 
396fa9e4066Sahrens /*
397fa9e4066Sahrens  * A safe form of malloc() which will die if the allocation fails.
398fa9e4066Sahrens  */
399fa9e4066Sahrens void *
40099653d4eSeschrock zfs_alloc(libzfs_handle_t *hdl, size_t size)
401fa9e4066Sahrens {
402fa9e4066Sahrens 	void *data;
403fa9e4066Sahrens 
404fa9e4066Sahrens 	if ((data = calloc(1, size)) == NULL)
40599653d4eSeschrock 		(void) no_memory(hdl);
406fa9e4066Sahrens 
407fa9e4066Sahrens 	return (data);
408fa9e4066Sahrens }
409fa9e4066Sahrens 
410e9dbad6fSeschrock /*
411e9dbad6fSeschrock  * A safe form of realloc(), which also zeroes newly allocated space.
412e9dbad6fSeschrock  */
413e9dbad6fSeschrock void *
414e9dbad6fSeschrock zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
415e9dbad6fSeschrock {
416e9dbad6fSeschrock 	void *ret;
417e9dbad6fSeschrock 
418e9dbad6fSeschrock 	if ((ret = realloc(ptr, newsize)) == NULL) {
419e9dbad6fSeschrock 		(void) no_memory(hdl);
420e9dbad6fSeschrock 		free(ptr);
421e9dbad6fSeschrock 		return (NULL);
422e9dbad6fSeschrock 	}
423e9dbad6fSeschrock 
424e9dbad6fSeschrock 	bzero((char *)ret + oldsize, (newsize - oldsize));
425e9dbad6fSeschrock 	return (ret);
426e9dbad6fSeschrock }
427e9dbad6fSeschrock 
428fa9e4066Sahrens /*
429fa9e4066Sahrens  * A safe form of strdup() which will die if the allocation fails.
430fa9e4066Sahrens  */
431fa9e4066Sahrens char *
43299653d4eSeschrock zfs_strdup(libzfs_handle_t *hdl, const char *str)
433fa9e4066Sahrens {
434fa9e4066Sahrens 	char *ret;
435fa9e4066Sahrens 
436fa9e4066Sahrens 	if ((ret = strdup(str)) == NULL)
43799653d4eSeschrock 		(void) no_memory(hdl);
438fa9e4066Sahrens 
439fa9e4066Sahrens 	return (ret);
440fa9e4066Sahrens }
441fa9e4066Sahrens 
442fa9e4066Sahrens /*
443fa9e4066Sahrens  * Convert a number to an appropriately human-readable output.
444fa9e4066Sahrens  */
445fa9e4066Sahrens void
446fa9e4066Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen)
447fa9e4066Sahrens {
448fa9e4066Sahrens 	uint64_t n = num;
449fa9e4066Sahrens 	int index = 0;
450fa9e4066Sahrens 	char u;
451fa9e4066Sahrens 
452fa9e4066Sahrens 	while (n >= 1024) {
4535c709891Seschrock 		n /= 1024;
454fa9e4066Sahrens 		index++;
455fa9e4066Sahrens 	}
456fa9e4066Sahrens 
457fa9e4066Sahrens 	u = " KMGTPE"[index];
458fa9e4066Sahrens 
4595c709891Seschrock 	if (index == 0) {
460fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu", n);
4615c709891Seschrock 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
4625c709891Seschrock 		/*
4635c709891Seschrock 		 * If this is an even multiple of the base, always display
4645c709891Seschrock 		 * without any decimal precision.
4655c709891Seschrock 		 */
466fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu%c", n, u);
4675c709891Seschrock 	} else {
4685c709891Seschrock 		/*
4695c709891Seschrock 		 * We want to choose a precision that reflects the best choice
4705c709891Seschrock 		 * for fitting in 5 characters.  This can get rather tricky when
4715c709891Seschrock 		 * we have numbers that are very close to an order of magnitude.
4725c709891Seschrock 		 * For example, when displaying 10239 (which is really 9.999K),
4735c709891Seschrock 		 * we want only a single place of precision for 10.0K.  We could
4745c709891Seschrock 		 * develop some complex heuristics for this, but it's much
4755c709891Seschrock 		 * easier just to try each combination in turn.
4765c709891Seschrock 		 */
4775c709891Seschrock 		int i;
4785c709891Seschrock 		for (i = 2; i >= 0; i--) {
4795c709891Seschrock 			(void) snprintf(buf, buflen, "%.*f%c", i,
4805c709891Seschrock 			    (double)num / (1ULL << 10 * index), u);
4815c709891Seschrock 			if (strlen(buf) <= 5)
4825c709891Seschrock 				break;
4835c709891Seschrock 		}
4845c709891Seschrock 	}
485fa9e4066Sahrens }
48699653d4eSeschrock 
48799653d4eSeschrock void
48899653d4eSeschrock libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
48999653d4eSeschrock {
49099653d4eSeschrock 	hdl->libzfs_printerr = printerr;
49199653d4eSeschrock }
49299653d4eSeschrock 
49399653d4eSeschrock libzfs_handle_t *
49499653d4eSeschrock libzfs_init(void)
49599653d4eSeschrock {
49699653d4eSeschrock 	libzfs_handle_t *hdl;
49799653d4eSeschrock 
49899653d4eSeschrock 	if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
49999653d4eSeschrock 		return (NULL);
50099653d4eSeschrock 	}
50199653d4eSeschrock 
502c08432ebSeschrock 	if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
50399653d4eSeschrock 		free(hdl);
50499653d4eSeschrock 		return (NULL);
50599653d4eSeschrock 	}
50699653d4eSeschrock 
50799653d4eSeschrock 	if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
50899653d4eSeschrock 		(void) close(hdl->libzfs_fd);
50999653d4eSeschrock 		free(hdl);
51099653d4eSeschrock 		return (NULL);
51199653d4eSeschrock 	}
51299653d4eSeschrock 
51399653d4eSeschrock 	hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
51499653d4eSeschrock 
51599653d4eSeschrock 	return (hdl);
51699653d4eSeschrock }
51799653d4eSeschrock 
51899653d4eSeschrock void
51999653d4eSeschrock libzfs_fini(libzfs_handle_t *hdl)
52099653d4eSeschrock {
52199653d4eSeschrock 	(void) close(hdl->libzfs_fd);
52299653d4eSeschrock 	if (hdl->libzfs_mnttab)
52399653d4eSeschrock 		(void) fclose(hdl->libzfs_mnttab);
52499653d4eSeschrock 	if (hdl->libzfs_sharetab)
52599653d4eSeschrock 		(void) fclose(hdl->libzfs_sharetab);
52699653d4eSeschrock 	namespace_clear(hdl);
52799653d4eSeschrock 	free(hdl);
52899653d4eSeschrock }
52999653d4eSeschrock 
53099653d4eSeschrock libzfs_handle_t *
53199653d4eSeschrock zpool_get_handle(zpool_handle_t *zhp)
53299653d4eSeschrock {
53399653d4eSeschrock 	return (zhp->zpool_hdl);
53499653d4eSeschrock }
53599653d4eSeschrock 
53699653d4eSeschrock libzfs_handle_t *
53799653d4eSeschrock zfs_get_handle(zfs_handle_t *zhp)
53899653d4eSeschrock {
53999653d4eSeschrock 	return (zhp->zfs_hdl);
54099653d4eSeschrock }
541e9dbad6fSeschrock 
5425aba80dbSck /*
5435aba80dbSck  * Given a name, determine whether or not it's a valid path
5445aba80dbSck  * (starts with '/' or "./").  If so, walk the mnttab trying
5455aba80dbSck  * to match the device number.  If not, treat the path as an
5465aba80dbSck  * fs/vol/snap name.
5475aba80dbSck  */
5485aba80dbSck zfs_handle_t *
5495aba80dbSck zfs_path_to_zhandle(libzfs_handle_t *hdl, char *path, zfs_type_t argtype)
5505aba80dbSck {
5515aba80dbSck 	struct stat64 statbuf;
5525aba80dbSck 	struct extmnttab entry;
5535aba80dbSck 	int ret;
5545aba80dbSck 
5555aba80dbSck 	if (path[0] != '/' && strncmp(path, "./", strlen("./")) != 0) {
5565aba80dbSck 		/*
5575aba80dbSck 		 * It's not a valid path, assume it's a name of type 'argtype'.
5585aba80dbSck 		 */
5595aba80dbSck 		return (zfs_open(hdl, path, argtype));
5605aba80dbSck 	}
5615aba80dbSck 
5625aba80dbSck 	if (stat64(path, &statbuf) != 0) {
5635aba80dbSck 		(void) fprintf(stderr, "%s: %s\n", path, strerror(errno));
5645aba80dbSck 		return (NULL);
5655aba80dbSck 	}
5665aba80dbSck 
5675aba80dbSck 	rewind(hdl->libzfs_mnttab);
5685aba80dbSck 	while ((ret = getextmntent(hdl->libzfs_mnttab, &entry, 0)) == 0) {
5695aba80dbSck 		if (makedevice(entry.mnt_major, entry.mnt_minor) ==
5705aba80dbSck 		    statbuf.st_dev) {
5715aba80dbSck 			break;
5725aba80dbSck 		}
5735aba80dbSck 	}
5745aba80dbSck 	if (ret != 0) {
5755aba80dbSck 		return (NULL);
5765aba80dbSck 	}
5775aba80dbSck 
5785aba80dbSck 	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
5795aba80dbSck 		(void) fprintf(stderr, gettext("'%s': not a ZFS filesystem\n"),
5805aba80dbSck 		    path);
5815aba80dbSck 		return (NULL);
5825aba80dbSck 	}
5835aba80dbSck 
5845aba80dbSck 	return (zfs_open(hdl, entry.mnt_special, ZFS_TYPE_FILESYSTEM));
5855aba80dbSck }
5865aba80dbSck 
587e9dbad6fSeschrock /*
588e9dbad6fSeschrock  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
589e9dbad6fSeschrock  * an ioctl().
590e9dbad6fSeschrock  */
591e9dbad6fSeschrock int
592e9dbad6fSeschrock zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
593e9dbad6fSeschrock {
594e9dbad6fSeschrock 	if (len == 0)
595a2eea2e1Sahrens 		len = 2048;
596e9dbad6fSeschrock 	zc->zc_nvlist_dst_size = len;
597e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
598e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
599e9dbad6fSeschrock 		return (-1);
600e9dbad6fSeschrock 
601e9dbad6fSeschrock 	return (0);
602e9dbad6fSeschrock }
603e9dbad6fSeschrock 
604e9dbad6fSeschrock /*
605e9dbad6fSeschrock  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
606e9dbad6fSeschrock  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
607e9dbad6fSeschrock  * filled in by the kernel to indicate the actual required size.
608e9dbad6fSeschrock  */
609e9dbad6fSeschrock int
610e9dbad6fSeschrock zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
611e9dbad6fSeschrock {
612e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
613e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
614e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size))
615e9dbad6fSeschrock 	    == NULL)
616e9dbad6fSeschrock 		return (-1);
617e9dbad6fSeschrock 
618e9dbad6fSeschrock 	return (0);
619e9dbad6fSeschrock }
620e9dbad6fSeschrock 
621e9dbad6fSeschrock /*
622a2eea2e1Sahrens  * Called to free the src and dst nvlists stored in the command structure.
623e9dbad6fSeschrock  */
624e9dbad6fSeschrock void
625e9dbad6fSeschrock zcmd_free_nvlists(zfs_cmd_t *zc)
626e9dbad6fSeschrock {
627e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_src);
628e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
629e9dbad6fSeschrock }
630e9dbad6fSeschrock 
631e9dbad6fSeschrock int
632e9dbad6fSeschrock zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
633e9dbad6fSeschrock     size_t *size)
634e9dbad6fSeschrock {
635e9dbad6fSeschrock 	char *packed;
636e9dbad6fSeschrock 	size_t len;
637e9dbad6fSeschrock 
638e9dbad6fSeschrock 	verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
639e9dbad6fSeschrock 
640e9dbad6fSeschrock 	if ((packed = zfs_alloc(hdl, len)) == NULL)
641e9dbad6fSeschrock 		return (-1);
642e9dbad6fSeschrock 
643e9dbad6fSeschrock 	verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
644e9dbad6fSeschrock 
645e9dbad6fSeschrock 	zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
646e9dbad6fSeschrock 	zc->zc_nvlist_src_size = len;
647e9dbad6fSeschrock 
648e9dbad6fSeschrock 	if (size)
649e9dbad6fSeschrock 		*size = len;
650e9dbad6fSeschrock 	return (0);
651e9dbad6fSeschrock }
652e9dbad6fSeschrock 
653e9dbad6fSeschrock /*
654e9dbad6fSeschrock  * Unpacks an nvlist from the ZFS ioctl command structure.
655e9dbad6fSeschrock  */
656e9dbad6fSeschrock int
657e9dbad6fSeschrock zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
658e9dbad6fSeschrock {
659e9dbad6fSeschrock 	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
660e9dbad6fSeschrock 	    zc->zc_nvlist_dst_size, nvlp, 0) != 0)
661e9dbad6fSeschrock 		return (no_memory(hdl));
662e9dbad6fSeschrock 
663e9dbad6fSeschrock 	return (0);
664e9dbad6fSeschrock }
665*b1b8ab34Slling 
666*b1b8ab34Slling static void
667*b1b8ab34Slling zfs_print_prop_headers(libzfs_get_cbdata_t *cbp)
668*b1b8ab34Slling {
669*b1b8ab34Slling 	zfs_proplist_t *pl = cbp->cb_proplist;
670*b1b8ab34Slling 	int i;
671*b1b8ab34Slling 	char *title;
672*b1b8ab34Slling 	size_t len;
673*b1b8ab34Slling 
674*b1b8ab34Slling 	cbp->cb_first = B_FALSE;
675*b1b8ab34Slling 	if (cbp->cb_scripted)
676*b1b8ab34Slling 		return;
677*b1b8ab34Slling 
678*b1b8ab34Slling 	/*
679*b1b8ab34Slling 	 * Start with the length of the column headers.
680*b1b8ab34Slling 	 */
681*b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_NAME] = strlen(dgettext(TEXT_DOMAIN, "NAME"));
682*b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(dgettext(TEXT_DOMAIN,
683*b1b8ab34Slling 	    "PROPERTY"));
684*b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_VALUE] = strlen(dgettext(TEXT_DOMAIN,
685*b1b8ab34Slling 	    "VALUE"));
686*b1b8ab34Slling 	cbp->cb_colwidths[GET_COL_SOURCE] = strlen(dgettext(TEXT_DOMAIN,
687*b1b8ab34Slling 	    "SOURCE"));
688*b1b8ab34Slling 
689*b1b8ab34Slling 	/*
690*b1b8ab34Slling 	 * Go through and calculate the widths for each column.  For the
691*b1b8ab34Slling 	 * 'source' column, we kludge it up by taking the worst-case scenario of
692*b1b8ab34Slling 	 * inheriting from the longest name.  This is acceptable because in the
693*b1b8ab34Slling 	 * majority of cases 'SOURCE' is the last column displayed, and we don't
694*b1b8ab34Slling 	 * use the width anyway.  Note that the 'VALUE' column can be oversized,
695*b1b8ab34Slling 	 * if the name of the property is much longer the any values we find.
696*b1b8ab34Slling 	 */
697*b1b8ab34Slling 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
698*b1b8ab34Slling 		/*
699*b1b8ab34Slling 		 * 'PROPERTY' column
700*b1b8ab34Slling 		 */
701*b1b8ab34Slling 		if (pl->pl_prop != ZFS_PROP_INVAL) {
702*b1b8ab34Slling 			len = strlen(zfs_prop_to_name(pl->pl_prop));
703*b1b8ab34Slling 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
704*b1b8ab34Slling 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
705*b1b8ab34Slling 		} else {
706*b1b8ab34Slling 			len = strlen(pl->pl_user_prop);
707*b1b8ab34Slling 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
708*b1b8ab34Slling 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
709*b1b8ab34Slling 		}
710*b1b8ab34Slling 
711*b1b8ab34Slling 		/*
712*b1b8ab34Slling 		 * 'VALUE' column
713*b1b8ab34Slling 		 */
714*b1b8ab34Slling 		if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) &&
715*b1b8ab34Slling 		    pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
716*b1b8ab34Slling 			cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
717*b1b8ab34Slling 
718*b1b8ab34Slling 		/*
719*b1b8ab34Slling 		 * 'NAME' and 'SOURCE' columns
720*b1b8ab34Slling 		 */
721*b1b8ab34Slling 		if (pl->pl_prop == ZFS_PROP_NAME &&
722*b1b8ab34Slling 		    pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
723*b1b8ab34Slling 			cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
724*b1b8ab34Slling 			cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
725*b1b8ab34Slling 			    strlen(dgettext(TEXT_DOMAIN, "inherited from"));
726*b1b8ab34Slling 		}
727*b1b8ab34Slling 	}
728*b1b8ab34Slling 
729*b1b8ab34Slling 	/*
730*b1b8ab34Slling 	 * Now go through and print the headers.
731*b1b8ab34Slling 	 */
732*b1b8ab34Slling 	for (i = 0; i < 4; i++) {
733*b1b8ab34Slling 		switch (cbp->cb_columns[i]) {
734*b1b8ab34Slling 		case GET_COL_NAME:
735*b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "NAME");
736*b1b8ab34Slling 			break;
737*b1b8ab34Slling 		case GET_COL_PROPERTY:
738*b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "PROPERTY");
739*b1b8ab34Slling 			break;
740*b1b8ab34Slling 		case GET_COL_VALUE:
741*b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "VALUE");
742*b1b8ab34Slling 			break;
743*b1b8ab34Slling 		case GET_COL_SOURCE:
744*b1b8ab34Slling 			title = dgettext(TEXT_DOMAIN, "SOURCE");
745*b1b8ab34Slling 			break;
746*b1b8ab34Slling 		default:
747*b1b8ab34Slling 			title = NULL;
748*b1b8ab34Slling 		}
749*b1b8ab34Slling 
750*b1b8ab34Slling 		if (title != NULL) {
751*b1b8ab34Slling 			if (i == 3 || cbp->cb_columns[i + 1] == 0)
752*b1b8ab34Slling 				(void) printf("%s", title);
753*b1b8ab34Slling 			else
754*b1b8ab34Slling 				(void) printf("%-*s  ",
755*b1b8ab34Slling 				    cbp->cb_colwidths[cbp->cb_columns[i]],
756*b1b8ab34Slling 				    title);
757*b1b8ab34Slling 		}
758*b1b8ab34Slling 	}
759*b1b8ab34Slling 	(void) printf("\n");
760*b1b8ab34Slling }
761*b1b8ab34Slling 
762*b1b8ab34Slling /*
763*b1b8ab34Slling  * Display a single line of output, according to the settings in the callback
764*b1b8ab34Slling  * structure.
765*b1b8ab34Slling  */
766*b1b8ab34Slling void
767*b1b8ab34Slling libzfs_print_one_property(const char *name, libzfs_get_cbdata_t *cbp,
768*b1b8ab34Slling     const char *propname, const char *value, zfs_source_t sourcetype,
769*b1b8ab34Slling     const char *source)
770*b1b8ab34Slling {
771*b1b8ab34Slling 	int i;
772*b1b8ab34Slling 	const char *str;
773*b1b8ab34Slling 	char buf[128];
774*b1b8ab34Slling 
775*b1b8ab34Slling 	/*
776*b1b8ab34Slling 	 * Ignore those source types that the user has chosen to ignore.
777*b1b8ab34Slling 	 */
778*b1b8ab34Slling 	if ((sourcetype & cbp->cb_sources) == 0)
779*b1b8ab34Slling 		return;
780*b1b8ab34Slling 
781*b1b8ab34Slling 	if (cbp->cb_first)
782*b1b8ab34Slling 		zfs_print_prop_headers(cbp);
783*b1b8ab34Slling 
784*b1b8ab34Slling 	for (i = 0; i < 4; i++) {
785*b1b8ab34Slling 		switch (cbp->cb_columns[i]) {
786*b1b8ab34Slling 		case GET_COL_NAME:
787*b1b8ab34Slling 			str = name;
788*b1b8ab34Slling 			break;
789*b1b8ab34Slling 
790*b1b8ab34Slling 		case GET_COL_PROPERTY:
791*b1b8ab34Slling 			str = propname;
792*b1b8ab34Slling 			break;
793*b1b8ab34Slling 
794*b1b8ab34Slling 		case GET_COL_VALUE:
795*b1b8ab34Slling 			str = value;
796*b1b8ab34Slling 			break;
797*b1b8ab34Slling 
798*b1b8ab34Slling 		case GET_COL_SOURCE:
799*b1b8ab34Slling 			switch (sourcetype) {
800*b1b8ab34Slling 			case ZFS_SRC_NONE:
801*b1b8ab34Slling 				str = "-";
802*b1b8ab34Slling 				break;
803*b1b8ab34Slling 
804*b1b8ab34Slling 			case ZFS_SRC_DEFAULT:
805*b1b8ab34Slling 				str = "default";
806*b1b8ab34Slling 				break;
807*b1b8ab34Slling 
808*b1b8ab34Slling 			case ZFS_SRC_LOCAL:
809*b1b8ab34Slling 				str = "local";
810*b1b8ab34Slling 				break;
811*b1b8ab34Slling 
812*b1b8ab34Slling 			case ZFS_SRC_TEMPORARY:
813*b1b8ab34Slling 				str = "temporary";
814*b1b8ab34Slling 				break;
815*b1b8ab34Slling 
816*b1b8ab34Slling 			case ZFS_SRC_INHERITED:
817*b1b8ab34Slling 				(void) snprintf(buf, sizeof (buf),
818*b1b8ab34Slling 				    "inherited from %s", source);
819*b1b8ab34Slling 				str = buf;
820*b1b8ab34Slling 				break;
821*b1b8ab34Slling 			}
822*b1b8ab34Slling 			break;
823*b1b8ab34Slling 
824*b1b8ab34Slling 		default:
825*b1b8ab34Slling 			continue;
826*b1b8ab34Slling 		}
827*b1b8ab34Slling 
828*b1b8ab34Slling 		if (cbp->cb_columns[i + 1] == 0)
829*b1b8ab34Slling 			(void) printf("%s", str);
830*b1b8ab34Slling 		else if (cbp->cb_scripted)
831*b1b8ab34Slling 			(void) printf("%s\t", str);
832*b1b8ab34Slling 		else
833*b1b8ab34Slling 			(void) printf("%-*s  ",
834*b1b8ab34Slling 			    cbp->cb_colwidths[cbp->cb_columns[i]],
835*b1b8ab34Slling 			    str);
836*b1b8ab34Slling 
837*b1b8ab34Slling 	}
838*b1b8ab34Slling 
839*b1b8ab34Slling 	(void) printf("\n");
840*b1b8ab34Slling }
841