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 *
inj_strdup(const char * s)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 *
inj_strndup(const char * s,size_t n)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
inj_strfree(const char * s)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
inj_strtoll(const char * str,int width,longlong_t * valp)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
inj_strtoull(const char * str,int width,u_longlong_t * valp)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
inj_strtime(hrtime_t * nsp,const char * units)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
inj_hashfn_string(void * key)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
inj_hashcmp_string(void * k1,void * k2)218 inj_hashcmp_string(void *k1, void *k2)
219 {
220 return (strcmp(k1, k2));
221 }
222
223 /*ARGSUSED*/
224 static void
inj_hashfree_string(inj_var_t * v,void * arg)225 inj_hashfree_string(inj_var_t *v, void *arg)
226 {
227 inj_strfree(inj_hash_get_key(v));
228 }
229
230 void
inj_strhash_create(inj_hash_t * h)231 inj_strhash_create(inj_hash_t *h)
232 {
233 inj_hash_create(h, inj_hashfn_string, inj_hashcmp_string);
234 }
235
236 int
inj_strhash_insert(inj_hash_t * h,const char * str,uintmax_t value)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 *
inj_strhash_lookup(inj_hash_t * h,const char * str)243 inj_strhash_lookup(inj_hash_t *h, const char *str)
244 {
245 return (inj_hash_lookup(h, (void *)str));
246 }
247
248 void
inj_strhash_destroy(inj_hash_t * h)249 inj_strhash_destroy(inj_hash_t *h)
250 {
251 inj_hash_destroy(h, inj_hashfree_string, NULL);
252 }
253