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 <strings.h>
30 #include <ctype.h>
31
32 #include <fmd_string.h>
33
34 char *
fmd_strdup(const char * s,int flags)35 fmd_strdup(const char *s, int flags)
36 {
37 char *p;
38
39 if (s != NULL)
40 p = fmd_alloc(strlen(s) + 1, flags);
41 else
42 p = NULL;
43
44 if (p != NULL)
45 (void) strcpy(p, s);
46
47 return (p);
48 }
49
50 void
fmd_strfree(char * s)51 fmd_strfree(char *s)
52 {
53 if (s != NULL)
54 fmd_free(s, strlen(s) + 1);
55 }
56
57 const char *
fmd_strbasename(const char * s)58 fmd_strbasename(const char *s)
59 {
60 const char *p = strrchr(s, '/');
61
62 if (p == NULL)
63 return (s);
64
65 return (++p);
66 }
67
68 char *
fmd_strdirname(char * s)69 fmd_strdirname(char *s)
70 {
71 static char slash[] = "/";
72 static char dot[] = ".";
73 char *p;
74
75 if (s == NULL || *s == '\0')
76 return (dot);
77
78 for (p = s + strlen(s); p != s && *--p == '/'; )
79 continue;
80
81 if (p == s && *p == '/')
82 return (slash);
83
84 while (p != s) {
85 if (*--p == '/') {
86 while (*p == '/' && p != s)
87 p--;
88 *++p = '\0';
89 return (s);
90 }
91 }
92
93 return (dot);
94 }
95
96 ulong_t
fmd_strhash(const char * key)97 fmd_strhash(const char *key)
98 {
99 ulong_t g, h = 0;
100 const char *p;
101
102 for (p = key; *p != '\0'; p++) {
103 h = (h << 4) + *p;
104
105 if ((g = (h & 0xf0000000)) != 0) {
106 h ^= (g >> 24);
107 h ^= g;
108 }
109 }
110
111 return (h);
112 }
113
114 /*
115 * Transform string s inline, converting each embedded C escape sequence string
116 * to the corresponding character. For example, the substring "\n" is replaced
117 * by an inline '\n' character. The length of the resulting string is returned.
118 */
119 size_t
fmd_stresc2chr(char * s)120 fmd_stresc2chr(char *s)
121 {
122 char *p, *q, c;
123 int esc = 0;
124 int x;
125
126 for (p = q = s; (c = *p) != '\0'; p++) {
127 if (esc) {
128 switch (c) {
129 case '0':
130 case '1':
131 case '2':
132 case '3':
133 case '4':
134 case '5':
135 case '6':
136 case '7':
137 c -= '0';
138 p++;
139
140 if (*p >= '0' && *p <= '7') {
141 c = c * 8 + *p++ - '0';
142
143 if (*p >= '0' && *p <= '7')
144 c = c * 8 + *p - '0';
145 else
146 p--;
147 } else
148 p--;
149
150 *q++ = c;
151 break;
152
153 case 'a':
154 *q++ = '\a';
155 break;
156 case 'b':
157 *q++ = '\b';
158 break;
159 case 'f':
160 *q++ = '\f';
161 break;
162 case 'n':
163 *q++ = '\n';
164 break;
165 case 'r':
166 *q++ = '\r';
167 break;
168 case 't':
169 *q++ = '\t';
170 break;
171 case 'v':
172 *q++ = '\v';
173 break;
174
175 case 'x':
176 for (x = 0; (c = *++p) != '\0'; ) {
177 if (c >= '0' && c <= '9')
178 x = x * 16 + c - '0';
179 else if (c >= 'a' && c <= 'f')
180 x = x * 16 + c - 'a' + 10;
181 else if (c >= 'A' && c <= 'F')
182 x = x * 16 + c - 'A' + 10;
183 else
184 break;
185 }
186 *q++ = (char)x;
187 p--;
188 break;
189
190 case '"':
191 case '\\':
192 *q++ = c;
193 break;
194 default:
195 *q++ = '\\';
196 *q++ = c;
197 }
198
199 esc = 0;
200
201 } else {
202 if ((esc = c == '\\') == 0)
203 *q++ = c;
204 }
205 }
206
207 *q = '\0';
208 return ((size_t)(q - s));
209 }
210
211 /*
212 * We require that identifiers for buffers, statistics, and properties conform
213 * to the regular expression [a-zA-Z0-9\-_.]. If check_prefixes is set, we
214 * also flag strings that begin with a set of prefixes reserved for use by fmd.
215 */
216 const char *
fmd_strbadid(const char * s,int check_prefixes)217 fmd_strbadid(const char *s, int check_prefixes)
218 {
219 const char *s0 = s;
220 int c = *s++;
221
222 while ((c = *s++) != '\0') {
223 if (!isupper(c) && !islower(c) &&
224 !isdigit(c) && c != '-' && c != '_' && c != '.')
225 return (s - 1);
226 }
227
228 if (check_prefixes && (s0[0] == '_' || s0[0] == '.' ||
229 strncmp(s0, "fmd_", 4) == 0 || strncmp(s0, "FMD_", 4) == 0 ||
230 strncmp(s0, "fmd.", 4) == 0 || strncmp(s0, "FMD.", 4) == 0))
231 return (s0);
232
233 return (NULL);
234 }
235
236 int
fmd_strmatch(const char * s,const char * p)237 fmd_strmatch(const char *s, const char *p)
238 {
239 char c;
240
241 if (p == NULL)
242 return (0);
243
244 if (s == NULL)
245 s = ""; /* treat NULL string as the empty string */
246
247 do {
248 if ((c = *p++) == '\0')
249 return (*s == '\0');
250
251 if (c == '*') {
252 while (*p == '*')
253 p++; /* consecutive *'s can be collapsed */
254
255 if (*p == '\0')
256 return (1);
257
258 while (*s != '\0') {
259 if (fmd_strmatch(s++, p) != 0)
260 return (1);
261 }
262
263 return (0);
264 }
265 } while (c == *s++);
266
267 return (0);
268 }
269