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 /*
22ea8dc4b6Seschrock  * Copyright 2006 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>
41fa9e4066Sahrens 
42fa9e4066Sahrens #include <libzfs.h>
43fa9e4066Sahrens 
44fa9e4066Sahrens #include "libzfs_impl.h"
45fa9e4066Sahrens 
4699653d4eSeschrock int
4799653d4eSeschrock libzfs_errno(libzfs_handle_t *hdl)
4899653d4eSeschrock {
4999653d4eSeschrock 	return (hdl->libzfs_error);
5099653d4eSeschrock }
51fa9e4066Sahrens 
5299653d4eSeschrock const char *
5399653d4eSeschrock libzfs_error_action(libzfs_handle_t *hdl)
5499653d4eSeschrock {
5599653d4eSeschrock 	return (hdl->libzfs_action);
5699653d4eSeschrock }
57fa9e4066Sahrens 
5899653d4eSeschrock const char *
5999653d4eSeschrock libzfs_error_description(libzfs_handle_t *hdl)
6099653d4eSeschrock {
6199653d4eSeschrock 	if (hdl->libzfs_desc[0] != '\0')
6299653d4eSeschrock 		return (hdl->libzfs_desc);
6399653d4eSeschrock 
6499653d4eSeschrock 	switch (hdl->libzfs_error) {
6599653d4eSeschrock 	case EZFS_NOMEM:
6699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "out of memory"));
6799653d4eSeschrock 	case EZFS_BADPROP:
6899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid property value"));
6999653d4eSeschrock 	case EZFS_PROPREADONLY:
7099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "read only property"));
7199653d4eSeschrock 	case EZFS_PROPTYPE:
7299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "property doesn't apply to "
7399653d4eSeschrock 		    "datasets of this type"));
7499653d4eSeschrock 	case EZFS_PROPNONINHERIT:
7599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "property cannot be inherited"));
7699653d4eSeschrock 	case EZFS_PROPSPACE:
7799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid quota or reservation"));
7899653d4eSeschrock 	case EZFS_BADTYPE:
7999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "operation not applicable to "
8099653d4eSeschrock 		    "datasets of this type"));
8199653d4eSeschrock 	case EZFS_BUSY:
8299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "pool or dataset is busy"));
8399653d4eSeschrock 	case EZFS_EXISTS:
8499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "pool or dataset exists"));
8599653d4eSeschrock 	case EZFS_NOENT:
8699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "no such pool or dataset"));
8799653d4eSeschrock 	case EZFS_BADSTREAM:
8899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid backup stream"));
8999653d4eSeschrock 	case EZFS_DSREADONLY:
9099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "dataset is read only"));
9199653d4eSeschrock 	case EZFS_VOLTOOBIG:
9299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "volume size exceeds limit for "
9399653d4eSeschrock 		    "this system"));
9499653d4eSeschrock 	case EZFS_VOLHASDATA:
9599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "volume has data"));
9699653d4eSeschrock 	case EZFS_INVALIDNAME:
9799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid name"));
9899653d4eSeschrock 	case EZFS_BADRESTORE:
9999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unable to restore to "
10099653d4eSeschrock 		    "destination"));
10199653d4eSeschrock 	case EZFS_BADBACKUP:
10299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "backup failed"));
10399653d4eSeschrock 	case EZFS_BADTARGET:
10499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid target vdev"));
10599653d4eSeschrock 	case EZFS_NODEVICE:
10699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "no such device in pool"));
10799653d4eSeschrock 	case EZFS_BADDEV:
10899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid device"));
10999653d4eSeschrock 	case EZFS_NOREPLICAS:
11099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "no valid replicas"));
11199653d4eSeschrock 	case EZFS_RESILVERING:
11299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "currently resilvering"));
11399653d4eSeschrock 	case EZFS_BADVERSION:
11499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unsupported version"));
11599653d4eSeschrock 	case EZFS_POOLUNAVAIL:
11699653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "pool is unavailable"));
11799653d4eSeschrock 	case EZFS_DEVOVERFLOW:
11899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "too many devices in one vdev"));
11999653d4eSeschrock 	case EZFS_BADPATH:
12099653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "must be an absolute path"));
12199653d4eSeschrock 	case EZFS_CROSSTARGET:
12299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "operation crosses datasets or "
12399653d4eSeschrock 		    "pools"));
12499653d4eSeschrock 	case EZFS_ZONED:
12599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "dataset in use by local zone"));
12699653d4eSeschrock 	case EZFS_MOUNTFAILED:
12799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "mount failed"));
12899653d4eSeschrock 	case EZFS_UMOUNTFAILED:
12999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "umount failed"));
13099653d4eSeschrock 	case EZFS_UNSHAREFAILED:
13199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unshare(1M) failed"));
13299653d4eSeschrock 	case EZFS_SHAREFAILED:
13399653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "share(1M) failed"));
13499653d4eSeschrock 	case EZFS_DEVLINKS:
13599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "failed to create /dev links"));
13699653d4eSeschrock 	case EZFS_PERM:
13799653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "permission denied"));
13899653d4eSeschrock 	case EZFS_NOSPC:
13999653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "out of space"));
14099653d4eSeschrock 	case EZFS_IO:
14199653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "I/O error"));
14299653d4eSeschrock 	case EZFS_INTR:
14399653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "signal received"));
14499653d4eSeschrock 	case EZFS_ISSPARE:
14599653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "device is reserved as a hot "
14699653d4eSeschrock 		    "spare"));
14799653d4eSeschrock 	case EZFS_INVALCONFIG:
14899653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "invalid vdev configuration"));
1493bb79becSeschrock 	case EZFS_RECURSIVE:
1503bb79becSeschrock 		return (dgettext(TEXT_DOMAIN, "recursive dataset dependency"));
151*06eeb2adSek 	case EZFS_NOHISTORY:
152*06eeb2adSek 		return (dgettext(TEXT_DOMAIN, "no history available"));
15399653d4eSeschrock 	case EZFS_UNKNOWN:
15499653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unknown error"));
15599653d4eSeschrock 	default:
156c08432ebSeschrock 		assert(hdl->libzfs_error == 0);
157c08432ebSeschrock 		return (dgettext(TEXT_DOMAIN, "no error"));
15899653d4eSeschrock 	}
15999653d4eSeschrock }
16099653d4eSeschrock 
16199653d4eSeschrock /*PRINTFLIKE2*/
162fa9e4066Sahrens void
16399653d4eSeschrock zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
164fa9e4066Sahrens {
165fa9e4066Sahrens 	va_list ap;
166fa9e4066Sahrens 
167fa9e4066Sahrens 	va_start(ap, fmt);
168fa9e4066Sahrens 
16999653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
17099653d4eSeschrock 	    fmt, ap);
17199653d4eSeschrock 	hdl->libzfs_desc_active = 1;
17299653d4eSeschrock 
17399653d4eSeschrock 	va_end(ap);
17499653d4eSeschrock }
17599653d4eSeschrock 
17699653d4eSeschrock static void
17799653d4eSeschrock zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
17899653d4eSeschrock {
17999653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
18099653d4eSeschrock 	    fmt, ap);
18199653d4eSeschrock 	hdl->libzfs_error = error;
18299653d4eSeschrock 
18399653d4eSeschrock 	if (hdl->libzfs_desc_active)
18499653d4eSeschrock 		hdl->libzfs_desc_active = 0;
18599653d4eSeschrock 	else
18699653d4eSeschrock 		hdl->libzfs_desc[0] = '\0';
18799653d4eSeschrock 
18899653d4eSeschrock 	if (hdl->libzfs_printerr) {
18999653d4eSeschrock 		if (error == EZFS_UNKNOWN) {
19099653d4eSeschrock 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
19199653d4eSeschrock 			    "error: %s\n"), libzfs_error_description(hdl));
19299653d4eSeschrock 			abort();
19399653d4eSeschrock 		}
19499653d4eSeschrock 
19599653d4eSeschrock 		(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
19699653d4eSeschrock 		    libzfs_error_description(hdl));
19799653d4eSeschrock 		if (error == EZFS_NOMEM)
19899653d4eSeschrock 			exit(1);
199fa9e4066Sahrens 	}
20099653d4eSeschrock }
20199653d4eSeschrock 
20299653d4eSeschrock /*PRINTFLIKE3*/
20399653d4eSeschrock int
20499653d4eSeschrock zfs_error(libzfs_handle_t *hdl, int error, const char *fmt, ...)
20599653d4eSeschrock {
20699653d4eSeschrock 	va_list ap;
20799653d4eSeschrock 
20899653d4eSeschrock 	va_start(ap, fmt);
20999653d4eSeschrock 
21099653d4eSeschrock 	zfs_verror(hdl, error, fmt, ap);
211fa9e4066Sahrens 
212fa9e4066Sahrens 	va_end(ap);
21399653d4eSeschrock 
21499653d4eSeschrock 	return (-1);
215fa9e4066Sahrens }
216fa9e4066Sahrens 
21799653d4eSeschrock static int
21899653d4eSeschrock zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
21999653d4eSeschrock     va_list ap)
22099653d4eSeschrock {
22199653d4eSeschrock 	switch (error) {
22299653d4eSeschrock 	case EPERM:
22399653d4eSeschrock 	case EACCES:
22499653d4eSeschrock 		zfs_verror(hdl, EZFS_PERM, fmt, ap);
22599653d4eSeschrock 		return (-1);
22699653d4eSeschrock 
22799653d4eSeschrock 	case EIO:
22899653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
22999653d4eSeschrock 		return (-1);
23099653d4eSeschrock 
23199653d4eSeschrock 	case EINTR:
23299653d4eSeschrock 		zfs_verror(hdl, EZFS_INTR, fmt, ap);
23399653d4eSeschrock 		return (-1);
23499653d4eSeschrock 	}
23599653d4eSeschrock 
23699653d4eSeschrock 	return (0);
23799653d4eSeschrock }
23899653d4eSeschrock 
23999653d4eSeschrock /*PRINTFLIKE3*/
24099653d4eSeschrock int
24199653d4eSeschrock zfs_standard_error(libzfs_handle_t *hdl, int error, const char *fmt, ...)
242fa9e4066Sahrens {
243fa9e4066Sahrens 	va_list ap;
244fa9e4066Sahrens 
245fa9e4066Sahrens 	va_start(ap, fmt);
246fa9e4066Sahrens 
24799653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
24899653d4eSeschrock 		va_end(ap);
24999653d4eSeschrock 		return (-1);
250fa9e4066Sahrens 	}
251fa9e4066Sahrens 
252fa9e4066Sahrens 
25399653d4eSeschrock 	switch (error) {
25499653d4eSeschrock 	case ENXIO:
25599653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
25699653d4eSeschrock 		break;
25799653d4eSeschrock 
25899653d4eSeschrock 	case ENOENT:
25999653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
26099653d4eSeschrock 		    "dataset does not exist"));
26199653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
26299653d4eSeschrock 		break;
26399653d4eSeschrock 
26499653d4eSeschrock 	case ENOSPC:
26599653d4eSeschrock 	case EDQUOT:
26699653d4eSeschrock 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
26799653d4eSeschrock 		return (-1);
26899653d4eSeschrock 
26999653d4eSeschrock 	case EEXIST:
27099653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
27199653d4eSeschrock 		    "dataset already exists"));
27299653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
27399653d4eSeschrock 		break;
27499653d4eSeschrock 
27599653d4eSeschrock 	case EBUSY:
27699653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
27799653d4eSeschrock 		    "dataset is busy"));
27899653d4eSeschrock 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
27999653d4eSeschrock 		break;
28099653d4eSeschrock 
28199653d4eSeschrock 	default:
28299653d4eSeschrock 		zfs_error_aux(hdl, strerror(errno));
28399653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
28499653d4eSeschrock 		break;
28599653d4eSeschrock 	}
28699653d4eSeschrock 
28799653d4eSeschrock 	va_end(ap);
28899653d4eSeschrock 	return (-1);
289fa9e4066Sahrens }
290fa9e4066Sahrens 
29199653d4eSeschrock /*PRINTFLIKE3*/
29299653d4eSeschrock int
29399653d4eSeschrock zpool_standard_error(libzfs_handle_t *hdl, int error, const char *fmt, ...)
294fa9e4066Sahrens {
29599653d4eSeschrock 	va_list ap;
29699653d4eSeschrock 
29799653d4eSeschrock 	va_start(ap, fmt);
29899653d4eSeschrock 
29999653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
30099653d4eSeschrock 		va_end(ap);
30199653d4eSeschrock 		return (-1);
30299653d4eSeschrock 	}
30399653d4eSeschrock 
30499653d4eSeschrock 	switch (error) {
30599653d4eSeschrock 	case ENODEV:
30699653d4eSeschrock 		zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
30799653d4eSeschrock 		break;
30899653d4eSeschrock 
30999653d4eSeschrock 	case ENOENT:
31099653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
31199653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
31299653d4eSeschrock 		break;
31399653d4eSeschrock 
31499653d4eSeschrock 	case EEXIST:
31599653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
31699653d4eSeschrock 		    "pool already exists"));
31799653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
31899653d4eSeschrock 		break;
31999653d4eSeschrock 
32099653d4eSeschrock 	case EBUSY:
32199653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
32299653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
32399653d4eSeschrock 		break;
32499653d4eSeschrock 
32599653d4eSeschrock 	case ENXIO:
32699653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
32799653d4eSeschrock 		    "one or more devices is currently unavailable"));
32899653d4eSeschrock 		zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
32999653d4eSeschrock 		break;
33099653d4eSeschrock 
33199653d4eSeschrock 	case ENAMETOOLONG:
33299653d4eSeschrock 		zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
33399653d4eSeschrock 		break;
33499653d4eSeschrock 
33599653d4eSeschrock 	default:
33699653d4eSeschrock 		zfs_error_aux(hdl, strerror(error));
33799653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
33899653d4eSeschrock 	}
33999653d4eSeschrock 
34099653d4eSeschrock 	va_end(ap);
34199653d4eSeschrock 	return (-1);
342fa9e4066Sahrens }
343fa9e4066Sahrens 
344fa9e4066Sahrens /*
345fa9e4066Sahrens  * Display an out of memory error message and abort the current program.
346fa9e4066Sahrens  */
34799653d4eSeschrock int
34899653d4eSeschrock no_memory(libzfs_handle_t *hdl)
349fa9e4066Sahrens {
35099653d4eSeschrock 	return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
351fa9e4066Sahrens }
352fa9e4066Sahrens 
353fa9e4066Sahrens /*
354fa9e4066Sahrens  * A safe form of malloc() which will die if the allocation fails.
355fa9e4066Sahrens  */
356fa9e4066Sahrens void *
35799653d4eSeschrock zfs_alloc(libzfs_handle_t *hdl, size_t size)
358fa9e4066Sahrens {
359fa9e4066Sahrens 	void *data;
360fa9e4066Sahrens 
361fa9e4066Sahrens 	if ((data = calloc(1, size)) == NULL)
36299653d4eSeschrock 		(void) no_memory(hdl);
363fa9e4066Sahrens 
364fa9e4066Sahrens 	return (data);
365fa9e4066Sahrens }
366fa9e4066Sahrens 
367e9dbad6fSeschrock /*
368e9dbad6fSeschrock  * A safe form of realloc(), which also zeroes newly allocated space.
369e9dbad6fSeschrock  */
370e9dbad6fSeschrock void *
371e9dbad6fSeschrock zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
372e9dbad6fSeschrock {
373e9dbad6fSeschrock 	void *ret;
374e9dbad6fSeschrock 
375e9dbad6fSeschrock 	if ((ret = realloc(ptr, newsize)) == NULL) {
376e9dbad6fSeschrock 		(void) no_memory(hdl);
377e9dbad6fSeschrock 		free(ptr);
378e9dbad6fSeschrock 		return (NULL);
379e9dbad6fSeschrock 	}
380e9dbad6fSeschrock 
381e9dbad6fSeschrock 	bzero((char *)ret + oldsize, (newsize - oldsize));
382e9dbad6fSeschrock 	return (ret);
383e9dbad6fSeschrock }
384e9dbad6fSeschrock 
385fa9e4066Sahrens /*
386fa9e4066Sahrens  * A safe form of strdup() which will die if the allocation fails.
387fa9e4066Sahrens  */
388fa9e4066Sahrens char *
38999653d4eSeschrock zfs_strdup(libzfs_handle_t *hdl, const char *str)
390fa9e4066Sahrens {
391fa9e4066Sahrens 	char *ret;
392fa9e4066Sahrens 
393fa9e4066Sahrens 	if ((ret = strdup(str)) == NULL)
39499653d4eSeschrock 		(void) no_memory(hdl);
395fa9e4066Sahrens 
396fa9e4066Sahrens 	return (ret);
397fa9e4066Sahrens }
398fa9e4066Sahrens 
399fa9e4066Sahrens /*
400fa9e4066Sahrens  * Convert a number to an appropriately human-readable output.
401fa9e4066Sahrens  */
402fa9e4066Sahrens void
403fa9e4066Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen)
404fa9e4066Sahrens {
405fa9e4066Sahrens 	uint64_t n = num;
406fa9e4066Sahrens 	int index = 0;
407fa9e4066Sahrens 	char u;
408fa9e4066Sahrens 
409fa9e4066Sahrens 	while (n >= 1024) {
4105c709891Seschrock 		n /= 1024;
411fa9e4066Sahrens 		index++;
412fa9e4066Sahrens 	}
413fa9e4066Sahrens 
414fa9e4066Sahrens 	u = " KMGTPE"[index];
415fa9e4066Sahrens 
4165c709891Seschrock 	if (index == 0) {
417fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu", n);
4185c709891Seschrock 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
4195c709891Seschrock 		/*
4205c709891Seschrock 		 * If this is an even multiple of the base, always display
4215c709891Seschrock 		 * without any decimal precision.
4225c709891Seschrock 		 */
423fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu%c", n, u);
4245c709891Seschrock 	} else {
4255c709891Seschrock 		/*
4265c709891Seschrock 		 * We want to choose a precision that reflects the best choice
4275c709891Seschrock 		 * for fitting in 5 characters.  This can get rather tricky when
4285c709891Seschrock 		 * we have numbers that are very close to an order of magnitude.
4295c709891Seschrock 		 * For example, when displaying 10239 (which is really 9.999K),
4305c709891Seschrock 		 * we want only a single place of precision for 10.0K.  We could
4315c709891Seschrock 		 * develop some complex heuristics for this, but it's much
4325c709891Seschrock 		 * easier just to try each combination in turn.
4335c709891Seschrock 		 */
4345c709891Seschrock 		int i;
4355c709891Seschrock 		for (i = 2; i >= 0; i--) {
4365c709891Seschrock 			(void) snprintf(buf, buflen, "%.*f%c", i,
4375c709891Seschrock 			    (double)num / (1ULL << 10 * index), u);
4385c709891Seschrock 			if (strlen(buf) <= 5)
4395c709891Seschrock 				break;
4405c709891Seschrock 		}
4415c709891Seschrock 	}
442fa9e4066Sahrens }
44399653d4eSeschrock 
44499653d4eSeschrock void
44599653d4eSeschrock libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
44699653d4eSeschrock {
44799653d4eSeschrock 	hdl->libzfs_printerr = printerr;
44899653d4eSeschrock }
44999653d4eSeschrock 
45099653d4eSeschrock libzfs_handle_t *
45199653d4eSeschrock libzfs_init(void)
45299653d4eSeschrock {
45399653d4eSeschrock 	libzfs_handle_t *hdl;
45499653d4eSeschrock 
45599653d4eSeschrock 	if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
45699653d4eSeschrock 		return (NULL);
45799653d4eSeschrock 	}
45899653d4eSeschrock 
459c08432ebSeschrock 	if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
46099653d4eSeschrock 		free(hdl);
46199653d4eSeschrock 		return (NULL);
46299653d4eSeschrock 	}
46399653d4eSeschrock 
46499653d4eSeschrock 	if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
46599653d4eSeschrock 		(void) close(hdl->libzfs_fd);
46699653d4eSeschrock 		free(hdl);
46799653d4eSeschrock 		return (NULL);
46899653d4eSeschrock 	}
46999653d4eSeschrock 
47099653d4eSeschrock 	hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
47199653d4eSeschrock 
47299653d4eSeschrock 	return (hdl);
47399653d4eSeschrock }
47499653d4eSeschrock 
47599653d4eSeschrock void
47699653d4eSeschrock libzfs_fini(libzfs_handle_t *hdl)
47799653d4eSeschrock {
47899653d4eSeschrock 	(void) close(hdl->libzfs_fd);
47999653d4eSeschrock 	if (hdl->libzfs_mnttab)
48099653d4eSeschrock 		(void) fclose(hdl->libzfs_mnttab);
48199653d4eSeschrock 	if (hdl->libzfs_sharetab)
48299653d4eSeschrock 		(void) fclose(hdl->libzfs_sharetab);
48399653d4eSeschrock 	namespace_clear(hdl);
48499653d4eSeschrock 	free(hdl);
48599653d4eSeschrock }
48699653d4eSeschrock 
48799653d4eSeschrock libzfs_handle_t *
48899653d4eSeschrock zpool_get_handle(zpool_handle_t *zhp)
48999653d4eSeschrock {
49099653d4eSeschrock 	return (zhp->zpool_hdl);
49199653d4eSeschrock }
49299653d4eSeschrock 
49399653d4eSeschrock libzfs_handle_t *
49499653d4eSeschrock zfs_get_handle(zfs_handle_t *zhp)
49599653d4eSeschrock {
49699653d4eSeschrock 	return (zhp->zfs_hdl);
49799653d4eSeschrock }
498e9dbad6fSeschrock 
499e9dbad6fSeschrock /*
500e9dbad6fSeschrock  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
501e9dbad6fSeschrock  * an ioctl().
502e9dbad6fSeschrock  */
503e9dbad6fSeschrock int
504e9dbad6fSeschrock zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
505e9dbad6fSeschrock {
506e9dbad6fSeschrock 	if (len == 0)
507a2eea2e1Sahrens 		len = 2048;
508e9dbad6fSeschrock 	zc->zc_nvlist_dst_size = len;
509e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
510e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
511e9dbad6fSeschrock 		return (-1);
512e9dbad6fSeschrock 
513e9dbad6fSeschrock 	return (0);
514e9dbad6fSeschrock }
515e9dbad6fSeschrock 
516e9dbad6fSeschrock /*
517e9dbad6fSeschrock  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
518e9dbad6fSeschrock  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
519e9dbad6fSeschrock  * filled in by the kernel to indicate the actual required size.
520e9dbad6fSeschrock  */
521e9dbad6fSeschrock int
522e9dbad6fSeschrock zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
523e9dbad6fSeschrock {
524e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
525e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
526e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size))
527e9dbad6fSeschrock 	    == NULL)
528e9dbad6fSeschrock 		return (-1);
529e9dbad6fSeschrock 
530e9dbad6fSeschrock 	return (0);
531e9dbad6fSeschrock }
532e9dbad6fSeschrock 
533e9dbad6fSeschrock /*
534a2eea2e1Sahrens  * Called to free the src and dst nvlists stored in the command structure.
535e9dbad6fSeschrock  */
536e9dbad6fSeschrock void
537e9dbad6fSeschrock zcmd_free_nvlists(zfs_cmd_t *zc)
538e9dbad6fSeschrock {
539e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_src);
540e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
541e9dbad6fSeschrock }
542e9dbad6fSeschrock 
543e9dbad6fSeschrock int
544e9dbad6fSeschrock zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
545e9dbad6fSeschrock     size_t *size)
546e9dbad6fSeschrock {
547e9dbad6fSeschrock 	char *packed;
548e9dbad6fSeschrock 	size_t len;
549e9dbad6fSeschrock 
550e9dbad6fSeschrock 	verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
551e9dbad6fSeschrock 
552e9dbad6fSeschrock 	if ((packed = zfs_alloc(hdl, len)) == NULL)
553e9dbad6fSeschrock 		return (-1);
554e9dbad6fSeschrock 
555e9dbad6fSeschrock 	verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
556e9dbad6fSeschrock 
557e9dbad6fSeschrock 	zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
558e9dbad6fSeschrock 	zc->zc_nvlist_src_size = len;
559e9dbad6fSeschrock 
560e9dbad6fSeschrock 	if (size)
561e9dbad6fSeschrock 		*size = len;
562e9dbad6fSeschrock 	return (0);
563e9dbad6fSeschrock }
564e9dbad6fSeschrock 
565e9dbad6fSeschrock /*
566e9dbad6fSeschrock  * Unpacks an nvlist from the ZFS ioctl command structure.
567e9dbad6fSeschrock  */
568e9dbad6fSeschrock int
569e9dbad6fSeschrock zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
570e9dbad6fSeschrock {
571e9dbad6fSeschrock 	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
572e9dbad6fSeschrock 	    zc->zc_nvlist_dst_size, nvlp, 0) != 0)
573e9dbad6fSeschrock 		return (no_memory(hdl));
574e9dbad6fSeschrock 
575e9dbad6fSeschrock 	return (0);
576e9dbad6fSeschrock }
577