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