1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5*ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6*ea8dc4b6Seschrock * 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 /* 22*ea8dc4b6Seschrock * 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 46*ea8dc4b6Seschrock static int zfs_fd = -1; 47*ea8dc4b6Seschrock static FILE *mnttab_file; 48*ea8dc4b6Seschrock static FILE *sharetab_file; 49*ea8dc4b6Seschrock static int sharetab_opened; 50fa9e4066Sahrens 51fa9e4066Sahrens void (*error_func)(const char *, va_list); 52fa9e4066Sahrens 53fa9e4066Sahrens /* 54fa9e4066Sahrens * All error handling is kept within libzfs where we have the most information 55fa9e4066Sahrens * immediately available. While this may not be suitable for a general purpose 56fa9e4066Sahrens * library, it greatly simplifies our commands. This command name is used to 57fa9e4066Sahrens * prefix all error messages appropriately. 58fa9e4066Sahrens */ 59fa9e4066Sahrens void 60fa9e4066Sahrens zfs_error(const char *fmt, ...) 61fa9e4066Sahrens { 62fa9e4066Sahrens va_list ap; 63fa9e4066Sahrens 64fa9e4066Sahrens va_start(ap, fmt); 65fa9e4066Sahrens 66fa9e4066Sahrens if (error_func != NULL) { 67fa9e4066Sahrens error_func(fmt, ap); 68fa9e4066Sahrens } else { 69fa9e4066Sahrens (void) vfprintf(stderr, fmt, ap); 70fa9e4066Sahrens (void) fprintf(stderr, "\n"); 71fa9e4066Sahrens } 72fa9e4066Sahrens 73fa9e4066Sahrens va_end(ap); 74fa9e4066Sahrens } 75fa9e4066Sahrens 76fa9e4066Sahrens /* 77fa9e4066Sahrens * An internal error is something that we cannot recover from, and should never 78fa9e4066Sahrens * happen (such as running out of memory). It should only be used in 79fa9e4066Sahrens * exceptional circumstances. 80fa9e4066Sahrens */ 81fa9e4066Sahrens void 82fa9e4066Sahrens zfs_fatal(const char *fmt, ...) 83fa9e4066Sahrens { 84fa9e4066Sahrens va_list ap; 85fa9e4066Sahrens 86fa9e4066Sahrens va_start(ap, fmt); 87fa9e4066Sahrens 88fa9e4066Sahrens if (error_func != NULL) { 89fa9e4066Sahrens error_func(fmt, ap); 90fa9e4066Sahrens } else { 91fa9e4066Sahrens (void) vfprintf(stderr, fmt, ap); 92fa9e4066Sahrens (void) fprintf(stderr, "\n"); 93fa9e4066Sahrens } 94fa9e4066Sahrens 95fa9e4066Sahrens va_end(ap); 96fa9e4066Sahrens 97fa9e4066Sahrens exit(1); 98fa9e4066Sahrens } 99fa9e4066Sahrens 100fa9e4066Sahrens /* 101fa9e4066Sahrens * Consumers (such as the JNI interface) that need to capture error output can 102fa9e4066Sahrens * override the default error handler using this function. 103fa9e4066Sahrens */ 104fa9e4066Sahrens void 105fa9e4066Sahrens zfs_set_error_handler(void (*func)(const char *, va_list)) 106fa9e4066Sahrens { 107fa9e4066Sahrens error_func = func; 108fa9e4066Sahrens } 109fa9e4066Sahrens 110fa9e4066Sahrens /* 111fa9e4066Sahrens * Display an out of memory error message and abort the current program. 112fa9e4066Sahrens */ 113fa9e4066Sahrens void 114fa9e4066Sahrens no_memory(void) 115fa9e4066Sahrens { 116fa9e4066Sahrens assert(errno == ENOMEM); 117fa9e4066Sahrens zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: out of memory\n")); 118fa9e4066Sahrens } 119fa9e4066Sahrens 120fa9e4066Sahrens /* 121fa9e4066Sahrens * A safe form of malloc() which will die if the allocation fails. 122fa9e4066Sahrens */ 123fa9e4066Sahrens void * 124fa9e4066Sahrens zfs_malloc(size_t size) 125fa9e4066Sahrens { 126fa9e4066Sahrens void *data; 127fa9e4066Sahrens 128fa9e4066Sahrens if ((data = calloc(1, size)) == NULL) 129fa9e4066Sahrens no_memory(); 130fa9e4066Sahrens 131fa9e4066Sahrens return (data); 132fa9e4066Sahrens } 133fa9e4066Sahrens 134fa9e4066Sahrens /* 135fa9e4066Sahrens * A safe form of strdup() which will die if the allocation fails. 136fa9e4066Sahrens */ 137fa9e4066Sahrens char * 138fa9e4066Sahrens zfs_strdup(const char *str) 139fa9e4066Sahrens { 140fa9e4066Sahrens char *ret; 141fa9e4066Sahrens 142fa9e4066Sahrens if ((ret = strdup(str)) == NULL) 143fa9e4066Sahrens no_memory(); 144fa9e4066Sahrens 145fa9e4066Sahrens return (ret); 146fa9e4066Sahrens } 147fa9e4066Sahrens 148fa9e4066Sahrens /* 149*ea8dc4b6Seschrock * Utility functions around common used files - /dev/zfs, /etc/mnttab, and 150*ea8dc4b6Seschrock * /etc/dfs/sharetab. 151fa9e4066Sahrens */ 152*ea8dc4b6Seschrock int 153*ea8dc4b6Seschrock zfs_ioctl(int cmd, zfs_cmd_t *zc) 154fa9e4066Sahrens { 155*ea8dc4b6Seschrock if (zfs_fd == -1 && 156*ea8dc4b6Seschrock (zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) 157*ea8dc4b6Seschrock zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to " 158*ea8dc4b6Seschrock "open ZFS device\n"), MNTTAB); 159fa9e4066Sahrens 160*ea8dc4b6Seschrock return (ioctl(zfs_fd, cmd, zc)); 161*ea8dc4b6Seschrock } 162*ea8dc4b6Seschrock 163*ea8dc4b6Seschrock FILE * 164*ea8dc4b6Seschrock zfs_mnttab(void) 165*ea8dc4b6Seschrock { 166*ea8dc4b6Seschrock if (mnttab_file == NULL && 167*ea8dc4b6Seschrock (mnttab_file = fopen(MNTTAB, "r")) == NULL) 168fa9e4066Sahrens zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to " 169fa9e4066Sahrens "open %s\n"), MNTTAB); 170fa9e4066Sahrens 171*ea8dc4b6Seschrock return (mnttab_file); 172*ea8dc4b6Seschrock } 173*ea8dc4b6Seschrock 174*ea8dc4b6Seschrock FILE * 175*ea8dc4b6Seschrock zfs_sharetab(void) 176*ea8dc4b6Seschrock { 177*ea8dc4b6Seschrock if (sharetab_opened) 178*ea8dc4b6Seschrock return (sharetab_file); 179*ea8dc4b6Seschrock 180*ea8dc4b6Seschrock sharetab_opened = TRUE; 181*ea8dc4b6Seschrock return (sharetab_file = fopen("/etc/dfs/sharetab", "r")); 182fa9e4066Sahrens } 183fa9e4066Sahrens 184fa9e4066Sahrens /* 185*ea8dc4b6Seschrock * Cleanup function for library. Close any file descriptors that were 186*ea8dc4b6Seschrock * opened as part of the above functions. 187fa9e4066Sahrens */ 188fa9e4066Sahrens #pragma fini(zfs_fini) 189fa9e4066Sahrens void 190fa9e4066Sahrens zfs_fini(void) 191fa9e4066Sahrens { 192*ea8dc4b6Seschrock if (zfs_fd != -1) 193*ea8dc4b6Seschrock (void) close(zfs_fd); 194*ea8dc4b6Seschrock if (sharetab_file) 195*ea8dc4b6Seschrock (void) fclose(sharetab_file); 196*ea8dc4b6Seschrock if (mnttab_file) 197*ea8dc4b6Seschrock (void) fclose(mnttab_file); 198fa9e4066Sahrens } 199fa9e4066Sahrens 200fa9e4066Sahrens /* 201fa9e4066Sahrens * Convert a number to an appropriately human-readable output. 202fa9e4066Sahrens */ 203fa9e4066Sahrens void 204fa9e4066Sahrens zfs_nicenum(uint64_t num, char *buf, size_t buflen) 205fa9e4066Sahrens { 206fa9e4066Sahrens uint64_t n = num; 207fa9e4066Sahrens int index = 0; 208fa9e4066Sahrens char u; 209fa9e4066Sahrens 210fa9e4066Sahrens while (n >= 1024) { 2115c709891Seschrock n /= 1024; 212fa9e4066Sahrens index++; 213fa9e4066Sahrens } 214fa9e4066Sahrens 215fa9e4066Sahrens u = " KMGTPE"[index]; 216fa9e4066Sahrens 2175c709891Seschrock if (index == 0) { 218fa9e4066Sahrens (void) snprintf(buf, buflen, "%llu", n); 2195c709891Seschrock } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { 2205c709891Seschrock /* 2215c709891Seschrock * If this is an even multiple of the base, always display 2225c709891Seschrock * without any decimal precision. 2235c709891Seschrock */ 224fa9e4066Sahrens (void) snprintf(buf, buflen, "%llu%c", n, u); 2255c709891Seschrock } else { 2265c709891Seschrock /* 2275c709891Seschrock * We want to choose a precision that reflects the best choice 2285c709891Seschrock * for fitting in 5 characters. This can get rather tricky when 2295c709891Seschrock * we have numbers that are very close to an order of magnitude. 2305c709891Seschrock * For example, when displaying 10239 (which is really 9.999K), 2315c709891Seschrock * we want only a single place of precision for 10.0K. We could 2325c709891Seschrock * develop some complex heuristics for this, but it's much 2335c709891Seschrock * easier just to try each combination in turn. 2345c709891Seschrock */ 2355c709891Seschrock int i; 2365c709891Seschrock for (i = 2; i >= 0; i--) { 2375c709891Seschrock (void) snprintf(buf, buflen, "%.*f%c", i, 2385c709891Seschrock (double)num / (1ULL << 10 * index), u); 2395c709891Seschrock if (strlen(buf) <= 5) 2405c709891Seschrock break; 2415c709891Seschrock } 2425c709891Seschrock } 243fa9e4066Sahrens } 244