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