1789Sahrens /*
2789Sahrens  * CDDL HEADER START
3789Sahrens  *
4789Sahrens  * The contents of this file are subject to the terms of the
5*1544Seschrock  * Common Development and Distribution License (the "License").
6*1544Seschrock  * You may not use this file except in compliance with the License.
7789Sahrens  *
8789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9789Sahrens  * or http://www.opensolaris.org/os/licensing.
10789Sahrens  * See the License for the specific language governing permissions
11789Sahrens  * and limitations under the License.
12789Sahrens  *
13789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18789Sahrens  *
19789Sahrens  * CDDL HEADER END
20789Sahrens  */
21789Sahrens /*
22*1544Seschrock  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23789Sahrens  * Use is subject to license terms.
24789Sahrens  */
25789Sahrens 
26789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
27789Sahrens 
28789Sahrens /*
29789Sahrens  * Internal utility routines for the ZFS library.
30789Sahrens  */
31789Sahrens 
32789Sahrens #include <errno.h>
33789Sahrens #include <fcntl.h>
34789Sahrens #include <libintl.h>
35789Sahrens #include <stdarg.h>
36789Sahrens #include <stdio.h>
37789Sahrens #include <stdlib.h>
38789Sahrens #include <strings.h>
39789Sahrens #include <unistd.h>
40789Sahrens #include <sys/mnttab.h>
41789Sahrens 
42789Sahrens #include <libzfs.h>
43789Sahrens 
44789Sahrens #include "libzfs_impl.h"
45789Sahrens 
46*1544Seschrock static int zfs_fd = -1;
47*1544Seschrock static FILE *mnttab_file;
48*1544Seschrock static FILE *sharetab_file;
49*1544Seschrock static int sharetab_opened;
50789Sahrens 
51789Sahrens void (*error_func)(const char *, va_list);
52789Sahrens 
53789Sahrens /*
54789Sahrens  * All error handling is kept within libzfs where we have the most information
55789Sahrens  * immediately available.  While this may not be suitable for a general purpose
56789Sahrens  * library, it greatly simplifies our commands.  This command name is used to
57789Sahrens  * prefix all error messages appropriately.
58789Sahrens  */
59789Sahrens void
60789Sahrens zfs_error(const char *fmt, ...)
61789Sahrens {
62789Sahrens 	va_list ap;
63789Sahrens 
64789Sahrens 	va_start(ap, fmt);
65789Sahrens 
66789Sahrens 	if (error_func != NULL) {
67789Sahrens 		error_func(fmt, ap);
68789Sahrens 	} else {
69789Sahrens 		(void) vfprintf(stderr, fmt, ap);
70789Sahrens 		(void) fprintf(stderr, "\n");
71789Sahrens 	}
72789Sahrens 
73789Sahrens 	va_end(ap);
74789Sahrens }
75789Sahrens 
76789Sahrens /*
77789Sahrens  * An internal error is something that we cannot recover from, and should never
78789Sahrens  * happen (such as running out of memory).  It should only be used in
79789Sahrens  * exceptional circumstances.
80789Sahrens  */
81789Sahrens void
82789Sahrens zfs_fatal(const char *fmt, ...)
83789Sahrens {
84789Sahrens 	va_list ap;
85789Sahrens 
86789Sahrens 	va_start(ap, fmt);
87789Sahrens 
88789Sahrens 	if (error_func != NULL) {
89789Sahrens 		error_func(fmt, ap);
90789Sahrens 	} else {
91789Sahrens 		(void) vfprintf(stderr, fmt, ap);
92789Sahrens 		(void) fprintf(stderr, "\n");
93789Sahrens 	}
94789Sahrens 
95789Sahrens 	va_end(ap);
96789Sahrens 
97789Sahrens 	exit(1);
98789Sahrens }
99789Sahrens 
100789Sahrens /*
101789Sahrens  * Consumers (such as the JNI interface) that need to capture error output can
102789Sahrens  * override the default error handler using this function.
103789Sahrens  */
104789Sahrens void
105789Sahrens zfs_set_error_handler(void (*func)(const char *, va_list))
106789Sahrens {
107789Sahrens 	error_func = func;
108789Sahrens }
109789Sahrens 
110789Sahrens /*
111789Sahrens  * Display an out of memory error message and abort the current program.
112789Sahrens  */
113789Sahrens void
114789Sahrens no_memory(void)
115789Sahrens {
116789Sahrens 	assert(errno == ENOMEM);
117789Sahrens 	zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: out of memory\n"));
118789Sahrens }
119789Sahrens 
120789Sahrens /*
121789Sahrens  * A safe form of malloc() which will die if the allocation fails.
122789Sahrens  */
123789Sahrens void *
124789Sahrens zfs_malloc(size_t size)
125789Sahrens {
126789Sahrens 	void *data;
127789Sahrens 
128789Sahrens 	if ((data = calloc(1, size)) == NULL)
129789Sahrens 		no_memory();
130789Sahrens 
131789Sahrens 	return (data);
132789Sahrens }
133789Sahrens 
134789Sahrens /*
135789Sahrens  * A safe form of strdup() which will die if the allocation fails.
136789Sahrens  */
137789Sahrens char *
138789Sahrens zfs_strdup(const char *str)
139789Sahrens {
140789Sahrens 	char *ret;
141789Sahrens 
142789Sahrens 	if ((ret = strdup(str)) == NULL)
143789Sahrens 		no_memory();
144789Sahrens 
145789Sahrens 	return (ret);
146789Sahrens }
147789Sahrens 
148789Sahrens /*
149*1544Seschrock  * Utility functions around common used files - /dev/zfs, /etc/mnttab, and
150*1544Seschrock  * /etc/dfs/sharetab.
151789Sahrens  */
152*1544Seschrock int
153*1544Seschrock zfs_ioctl(int cmd, zfs_cmd_t *zc)
154789Sahrens {
155*1544Seschrock 	if (zfs_fd == -1 &&
156*1544Seschrock 	    (zfs_fd = open(ZFS_DEV, O_RDWR)) < 0)
157*1544Seschrock 		zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to "
158*1544Seschrock 		    "open ZFS device\n"), MNTTAB);
159789Sahrens 
160*1544Seschrock 	return (ioctl(zfs_fd, cmd, zc));
161*1544Seschrock }
162*1544Seschrock 
163*1544Seschrock FILE *
164*1544Seschrock zfs_mnttab(void)
165*1544Seschrock {
166*1544Seschrock 	if (mnttab_file == NULL &&
167*1544Seschrock 	    (mnttab_file = fopen(MNTTAB, "r")) == NULL)
168789Sahrens 		zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to "
169789Sahrens 		    "open %s\n"), MNTTAB);
170789Sahrens 
171*1544Seschrock 	return (mnttab_file);
172*1544Seschrock }
173*1544Seschrock 
174*1544Seschrock FILE *
175*1544Seschrock zfs_sharetab(void)
176*1544Seschrock {
177*1544Seschrock 	if (sharetab_opened)
178*1544Seschrock 		return (sharetab_file);
179*1544Seschrock 
180*1544Seschrock 	sharetab_opened = TRUE;
181*1544Seschrock 	return (sharetab_file = fopen("/etc/dfs/sharetab", "r"));
182789Sahrens }
183789Sahrens 
184789Sahrens /*
185*1544Seschrock  * Cleanup function for library.  Close any file descriptors that were
186*1544Seschrock  * opened as part of the above functions.
187789Sahrens  */
188789Sahrens #pragma fini(zfs_fini)
189789Sahrens void
190789Sahrens zfs_fini(void)
191789Sahrens {
192*1544Seschrock 	if (zfs_fd != -1)
193*1544Seschrock 		(void) close(zfs_fd);
194*1544Seschrock 	if (sharetab_file)
195*1544Seschrock 		(void) fclose(sharetab_file);
196*1544Seschrock 	if (mnttab_file)
197*1544Seschrock 		(void) fclose(mnttab_file);
198789Sahrens }
199789Sahrens 
200789Sahrens /*
201789Sahrens  * Convert a number to an appropriately human-readable output.
202789Sahrens  */
203789Sahrens void
204789Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen)
205789Sahrens {
206789Sahrens 	uint64_t n = num;
207789Sahrens 	int index = 0;
208789Sahrens 	char u;
209789Sahrens 
210789Sahrens 	while (n >= 1024) {
2111162Seschrock 		n /= 1024;
212789Sahrens 		index++;
213789Sahrens 	}
214789Sahrens 
215789Sahrens 	u = " KMGTPE"[index];
216789Sahrens 
2171162Seschrock 	if (index == 0) {
218789Sahrens 		(void) snprintf(buf, buflen, "%llu", n);
2191162Seschrock 	} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
2201162Seschrock 		/*
2211162Seschrock 		 * If this is an even multiple of the base, always display
2221162Seschrock 		 * without any decimal precision.
2231162Seschrock 		 */
224789Sahrens 		(void) snprintf(buf, buflen, "%llu%c", n, u);
2251162Seschrock 	} else {
2261162Seschrock 		/*
2271162Seschrock 		 * We want to choose a precision that reflects the best choice
2281162Seschrock 		 * for fitting in 5 characters.  This can get rather tricky when
2291162Seschrock 		 * we have numbers that are very close to an order of magnitude.
2301162Seschrock 		 * For example, when displaying 10239 (which is really 9.999K),
2311162Seschrock 		 * we want only a single place of precision for 10.0K.  We could
2321162Seschrock 		 * develop some complex heuristics for this, but it's much
2331162Seschrock 		 * easier just to try each combination in turn.
2341162Seschrock 		 */
2351162Seschrock 		int i;
2361162Seschrock 		for (i = 2; i >= 0; i--) {
2371162Seschrock 			(void) snprintf(buf, buflen, "%.*f%c", i,
2381162Seschrock 			    (double)num / (1ULL << 10 * index), u);
2391162Seschrock 			if (strlen(buf) <= 5)
2401162Seschrock 				break;
2411162Seschrock 		}
2421162Seschrock 	}
243789Sahrens }
244