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 #include <string.h> 28 #include <limits.h> 29 #include <stdlib.h> 30 #include <sys/types.h> 31 32 #include <inj.h> 33 #include <inj_err.h> 34 #include <inj_string.h> 35 36 char * 37 inj_strdup(const char *s) 38 { 39 char *s1 = inj_alloc(strlen(s) + 1); 40 41 (void) strcpy(s1, s); 42 return (s1); 43 } 44 45 char * 46 inj_strndup(const char *s, size_t n) 47 { 48 char *s2 = inj_alloc(n + 1); 49 50 (void) strncpy(s2, s, n + 1); 51 s2[n] = '\0'; 52 return (s2); 53 } 54 55 void 56 inj_strfree(const char *s) 57 { 58 inj_free((void *)s, strlen(s) + 1); 59 } 60 61 typedef struct type_desc { 62 int64_t td_min; 63 uint64_t td_max; 64 } type_desc_t; 65 66 static const type_desc_t signed_types[] = { 67 { 0, 0 }, 68 { INT8_MIN, INT8_MAX }, 69 { INT16_MIN, INT16_MAX }, 70 { 0, 0 }, 71 { INT32_MIN, INT32_MAX }, 72 { 0, 0 }, 73 { 0, 0 }, 74 { 0, 0 }, 75 { INT64_MIN, INT64_MAX } 76 }; 77 78 static const type_desc_t unsigned_types[] = { 79 { 0, 0 }, 80 { 0, UINT8_MAX }, 81 { 0, UINT16_MAX }, 82 { 0, 0 }, 83 { 0, UINT32_MAX }, 84 { 0, 0 }, 85 { 0, 0 }, 86 { 0, 0 }, 87 { 0, UINT64_MAX } 88 }; 89 90 int 91 inj_strtoll(const char *str, int width, longlong_t *valp) 92 { 93 const type_desc_t *desc; 94 longlong_t val; 95 char *c; 96 97 if (width != 0) { 98 assert(width / 8 < (sizeof (signed_types) / 99 sizeof (signed_types[0]))); 100 desc = &signed_types[width / 8]; 101 assert(desc->td_max != 0); 102 } 103 104 errno = 0; 105 val = strtoll(str, &c, 0); 106 if (*c != '\0' || errno == EINVAL) 107 return (inj_set_errno(EINVAL)); 108 109 if (errno == ERANGE || (width != 0 && (val < desc->td_min || 110 val > (longlong_t)desc->td_max))) 111 return (inj_set_errno(ERANGE)); 112 113 if (valp != NULL) 114 *valp = val; 115 116 return (0); 117 } 118 119 int 120 inj_strtoull(const char *str, int width, u_longlong_t *valp) 121 { 122 const type_desc_t *desc; 123 u_longlong_t val; 124 char *c; 125 126 if (width != 0) { 127 assert(width / 8 < (sizeof (unsigned_types) / 128 sizeof (unsigned_types[0]))); 129 desc = &unsigned_types[width / 8]; 130 assert(desc->td_max != 0); 131 } 132 133 errno = 0; 134 val = strtoull(str, &c, 0); 135 if (*c != '\0' || errno == EINVAL) 136 return (inj_set_errno(EINVAL)); 137 138 if (errno == ERANGE || (width != 0 && val > desc->td_max)) 139 return (inj_set_errno(ERANGE)); 140 141 if (valp != NULL) 142 *valp = val; 143 144 return (0); 145 } 146 147 int 148 inj_strtime(hrtime_t *nsp, const char *units) 149 { 150 static const struct { 151 const char *name; 152 hrtime_t mul; 153 } suffix[] = { 154 { "ns", NANOSEC / NANOSEC }, 155 { "nsec", NANOSEC / NANOSEC }, 156 { "us", NANOSEC / MICROSEC }, 157 { "usec", NANOSEC / MICROSEC }, 158 { "ms", NANOSEC / MILLISEC }, 159 { "msec", NANOSEC / MILLISEC }, 160 { "s", NANOSEC / SEC }, 161 { "sec", NANOSEC / SEC }, 162 { "m", NANOSEC * (hrtime_t)60 }, 163 { "min", NANOSEC * (hrtime_t)60 }, 164 { "h", NANOSEC * (hrtime_t)(60 * 60) }, 165 { "hour", NANOSEC * (hrtime_t)(60 * 60) }, 166 { "d", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 167 { "day", NANOSEC * (hrtime_t)(24 * 60 * 60) }, 168 { "hz", 0 }, 169 { NULL } 170 }; 171 172 hrtime_t val = *nsp, mul = 1; 173 int i; 174 175 for (i = 0; suffix[i].name != NULL; i++) { 176 if (strcasecmp(suffix[i].name, units) == 0) { 177 mul = suffix[i].mul; 178 break; 179 } 180 } 181 182 if (suffix[i].name == NULL && *units != '\0') 183 return (inj_set_errno(EINVAL)); 184 185 if (mul == 0) { 186 if (val != 0) 187 val = NANOSEC / val; /* compute val as value per sec */ 188 } else 189 val *= mul; 190 191 *nsp = val; 192 return (0); 193 } 194 195 static ulong_t 196 inj_hashfn_string(void *key) 197 { 198 size_t g, h = 0; 199 char *p; 200 201 assert(key != NULL); 202 203 for (p = key; *p != '\0'; p++) { 204 h = (h << 4) + *p; 205 206 if ((g = (h & 0xf0000000)) != 0) { 207 h ^= (g >> 24); 208 h ^= g; 209 } 210 } 211 212 return (h); 213 } 214 215 static int 216 inj_hashcmp_string(void *k1, void *k2) 217 { 218 return (strcmp(k1, k2)); 219 } 220 221 /*ARGSUSED*/ 222 static void 223 inj_hashfree_string(inj_var_t *v, void *arg) 224 { 225 inj_strfree(inj_hash_get_key(v)); 226 } 227 228 void 229 inj_strhash_create(inj_hash_t *h) 230 { 231 inj_hash_create(h, inj_hashfn_string, inj_hashcmp_string); 232 } 233 234 int 235 inj_strhash_insert(inj_hash_t *h, const char *str, uintmax_t value) 236 { 237 return (inj_hash_insert(h, (void *)inj_strdup(str), value)); 238 } 239 240 inj_var_t * 241 inj_strhash_lookup(inj_hash_t *h, const char *str) 242 { 243 return (inj_hash_lookup(h, (void *)str)); 244 } 245 246 void 247 inj_strhash_destroy(inj_hash_t *h) 248 { 249 inj_hash_destroy(h, inj_hashfree_string, NULL); 250 } 251