17aec1d6eScindi /*
27aec1d6eScindi * CDDL HEADER START
37aec1d6eScindi *
47aec1d6eScindi * The contents of this file are subject to the terms of the
57aec1d6eScindi * Common Development and Distribution License, Version 1.0 only
67aec1d6eScindi * (the "License"). You may not use this file except in compliance
77aec1d6eScindi * with the License.
87aec1d6eScindi *
97aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107aec1d6eScindi * or http://www.opensolaris.org/os/licensing.
117aec1d6eScindi * See the License for the specific language governing permissions
127aec1d6eScindi * and limitations under the License.
137aec1d6eScindi *
147aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each
157aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the
177aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying
187aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner]
197aec1d6eScindi *
207aec1d6eScindi * CDDL HEADER END
217aec1d6eScindi */
227aec1d6eScindi /*
237aec1d6eScindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
247aec1d6eScindi * Use is subject to license terms.
257aec1d6eScindi */
26e2336878SRob Johnston /*
27e2336878SRob Johnston * Copyright 2019 Joyent, Inc.
28*9c994d58SRobert Mustacchi * Copyright 2023 Oxide computer Company
29e2336878SRob Johnston */
307aec1d6eScindi
317aec1d6eScindi #include <strings.h>
327aec1d6eScindi #include <ctype.h>
337aec1d6eScindi #include <fm/libtopo.h>
347aec1d6eScindi #include <fm/topo_mod.h>
357aec1d6eScindi #include <topo_alloc.h>
367aec1d6eScindi
377aec1d6eScindi char *
topo_hdl_strdup(topo_hdl_t * thp,const char * s)387aec1d6eScindi topo_hdl_strdup(topo_hdl_t *thp, const char *s)
397aec1d6eScindi {
407aec1d6eScindi char *p;
417aec1d6eScindi
427aec1d6eScindi if (s != NULL)
437aec1d6eScindi p = topo_hdl_alloc(thp, strlen(s) + 1);
447aec1d6eScindi else
457aec1d6eScindi p = NULL;
467aec1d6eScindi
477aec1d6eScindi if (p != NULL)
487aec1d6eScindi (void) strcpy(p, s);
497aec1d6eScindi
507aec1d6eScindi return (p);
517aec1d6eScindi }
527aec1d6eScindi
537aec1d6eScindi void
topo_hdl_strfree(topo_hdl_t * thp,char * s)547aec1d6eScindi topo_hdl_strfree(topo_hdl_t *thp, char *s)
557aec1d6eScindi {
567aec1d6eScindi if (s != NULL)
577aec1d6eScindi topo_hdl_free(thp, s, strlen(s) + 1);
587aec1d6eScindi }
597aec1d6eScindi
60e2336878SRob Johnston void
topo_hdl_strfreev(topo_hdl_t * thp,char ** strarr,uint_t nelem)61e2336878SRob Johnston topo_hdl_strfreev(topo_hdl_t *thp, char **strarr, uint_t nelem)
62e2336878SRob Johnston {
63e2336878SRob Johnston for (uint_t i = 0; i < nelem; i++)
64e2336878SRob Johnston topo_hdl_strfree(thp, strarr[i]);
65e2336878SRob Johnston
66e2336878SRob Johnston topo_hdl_free(thp, strarr, (nelem * sizeof (char *)));
67e2336878SRob Johnston }
68e2336878SRob Johnston
697aec1d6eScindi char *
topo_mod_strdup(topo_mod_t * mod,const char * s)707aec1d6eScindi topo_mod_strdup(topo_mod_t *mod, const char *s)
717aec1d6eScindi {
727aec1d6eScindi return (topo_hdl_strdup(mod->tm_hdl, s));
737aec1d6eScindi }
747aec1d6eScindi
75*9c994d58SRobert Mustacchi int
topo_hdl_vasprintf(topo_hdl_t * thp,char ** str,const char * fmt,va_list ap)76*9c994d58SRobert Mustacchi topo_hdl_vasprintf(topo_hdl_t *thp, char **str, const char *fmt, va_list ap)
77*9c994d58SRobert Mustacchi {
78*9c994d58SRobert Mustacchi int len, ret;
79*9c994d58SRobert Mustacchi
80*9c994d58SRobert Mustacchi *str = NULL;
81*9c994d58SRobert Mustacchi len = vsnprintf(NULL, 0, fmt, ap);
82*9c994d58SRobert Mustacchi if (len < 0) {
83*9c994d58SRobert Mustacchi return (len);
84*9c994d58SRobert Mustacchi }
85*9c994d58SRobert Mustacchi
86*9c994d58SRobert Mustacchi if (len == INT_MAX) {
87*9c994d58SRobert Mustacchi return (-1);
88*9c994d58SRobert Mustacchi }
89*9c994d58SRobert Mustacchi len++;
90*9c994d58SRobert Mustacchi
91*9c994d58SRobert Mustacchi *str = topo_hdl_alloc(thp, len);
92*9c994d58SRobert Mustacchi if (*str == NULL) {
93*9c994d58SRobert Mustacchi return (-1);
94*9c994d58SRobert Mustacchi }
95*9c994d58SRobert Mustacchi
96*9c994d58SRobert Mustacchi /*
97*9c994d58SRobert Mustacchi * If an attempt to format a given string is inconsistent, then that
98*9c994d58SRobert Mustacchi * means something is extremely wrong and we're not going to try again
99*9c994d58SRobert Mustacchi * and leave that ultimately to the caller to deal with as it suggests
100*9c994d58SRobert Mustacchi * they were changing something about the arguments themselves. While
101*9c994d58SRobert Mustacchi * asprintf(3C) does loop on this, we are not as forgiving.
102*9c994d58SRobert Mustacchi */
103*9c994d58SRobert Mustacchi ret = vsnprintf(*str, len, fmt, ap);
104*9c994d58SRobert Mustacchi if (ret < 0 || ret + 1 != len) {
105*9c994d58SRobert Mustacchi topo_hdl_free(thp, *str, len + 1);
106*9c994d58SRobert Mustacchi *str = NULL;
107*9c994d58SRobert Mustacchi return (-1);
108*9c994d58SRobert Mustacchi }
109*9c994d58SRobert Mustacchi
110*9c994d58SRobert Mustacchi return (ret);
111*9c994d58SRobert Mustacchi }
112*9c994d58SRobert Mustacchi
113*9c994d58SRobert Mustacchi int
topo_hdl_asprintf(topo_hdl_t * thp,char ** str,const char * fmt,...)114*9c994d58SRobert Mustacchi topo_hdl_asprintf(topo_hdl_t *thp, char **str, const char *fmt, ...)
115*9c994d58SRobert Mustacchi {
116*9c994d58SRobert Mustacchi int ret;
117*9c994d58SRobert Mustacchi va_list ap;
118*9c994d58SRobert Mustacchi
119*9c994d58SRobert Mustacchi va_start(ap, fmt);
120*9c994d58SRobert Mustacchi ret = topo_hdl_vasprintf(thp, str, fmt, ap);
121*9c994d58SRobert Mustacchi va_end(ap);
122*9c994d58SRobert Mustacchi return (ret);
123*9c994d58SRobert Mustacchi }
124*9c994d58SRobert Mustacchi
125*9c994d58SRobert Mustacchi int
topo_mod_vasprintf(topo_mod_t * mod,char ** str,const char * fmt,va_list ap)126*9c994d58SRobert Mustacchi topo_mod_vasprintf(topo_mod_t *mod, char **str, const char *fmt, va_list ap)
127*9c994d58SRobert Mustacchi {
128*9c994d58SRobert Mustacchi return (topo_hdl_vasprintf(mod->tm_hdl, str, fmt, ap));
129*9c994d58SRobert Mustacchi }
130*9c994d58SRobert Mustacchi
131*9c994d58SRobert Mustacchi int
topo_mod_asprintf(topo_mod_t * mod,char ** str,const char * fmt,...)132*9c994d58SRobert Mustacchi topo_mod_asprintf(topo_mod_t *mod, char **str, const char *fmt, ...)
133*9c994d58SRobert Mustacchi {
134*9c994d58SRobert Mustacchi int ret;
135*9c994d58SRobert Mustacchi va_list ap;
136*9c994d58SRobert Mustacchi
137*9c994d58SRobert Mustacchi va_start(ap, fmt);
138*9c994d58SRobert Mustacchi ret = topo_hdl_vasprintf(mod->tm_hdl, str, fmt, ap);
139*9c994d58SRobert Mustacchi va_end(ap);
140*9c994d58SRobert Mustacchi return (ret);
141*9c994d58SRobert Mustacchi }
142*9c994d58SRobert Mustacchi
1437aec1d6eScindi void
topo_mod_strfree(topo_mod_t * mod,char * s)1447aec1d6eScindi topo_mod_strfree(topo_mod_t *mod, char *s)
1457aec1d6eScindi {
1467aec1d6eScindi topo_hdl_strfree(mod->tm_hdl, s);
1477aec1d6eScindi }
1487aec1d6eScindi
149e2336878SRob Johnston void
topo_mod_strfreev(topo_mod_t * mod,char ** strarr,uint_t nelem)150e2336878SRob Johnston topo_mod_strfreev(topo_mod_t *mod, char **strarr, uint_t nelem)
151e2336878SRob Johnston {
152e2336878SRob Johnston topo_hdl_strfreev(mod->tm_hdl, strarr, nelem);
153e2336878SRob Johnston }
154e2336878SRob Johnston
1557aec1d6eScindi const char *
topo_strbasename(const char * s)1567aec1d6eScindi topo_strbasename(const char *s)
1577aec1d6eScindi {
1587aec1d6eScindi const char *p = strrchr(s, '/');
1597aec1d6eScindi
1607aec1d6eScindi if (p == NULL)
1617aec1d6eScindi return (s);
1627aec1d6eScindi
1637aec1d6eScindi return (++p);
1647aec1d6eScindi }
1657aec1d6eScindi
1667aec1d6eScindi char *
topo_strdirname(char * s)1677aec1d6eScindi topo_strdirname(char *s)
1687aec1d6eScindi {
1697aec1d6eScindi static char slash[] = "/";
1707aec1d6eScindi static char dot[] = ".";
1717aec1d6eScindi char *p;
1727aec1d6eScindi
1737aec1d6eScindi if (s == NULL || *s == '\0')
1747aec1d6eScindi return (dot);
1757aec1d6eScindi
1767aec1d6eScindi for (p = s + strlen(s); p != s && *--p == '/'; )
1777aec1d6eScindi continue;
1787aec1d6eScindi
1797aec1d6eScindi if (p == s && *p == '/')
1807aec1d6eScindi return (slash);
1817aec1d6eScindi
1827aec1d6eScindi while (p != s) {
1837aec1d6eScindi if (*--p == '/') {
1847aec1d6eScindi while (*p == '/' && p != s)
1857aec1d6eScindi p--;
1867aec1d6eScindi *++p = '\0';
1877aec1d6eScindi return (s);
1887aec1d6eScindi }
1897aec1d6eScindi }
1907aec1d6eScindi
1917aec1d6eScindi return (dot);
1927aec1d6eScindi }
1937aec1d6eScindi
1947aec1d6eScindi ulong_t
topo_strhash(const char * key)1957aec1d6eScindi topo_strhash(const char *key)
1967aec1d6eScindi {
1977aec1d6eScindi ulong_t g, h = 0;
1987aec1d6eScindi const char *p;
1997aec1d6eScindi
2007aec1d6eScindi for (p = key; *p != '\0'; p++) {
2017aec1d6eScindi h = (h << 4) + *p;
2027aec1d6eScindi
2037aec1d6eScindi if ((g = (h & 0xf0000000)) != 0) {
2047aec1d6eScindi h ^= (g >> 24);
2057aec1d6eScindi h ^= g;
2067aec1d6eScindi }
2077aec1d6eScindi }
2087aec1d6eScindi
2097aec1d6eScindi return (h);
2107aec1d6eScindi }
2117aec1d6eScindi
2127aec1d6eScindi /*
2137aec1d6eScindi * Transform string s inline, converting each embedded C escape sequence string
2147aec1d6eScindi * to the corresponding character. For example, the substring "\n" is replaced
2157aec1d6eScindi * by an inline '\n' character. The length of the resulting string is returned.
2167aec1d6eScindi */
2177aec1d6eScindi size_t
topo_stresc2chr(char * s)2187aec1d6eScindi topo_stresc2chr(char *s)
2197aec1d6eScindi {
2207aec1d6eScindi char *p, *q, c;
2217aec1d6eScindi int esc = 0;
2227aec1d6eScindi int x;
2237aec1d6eScindi
2247aec1d6eScindi for (p = q = s; (c = *p) != '\0'; p++) {
2257aec1d6eScindi if (esc) {
2267aec1d6eScindi switch (c) {
2277aec1d6eScindi case '0':
2287aec1d6eScindi case '1':
2297aec1d6eScindi case '2':
2307aec1d6eScindi case '3':
2317aec1d6eScindi case '4':
2327aec1d6eScindi case '5':
2337aec1d6eScindi case '6':
2347aec1d6eScindi case '7':
2357aec1d6eScindi c -= '0';
2367aec1d6eScindi p++;
2377aec1d6eScindi
2387aec1d6eScindi if (*p >= '0' && *p <= '7') {
2397aec1d6eScindi c = c * 8 + *p++ - '0';
2407aec1d6eScindi
2417aec1d6eScindi if (*p >= '0' && *p <= '7')
2427aec1d6eScindi c = c * 8 + *p - '0';
2437aec1d6eScindi else
2447aec1d6eScindi p--;
2457aec1d6eScindi } else
2467aec1d6eScindi p--;
2477aec1d6eScindi
2487aec1d6eScindi *q++ = c;
2497aec1d6eScindi break;
2507aec1d6eScindi
2517aec1d6eScindi case 'a':
2527aec1d6eScindi *q++ = '\a';
2537aec1d6eScindi break;
2547aec1d6eScindi case 'b':
2557aec1d6eScindi *q++ = '\b';
2567aec1d6eScindi break;
2577aec1d6eScindi case 'f':
2587aec1d6eScindi *q++ = '\f';
2597aec1d6eScindi break;
2607aec1d6eScindi case 'n':
2617aec1d6eScindi *q++ = '\n';
2627aec1d6eScindi break;
2637aec1d6eScindi case 'r':
2647aec1d6eScindi *q++ = '\r';
2657aec1d6eScindi break;
2667aec1d6eScindi case 't':
2677aec1d6eScindi *q++ = '\t';
2687aec1d6eScindi break;
2697aec1d6eScindi case 'v':
2707aec1d6eScindi *q++ = '\v';
2717aec1d6eScindi break;
2727aec1d6eScindi
2737aec1d6eScindi case 'x':
2747aec1d6eScindi for (x = 0; (c = *++p) != '\0'; ) {
2757aec1d6eScindi if (c >= '0' && c <= '9')
2767aec1d6eScindi x = x * 16 + c - '0';
2777aec1d6eScindi else if (c >= 'a' && c <= 'f')
2787aec1d6eScindi x = x * 16 + c - 'a' + 10;
2797aec1d6eScindi else if (c >= 'A' && c <= 'F')
2807aec1d6eScindi x = x * 16 + c - 'A' + 10;
2817aec1d6eScindi else
2827aec1d6eScindi break;
2837aec1d6eScindi }
2847aec1d6eScindi *q++ = (char)x;
2857aec1d6eScindi p--;
2867aec1d6eScindi break;
2877aec1d6eScindi
2887aec1d6eScindi case '"':
2897aec1d6eScindi case '\\':
2907aec1d6eScindi *q++ = c;
2917aec1d6eScindi break;
2927aec1d6eScindi default:
2937aec1d6eScindi *q++ = '\\';
2947aec1d6eScindi *q++ = c;
2957aec1d6eScindi }
2967aec1d6eScindi
2977aec1d6eScindi esc = 0;
2987aec1d6eScindi
2997aec1d6eScindi } else {
3007aec1d6eScindi if ((esc = c == '\\') == 0)
3017aec1d6eScindi *q++ = c;
3027aec1d6eScindi }
3037aec1d6eScindi }
3047aec1d6eScindi
3057aec1d6eScindi *q = '\0';
3067aec1d6eScindi return ((size_t)(q - s));
3077aec1d6eScindi }
3087aec1d6eScindi
3097aec1d6eScindi int
topo_strmatch(const char * s,const char * p)3107aec1d6eScindi topo_strmatch(const char *s, const char *p)
3117aec1d6eScindi {
3127aec1d6eScindi char c;
3137aec1d6eScindi
3147aec1d6eScindi if (p == NULL)
3157aec1d6eScindi return (0);
3167aec1d6eScindi
3177aec1d6eScindi if (s == NULL)
3187aec1d6eScindi s = ""; /* treat NULL string as the empty string */
3197aec1d6eScindi
3207aec1d6eScindi do {
3217aec1d6eScindi if ((c = *p++) == '\0')
3227aec1d6eScindi return (*s == '\0');
3237aec1d6eScindi
3247aec1d6eScindi if (c == '*') {
3257aec1d6eScindi while (*p == '*')
3267aec1d6eScindi p++; /* consecutive *'s can be collapsed */
3277aec1d6eScindi
3287aec1d6eScindi if (*p == '\0')
3297aec1d6eScindi return (1);
3307aec1d6eScindi
3317aec1d6eScindi while (*s != '\0') {
3327aec1d6eScindi if (topo_strmatch(s++, p) != 0)
3337aec1d6eScindi return (1);
3347aec1d6eScindi }
3357aec1d6eScindi
3367aec1d6eScindi return (0);
3377aec1d6eScindi }
3387aec1d6eScindi } while (c == *s++);
3397aec1d6eScindi
3407aec1d6eScindi return (0);
3417aec1d6eScindi }
342