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 2019 Joyent, Inc. 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 void 60 topo_hdl_strfreev(topo_hdl_t *thp, char **strarr, uint_t nelem) 61 { 62 for (uint_t i = 0; i < nelem; i++) 63 topo_hdl_strfree(thp, strarr[i]); 64 65 topo_hdl_free(thp, strarr, (nelem * sizeof (char *))); 66 } 67 68 char * 69 topo_mod_strdup(topo_mod_t *mod, const char *s) 70 { 71 return (topo_hdl_strdup(mod->tm_hdl, s)); 72 } 73 74 void 75 topo_mod_strfree(topo_mod_t *mod, char *s) 76 { 77 topo_hdl_strfree(mod->tm_hdl, s); 78 } 79 80 void 81 topo_mod_strfreev(topo_mod_t *mod, char **strarr, uint_t nelem) 82 { 83 topo_hdl_strfreev(mod->tm_hdl, strarr, nelem); 84 } 85 86 const char * 87 topo_strbasename(const char *s) 88 { 89 const char *p = strrchr(s, '/'); 90 91 if (p == NULL) 92 return (s); 93 94 return (++p); 95 } 96 97 char * 98 topo_strdirname(char *s) 99 { 100 static char slash[] = "/"; 101 static char dot[] = "."; 102 char *p; 103 104 if (s == NULL || *s == '\0') 105 return (dot); 106 107 for (p = s + strlen(s); p != s && *--p == '/'; ) 108 continue; 109 110 if (p == s && *p == '/') 111 return (slash); 112 113 while (p != s) { 114 if (*--p == '/') { 115 while (*p == '/' && p != s) 116 p--; 117 *++p = '\0'; 118 return (s); 119 } 120 } 121 122 return (dot); 123 } 124 125 ulong_t 126 topo_strhash(const char *key) 127 { 128 ulong_t g, h = 0; 129 const char *p; 130 131 for (p = key; *p != '\0'; p++) { 132 h = (h << 4) + *p; 133 134 if ((g = (h & 0xf0000000)) != 0) { 135 h ^= (g >> 24); 136 h ^= g; 137 } 138 } 139 140 return (h); 141 } 142 143 /* 144 * Transform string s inline, converting each embedded C escape sequence string 145 * to the corresponding character. For example, the substring "\n" is replaced 146 * by an inline '\n' character. The length of the resulting string is returned. 147 */ 148 size_t 149 topo_stresc2chr(char *s) 150 { 151 char *p, *q, c; 152 int esc = 0; 153 int x; 154 155 for (p = q = s; (c = *p) != '\0'; p++) { 156 if (esc) { 157 switch (c) { 158 case '0': 159 case '1': 160 case '2': 161 case '3': 162 case '4': 163 case '5': 164 case '6': 165 case '7': 166 c -= '0'; 167 p++; 168 169 if (*p >= '0' && *p <= '7') { 170 c = c * 8 + *p++ - '0'; 171 172 if (*p >= '0' && *p <= '7') 173 c = c * 8 + *p - '0'; 174 else 175 p--; 176 } else 177 p--; 178 179 *q++ = c; 180 break; 181 182 case 'a': 183 *q++ = '\a'; 184 break; 185 case 'b': 186 *q++ = '\b'; 187 break; 188 case 'f': 189 *q++ = '\f'; 190 break; 191 case 'n': 192 *q++ = '\n'; 193 break; 194 case 'r': 195 *q++ = '\r'; 196 break; 197 case 't': 198 *q++ = '\t'; 199 break; 200 case 'v': 201 *q++ = '\v'; 202 break; 203 204 case 'x': 205 for (x = 0; (c = *++p) != '\0'; ) { 206 if (c >= '0' && c <= '9') 207 x = x * 16 + c - '0'; 208 else if (c >= 'a' && c <= 'f') 209 x = x * 16 + c - 'a' + 10; 210 else if (c >= 'A' && c <= 'F') 211 x = x * 16 + c - 'A' + 10; 212 else 213 break; 214 } 215 *q++ = (char)x; 216 p--; 217 break; 218 219 case '"': 220 case '\\': 221 *q++ = c; 222 break; 223 default: 224 *q++ = '\\'; 225 *q++ = c; 226 } 227 228 esc = 0; 229 230 } else { 231 if ((esc = c == '\\') == 0) 232 *q++ = c; 233 } 234 } 235 236 *q = '\0'; 237 return ((size_t)(q - s)); 238 } 239 240 int 241 topo_strmatch(const char *s, const char *p) 242 { 243 char c; 244 245 if (p == NULL) 246 return (0); 247 248 if (s == NULL) 249 s = ""; /* treat NULL string as the empty string */ 250 251 do { 252 if ((c = *p++) == '\0') 253 return (*s == '\0'); 254 255 if (c == '*') { 256 while (*p == '*') 257 p++; /* consecutive *'s can be collapsed */ 258 259 if (*p == '\0') 260 return (1); 261 262 while (*s != '\0') { 263 if (topo_strmatch(s++, p) != 0) 264 return (1); 265 } 266 267 return (0); 268 } 269 } while (c == *s++); 270 271 return (0); 272 } 273