xref: /illumos-gate/usr/src/cmd/fm/fminject/common/inj_string.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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