xref: /titanic_52/usr/src/cmd/fm/fmd/common/fmd_fmri.c (revision 06e46062ef4f5f4b687cbafb4518fb123fe23920)
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 2004 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 <ctype.h>
30 #include <errno.h>
31 #include <stdarg.h>
32 
33 #include <fmd_alloc.h>
34 #include <fmd_subr.h>
35 #include <fmd_error.h>
36 #include <fmd_string.h>
37 #include <fmd_scheme.h>
38 #include <fmd_fmri.h>
39 #include <fmd.h>
40 
41 /*
42  * Interfaces to be used by the plugins
43  */
44 
45 void *
46 fmd_fmri_alloc(size_t size)
47 {
48 	return (fmd_alloc(size, FMD_SLEEP));
49 }
50 
51 void *
52 fmd_fmri_zalloc(size_t size)
53 {
54 	return (fmd_zalloc(size, FMD_SLEEP));
55 }
56 
57 void
58 fmd_fmri_free(void *data, size_t size)
59 {
60 	fmd_free(data, size);
61 }
62 
63 int
64 fmd_fmri_set_errno(int err)
65 {
66 	errno = err;
67 	return (-1);
68 }
69 
70 void
71 fmd_fmri_warn(const char *format, ...)
72 {
73 	va_list ap;
74 
75 	va_start(ap, format);
76 	fmd_verror(EFMD_FMRI_SCHEME, format, ap);
77 	va_end(ap);
78 }
79 
80 /*
81  * Convert an input string to a URI escaped string and return the new string.
82  * RFC2396 Section 2.4 says that data must be escaped if it does not have a
83  * representation using an unreserved character, where an unreserved character
84  * is one that is either alphanumberic or one of the marks defined in S2.3.
85  * We've amended the unreserved character list to include commas and colons,
86  * as both are needed to make FMRIs readable without escaping.  We also permit
87  * "/" to pass through unescaped as any path delimiters used by the event
88  * creator are presumably intended to appear in the final path.
89  */
90 char *
91 fmd_fmri_strescape(const char *s)
92 {
93 	static const char rfc2396_mark[] = "-_.!~*'()" ":,";
94 	static const char hex_digits[] = "0123456789ABCDEF";
95 
96 	const char *p;
97 	char c, *q, *s2;
98 	size_t n = 0;
99 
100 	if (s == NULL)
101 		return (NULL);
102 
103 	for (p = s; (c = *p) != '\0'; p++) {
104 		if (isalnum(c) || c == '/' || strchr(rfc2396_mark, c) != NULL)
105 			n++;	/* represent c as itself */
106 		else
107 			n += 3; /* represent c as escape */
108 	}
109 
110 	s2 = fmd_alloc(n + 1, FMD_SLEEP);
111 
112 	for (p = s, q = s2; (c = *p) != '\0'; p++) {
113 		if (isalnum(c) || c == '/' || strchr(rfc2396_mark, c) != NULL) {
114 			*q++ = c;
115 		} else {
116 			*q++ = '%';
117 			*q++ = hex_digits[((uchar_t)c & 0xf0) >> 4];
118 			*q++ = hex_digits[(uchar_t)c & 0xf];
119 		}
120 	}
121 
122 	ASSERT(q == s2 + n);
123 	*q = '\0';
124 	return (s2);
125 }
126 
127 char *
128 fmd_fmri_strdup(const char *s)
129 {
130 	return (fmd_strdup(s, FMD_SLEEP));
131 }
132 
133 void
134 fmd_fmri_strfree(char *s)
135 {
136 	fmd_strfree(s);
137 }
138 
139 const char *
140 fmd_fmri_get_rootdir(void)
141 {
142 	return (fmd.d_rootdir);
143 }
144 
145 const char *
146 fmd_fmri_get_platform(void)
147 {
148 	return (fmd.d_platform);
149 }
150 
151 uint64_t
152 fmd_fmri_get_drgen(void)
153 {
154 	uint64_t gen;
155 
156 	(void) pthread_mutex_lock(&fmd.d_stats_lock);
157 	gen = fmd.d_stats->ds_dr_gen.fmds_value.ui64;
158 	(void) pthread_mutex_unlock(&fmd.d_stats_lock);
159 
160 	return (gen);
161 }
162 
163 /*
164  * Interfaces for users of the plugins
165  */
166 
167 static fmd_scheme_t *
168 nvl2scheme(nvlist_t *nvl)
169 {
170 	char *name;
171 
172 	if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
173 		(void) fmd_set_errno(EFMD_FMRI_INVAL);
174 		return (NULL);
175 	}
176 
177 	return (fmd_scheme_hash_lookup(fmd.d_schemes, name));
178 }
179 
180 ssize_t
181 fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
182 {
183 	fmd_scheme_t *sp;
184 	char c;
185 	ssize_t rv;
186 
187 	if (buf == NULL && buflen == 0) {
188 		buf = &c;
189 		buflen = sizeof (c);
190 	}
191 
192 	if ((sp = nvl2scheme(nvl)) == NULL)
193 		return (-1); /* errno is set for us */
194 
195 	(void) pthread_mutex_lock(&sp->sch_opslock);
196 	ASSERT(buf != NULL || buflen == 0);
197 	rv = sp->sch_ops.sop_nvl2str(nvl, buf, buflen);
198 	(void) pthread_mutex_unlock(&sp->sch_opslock);
199 
200 	fmd_scheme_hash_release(fmd.d_schemes, sp);
201 	return (rv);
202 }
203 
204 int
205 fmd_fmri_expand(nvlist_t *nvl)
206 {
207 	fmd_scheme_t *sp;
208 	int rv;
209 
210 	if ((sp = nvl2scheme(nvl)) == NULL)
211 		return (-1); /* errno is set for us */
212 
213 	(void) pthread_mutex_lock(&sp->sch_opslock);
214 	rv = sp->sch_ops.sop_expand(nvl);
215 	(void) pthread_mutex_unlock(&sp->sch_opslock);
216 
217 	fmd_scheme_hash_release(fmd.d_schemes, sp);
218 	return (rv);
219 }
220 
221 int
222 fmd_fmri_present(nvlist_t *nvl)
223 {
224 	fmd_scheme_t *sp;
225 	int rv;
226 
227 	if ((sp = nvl2scheme(nvl)) == NULL)
228 		return (-1); /* errno is set for us */
229 
230 	(void) pthread_mutex_lock(&sp->sch_opslock);
231 	rv = sp->sch_ops.sop_present(nvl);
232 	(void) pthread_mutex_unlock(&sp->sch_opslock);
233 
234 	fmd_scheme_hash_release(fmd.d_schemes, sp);
235 	return (rv);
236 }
237 
238 int
239 fmd_fmri_unusable(nvlist_t *nvl)
240 {
241 	fmd_scheme_t *sp;
242 	int rv;
243 
244 	if ((sp = nvl2scheme(nvl)) == NULL)
245 		return (-1); /* errno is set for us */
246 
247 	(void) pthread_mutex_lock(&sp->sch_opslock);
248 	rv = sp->sch_ops.sop_unusable(nvl);
249 	(void) pthread_mutex_unlock(&sp->sch_opslock);
250 
251 	fmd_scheme_hash_release(fmd.d_schemes, sp);
252 	return (rv);
253 }
254 
255 int
256 fmd_fmri_contains(nvlist_t *er, nvlist_t *ee)
257 {
258 	fmd_scheme_t *sp;
259 	char *ername, *eename;
260 	int rv;
261 
262 	if (nvlist_lookup_string(er, FM_FMRI_SCHEME, &ername) != 0 ||
263 	    nvlist_lookup_string(ee, FM_FMRI_SCHEME, &eename) != 0 ||
264 	    strcmp(ername, eename) != 0)
265 		return (fmd_set_errno(EFMD_FMRI_INVAL));
266 
267 	if ((sp = fmd_scheme_hash_lookup(fmd.d_schemes, ername)) == NULL)
268 		return (-1); /* errno is set for us */
269 
270 	(void) pthread_mutex_lock(&sp->sch_opslock);
271 	rv = sp->sch_ops.sop_contains(er, ee);
272 	(void) pthread_mutex_unlock(&sp->sch_opslock);
273 
274 	fmd_scheme_hash_release(fmd.d_schemes, sp);
275 	return (rv);
276 }
277