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