xref: /illumos-gate/usr/src/lib/libzfs/common/libzfs_util.c (revision e9dbad6f263d5570ed7ff5443ec5b958af8c24d7)
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"));
15199653d4eSeschrock 	case EZFS_UNKNOWN:
15299653d4eSeschrock 		return (dgettext(TEXT_DOMAIN, "unknown error"));
15399653d4eSeschrock 	default:
154c08432ebSeschrock 		assert(hdl->libzfs_error == 0);
155c08432ebSeschrock 		return (dgettext(TEXT_DOMAIN, "no error"));
15699653d4eSeschrock 	}
15799653d4eSeschrock }
15899653d4eSeschrock 
15999653d4eSeschrock /*PRINTFLIKE2*/
160fa9e4066Sahrens void
16199653d4eSeschrock zfs_error_aux(libzfs_handle_t *hdl, const char *fmt, ...)
162fa9e4066Sahrens {
163fa9e4066Sahrens 	va_list ap;
164fa9e4066Sahrens 
165fa9e4066Sahrens 	va_start(ap, fmt);
166fa9e4066Sahrens 
16799653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_desc, sizeof (hdl->libzfs_desc),
16899653d4eSeschrock 	    fmt, ap);
16999653d4eSeschrock 	hdl->libzfs_desc_active = 1;
17099653d4eSeschrock 
17199653d4eSeschrock 	va_end(ap);
17299653d4eSeschrock }
17399653d4eSeschrock 
17499653d4eSeschrock static void
17599653d4eSeschrock zfs_verror(libzfs_handle_t *hdl, int error, const char *fmt, va_list ap)
17699653d4eSeschrock {
17799653d4eSeschrock 	(void) vsnprintf(hdl->libzfs_action, sizeof (hdl->libzfs_action),
17899653d4eSeschrock 	    fmt, ap);
17999653d4eSeschrock 	hdl->libzfs_error = error;
18099653d4eSeschrock 
18199653d4eSeschrock 	if (hdl->libzfs_desc_active)
18299653d4eSeschrock 		hdl->libzfs_desc_active = 0;
18399653d4eSeschrock 	else
18499653d4eSeschrock 		hdl->libzfs_desc[0] = '\0';
18599653d4eSeschrock 
18699653d4eSeschrock 	if (hdl->libzfs_printerr) {
18799653d4eSeschrock 		if (error == EZFS_UNKNOWN) {
18899653d4eSeschrock 			(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "internal "
18999653d4eSeschrock 			    "error: %s\n"), libzfs_error_description(hdl));
19099653d4eSeschrock 			abort();
19199653d4eSeschrock 		}
19299653d4eSeschrock 
19399653d4eSeschrock 		(void) fprintf(stderr, "%s: %s\n", hdl->libzfs_action,
19499653d4eSeschrock 		    libzfs_error_description(hdl));
19599653d4eSeschrock 		if (error == EZFS_NOMEM)
19699653d4eSeschrock 			exit(1);
197fa9e4066Sahrens 	}
19899653d4eSeschrock }
19999653d4eSeschrock 
20099653d4eSeschrock /*PRINTFLIKE3*/
20199653d4eSeschrock int
20299653d4eSeschrock zfs_error(libzfs_handle_t *hdl, int error, const char *fmt, ...)
20399653d4eSeschrock {
20499653d4eSeschrock 	va_list ap;
20599653d4eSeschrock 
20699653d4eSeschrock 	va_start(ap, fmt);
20799653d4eSeschrock 
20899653d4eSeschrock 	zfs_verror(hdl, error, fmt, ap);
209fa9e4066Sahrens 
210fa9e4066Sahrens 	va_end(ap);
21199653d4eSeschrock 
21299653d4eSeschrock 	return (-1);
213fa9e4066Sahrens }
214fa9e4066Sahrens 
21599653d4eSeschrock static int
21699653d4eSeschrock zfs_common_error(libzfs_handle_t *hdl, int error, const char *fmt,
21799653d4eSeschrock     va_list ap)
21899653d4eSeschrock {
21999653d4eSeschrock 	switch (error) {
22099653d4eSeschrock 	case EPERM:
22199653d4eSeschrock 	case EACCES:
22299653d4eSeschrock 		zfs_verror(hdl, EZFS_PERM, fmt, ap);
22399653d4eSeschrock 		return (-1);
22499653d4eSeschrock 
22599653d4eSeschrock 	case EIO:
22699653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
22799653d4eSeschrock 		return (-1);
22899653d4eSeschrock 
22999653d4eSeschrock 	case EINTR:
23099653d4eSeschrock 		zfs_verror(hdl, EZFS_INTR, fmt, ap);
23199653d4eSeschrock 		return (-1);
23299653d4eSeschrock 	}
23399653d4eSeschrock 
23499653d4eSeschrock 	return (0);
23599653d4eSeschrock }
23699653d4eSeschrock 
23799653d4eSeschrock /*PRINTFLIKE3*/
23899653d4eSeschrock int
23999653d4eSeschrock zfs_standard_error(libzfs_handle_t *hdl, int error, const char *fmt, ...)
240fa9e4066Sahrens {
241fa9e4066Sahrens 	va_list ap;
242fa9e4066Sahrens 
243fa9e4066Sahrens 	va_start(ap, fmt);
244fa9e4066Sahrens 
24599653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
24699653d4eSeschrock 		va_end(ap);
24799653d4eSeschrock 		return (-1);
248fa9e4066Sahrens 	}
249fa9e4066Sahrens 
250fa9e4066Sahrens 
25199653d4eSeschrock 	switch (error) {
25299653d4eSeschrock 	case ENXIO:
25399653d4eSeschrock 		zfs_verror(hdl, EZFS_IO, fmt, ap);
25499653d4eSeschrock 		break;
25599653d4eSeschrock 
25699653d4eSeschrock 	case ENOENT:
25799653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
25899653d4eSeschrock 		    "dataset does not exist"));
25999653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
26099653d4eSeschrock 		break;
26199653d4eSeschrock 
26299653d4eSeschrock 	case ENOSPC:
26399653d4eSeschrock 	case EDQUOT:
26499653d4eSeschrock 		zfs_verror(hdl, EZFS_NOSPC, fmt, ap);
26599653d4eSeschrock 		return (-1);
26699653d4eSeschrock 
26799653d4eSeschrock 	case EEXIST:
26899653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
26999653d4eSeschrock 		    "dataset already exists"));
27099653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
27199653d4eSeschrock 		break;
27299653d4eSeschrock 
27399653d4eSeschrock 	case EBUSY:
27499653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
27599653d4eSeschrock 		    "dataset is busy"));
27699653d4eSeschrock 		zfs_verror(hdl, EZFS_BUSY, fmt, ap);
27799653d4eSeschrock 		break;
27899653d4eSeschrock 
27999653d4eSeschrock 	default:
28099653d4eSeschrock 		zfs_error_aux(hdl, strerror(errno));
28199653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
28299653d4eSeschrock 		break;
28399653d4eSeschrock 	}
28499653d4eSeschrock 
28599653d4eSeschrock 	va_end(ap);
28699653d4eSeschrock 	return (-1);
287fa9e4066Sahrens }
288fa9e4066Sahrens 
28999653d4eSeschrock /*PRINTFLIKE3*/
29099653d4eSeschrock int
29199653d4eSeschrock zpool_standard_error(libzfs_handle_t *hdl, int error, const char *fmt, ...)
292fa9e4066Sahrens {
29399653d4eSeschrock 	va_list ap;
29499653d4eSeschrock 
29599653d4eSeschrock 	va_start(ap, fmt);
29699653d4eSeschrock 
29799653d4eSeschrock 	if (zfs_common_error(hdl, error, fmt, ap) != 0) {
29899653d4eSeschrock 		va_end(ap);
29999653d4eSeschrock 		return (-1);
30099653d4eSeschrock 	}
30199653d4eSeschrock 
30299653d4eSeschrock 	switch (error) {
30399653d4eSeschrock 	case ENODEV:
30499653d4eSeschrock 		zfs_verror(hdl, EZFS_NODEVICE, fmt, ap);
30599653d4eSeschrock 		break;
30699653d4eSeschrock 
30799653d4eSeschrock 	case ENOENT:
30899653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "no such pool"));
30999653d4eSeschrock 		zfs_verror(hdl, EZFS_NOENT, fmt, ap);
31099653d4eSeschrock 		break;
31199653d4eSeschrock 
31299653d4eSeschrock 	case EEXIST:
31399653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
31499653d4eSeschrock 		    "pool already exists"));
31599653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
31699653d4eSeschrock 		break;
31799653d4eSeschrock 
31899653d4eSeschrock 	case EBUSY:
31999653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool is busy"));
32099653d4eSeschrock 		zfs_verror(hdl, EZFS_EXISTS, fmt, ap);
32199653d4eSeschrock 		break;
32299653d4eSeschrock 
32399653d4eSeschrock 	case ENXIO:
32499653d4eSeschrock 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
32599653d4eSeschrock 		    "one or more devices is currently unavailable"));
32699653d4eSeschrock 		zfs_verror(hdl, EZFS_BADDEV, fmt, ap);
32799653d4eSeschrock 		break;
32899653d4eSeschrock 
32999653d4eSeschrock 	case ENAMETOOLONG:
33099653d4eSeschrock 		zfs_verror(hdl, EZFS_DEVOVERFLOW, fmt, ap);
33199653d4eSeschrock 		break;
33299653d4eSeschrock 
33399653d4eSeschrock 	default:
33499653d4eSeschrock 		zfs_error_aux(hdl, strerror(error));
33599653d4eSeschrock 		zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
33699653d4eSeschrock 	}
33799653d4eSeschrock 
33899653d4eSeschrock 	va_end(ap);
33999653d4eSeschrock 	return (-1);
340fa9e4066Sahrens }
341fa9e4066Sahrens 
342fa9e4066Sahrens /*
343fa9e4066Sahrens  * Display an out of memory error message and abort the current program.
344fa9e4066Sahrens  */
34599653d4eSeschrock int
34699653d4eSeschrock no_memory(libzfs_handle_t *hdl)
347fa9e4066Sahrens {
34899653d4eSeschrock 	return (zfs_error(hdl, EZFS_NOMEM, "internal error"));
349fa9e4066Sahrens }
350fa9e4066Sahrens 
351fa9e4066Sahrens /*
352fa9e4066Sahrens  * A safe form of malloc() which will die if the allocation fails.
353fa9e4066Sahrens  */
354fa9e4066Sahrens void *
35599653d4eSeschrock zfs_alloc(libzfs_handle_t *hdl, size_t size)
356fa9e4066Sahrens {
357fa9e4066Sahrens 	void *data;
358fa9e4066Sahrens 
359fa9e4066Sahrens 	if ((data = calloc(1, size)) == NULL)
36099653d4eSeschrock 		(void) no_memory(hdl);
361fa9e4066Sahrens 
362fa9e4066Sahrens 	return (data);
363fa9e4066Sahrens }
364fa9e4066Sahrens 
365*e9dbad6fSeschrock /*
366*e9dbad6fSeschrock  * A safe form of realloc(), which also zeroes newly allocated space.
367*e9dbad6fSeschrock  */
368*e9dbad6fSeschrock void *
369*e9dbad6fSeschrock zfs_realloc(libzfs_handle_t *hdl, void *ptr, size_t oldsize, size_t newsize)
370*e9dbad6fSeschrock {
371*e9dbad6fSeschrock 	void *ret;
372*e9dbad6fSeschrock 
373*e9dbad6fSeschrock 	if ((ret = realloc(ptr, newsize)) == NULL) {
374*e9dbad6fSeschrock 		(void) no_memory(hdl);
375*e9dbad6fSeschrock 		free(ptr);
376*e9dbad6fSeschrock 		return (NULL);
377*e9dbad6fSeschrock 	}
378*e9dbad6fSeschrock 
379*e9dbad6fSeschrock 	bzero((char *)ret + oldsize, (newsize - oldsize));
380*e9dbad6fSeschrock 	return (ret);
381*e9dbad6fSeschrock }
382*e9dbad6fSeschrock 
383fa9e4066Sahrens /*
384fa9e4066Sahrens  * A safe form of strdup() which will die if the allocation fails.
385fa9e4066Sahrens  */
386fa9e4066Sahrens char *
38799653d4eSeschrock zfs_strdup(libzfs_handle_t *hdl, const char *str)
388fa9e4066Sahrens {
389fa9e4066Sahrens 	char *ret;
390fa9e4066Sahrens 
391fa9e4066Sahrens 	if ((ret = strdup(str)) == NULL)
39299653d4eSeschrock 		(void) no_memory(hdl);
393fa9e4066Sahrens 
394fa9e4066Sahrens 	return (ret);
395fa9e4066Sahrens }
396fa9e4066Sahrens 
397fa9e4066Sahrens /*
398fa9e4066Sahrens  * Convert a number to an appropriately human-readable output.
399fa9e4066Sahrens  */
400fa9e4066Sahrens void
401fa9e4066Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen)
402fa9e4066Sahrens {
403fa9e4066Sahrens 	uint64_t n = num;
404fa9e4066Sahrens 	int index = 0;
405fa9e4066Sahrens 	char u;
406fa9e4066Sahrens 
407fa9e4066Sahrens 	while (n >= 1024) {
4085c709891Seschrock 		n /= 1024;
409fa9e4066Sahrens 		index++;
410fa9e4066Sahrens 	}
411fa9e4066Sahrens 
412fa9e4066Sahrens 	u = " KMGTPE"[index];
413fa9e4066Sahrens 
4145c709891Seschrock 	if (index == 0) {
415fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu", n);
4165c709891Seschrock 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
4175c709891Seschrock 		/*
4185c709891Seschrock 		 * If this is an even multiple of the base, always display
4195c709891Seschrock 		 * without any decimal precision.
4205c709891Seschrock 		 */
421fa9e4066Sahrens 		(void) snprintf(buf, buflen, "%llu%c", n, u);
4225c709891Seschrock 	} else {
4235c709891Seschrock 		/*
4245c709891Seschrock 		 * We want to choose a precision that reflects the best choice
4255c709891Seschrock 		 * for fitting in 5 characters.  This can get rather tricky when
4265c709891Seschrock 		 * we have numbers that are very close to an order of magnitude.
4275c709891Seschrock 		 * For example, when displaying 10239 (which is really 9.999K),
4285c709891Seschrock 		 * we want only a single place of precision for 10.0K.  We could
4295c709891Seschrock 		 * develop some complex heuristics for this, but it's much
4305c709891Seschrock 		 * easier just to try each combination in turn.
4315c709891Seschrock 		 */
4325c709891Seschrock 		int i;
4335c709891Seschrock 		for (i = 2; i >= 0; i--) {
4345c709891Seschrock 			(void) snprintf(buf, buflen, "%.*f%c", i,
4355c709891Seschrock 			    (double)num / (1ULL << 10 * index), u);
4365c709891Seschrock 			if (strlen(buf) <= 5)
4375c709891Seschrock 				break;
4385c709891Seschrock 		}
4395c709891Seschrock 	}
440fa9e4066Sahrens }
44199653d4eSeschrock 
44299653d4eSeschrock void
44399653d4eSeschrock libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
44499653d4eSeschrock {
44599653d4eSeschrock 	hdl->libzfs_printerr = printerr;
44699653d4eSeschrock }
44799653d4eSeschrock 
44899653d4eSeschrock libzfs_handle_t *
44999653d4eSeschrock libzfs_init(void)
45099653d4eSeschrock {
45199653d4eSeschrock 	libzfs_handle_t *hdl;
45299653d4eSeschrock 
45399653d4eSeschrock 	if ((hdl = calloc(sizeof (libzfs_handle_t), 1)) == NULL) {
45499653d4eSeschrock 		return (NULL);
45599653d4eSeschrock 	}
45699653d4eSeschrock 
457c08432ebSeschrock 	if ((hdl->libzfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
45899653d4eSeschrock 		free(hdl);
45999653d4eSeschrock 		return (NULL);
46099653d4eSeschrock 	}
46199653d4eSeschrock 
46299653d4eSeschrock 	if ((hdl->libzfs_mnttab = fopen(MNTTAB, "r")) == NULL) {
46399653d4eSeschrock 		(void) close(hdl->libzfs_fd);
46499653d4eSeschrock 		free(hdl);
46599653d4eSeschrock 		return (NULL);
46699653d4eSeschrock 	}
46799653d4eSeschrock 
46899653d4eSeschrock 	hdl->libzfs_sharetab = fopen("/etc/dfs/sharetab", "r");
46999653d4eSeschrock 
47099653d4eSeschrock 	return (hdl);
47199653d4eSeschrock }
47299653d4eSeschrock 
47399653d4eSeschrock void
47499653d4eSeschrock libzfs_fini(libzfs_handle_t *hdl)
47599653d4eSeschrock {
47699653d4eSeschrock 	(void) close(hdl->libzfs_fd);
47799653d4eSeschrock 	if (hdl->libzfs_mnttab)
47899653d4eSeschrock 		(void) fclose(hdl->libzfs_mnttab);
47999653d4eSeschrock 	if (hdl->libzfs_sharetab)
48099653d4eSeschrock 		(void) fclose(hdl->libzfs_sharetab);
48199653d4eSeschrock 	namespace_clear(hdl);
48299653d4eSeschrock 	free(hdl);
48399653d4eSeschrock }
48499653d4eSeschrock 
48599653d4eSeschrock libzfs_handle_t *
48699653d4eSeschrock zpool_get_handle(zpool_handle_t *zhp)
48799653d4eSeschrock {
48899653d4eSeschrock 	return (zhp->zpool_hdl);
48999653d4eSeschrock }
49099653d4eSeschrock 
49199653d4eSeschrock libzfs_handle_t *
49299653d4eSeschrock zfs_get_handle(zfs_handle_t *zhp)
49399653d4eSeschrock {
49499653d4eSeschrock 	return (zhp->zfs_hdl);
49599653d4eSeschrock }
496*e9dbad6fSeschrock 
497*e9dbad6fSeschrock /*
498*e9dbad6fSeschrock  * Initialize the zc_nvlist_dst member to prepare for receiving an nvlist from
499*e9dbad6fSeschrock  * an ioctl().
500*e9dbad6fSeschrock  */
501*e9dbad6fSeschrock int
502*e9dbad6fSeschrock zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
503*e9dbad6fSeschrock {
504*e9dbad6fSeschrock 	if (len == 0)
505*e9dbad6fSeschrock 		len = 1024;
506*e9dbad6fSeschrock 	zc->zc_nvlist_dst_size = len;
507*e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
508*e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == NULL)
509*e9dbad6fSeschrock 		return (-1);
510*e9dbad6fSeschrock 
511*e9dbad6fSeschrock 	return (0);
512*e9dbad6fSeschrock }
513*e9dbad6fSeschrock 
514*e9dbad6fSeschrock /*
515*e9dbad6fSeschrock  * Called when an ioctl() which returns an nvlist fails with ENOMEM.  This will
516*e9dbad6fSeschrock  * expand the nvlist to the size specified in 'zc_nvlist_dst_size', which was
517*e9dbad6fSeschrock  * filled in by the kernel to indicate the actual required size.
518*e9dbad6fSeschrock  */
519*e9dbad6fSeschrock int
520*e9dbad6fSeschrock zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
521*e9dbad6fSeschrock {
522*e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
523*e9dbad6fSeschrock 	if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
524*e9dbad6fSeschrock 	    zfs_alloc(hdl, zc->zc_nvlist_dst_size))
525*e9dbad6fSeschrock 	    == NULL)
526*e9dbad6fSeschrock 		return (-1);
527*e9dbad6fSeschrock 
528*e9dbad6fSeschrock 	return (0);
529*e9dbad6fSeschrock }
530*e9dbad6fSeschrock 
531*e9dbad6fSeschrock /*
532*e9dbad6fSeschrock  * Called to free the destination nvlist stored in the command structure.  This
533*e9dbad6fSeschrock  * is only needed if the caller must abort abnormally.  The various other
534*e9dbad6fSeschrock  * zcmd_*() routines will free it on failure (or on success, for
535*e9dbad6fSeschrock  * zcmd_read_nvlist).
536*e9dbad6fSeschrock  */
537*e9dbad6fSeschrock void
538*e9dbad6fSeschrock zcmd_free_nvlists(zfs_cmd_t *zc)
539*e9dbad6fSeschrock {
540*e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_src);
541*e9dbad6fSeschrock 	free((void *)(uintptr_t)zc->zc_nvlist_dst);
542*e9dbad6fSeschrock }
543*e9dbad6fSeschrock 
544*e9dbad6fSeschrock int
545*e9dbad6fSeschrock zcmd_write_src_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t *nvl,
546*e9dbad6fSeschrock     size_t *size)
547*e9dbad6fSeschrock {
548*e9dbad6fSeschrock 	char *packed;
549*e9dbad6fSeschrock 	size_t len;
550*e9dbad6fSeschrock 
551*e9dbad6fSeschrock 	verify(nvlist_size(nvl, &len, NV_ENCODE_NATIVE) == 0);
552*e9dbad6fSeschrock 
553*e9dbad6fSeschrock 	if ((packed = zfs_alloc(hdl, len)) == NULL)
554*e9dbad6fSeschrock 		return (-1);
555*e9dbad6fSeschrock 
556*e9dbad6fSeschrock 	verify(nvlist_pack(nvl, &packed, &len, NV_ENCODE_NATIVE, 0) == 0);
557*e9dbad6fSeschrock 
558*e9dbad6fSeschrock 	zc->zc_nvlist_src = (uint64_t)(uintptr_t)packed;
559*e9dbad6fSeschrock 	zc->zc_nvlist_src_size = len;
560*e9dbad6fSeschrock 
561*e9dbad6fSeschrock 	if (size)
562*e9dbad6fSeschrock 		*size = len;
563*e9dbad6fSeschrock 	return (0);
564*e9dbad6fSeschrock }
565*e9dbad6fSeschrock 
566*e9dbad6fSeschrock /*
567*e9dbad6fSeschrock  * Unpacks an nvlist from the ZFS ioctl command structure.
568*e9dbad6fSeschrock  */
569*e9dbad6fSeschrock int
570*e9dbad6fSeschrock zcmd_read_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, nvlist_t **nvlp)
571*e9dbad6fSeschrock {
572*e9dbad6fSeschrock 	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
573*e9dbad6fSeschrock 	    zc->zc_nvlist_dst_size, nvlp, 0) != 0)
574*e9dbad6fSeschrock 		return (no_memory(hdl));
575*e9dbad6fSeschrock 
576*e9dbad6fSeschrock 	return (0);
577*e9dbad6fSeschrock }
578