1*789Sahrens /*
2*789Sahrens  * CDDL HEADER START
3*789Sahrens  *
4*789Sahrens  * The contents of this file are subject to the terms of the
5*789Sahrens  * Common Development and Distribution License, Version 1.0 only
6*789Sahrens  * (the "License").  You may not use this file except in compliance
7*789Sahrens  * with the License.
8*789Sahrens  *
9*789Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*789Sahrens  * or http://www.opensolaris.org/os/licensing.
11*789Sahrens  * See the License for the specific language governing permissions
12*789Sahrens  * and limitations under the License.
13*789Sahrens  *
14*789Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
15*789Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*789Sahrens  * If applicable, add the following below this CDDL HEADER, with the
17*789Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
18*789Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
19*789Sahrens  *
20*789Sahrens  * CDDL HEADER END
21*789Sahrens  */
22*789Sahrens /*
23*789Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*789Sahrens  * Use is subject to license terms.
25*789Sahrens  */
26*789Sahrens 
27*789Sahrens #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*789Sahrens 
29*789Sahrens /*
30*789Sahrens  * Internal utility routines for the ZFS library.
31*789Sahrens  */
32*789Sahrens 
33*789Sahrens #include <errno.h>
34*789Sahrens #include <fcntl.h>
35*789Sahrens #include <libintl.h>
36*789Sahrens #include <stdarg.h>
37*789Sahrens #include <stdio.h>
38*789Sahrens #include <stdlib.h>
39*789Sahrens #include <strings.h>
40*789Sahrens #include <unistd.h>
41*789Sahrens #include <sys/mnttab.h>
42*789Sahrens 
43*789Sahrens #include <libzfs.h>
44*789Sahrens 
45*789Sahrens #include "libzfs_impl.h"
46*789Sahrens 
47*789Sahrens int zfs_fd;
48*789Sahrens 
49*789Sahrens void (*error_func)(const char *, va_list);
50*789Sahrens 
51*789Sahrens /*
52*789Sahrens  * All error handling is kept within libzfs where we have the most information
53*789Sahrens  * immediately available.  While this may not be suitable for a general purpose
54*789Sahrens  * library, it greatly simplifies our commands.  This command name is used to
55*789Sahrens  * prefix all error messages appropriately.
56*789Sahrens  */
57*789Sahrens void
58*789Sahrens zfs_error(const char *fmt, ...)
59*789Sahrens {
60*789Sahrens 	va_list ap;
61*789Sahrens 
62*789Sahrens 	va_start(ap, fmt);
63*789Sahrens 
64*789Sahrens 	if (error_func != NULL) {
65*789Sahrens 		error_func(fmt, ap);
66*789Sahrens 	} else {
67*789Sahrens 		(void) vfprintf(stderr, fmt, ap);
68*789Sahrens 		(void) fprintf(stderr, "\n");
69*789Sahrens 	}
70*789Sahrens 
71*789Sahrens 	va_end(ap);
72*789Sahrens }
73*789Sahrens 
74*789Sahrens /*
75*789Sahrens  * An internal error is something that we cannot recover from, and should never
76*789Sahrens  * happen (such as running out of memory).  It should only be used in
77*789Sahrens  * exceptional circumstances.
78*789Sahrens  */
79*789Sahrens void
80*789Sahrens zfs_fatal(const char *fmt, ...)
81*789Sahrens {
82*789Sahrens 	va_list ap;
83*789Sahrens 
84*789Sahrens 	va_start(ap, fmt);
85*789Sahrens 
86*789Sahrens 	if (error_func != NULL) {
87*789Sahrens 		error_func(fmt, ap);
88*789Sahrens 	} else {
89*789Sahrens 		(void) vfprintf(stderr, fmt, ap);
90*789Sahrens 		(void) fprintf(stderr, "\n");
91*789Sahrens 	}
92*789Sahrens 
93*789Sahrens 	va_end(ap);
94*789Sahrens 
95*789Sahrens 	exit(1);
96*789Sahrens }
97*789Sahrens 
98*789Sahrens /*
99*789Sahrens  * Consumers (such as the JNI interface) that need to capture error output can
100*789Sahrens  * override the default error handler using this function.
101*789Sahrens  */
102*789Sahrens void
103*789Sahrens zfs_set_error_handler(void (*func)(const char *, va_list))
104*789Sahrens {
105*789Sahrens 	error_func = func;
106*789Sahrens }
107*789Sahrens 
108*789Sahrens /*
109*789Sahrens  * Display an out of memory error message and abort the current program.
110*789Sahrens  */
111*789Sahrens void
112*789Sahrens no_memory(void)
113*789Sahrens {
114*789Sahrens 	assert(errno == ENOMEM);
115*789Sahrens 	zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: out of memory\n"));
116*789Sahrens }
117*789Sahrens 
118*789Sahrens /*
119*789Sahrens  * A safe form of malloc() which will die if the allocation fails.
120*789Sahrens  */
121*789Sahrens void *
122*789Sahrens zfs_malloc(size_t size)
123*789Sahrens {
124*789Sahrens 	void *data;
125*789Sahrens 
126*789Sahrens 	if ((data = calloc(1, size)) == NULL)
127*789Sahrens 		no_memory();
128*789Sahrens 
129*789Sahrens 	return (data);
130*789Sahrens }
131*789Sahrens 
132*789Sahrens /*
133*789Sahrens  * A safe form of strdup() which will die if the allocation fails.
134*789Sahrens  */
135*789Sahrens char *
136*789Sahrens zfs_strdup(const char *str)
137*789Sahrens {
138*789Sahrens 	char *ret;
139*789Sahrens 
140*789Sahrens 	if ((ret = strdup(str)) == NULL)
141*789Sahrens 		no_memory();
142*789Sahrens 
143*789Sahrens 	return (ret);
144*789Sahrens }
145*789Sahrens 
146*789Sahrens /*
147*789Sahrens  * Initialize the library.  Sets the command name used when reporting errors.
148*789Sahrens  * This command name is used to prefix all error messages appropriately.
149*789Sahrens  * Also opens /dev/zfs and dies if it cannot be opened.
150*789Sahrens  */
151*789Sahrens #pragma init(zfs_init)
152*789Sahrens void
153*789Sahrens zfs_init(void)
154*789Sahrens {
155*789Sahrens 	if ((zfs_fd = open(ZFS_DEV, O_RDWR)) < 0)
156*789Sahrens 		zfs_fatal(dgettext(TEXT_DOMAIN,
157*789Sahrens 		    "internal error: cannot open zfs device"));
158*789Sahrens 
159*789Sahrens 	if ((mnttab_file = fopen(MNTTAB, "r")) == NULL)
160*789Sahrens 		zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to "
161*789Sahrens 		    "open %s\n"), MNTTAB);
162*789Sahrens 
163*789Sahrens 	sharetab_file = fopen("/etc/dfs/sharetab", "r");
164*789Sahrens }
165*789Sahrens 
166*789Sahrens /*
167*789Sahrens  * Cleanup function for library.  Simply close the file descriptors that we
168*789Sahrens  * opened as part of libzfs_init().
169*789Sahrens  */
170*789Sahrens #pragma fini(zfs_fini)
171*789Sahrens void
172*789Sahrens zfs_fini(void)
173*789Sahrens {
174*789Sahrens 	(void) close(zfs_fd);
175*789Sahrens }
176*789Sahrens 
177*789Sahrens /*
178*789Sahrens  * Convert a number to an appropriately human-readable output.
179*789Sahrens  */
180*789Sahrens void
181*789Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen)
182*789Sahrens {
183*789Sahrens 	uint64_t n = num;
184*789Sahrens 	int index = 0;
185*789Sahrens 	char u;
186*789Sahrens 
187*789Sahrens 	while (n >= 1024) {
188*789Sahrens 		n = (n + (1024 / 2)) / 1024; /* Round up or down */
189*789Sahrens 		index++;
190*789Sahrens 	}
191*789Sahrens 
192*789Sahrens 	u = " KMGTPE"[index];
193*789Sahrens 
194*789Sahrens 	if (index == 0)
195*789Sahrens 		(void) snprintf(buf, buflen, "%llu", n);
196*789Sahrens 	else if (n < 10 && (num & (num - 1)) != 0)
197*789Sahrens 		(void) snprintf(buf, buflen, "%.2f%c",
198*789Sahrens 		    (double)num / (1ULL << 10 * index), u);
199*789Sahrens 	else if (n < 100 && (num & (num - 1)) != 0)
200*789Sahrens 		(void) snprintf(buf, buflen, "%.1f%c",
201*789Sahrens 		    (double)num / (1ULL << 10 * index), u);
202*789Sahrens 	else
203*789Sahrens 		(void) snprintf(buf, buflen, "%llu%c", n, u);
204*789Sahrens }
205