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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
31 #include <fmd_alloc.h>
33 #include <fmd_error.h>
34 #include <fmd_string.h>
35 #include <fmd_scheme.h>
41 * Interfaces to be used by the plugins
45 fmd_fmri_alloc(size_t size
)
47 return (fmd_alloc(size
, FMD_SLEEP
));
51 fmd_fmri_zalloc(size_t size
)
53 return (fmd_zalloc(size
, FMD_SLEEP
));
57 fmd_fmri_free(void *data
, size_t size
)
63 fmd_fmri_set_errno(int err
)
70 fmd_fmri_warn(const char *format
, ...)
75 fmd_verror(EFMD_FMRI_SCHEME
, format
, ap
);
80 * Convert an input string to a URI escaped string and return the new string.
81 * RFC2396 Section 2.4 says that data must be escaped if it does not have a
82 * representation using an unreserved character, where an unreserved character
83 * is one that is either alphanumeric or one of the marks defined in S2.3.
86 fmd_fmri_uriescape(const char *s
, const char *xmark
, char *buf
, size_t len
)
88 static const char rfc2396_mark
[] = "-_.!~*'()";
89 static const char hex_digits
[] = "0123456789ABCDEF";
90 static const char empty_str
[] = "";
102 for (p
= s
; (c
= *p
) != '\0'; p
++) {
103 if (isalnum(c
) || strchr(rfc2396_mark
, c
) || strchr(xmark
, c
))
104 n
++; /* represent c as itself */
106 n
+= 3; /* represent c as escape */
112 for (p
= s
, q
= buf
; (c
= *p
) != '\0' && q
< buf
+ len
; p
++) {
113 if (isalnum(c
) || strchr(rfc2396_mark
, c
) || strchr(xmark
, c
)) {
117 *q
++ = hex_digits
[((uchar_t
)c
& 0xf0) >> 4];
118 *q
++ = hex_digits
[(uchar_t
)c
& 0xf];
123 q
--; /* len is too small: truncate output string */
130 * Convert a name-value pair list representing an FMRI authority into the
131 * corresponding RFC2396 string representation and return the new string.
134 fmd_fmri_auth2str(nvlist_t
*nvl
)
140 for (nvp
= nvlist_next_nvpair(nvl
, NULL
);
141 nvp
!= NULL
; nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
143 if (nvpair_type(nvp
) != DATA_TYPE_STRING
)
144 continue; /* do not format non-string elements */
146 n
+= fmd_fmri_uriescape(nvpair_name(nvp
), NULL
, NULL
, 0) + 1;
147 (void) nvpair_value_string(nvp
, &v
);
148 n
+= fmd_fmri_uriescape(v
, ":", NULL
, 0) + 1;
151 p
= s
= fmd_alloc(n
, FMD_SLEEP
);
153 for (nvp
= nvlist_next_nvpair(nvl
, NULL
);
154 nvp
!= NULL
; nvp
= nvlist_next_nvpair(nvl
, nvp
)) {
156 if (nvpair_type(nvp
) != DATA_TYPE_STRING
)
157 continue; /* do not format non-string elements */
162 p
+= fmd_fmri_uriescape(nvpair_name(nvp
), NULL
, p
, n
);
164 (void) nvpair_value_string(nvp
, &v
);
165 p
+= fmd_fmri_uriescape(v
, ":", p
, n
);
172 * Convert an input string to a URI escaped string and return the new string.
173 * We amend the unreserved character list to include commas and colons,
174 * as both are needed to make FMRIs readable without escaping. We also permit
175 * "/" to pass through unescaped as any path delimiters used by the event
176 * creator are presumably intended to appear in the final path.
179 fmd_fmri_strescape(const char *s
)
187 n
= fmd_fmri_uriescape(s
, ":,/", NULL
, 0);
188 s2
= fmd_alloc(n
+ 1, FMD_SLEEP
);
189 (void) fmd_fmri_uriescape(s
, ":,/", s2
, n
+ 1);
195 fmd_fmri_strdup(const char *s
)
197 return (fmd_strdup(s
, FMD_SLEEP
));
201 fmd_fmri_strfree(char *s
)
207 fmd_fmri_get_rootdir(void)
209 return (fmd
.d_rootdir
);
213 fmd_fmri_get_platform(void)
215 return (fmd
.d_platform
);
219 fmd_fmri_get_drgen(void)
223 (void) pthread_mutex_lock(&fmd
.d_stats_lock
);
224 gen
= fmd
.d_stats
->ds_dr_gen
.fmds_value
.ui64
;
225 (void) pthread_mutex_unlock(&fmd
.d_stats_lock
);
231 fmd_fmri_topo_hold(int version
)
235 if (version
!= TOPO_VERSION
)
238 ftp
= fmd_topo_hold();
240 return (ftp
->ft_hdl
);
244 fmd_fmri_topo_rele(struct topo_hdl
*thp
)
246 fmd_topo_rele_hdl(thp
);
250 * Interfaces for users of the plugins
253 static fmd_scheme_t
*
254 nvl2scheme(nvlist_t
*nvl
)
258 if (nvlist_lookup_string(nvl
, FM_FMRI_SCHEME
, &name
) != 0) {
259 (void) fmd_set_errno(EFMD_FMRI_INVAL
);
263 return (fmd_scheme_hash_lookup(fmd
.d_schemes
, name
));
267 fmd_fmri_nvl2str(nvlist_t
*nvl
, char *buf
, size_t buflen
)
273 if (buf
== NULL
&& buflen
== 0) {
278 if ((sp
= nvl2scheme(nvl
)) == NULL
)
279 return (-1); /* errno is set for us */
281 (void) pthread_mutex_lock(&sp
->sch_opslock
);
282 ASSERT(buf
!= NULL
|| buflen
== 0);
283 rv
= sp
->sch_ops
.sop_nvl2str(nvl
, buf
, buflen
);
284 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
286 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
291 fmd_fmri_expand(nvlist_t
*nvl
)
296 if ((sp
= nvl2scheme(nvl
)) == NULL
)
297 return (-1); /* errno is set for us */
299 (void) pthread_mutex_lock(&sp
->sch_opslock
);
300 rv
= sp
->sch_ops
.sop_expand(nvl
);
301 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
303 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
308 fmd_fmri_present(nvlist_t
*nvl
)
313 if ((sp
= nvl2scheme(nvl
)) == NULL
)
314 return (-1); /* errno is set for us */
316 (void) pthread_mutex_lock(&sp
->sch_opslock
);
317 rv
= sp
->sch_ops
.sop_present(nvl
);
318 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
320 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
325 fmd_fmri_replaced(nvlist_t
*nvl
)
330 if ((sp
= nvl2scheme(nvl
)) == NULL
)
331 return (-1); /* errno is set for us */
333 (void) pthread_mutex_lock(&sp
->sch_opslock
);
334 rv
= sp
->sch_ops
.sop_replaced(nvl
);
335 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
337 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
342 fmd_fmri_service_state(nvlist_t
*nvl
)
347 if ((sp
= nvl2scheme(nvl
)) == NULL
)
348 return (-1); /* errno is set for us */
350 (void) pthread_mutex_lock(&sp
->sch_opslock
);
351 rv
= sp
->sch_ops
.sop_service_state(nvl
);
352 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
354 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
359 fmd_fmri_unusable(nvlist_t
*nvl
)
364 if ((sp
= nvl2scheme(nvl
)) == NULL
)
365 return (-1); /* errno is set for us */
367 (void) pthread_mutex_lock(&sp
->sch_opslock
);
368 rv
= sp
->sch_ops
.sop_unusable(nvl
);
369 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
371 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
376 * Someday we'll retire the scheme plugins. For the
377 * retire/unretire operations, the topo interfaces
378 * are called directly.
381 fmd_fmri_retire(nvlist_t
*nvl
)
386 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
389 rv
= topo_fmri_retire(thp
, nvl
, &err
);
390 fmd_fmri_topo_rele(thp
);
396 fmd_fmri_unretire(nvlist_t
*nvl
)
401 if ((thp
= fmd_fmri_topo_hold(TOPO_VERSION
)) == NULL
)
404 rv
= topo_fmri_unretire(thp
, nvl
, &err
);
405 fmd_fmri_topo_rele(thp
);
411 fmd_fmri_contains(nvlist_t
*er
, nvlist_t
*ee
)
414 char *ername
, *eename
;
417 if (nvlist_lookup_string(er
, FM_FMRI_SCHEME
, &ername
) != 0 ||
418 nvlist_lookup_string(ee
, FM_FMRI_SCHEME
, &eename
) != 0 ||
419 strcmp(ername
, eename
) != 0)
420 return (fmd_set_errno(EFMD_FMRI_INVAL
));
422 if ((sp
= fmd_scheme_hash_lookup(fmd
.d_schemes
, ername
)) == NULL
)
423 return (-1); /* errno is set for us */
425 (void) pthread_mutex_lock(&sp
->sch_opslock
);
426 rv
= sp
->sch_ops
.sop_contains(er
, ee
);
427 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
429 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);
434 fmd_fmri_translate(nvlist_t
*fmri
, nvlist_t
*auth
)
439 if ((sp
= nvl2scheme(fmri
)) == NULL
)
440 return (NULL
); /* errno is set for us */
442 (void) pthread_mutex_lock(&sp
->sch_opslock
);
443 nvl
= sp
->sch_ops
.sop_translate(fmri
, auth
);
444 (void) pthread_mutex_unlock(&sp
->sch_opslock
);
446 fmd_scheme_hash_release(fmd
.d_schemes
, sp
);