1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Internal utility routines for the ZFS library. 30 */ 31 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <libintl.h> 35 #include <stdarg.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <strings.h> 39 #include <unistd.h> 40 #include <sys/mnttab.h> 41 42 #include <libzfs.h> 43 44 #include "libzfs_impl.h" 45 46 static int zfs_fd = -1; 47 static FILE *mnttab_file; 48 static FILE *sharetab_file; 49 static int sharetab_opened; 50 51 void (*error_func)(const char *, va_list); 52 53 /* 54 * All error handling is kept within libzfs where we have the most information 55 * immediately available. While this may not be suitable for a general purpose 56 * library, it greatly simplifies our commands. This command name is used to 57 * prefix all error messages appropriately. 58 */ 59 void 60 zfs_error(const char *fmt, ...) 61 { 62 va_list ap; 63 64 va_start(ap, fmt); 65 66 if (error_func != NULL) { 67 error_func(fmt, ap); 68 } else { 69 (void) vfprintf(stderr, fmt, ap); 70 (void) fprintf(stderr, "\n"); 71 } 72 73 va_end(ap); 74 } 75 76 /* 77 * An internal error is something that we cannot recover from, and should never 78 * happen (such as running out of memory). It should only be used in 79 * exceptional circumstances. 80 */ 81 void 82 zfs_fatal(const char *fmt, ...) 83 { 84 va_list ap; 85 86 va_start(ap, fmt); 87 88 if (error_func != NULL) { 89 error_func(fmt, ap); 90 } else { 91 (void) vfprintf(stderr, fmt, ap); 92 (void) fprintf(stderr, "\n"); 93 } 94 95 va_end(ap); 96 97 exit(1); 98 } 99 100 /* 101 * Consumers (such as the JNI interface) that need to capture error output can 102 * override the default error handler using this function. 103 */ 104 void 105 zfs_set_error_handler(void (*func)(const char *, va_list)) 106 { 107 error_func = func; 108 } 109 110 /* 111 * Display an out of memory error message and abort the current program. 112 */ 113 void 114 no_memory(void) 115 { 116 assert(errno == ENOMEM); 117 zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: out of memory\n")); 118 } 119 120 /* 121 * A safe form of malloc() which will die if the allocation fails. 122 */ 123 void * 124 zfs_malloc(size_t size) 125 { 126 void *data; 127 128 if ((data = calloc(1, size)) == NULL) 129 no_memory(); 130 131 return (data); 132 } 133 134 /* 135 * A safe form of strdup() which will die if the allocation fails. 136 */ 137 char * 138 zfs_strdup(const char *str) 139 { 140 char *ret; 141 142 if ((ret = strdup(str)) == NULL) 143 no_memory(); 144 145 return (ret); 146 } 147 148 /* 149 * Utility functions around common used files - /dev/zfs, /etc/mnttab, and 150 * /etc/dfs/sharetab. 151 */ 152 int 153 zfs_ioctl(int cmd, zfs_cmd_t *zc) 154 { 155 if (zfs_fd == -1 && 156 (zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) 157 zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to " 158 "open ZFS device\n"), MNTTAB); 159 160 return (ioctl(zfs_fd, cmd, zc)); 161 } 162 163 FILE * 164 zfs_mnttab(void) 165 { 166 if (mnttab_file == NULL && 167 (mnttab_file = fopen(MNTTAB, "r")) == NULL) 168 zfs_fatal(dgettext(TEXT_DOMAIN, "internal error: unable to " 169 "open %s\n"), MNTTAB); 170 171 return (mnttab_file); 172 } 173 174 FILE * 175 zfs_sharetab(void) 176 { 177 if (sharetab_opened) 178 return (sharetab_file); 179 180 sharetab_opened = TRUE; 181 return (sharetab_file = fopen("/etc/dfs/sharetab", "r")); 182 } 183 184 /* 185 * Cleanup function for library. Close any file descriptors that were 186 * opened as part of the above functions. 187 */ 188 #pragma fini(zfs_fini) 189 void 190 zfs_fini(void) 191 { 192 if (zfs_fd != -1) 193 (void) close(zfs_fd); 194 if (sharetab_file) 195 (void) fclose(sharetab_file); 196 if (mnttab_file) 197 (void) fclose(mnttab_file); 198 } 199 200 /* 201 * Convert a number to an appropriately human-readable output. 202 */ 203 void 204 zfs_nicenum(uint64_t num, char *buf, size_t buflen) 205 { 206 uint64_t n = num; 207 int index = 0; 208 char u; 209 210 while (n >= 1024) { 211 n /= 1024; 212 index++; 213 } 214 215 u = " KMGTPE"[index]; 216 217 if (index == 0) { 218 (void) snprintf(buf, buflen, "%llu", n); 219 } else if ((num & ((1ULL << 10 * index) - 1)) == 0) { 220 /* 221 * If this is an even multiple of the base, always display 222 * without any decimal precision. 223 */ 224 (void) snprintf(buf, buflen, "%llu%c", n, u); 225 } else { 226 /* 227 * We want to choose a precision that reflects the best choice 228 * for fitting in 5 characters. This can get rather tricky when 229 * we have numbers that are very close to an order of magnitude. 230 * For example, when displaying 10239 (which is really 9.999K), 231 * we want only a single place of precision for 10.0K. We could 232 * develop some complex heuristics for this, but it's much 233 * easier just to try each combination in turn. 234 */ 235 int i; 236 for (i = 2; i >= 0; i--) { 237 (void) snprintf(buf, buflen, "%.*f%c", i, 238 (double)num / (1ULL << 10 * index), u); 239 if (strlen(buf) <= 5) 240 break; 241 } 242 } 243 } 244