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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright (c) 2013, Joyent, Inc. All rights reserved. 28 */ 29 30 #include <strings.h> 31 #include <ctype.h> 32 #include <fm/libtopo.h> 33 #include <fm/topo_mod.h> 34 #include <topo_alloc.h> 35 36 char * 37 topo_hdl_strdup(topo_hdl_t *thp, const char *s) 38 { 39 char *p; 40 41 if (s != NULL) 42 p = topo_hdl_alloc(thp, strlen(s) + 1); 43 else 44 p = NULL; 45 46 if (p != NULL) 47 (void) strcpy(p, s); 48 49 return (p); 50 } 51 52 void 53 topo_hdl_strfree(topo_hdl_t *thp, char *s) 54 { 55 if (s != NULL) 56 topo_hdl_free(thp, s, strlen(s) + 1); 57 } 58 59 char * 60 topo_hdl_strsplit(topo_hdl_t *hdl, const char *input, const char *sep, 61 char **lastp) 62 { 63 size_t seplen = strlen(sep); 64 const char *scanstart; 65 char *token; 66 char *ret; 67 68 if (input != NULL) { 69 /* 70 * Start scanning at beginning of input: 71 */ 72 scanstart = input; 73 } else if (*lastp == NULL) { 74 /* 75 * If we have already finished scanning, return NULL. 76 */ 77 return (NULL); 78 } else { 79 /* 80 * Otherwise, start scanning where we left off: 81 */ 82 scanstart = *lastp; 83 } 84 85 token = strstr(scanstart, sep); 86 if (token != NULL) { 87 /* 88 * We still have a separator, so advance the next-start 89 * pointer past it: 90 */ 91 *lastp = token + seplen; 92 /* 93 * Copy out this element. The buffer must fit the string 94 * exactly, so that topo_hdl_strfree() can determine its 95 * size with strlen(). 96 */ 97 ret = topo_hdl_alloc(hdl, token - scanstart + 1); 98 (void) strncpy(ret, scanstart, token - scanstart); 99 ret[token - scanstart] = '\0'; 100 } else { 101 /* 102 * We have no separator, so this is the last element: 103 */ 104 *lastp = NULL; 105 ret = topo_hdl_strdup(hdl, scanstart); 106 } 107 108 return (ret); 109 } 110 111 char * 112 topo_mod_strdup(topo_mod_t *mod, const char *s) 113 { 114 return (topo_hdl_strdup(mod->tm_hdl, s)); 115 } 116 117 void 118 topo_mod_strfree(topo_mod_t *mod, char *s) 119 { 120 topo_hdl_strfree(mod->tm_hdl, s); 121 } 122 123 char * 124 topo_mod_strsplit(topo_mod_t *mod, const char *input, const char *sep, 125 char **lastp) 126 { 127 return (topo_hdl_strsplit(mod->tm_hdl, input, sep, lastp)); 128 } 129 130 const char * 131 topo_strbasename(const char *s) 132 { 133 const char *p = strrchr(s, '/'); 134 135 if (p == NULL) 136 return (s); 137 138 return (++p); 139 } 140 141 char * 142 topo_strdirname(char *s) 143 { 144 static char slash[] = "/"; 145 static char dot[] = "."; 146 char *p; 147 148 if (s == NULL || *s == '\0') 149 return (dot); 150 151 for (p = s + strlen(s); p != s && *--p == '/'; ) 152 continue; 153 154 if (p == s && *p == '/') 155 return (slash); 156 157 while (p != s) { 158 if (*--p == '/') { 159 while (*p == '/' && p != s) 160 p--; 161 *++p = '\0'; 162 return (s); 163 } 164 } 165 166 return (dot); 167 } 168 169 ulong_t 170 topo_strhash(const char *key) 171 { 172 ulong_t g, h = 0; 173 const char *p; 174 175 for (p = key; *p != '\0'; p++) { 176 h = (h << 4) + *p; 177 178 if ((g = (h & 0xf0000000)) != 0) { 179 h ^= (g >> 24); 180 h ^= g; 181 } 182 } 183 184 return (h); 185 } 186 187 /* 188 * Transform string s inline, converting each embedded C escape sequence string 189 * to the corresponding character. For example, the substring "\n" is replaced 190 * by an inline '\n' character. The length of the resulting string is returned. 191 */ 192 size_t 193 topo_stresc2chr(char *s) 194 { 195 char *p, *q, c; 196 int esc = 0; 197 int x; 198 199 for (p = q = s; (c = *p) != '\0'; p++) { 200 if (esc) { 201 switch (c) { 202 case '0': 203 case '1': 204 case '2': 205 case '3': 206 case '4': 207 case '5': 208 case '6': 209 case '7': 210 c -= '0'; 211 p++; 212 213 if (*p >= '0' && *p <= '7') { 214 c = c * 8 + *p++ - '0'; 215 216 if (*p >= '0' && *p <= '7') 217 c = c * 8 + *p - '0'; 218 else 219 p--; 220 } else 221 p--; 222 223 *q++ = c; 224 break; 225 226 case 'a': 227 *q++ = '\a'; 228 break; 229 case 'b': 230 *q++ = '\b'; 231 break; 232 case 'f': 233 *q++ = '\f'; 234 break; 235 case 'n': 236 *q++ = '\n'; 237 break; 238 case 'r': 239 *q++ = '\r'; 240 break; 241 case 't': 242 *q++ = '\t'; 243 break; 244 case 'v': 245 *q++ = '\v'; 246 break; 247 248 case 'x': 249 for (x = 0; (c = *++p) != '\0'; ) { 250 if (c >= '0' && c <= '9') 251 x = x * 16 + c - '0'; 252 else if (c >= 'a' && c <= 'f') 253 x = x * 16 + c - 'a' + 10; 254 else if (c >= 'A' && c <= 'F') 255 x = x * 16 + c - 'A' + 10; 256 else 257 break; 258 } 259 *q++ = (char)x; 260 p--; 261 break; 262 263 case '"': 264 case '\\': 265 *q++ = c; 266 break; 267 default: 268 *q++ = '\\'; 269 *q++ = c; 270 } 271 272 esc = 0; 273 274 } else { 275 if ((esc = c == '\\') == 0) 276 *q++ = c; 277 } 278 } 279 280 *q = '\0'; 281 return ((size_t)(q - s)); 282 } 283 284 int 285 topo_strmatch(const char *s, const char *p) 286 { 287 char c; 288 289 if (p == NULL) 290 return (0); 291 292 if (s == NULL) 293 s = ""; /* treat NULL string as the empty string */ 294 295 do { 296 if ((c = *p++) == '\0') 297 return (*s == '\0'); 298 299 if (c == '*') { 300 while (*p == '*') 301 p++; /* consecutive *'s can be collapsed */ 302 303 if (*p == '\0') 304 return (1); 305 306 while (*s != '\0') { 307 if (topo_strmatch(s++, p) != 0) 308 return (1); 309 } 310 311 return (0); 312 } 313 } while (c == *s++); 314 315 return (0); 316 }