xref: /illumos-gate/usr/src/lib/fm/topo/libtopo/common/topo_subr.c (revision 80ab886d233f514d54c2a6bdeb9fdfd951bd6881)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <alloca.h>
30 #include <syslog.h>
31 #include <strings.h>
32 
33 #include <topo_error.h>
34 #include <topo_subr.h>
35 
36 struct _rwlock;
37 struct _lwp_mutex;
38 
39 int _topo_debug = 0;	/* debug messages enabled (off) */
40 int _topo_dbout = 0;	/* debug messages output mode */
41 
42 int
43 topo_rw_read_held(pthread_rwlock_t *lock)
44 {
45 	extern int _rw_read_held(struct _rwlock *);
46 	return (_rw_read_held((struct _rwlock *)lock));
47 }
48 
49 int
50 topo_rw_write_held(pthread_rwlock_t *lock)
51 {
52 	extern int _rw_write_held(struct _rwlock *);
53 	return (_rw_write_held((struct _rwlock *)lock));
54 }
55 
56 int
57 topo_mutex_held(pthread_mutex_t *lock)
58 {
59 	extern int _mutex_held(struct _lwp_mutex *);
60 	return (_mutex_held((struct _lwp_mutex *)lock));
61 }
62 
63 void
64 topo_hdl_lock(topo_hdl_t *thp)
65 {
66 	(void) pthread_mutex_lock(&thp->th_lock);
67 }
68 
69 void
70 topo_hdl_unlock(topo_hdl_t *thp)
71 {
72 	(void) pthread_mutex_unlock(&thp->th_lock);
73 }
74 
75 const char *
76 topo_stability_name(topo_stability_t s)
77 {
78 	switch (s) {
79 	case TOPO_STABILITY_INTERNAL:	return ("Internal");
80 	case TOPO_STABILITY_PRIVATE:	return ("Private");
81 	case TOPO_STABILITY_OBSOLETE:	return ("Obsolete");
82 	case TOPO_STABILITY_EXTERNAL:	return ("External");
83 	case TOPO_STABILITY_UNSTABLE:	return ("Unstable");
84 	case TOPO_STABILITY_EVOLVING:	return ("Evolving");
85 	case TOPO_STABILITY_STABLE:	return ("Stable");
86 	case TOPO_STABILITY_STANDARD:	return ("Standard");
87 	default:			return (NULL);
88 	}
89 }
90 
91 static const topo_debug_mode_t _topo_dbout_modes[] = {
92 	{ "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR },
93 	{ "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG },
94 	{ NULL, NULL, 0 }
95 };
96 
97 void
98 topo_debug_set(topo_hdl_t *thp, int mask, char *dout)
99 {
100 	int i;
101 
102 	for (i = 0; i < 2; ++i) {
103 		if (strcmp(_topo_dbout_modes[i].tdm_name, dout) == 0) {
104 			thp->th_dbout = _topo_dbout =
105 			    _topo_dbout_modes[i].tdm_mode;
106 			thp->th_debug = _topo_debug = mask;
107 			topo_dprintf(mask, _topo_dbout_modes[i].tdm_desc);
108 		}
109 	}
110 }
111 
112 void
113 topo_vdprintf(int mask, const char *format, va_list ap)
114 {
115 	char *msg;
116 	size_t len;
117 	char c;
118 
119 	if (!(_topo_debug & mask))
120 		return;
121 
122 	len = vsnprintf(&c, 1, format, ap);
123 	msg = alloca(len + 2);
124 	(void) vsnprintf(msg, len + 1, format, ap);
125 
126 	if (msg[len - 1] != '\n')
127 		(void) strcpy(&msg[len], "\n");
128 
129 	if (_topo_dbout == TOPO_DBOUT_STDERR)
130 		(void) fprintf(stderr, "libtopo DEBUG: %s", msg);
131 
132 	if (_topo_dbout == TOPO_DBOUT_SYSLOG)
133 		syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg);
134 }
135 
136 /*PRINTFLIKE2*/
137 void
138 topo_dprintf(int mask, const char *format, ...)
139 {
140 	va_list ap;
141 
142 	if (!(_topo_debug & mask))
143 		return;
144 
145 	va_start(ap, format);
146 	topo_vdprintf(mask, format, ap);
147 	va_end(ap);
148 }
149 
150 tnode_t *
151 topo_hdl_root(topo_hdl_t *thp, const char *scheme)
152 {
153 	ttree_t *tp;
154 
155 	for (tp = topo_list_next(&thp->th_trees); tp != NULL;
156 	    tp = topo_list_next(tp)) {
157 		if (strcmp(scheme, tp->tt_scheme) == 0)
158 			return (tp->tt_root);
159 	}
160 
161 	return (NULL);
162 }
163 
164 /*
165  * buf_append -- Append str to buf (if it's non-NULL).  Place prepend
166  * in buf in front of str and append behind it (if they're non-NULL).
167  * Continue to update size even if we run out of space to actually
168  * stuff characters in the buffer.
169  */
170 void
171 topo_fmristr_build(ssize_t *sz, char *buf, size_t buflen, char *str,
172     char *prepend, char *append)
173 {
174 	ssize_t left;
175 
176 	if (str == NULL)
177 		return;
178 
179 	if (buflen == 0 || (left = buflen - *sz) < 0)
180 		left = 0;
181 
182 	if (buf != NULL && left != 0)
183 		buf += *sz;
184 
185 	if (prepend == NULL && append == NULL)
186 		*sz += snprintf(buf, left, "%s", str);
187 	else if (append == NULL)
188 		*sz += snprintf(buf, left, "%s%s", prepend, str);
189 	else if (prepend == NULL)
190 		*sz += snprintf(buf, left, "%s%s", str, append);
191 	else
192 		*sz += snprintf(buf, left, "%s%s%s", prepend, str, append);
193 }
194