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