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