17aec1d6eScindi /* 27aec1d6eScindi * CDDL HEADER START 37aec1d6eScindi * 47aec1d6eScindi * The contents of this file are subject to the terms of the 574a31ce6Stimh * Common Development and Distribution License (the "License"). 674a31ce6Stimh * You may not use this file except in compliance with the License. 77aec1d6eScindi * 87aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97aec1d6eScindi * or http://www.opensolaris.org/os/licensing. 107aec1d6eScindi * See the License for the specific language governing permissions 117aec1d6eScindi * and limitations under the License. 127aec1d6eScindi * 137aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each 147aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the 167aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying 177aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner] 187aec1d6eScindi * 197aec1d6eScindi * CDDL HEADER END 207aec1d6eScindi */ 217aec1d6eScindi 227aec1d6eScindi /* 237aec1d6eScindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247aec1d6eScindi * Use is subject to license terms. 257aec1d6eScindi */ 267aec1d6eScindi 277aec1d6eScindi #pragma ident "%Z%%M% %I% %E% SMI" 287aec1d6eScindi 297aec1d6eScindi #include <alloca.h> 30*0eb822a1Scindi #include <ctype.h> 31*0eb822a1Scindi #include <limits.h> 327aec1d6eScindi #include <syslog.h> 337aec1d6eScindi #include <strings.h> 34*0eb822a1Scindi #include <unistd.h> 357aec1d6eScindi 367aec1d6eScindi #include <topo_error.h> 377aec1d6eScindi #include <topo_subr.h> 387aec1d6eScindi 397aec1d6eScindi struct _rwlock; 407aec1d6eScindi struct _lwp_mutex; 417aec1d6eScindi 427aec1d6eScindi int 437aec1d6eScindi topo_rw_read_held(pthread_rwlock_t *lock) 447aec1d6eScindi { 457aec1d6eScindi extern int _rw_read_held(struct _rwlock *); 467aec1d6eScindi return (_rw_read_held((struct _rwlock *)lock)); 477aec1d6eScindi } 487aec1d6eScindi 497aec1d6eScindi int 507aec1d6eScindi topo_rw_write_held(pthread_rwlock_t *lock) 517aec1d6eScindi { 527aec1d6eScindi extern int _rw_write_held(struct _rwlock *); 537aec1d6eScindi return (_rw_write_held((struct _rwlock *)lock)); 547aec1d6eScindi } 557aec1d6eScindi 567aec1d6eScindi int 577aec1d6eScindi topo_mutex_held(pthread_mutex_t *lock) 587aec1d6eScindi { 597aec1d6eScindi extern int _mutex_held(struct _lwp_mutex *); 607aec1d6eScindi return (_mutex_held((struct _lwp_mutex *)lock)); 617aec1d6eScindi } 627aec1d6eScindi 637aec1d6eScindi void 647aec1d6eScindi topo_hdl_lock(topo_hdl_t *thp) 657aec1d6eScindi { 667aec1d6eScindi (void) pthread_mutex_lock(&thp->th_lock); 677aec1d6eScindi } 687aec1d6eScindi 697aec1d6eScindi void 707aec1d6eScindi topo_hdl_unlock(topo_hdl_t *thp) 717aec1d6eScindi { 727aec1d6eScindi (void) pthread_mutex_unlock(&thp->th_lock); 737aec1d6eScindi } 747aec1d6eScindi 757aec1d6eScindi const char * 76*0eb822a1Scindi topo_stability2name(topo_stability_t s) 777aec1d6eScindi { 787aec1d6eScindi switch (s) { 79*0eb822a1Scindi case TOPO_STABILITY_INTERNAL: return (TOPO_STABSTR_INTERNAL); 80*0eb822a1Scindi case TOPO_STABILITY_PRIVATE: return (TOPO_STABSTR_PRIVATE); 81*0eb822a1Scindi case TOPO_STABILITY_OBSOLETE: return (TOPO_STABSTR_OBSOLETE); 82*0eb822a1Scindi case TOPO_STABILITY_EXTERNAL: return (TOPO_STABSTR_EXTERNAL); 83*0eb822a1Scindi case TOPO_STABILITY_UNSTABLE: return (TOPO_STABSTR_UNSTABLE); 84*0eb822a1Scindi case TOPO_STABILITY_EVOLVING: return (TOPO_STABSTR_EVOLVING); 85*0eb822a1Scindi case TOPO_STABILITY_STABLE: return (TOPO_STABSTR_STABLE); 86*0eb822a1Scindi case TOPO_STABILITY_STANDARD: return (TOPO_STABSTR_STANDARD); 87*0eb822a1Scindi default: return (TOPO_STABSTR_UNKNOWN); 887aec1d6eScindi } 897aec1d6eScindi } 907aec1d6eScindi 91*0eb822a1Scindi topo_stability_t 92*0eb822a1Scindi topo_name2stability(const char *name) 93*0eb822a1Scindi { 94*0eb822a1Scindi if (strcmp(name, TOPO_STABSTR_INTERNAL) == 0) 95*0eb822a1Scindi return (TOPO_STABILITY_INTERNAL); 96*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_PRIVATE) == 0) 97*0eb822a1Scindi return (TOPO_STABILITY_PRIVATE); 98*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_OBSOLETE) == 0) 99*0eb822a1Scindi return (TOPO_STABILITY_OBSOLETE); 100*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_EXTERNAL) == 0) 101*0eb822a1Scindi return (TOPO_STABILITY_EXTERNAL); 102*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_UNSTABLE) == 0) 103*0eb822a1Scindi return (TOPO_STABILITY_UNSTABLE); 104*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_EVOLVING) == 0) 105*0eb822a1Scindi return (TOPO_STABILITY_EVOLVING); 106*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_STABLE) == 0) 107*0eb822a1Scindi return (TOPO_STABILITY_STABLE); 108*0eb822a1Scindi else if (strcmp(name, TOPO_STABSTR_STANDARD) == 0) 109*0eb822a1Scindi return (TOPO_STABILITY_STANDARD); 110*0eb822a1Scindi 111*0eb822a1Scindi return (TOPO_STABILITY_UNKNOWN); 112*0eb822a1Scindi } 113*0eb822a1Scindi 1147aec1d6eScindi static const topo_debug_mode_t _topo_dbout_modes[] = { 1157aec1d6eScindi { "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR }, 1167aec1d6eScindi { "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG }, 1177aec1d6eScindi { NULL, NULL, 0 } 1187aec1d6eScindi }; 1197aec1d6eScindi 120*0eb822a1Scindi static const topo_debug_mode_t _topo_dbflag_modes[] = { 121*0eb822a1Scindi { "error", "error handling debug messages enabled", TOPO_DBG_ERR }, 122*0eb822a1Scindi { "module", "module debug messages enabled", TOPO_DBG_MOD }, 123*0eb822a1Scindi { "modulesvc", "module services debug messages enabled", 124*0eb822a1Scindi TOPO_DBG_MODSVC }, 125*0eb822a1Scindi { "walk", "walker subsystem debug messages enabled", TOPO_DBG_WALK }, 126*0eb822a1Scindi { "xml", "xml file parsing messages enabled", TOPO_DBG_XML }, 127*0eb822a1Scindi { "all", "all debug modes enabled", TOPO_DBG_ALL}, 128*0eb822a1Scindi { NULL, NULL, 0 } 129*0eb822a1Scindi }; 130*0eb822a1Scindi 1317aec1d6eScindi void 132*0eb822a1Scindi env_process_value(topo_hdl_t *thp, const char *begin, const char *end) 1337aec1d6eScindi { 134*0eb822a1Scindi char buf[MAXNAMELEN]; 135*0eb822a1Scindi size_t count; 136*0eb822a1Scindi topo_debug_mode_t *dbp; 137*0eb822a1Scindi 138*0eb822a1Scindi while (begin < end && isspace(*begin)) 139*0eb822a1Scindi begin++; 140*0eb822a1Scindi 141*0eb822a1Scindi while (begin < end && isspace(*(end - 1))) 142*0eb822a1Scindi end--; 143*0eb822a1Scindi 144*0eb822a1Scindi if (begin >= end) 145*0eb822a1Scindi return; 146*0eb822a1Scindi 147*0eb822a1Scindi count = end - begin; 148*0eb822a1Scindi count += 1; 149*0eb822a1Scindi 150*0eb822a1Scindi if (count > sizeof (buf)) 151*0eb822a1Scindi return; 152*0eb822a1Scindi 153*0eb822a1Scindi (void) snprintf(buf, count, "%s", begin); 154*0eb822a1Scindi 155*0eb822a1Scindi for (dbp = (topo_debug_mode_t *)_topo_dbflag_modes; 156*0eb822a1Scindi dbp->tdm_name != NULL; ++dbp) { 157*0eb822a1Scindi if (strcmp(buf, dbp->tdm_name) == 0) 158*0eb822a1Scindi thp->th_debug |= dbp->tdm_mode; 159*0eb822a1Scindi } 160*0eb822a1Scindi } 161*0eb822a1Scindi 162*0eb822a1Scindi void 163*0eb822a1Scindi topo_debug_set(topo_hdl_t *thp, const char *dbmode, const char *dout) 164*0eb822a1Scindi { 165*0eb822a1Scindi char *end, *value, *next; 166*0eb822a1Scindi topo_debug_mode_t *dbp; 167*0eb822a1Scindi 168*0eb822a1Scindi topo_hdl_lock(thp); 169*0eb822a1Scindi value = (char *)dbmode; 170*0eb822a1Scindi 171*0eb822a1Scindi for (end = (char *)dbmode; *end != '\0'; value = next) { 172*0eb822a1Scindi end = strchr(value, ','); 173*0eb822a1Scindi if (end != NULL) 174*0eb822a1Scindi next = end + 1; /* skip the comma */ 175*0eb822a1Scindi else 176*0eb822a1Scindi next = end = value + strlen(value); 177*0eb822a1Scindi 178*0eb822a1Scindi env_process_value(thp, value, end); 179*0eb822a1Scindi } 180*0eb822a1Scindi 181*0eb822a1Scindi if (dout == NULL) { 182*0eb822a1Scindi topo_hdl_unlock(thp); 183*0eb822a1Scindi return; 1847aec1d6eScindi } 185*0eb822a1Scindi 186*0eb822a1Scindi for (dbp = (topo_debug_mode_t *)_topo_dbout_modes; 187*0eb822a1Scindi dbp->tdm_name != NULL; ++dbp) { 188*0eb822a1Scindi if (strcmp(dout, dbp->tdm_name) == 0) 189*0eb822a1Scindi thp->th_dbout = dbp->tdm_mode; 190*0eb822a1Scindi } 191*0eb822a1Scindi topo_hdl_unlock(thp); 1927aec1d6eScindi } 1937aec1d6eScindi 1947aec1d6eScindi void 195*0eb822a1Scindi topo_vdprintf(topo_hdl_t *thp, int mask, const char *mod, const char *format, 196*0eb822a1Scindi va_list ap) 1977aec1d6eScindi { 1987aec1d6eScindi char *msg; 1997aec1d6eScindi size_t len; 2007aec1d6eScindi char c; 2017aec1d6eScindi 202*0eb822a1Scindi if (!(thp->th_debug & mask)) 2037aec1d6eScindi return; 2047aec1d6eScindi 2057aec1d6eScindi len = vsnprintf(&c, 1, format, ap); 2067aec1d6eScindi msg = alloca(len + 2); 2077aec1d6eScindi (void) vsnprintf(msg, len + 1, format, ap); 2087aec1d6eScindi 2097aec1d6eScindi if (msg[len - 1] != '\n') 2107aec1d6eScindi (void) strcpy(&msg[len], "\n"); 2117aec1d6eScindi 212*0eb822a1Scindi if (thp->th_dbout == TOPO_DBOUT_SYSLOG) { 213*0eb822a1Scindi if (mod == NULL) { 214*0eb822a1Scindi syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg); 215*0eb822a1Scindi } else { 216*0eb822a1Scindi syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s: %s", 217*0eb822a1Scindi mod, msg); 218*0eb822a1Scindi } 219*0eb822a1Scindi } else { 220*0eb822a1Scindi if (mod == NULL) { 221*0eb822a1Scindi (void) fprintf(stderr, "libtopo DEBUG: %s", msg); 222*0eb822a1Scindi } else { 223*0eb822a1Scindi (void) fprintf(stderr, "libtopo DEBUG: %s: %s", mod, 224*0eb822a1Scindi msg); 225*0eb822a1Scindi } 226*0eb822a1Scindi } 2277aec1d6eScindi } 2287aec1d6eScindi 229*0eb822a1Scindi /*PRINTFLIKE3*/ 2307aec1d6eScindi void 231*0eb822a1Scindi topo_dprintf(topo_hdl_t *thp, int mask, const char *format, ...) 2327aec1d6eScindi { 2337aec1d6eScindi va_list ap; 2347aec1d6eScindi 2357aec1d6eScindi va_start(ap, format); 236*0eb822a1Scindi topo_vdprintf(thp, mask, NULL, format, ap); 2377aec1d6eScindi va_end(ap); 2387aec1d6eScindi } 2397aec1d6eScindi 2407aec1d6eScindi tnode_t * 2417aec1d6eScindi topo_hdl_root(topo_hdl_t *thp, const char *scheme) 2427aec1d6eScindi { 2437aec1d6eScindi ttree_t *tp; 2447aec1d6eScindi 2457aec1d6eScindi for (tp = topo_list_next(&thp->th_trees); tp != NULL; 2467aec1d6eScindi tp = topo_list_next(tp)) { 2477aec1d6eScindi if (strcmp(scheme, tp->tt_scheme) == 0) 2487aec1d6eScindi return (tp->tt_root); 2497aec1d6eScindi } 2507aec1d6eScindi 2517aec1d6eScindi return (NULL); 2527aec1d6eScindi } 25374a31ce6Stimh 25474a31ce6Stimh /* 25574a31ce6Stimh * buf_append -- Append str to buf (if it's non-NULL). Place prepend 25674a31ce6Stimh * in buf in front of str and append behind it (if they're non-NULL). 25774a31ce6Stimh * Continue to update size even if we run out of space to actually 25874a31ce6Stimh * stuff characters in the buffer. 25974a31ce6Stimh */ 26074a31ce6Stimh void 26174a31ce6Stimh topo_fmristr_build(ssize_t *sz, char *buf, size_t buflen, char *str, 26274a31ce6Stimh char *prepend, char *append) 26374a31ce6Stimh { 26474a31ce6Stimh ssize_t left; 26574a31ce6Stimh 26674a31ce6Stimh if (str == NULL) 26774a31ce6Stimh return; 26874a31ce6Stimh 26974a31ce6Stimh if (buflen == 0 || (left = buflen - *sz) < 0) 27074a31ce6Stimh left = 0; 27174a31ce6Stimh 27274a31ce6Stimh if (buf != NULL && left != 0) 27374a31ce6Stimh buf += *sz; 27474a31ce6Stimh 27574a31ce6Stimh if (prepend == NULL && append == NULL) 27674a31ce6Stimh *sz += snprintf(buf, left, "%s", str); 27774a31ce6Stimh else if (append == NULL) 27874a31ce6Stimh *sz += snprintf(buf, left, "%s%s", prepend, str); 27974a31ce6Stimh else if (prepend == NULL) 28074a31ce6Stimh *sz += snprintf(buf, left, "%s%s", str, append); 28174a31ce6Stimh else 28274a31ce6Stimh *sz += snprintf(buf, left, "%s%s%s", prepend, str, append); 28374a31ce6Stimh } 284*0eb822a1Scindi 285*0eb822a1Scindi #define TOPO_PLATFORM_PATH "%s/usr/platform/%s/lib/fm/topo/%s" 286*0eb822a1Scindi #define TOPO_COMMON_PATH "%s/usr/lib/fm/topo/%s" 287*0eb822a1Scindi 288*0eb822a1Scindi char * 289*0eb822a1Scindi topo_search_path(topo_mod_t *mod, const char *rootdir, const char *file) 290*0eb822a1Scindi { 291*0eb822a1Scindi char *pp, sp[PATH_MAX]; 292*0eb822a1Scindi topo_hdl_t *thp = mod->tm_hdl; 293*0eb822a1Scindi 294*0eb822a1Scindi /* 295*0eb822a1Scindi * Search for file name in order of platform, machine and common 296*0eb822a1Scindi * topo directories 297*0eb822a1Scindi */ 298*0eb822a1Scindi (void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH, rootdir, 299*0eb822a1Scindi thp->th_platform, file); 300*0eb822a1Scindi if (access(sp, F_OK) != 0) { 301*0eb822a1Scindi (void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH, 302*0eb822a1Scindi thp->th_rootdir, thp->th_machine, file); 303*0eb822a1Scindi if (access(sp, F_OK) != 0) { 304*0eb822a1Scindi (void) snprintf(sp, PATH_MAX, TOPO_COMMON_PATH, 305*0eb822a1Scindi thp->th_rootdir, file); 306*0eb822a1Scindi if (access(sp, F_OK) != 0) { 307*0eb822a1Scindi return (NULL); 308*0eb822a1Scindi } 309*0eb822a1Scindi } 310*0eb822a1Scindi } 311*0eb822a1Scindi 312*0eb822a1Scindi pp = topo_mod_strdup(mod, sp); 313*0eb822a1Scindi 314*0eb822a1Scindi return (pp); 315*0eb822a1Scindi } 316