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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <string.h> 30 #include <limits.h> 31 #include <stdlib.h> 32 #include <sys/types.h> 33 34 #include <inj.h> 35 #include <inj_err.h> 36 #include <inj_string.h> 37 38 char * 39 inj_strdup(const char *s) 40 { 41 char *s1 = inj_alloc(strlen(s) + 1); 42 43 (void) strcpy(s1, s); 44 return (s1); 45 } 46 47 char * 48 inj_strndup(const char *s, size_t n) 49 { 50 char *s2 = inj_alloc(n + 1); 51 52 (void) strncpy(s2, s, n + 1); 53 s2[n] = '\0'; 54 return (s2); 55 } 56 57 void 58 inj_strfree(const char *s) 59 { 60 inj_free((void *)s, strlen(s) + 1); 61 } 62 63 typedef struct type_desc { 64 int64_t td_min; 65 uint64_t td_max; 66 } type_desc_t; 67 68 static const type_desc_t signed_types[] = { 69 { 0, 0 }, 70 { INT8_MIN, INT8_MAX }, 71 { INT16_MIN, INT16_MAX }, 72 { 0, 0 }, 73 { INT32_MIN, INT32_MAX }, 74 { 0, 0 }, 75 { 0, 0 }, 76 { 0, 0 }, 77 { INT64_MIN, INT64_MAX } 78 }; 79 80 static const type_desc_t unsigned_types[] = { 81 { 0, 0 }, 82 { 0, UINT8_MAX }, 83 { 0, UINT16_MAX }, 84 { 0, 0 }, 85 { 0, UINT32_MAX }, 86 { 0, 0 }, 87 { 0, 0 }, 88 { 0, 0 }, 89 { 0, UINT64_MAX } 90 }; 91 92 int 93 inj_strtoll(const char *str, int width, longlong_t *valp) 94 { 95 const type_desc_t *desc; 96 longlong_t val; 97 char *c; 98 99 if (width != 0) { 100 assert(width / 8 < (sizeof (signed_types) / 101 sizeof (signed_types[0]))); 102 desc = &signed_types[width / 8]; 103 assert(desc->td_max != 0); 104 } 105 106 errno = 0; 107 val = strtoll(str, &c, 0); 108 if (*c != '\0' || errno == EINVAL) 109 return (inj_set_errno(EINVAL)); 110 111 if (errno == ERANGE || (width != 0 && (val < desc->td_min || 112 val > (longlong_t)desc->td_max))) 113 return (inj_set_errno(ERANGE)); 114 115 if (valp != NULL) 116 *valp = val; 117 118 return (0); 119 } 120 121 int 122 inj_strtoull(const char *str, int width, u_longlong_t *valp) 123 { 124 const type_desc_t *desc; 125 u_longlong_t val; 126 char *c; 127 128 if (width != 0) { 129 assert(width / 8 < (sizeof (unsigned_types) / 130 sizeof (unsigned_types[0]))); 131 desc = &unsigned_types[width / 8]; 132 assert(desc->td_max != 0); 133 } 134 135 errno = 0; 136 val = strtoull(str, &c, 0); 137 if (*c != '\0' || errno == EINVAL) 138 return (inj_set_errno(EINVAL)); 139 140 if (errno == ERANGE || (width != 0 && val > desc->td_max)) 141 return (inj_set_errno(ERANGE)); 142 143 if (valp != NULL) 144 *valp = val; 145 146 return (0); 147 } 148 149 int 150 inj_strtime(hrtime_t *nsp, const char *units) 151 { 152 static const struct { 153 const char *name; 154 hrtime_t mul; 155 } suffix[] = { 156 { "ns", NANOSEC / NANOSEC }, 157 { "nsec", NANOSEC / NANOSEC }, 158 { "us", NANOSEC / MICROSEC }, 159 { "usec", NANOSEC / MICROSEC }, 160 { "ms", NANOSEC / MILLISEC }, 161 { "msec", NANOSEC / MILLISEC }, 162 { "s", NANOSEC / SEC }, 163 { "sec", NANOSEC / SEC }, 164 { "m", NANOSEC * (hrtime_t)60 }, 165 { "min", NANOSEC * (hrtime_t)60 }, 166 { "h", NANOSEC * (hrtime_t)(60 * 60) }, 167 { "hour", NANOSEC * (hrtime_t)(60 * 60) }, 168 { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 169 { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 170 { "hz", 0 }, 171 { NULL } 172 }; 173 174 hrtime_t val = *nsp, mul = 1; 175 int i; 176 177 for (i = 0; suffix[i].name != NULL; i++) { 178 if (strcasecmp(suffix[i].name, units) == 0) { 179 mul = suffix[i].mul; 180 break; 181 } 182 } 183 184 if (suffix[i].name == NULL && *units != '\0') 185 return (inj_set_errno(EINVAL)); 186 187 if (mul == 0) { 188 if (val != 0) 189 val = NANOSEC / val; /* compute val as value per sec */ 190 } else 191 val *= mul; 192 193 *nsp = val; 194 return (0); 195 } 196 197 static ulong_t 198 inj_hashfn_string(void *key) 199 { 200 size_t g, h = 0; 201 char *p; 202 203 assert(key != NULL); 204 205 for (p = key; *p != '\0'; p++) { 206 h = (h << 4) + *p; 207 208 if ((g = (h & 0xf0000000)) != 0) { 209 h ^= (g >> 24); 210 h ^= g; 211 } 212 } 213 214 return (h); 215 } 216 217 static int 218 inj_hashcmp_string(void *k1, void *k2) 219 { 220 return (strcmp(k1, k2)); 221 } 222 223 /*ARGSUSED*/ 224 static void 225 inj_hashfree_string(inj_var_t *v, void *arg) 226 { 227 inj_strfree(inj_hash_get_key(v)); 228 } 229 230 void 231 inj_strhash_create(inj_hash_t *h) 232 { 233 inj_hash_create(h, inj_hashfn_string, inj_hashcmp_string); 234 } 235 236 int 237 inj_strhash_insert(inj_hash_t *h, const char *str, uintmax_t value) 238 { 239 return (inj_hash_insert(h, (void *)inj_strdup(str), value)); 240 } 241 242 inj_var_t * 243 inj_strhash_lookup(inj_hash_t *h, const char *str) 244 { 245 return (inj_hash_lookup(h, (void *)str)); 246 } 247 248 void 249 inj_strhash_destroy(inj_hash_t *h) 250 { 251 inj_hash_destroy(h, inj_hashfree_string, NULL); 252 } 253