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 * 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 51 fmd_strfree(char *s) 52 { 53 if (s != NULL) 54 fmd_free(s, strlen(s) + 1); 55 } 56 57 const char * 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 * 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 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 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 * 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 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