10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53062Scindi * Common Development and Distribution License (the "License").
63062Scindi * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
211193Smws
220Sstevel@tonic-gate /*
237275Sstephh * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <ctype.h>
280Sstevel@tonic-gate #include <errno.h>
290Sstevel@tonic-gate #include <stdarg.h>
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <fmd_alloc.h>
320Sstevel@tonic-gate #include <fmd_subr.h>
330Sstevel@tonic-gate #include <fmd_error.h>
340Sstevel@tonic-gate #include <fmd_string.h>
350Sstevel@tonic-gate #include <fmd_scheme.h>
360Sstevel@tonic-gate #include <fmd_fmri.h>
373062Scindi #include <fmd_topo.h>
380Sstevel@tonic-gate #include <fmd.h>
390Sstevel@tonic-gate
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate * Interfaces to be used by the plugins
420Sstevel@tonic-gate */
430Sstevel@tonic-gate
440Sstevel@tonic-gate void *
fmd_fmri_alloc(size_t size)450Sstevel@tonic-gate fmd_fmri_alloc(size_t size)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate return (fmd_alloc(size, FMD_SLEEP));
480Sstevel@tonic-gate }
490Sstevel@tonic-gate
500Sstevel@tonic-gate void *
fmd_fmri_zalloc(size_t size)510Sstevel@tonic-gate fmd_fmri_zalloc(size_t size)
520Sstevel@tonic-gate {
530Sstevel@tonic-gate return (fmd_zalloc(size, FMD_SLEEP));
540Sstevel@tonic-gate }
550Sstevel@tonic-gate
560Sstevel@tonic-gate void
fmd_fmri_free(void * data,size_t size)570Sstevel@tonic-gate fmd_fmri_free(void *data, size_t size)
580Sstevel@tonic-gate {
590Sstevel@tonic-gate fmd_free(data, size);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate
620Sstevel@tonic-gate int
fmd_fmri_set_errno(int err)630Sstevel@tonic-gate fmd_fmri_set_errno(int err)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate errno = err;
660Sstevel@tonic-gate return (-1);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate
690Sstevel@tonic-gate void
fmd_fmri_warn(const char * format,...)700Sstevel@tonic-gate fmd_fmri_warn(const char *format, ...)
710Sstevel@tonic-gate {
720Sstevel@tonic-gate va_list ap;
730Sstevel@tonic-gate
740Sstevel@tonic-gate va_start(ap, format);
750Sstevel@tonic-gate fmd_verror(EFMD_FMRI_SCHEME, format, ap);
760Sstevel@tonic-gate va_end(ap);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate * Convert an input string to a URI escaped string and return the new string.
810Sstevel@tonic-gate * RFC2396 Section 2.4 says that data must be escaped if it does not have a
820Sstevel@tonic-gate * representation using an unreserved character, where an unreserved character
834198Seschrock * is one that is either alphanumeric or one of the marks defined in S2.3.
840Sstevel@tonic-gate */
851193Smws static size_t
fmd_fmri_uriescape(const char * s,const char * xmark,char * buf,size_t len)861193Smws fmd_fmri_uriescape(const char *s, const char *xmark, char *buf, size_t len)
870Sstevel@tonic-gate {
881193Smws static const char rfc2396_mark[] = "-_.!~*'()";
890Sstevel@tonic-gate static const char hex_digits[] = "0123456789ABCDEF";
901193Smws static const char empty_str[] = "";
910Sstevel@tonic-gate
920Sstevel@tonic-gate const char *p;
931193Smws char c, *q;
940Sstevel@tonic-gate size_t n = 0;
950Sstevel@tonic-gate
960Sstevel@tonic-gate if (s == NULL)
971193Smws s = empty_str;
981193Smws
991193Smws if (xmark == NULL)
1001193Smws xmark = empty_str;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate for (p = s; (c = *p) != '\0'; p++) {
1031193Smws if (isalnum(c) || strchr(rfc2396_mark, c) || strchr(xmark, c))
1040Sstevel@tonic-gate n++; /* represent c as itself */
1050Sstevel@tonic-gate else
1060Sstevel@tonic-gate n += 3; /* represent c as escape */
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate
1091193Smws if (buf == NULL)
1101193Smws return (n);
1110Sstevel@tonic-gate
1121193Smws for (p = s, q = buf; (c = *p) != '\0' && q < buf + len; p++) {
1131193Smws if (isalnum(c) || strchr(rfc2396_mark, c) || strchr(xmark, c)) {
1140Sstevel@tonic-gate *q++ = c;
1150Sstevel@tonic-gate } else {
1160Sstevel@tonic-gate *q++ = '%';
1170Sstevel@tonic-gate *q++ = hex_digits[((uchar_t)c & 0xf0) >> 4];
1180Sstevel@tonic-gate *q++ = hex_digits[(uchar_t)c & 0xf];
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate
1221193Smws if (q == buf + len)
1231193Smws q--; /* len is too small: truncate output string */
1241193Smws
1250Sstevel@tonic-gate *q = '\0';
1261193Smws return (n);
1271193Smws }
1281193Smws
1291193Smws /*
1301193Smws * Convert a name-value pair list representing an FMRI authority into the
1311193Smws * corresponding RFC2396 string representation and return the new string.
1321193Smws */
1331193Smws char *
fmd_fmri_auth2str(nvlist_t * nvl)1341193Smws fmd_fmri_auth2str(nvlist_t *nvl)
1351193Smws {
1361193Smws nvpair_t *nvp;
1371193Smws char *s, *p, *v;
1381193Smws size_t n = 0;
1391193Smws
1401193Smws for (nvp = nvlist_next_nvpair(nvl, NULL);
1411193Smws nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) {
1421193Smws
1431193Smws if (nvpair_type(nvp) != DATA_TYPE_STRING)
1441193Smws continue; /* do not format non-string elements */
1451193Smws
1461193Smws n += fmd_fmri_uriescape(nvpair_name(nvp), NULL, NULL, 0) + 1;
1471193Smws (void) nvpair_value_string(nvp, &v);
1481193Smws n += fmd_fmri_uriescape(v, ":", NULL, 0) + 1;
1491193Smws }
1501193Smws
1511193Smws p = s = fmd_alloc(n, FMD_SLEEP);
1521193Smws
1531193Smws for (nvp = nvlist_next_nvpair(nvl, NULL);
1541193Smws nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) {
1551193Smws
1561193Smws if (nvpair_type(nvp) != DATA_TYPE_STRING)
1571193Smws continue; /* do not format non-string elements */
1581193Smws
1591193Smws if (p != s)
1601193Smws *p++ = ',';
1611193Smws
1621193Smws p += fmd_fmri_uriescape(nvpair_name(nvp), NULL, p, n);
1631193Smws *p++ = '=';
1641193Smws (void) nvpair_value_string(nvp, &v);
1651193Smws p += fmd_fmri_uriescape(v, ":", p, n);
1661193Smws }
1671193Smws
1681193Smws return (s);
1691193Smws }
1701193Smws
1711193Smws /*
1721193Smws * Convert an input string to a URI escaped string and return the new string.
1731193Smws * We amend the unreserved character list to include commas and colons,
1741193Smws * as both are needed to make FMRIs readable without escaping. We also permit
1751193Smws * "/" to pass through unescaped as any path delimiters used by the event
1761193Smws * creator are presumably intended to appear in the final path.
1771193Smws */
1781193Smws char *
fmd_fmri_strescape(const char * s)1791193Smws fmd_fmri_strescape(const char *s)
1801193Smws {
1811193Smws char *s2;
1821193Smws size_t n;
1831193Smws
1841193Smws if (s == NULL)
1851193Smws return (NULL);
1861193Smws
1871193Smws n = fmd_fmri_uriescape(s, ":,/", NULL, 0);
1881193Smws s2 = fmd_alloc(n + 1, FMD_SLEEP);
1891193Smws (void) fmd_fmri_uriescape(s, ":,/", s2, n + 1);
1901193Smws
1910Sstevel@tonic-gate return (s2);
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate char *
fmd_fmri_strdup(const char * s)1950Sstevel@tonic-gate fmd_fmri_strdup(const char *s)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate return (fmd_strdup(s, FMD_SLEEP));
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate void
fmd_fmri_strfree(char * s)2010Sstevel@tonic-gate fmd_fmri_strfree(char *s)
2020Sstevel@tonic-gate {
2030Sstevel@tonic-gate fmd_strfree(s);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate const char *
fmd_fmri_get_rootdir(void)2070Sstevel@tonic-gate fmd_fmri_get_rootdir(void)
2080Sstevel@tonic-gate {
2090Sstevel@tonic-gate return (fmd.d_rootdir);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate const char *
fmd_fmri_get_platform(void)2130Sstevel@tonic-gate fmd_fmri_get_platform(void)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate return (fmd.d_platform);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate uint64_t
fmd_fmri_get_drgen(void)2190Sstevel@tonic-gate fmd_fmri_get_drgen(void)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate uint64_t gen;
2220Sstevel@tonic-gate
2230Sstevel@tonic-gate (void) pthread_mutex_lock(&fmd.d_stats_lock);
2240Sstevel@tonic-gate gen = fmd.d_stats->ds_dr_gen.fmds_value.ui64;
2250Sstevel@tonic-gate (void) pthread_mutex_unlock(&fmd.d_stats_lock);
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate return (gen);
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate
2301414Scindi struct topo_hdl *
fmd_fmri_topo_hold(int version)2314198Seschrock fmd_fmri_topo_hold(int version)
2321414Scindi {
2334198Seschrock fmd_topo_t *ftp;
2344198Seschrock
2354198Seschrock if (version != TOPO_VERSION)
2364198Seschrock return (NULL);
2374198Seschrock
2384198Seschrock ftp = fmd_topo_hold();
2394198Seschrock
2404198Seschrock return (ftp->ft_hdl);
2414198Seschrock }
2424198Seschrock
2434198Seschrock void
fmd_fmri_topo_rele(struct topo_hdl * thp)2444198Seschrock fmd_fmri_topo_rele(struct topo_hdl *thp)
2454198Seschrock {
2464198Seschrock fmd_topo_rele_hdl(thp);
2471414Scindi }
2481414Scindi
2490Sstevel@tonic-gate /*
2500Sstevel@tonic-gate * Interfaces for users of the plugins
2510Sstevel@tonic-gate */
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate static fmd_scheme_t *
nvl2scheme(nvlist_t * nvl)2540Sstevel@tonic-gate nvl2scheme(nvlist_t *nvl)
2550Sstevel@tonic-gate {
2560Sstevel@tonic-gate char *name;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) != 0) {
2590Sstevel@tonic-gate (void) fmd_set_errno(EFMD_FMRI_INVAL);
2600Sstevel@tonic-gate return (NULL);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate return (fmd_scheme_hash_lookup(fmd.d_schemes, name));
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate ssize_t
fmd_fmri_nvl2str(nvlist_t * nvl,char * buf,size_t buflen)2670Sstevel@tonic-gate fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate fmd_scheme_t *sp;
2700Sstevel@tonic-gate char c;
2710Sstevel@tonic-gate ssize_t rv;
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate if (buf == NULL && buflen == 0) {
2740Sstevel@tonic-gate buf = &c;
2750Sstevel@tonic-gate buflen = sizeof (c);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if ((sp = nvl2scheme(nvl)) == NULL)
2790Sstevel@tonic-gate return (-1); /* errno is set for us */
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->sch_opslock);
2820Sstevel@tonic-gate ASSERT(buf != NULL || buflen == 0);
2830Sstevel@tonic-gate rv = sp->sch_ops.sop_nvl2str(nvl, buf, buflen);
2840Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->sch_opslock);
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate fmd_scheme_hash_release(fmd.d_schemes, sp);
2870Sstevel@tonic-gate return (rv);
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate int
fmd_fmri_expand(nvlist_t * nvl)2910Sstevel@tonic-gate fmd_fmri_expand(nvlist_t *nvl)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate fmd_scheme_t *sp;
2940Sstevel@tonic-gate int rv;
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate if ((sp = nvl2scheme(nvl)) == NULL)
2970Sstevel@tonic-gate return (-1); /* errno is set for us */
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->sch_opslock);
3000Sstevel@tonic-gate rv = sp->sch_ops.sop_expand(nvl);
3010Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->sch_opslock);
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate fmd_scheme_hash_release(fmd.d_schemes, sp);
3040Sstevel@tonic-gate return (rv);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate int
fmd_fmri_present(nvlist_t * nvl)3080Sstevel@tonic-gate fmd_fmri_present(nvlist_t *nvl)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate fmd_scheme_t *sp;
3110Sstevel@tonic-gate int rv;
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate if ((sp = nvl2scheme(nvl)) == NULL)
3140Sstevel@tonic-gate return (-1); /* errno is set for us */
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->sch_opslock);
3170Sstevel@tonic-gate rv = sp->sch_ops.sop_present(nvl);
3180Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->sch_opslock);
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate fmd_scheme_hash_release(fmd.d_schemes, sp);
3210Sstevel@tonic-gate return (rv);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate int
fmd_fmri_replaced(nvlist_t * nvl)3257275Sstephh fmd_fmri_replaced(nvlist_t *nvl)
3267275Sstephh {
3277275Sstephh fmd_scheme_t *sp;
3287275Sstephh int rv;
3297275Sstephh
3307275Sstephh if ((sp = nvl2scheme(nvl)) == NULL)
3317275Sstephh return (-1); /* errno is set for us */
3327275Sstephh
3337275Sstephh (void) pthread_mutex_lock(&sp->sch_opslock);
3347275Sstephh rv = sp->sch_ops.sop_replaced(nvl);
3357275Sstephh (void) pthread_mutex_unlock(&sp->sch_opslock);
3367275Sstephh
3377275Sstephh fmd_scheme_hash_release(fmd.d_schemes, sp);
3387275Sstephh return (rv);
3397275Sstephh }
3407275Sstephh
3417275Sstephh int
fmd_fmri_service_state(nvlist_t * nvl)3427275Sstephh fmd_fmri_service_state(nvlist_t *nvl)
3437275Sstephh {
3447275Sstephh fmd_scheme_t *sp;
3457275Sstephh int rv;
3467275Sstephh
3477275Sstephh if ((sp = nvl2scheme(nvl)) == NULL)
3487275Sstephh return (-1); /* errno is set for us */
3497275Sstephh
3507275Sstephh (void) pthread_mutex_lock(&sp->sch_opslock);
3517275Sstephh rv = sp->sch_ops.sop_service_state(nvl);
3527275Sstephh (void) pthread_mutex_unlock(&sp->sch_opslock);
3537275Sstephh
3547275Sstephh fmd_scheme_hash_release(fmd.d_schemes, sp);
3557275Sstephh return (rv);
3567275Sstephh }
3577275Sstephh
3587275Sstephh int
fmd_fmri_unusable(nvlist_t * nvl)3590Sstevel@tonic-gate fmd_fmri_unusable(nvlist_t *nvl)
3600Sstevel@tonic-gate {
3610Sstevel@tonic-gate fmd_scheme_t *sp;
3620Sstevel@tonic-gate int rv;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate if ((sp = nvl2scheme(nvl)) == NULL)
3650Sstevel@tonic-gate return (-1); /* errno is set for us */
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->sch_opslock);
3680Sstevel@tonic-gate rv = sp->sch_ops.sop_unusable(nvl);
3690Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->sch_opslock);
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate fmd_scheme_hash_release(fmd.d_schemes, sp);
3720Sstevel@tonic-gate return (rv);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
375*7532SSean.Ye@Sun.COM /*
376*7532SSean.Ye@Sun.COM * Someday we'll retire the scheme plugins. For the
377*7532SSean.Ye@Sun.COM * retire/unretire operations, the topo interfaces
378*7532SSean.Ye@Sun.COM * are called directly.
379*7532SSean.Ye@Sun.COM */
380*7532SSean.Ye@Sun.COM int
fmd_fmri_retire(nvlist_t * nvl)381*7532SSean.Ye@Sun.COM fmd_fmri_retire(nvlist_t *nvl)
382*7532SSean.Ye@Sun.COM {
383*7532SSean.Ye@Sun.COM topo_hdl_t *thp;
384*7532SSean.Ye@Sun.COM int rv, err;
385*7532SSean.Ye@Sun.COM
386*7532SSean.Ye@Sun.COM if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL)
387*7532SSean.Ye@Sun.COM return (-1);
388*7532SSean.Ye@Sun.COM
389*7532SSean.Ye@Sun.COM rv = topo_fmri_retire(thp, nvl, &err);
390*7532SSean.Ye@Sun.COM fmd_fmri_topo_rele(thp);
391*7532SSean.Ye@Sun.COM
392*7532SSean.Ye@Sun.COM return (rv);
393*7532SSean.Ye@Sun.COM }
394*7532SSean.Ye@Sun.COM
395*7532SSean.Ye@Sun.COM int
fmd_fmri_unretire(nvlist_t * nvl)396*7532SSean.Ye@Sun.COM fmd_fmri_unretire(nvlist_t *nvl)
397*7532SSean.Ye@Sun.COM {
398*7532SSean.Ye@Sun.COM topo_hdl_t *thp;
399*7532SSean.Ye@Sun.COM int rv, err;
400*7532SSean.Ye@Sun.COM
401*7532SSean.Ye@Sun.COM if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL)
402*7532SSean.Ye@Sun.COM return (-1);
403*7532SSean.Ye@Sun.COM
404*7532SSean.Ye@Sun.COM rv = topo_fmri_unretire(thp, nvl, &err);
405*7532SSean.Ye@Sun.COM fmd_fmri_topo_rele(thp);
406*7532SSean.Ye@Sun.COM
407*7532SSean.Ye@Sun.COM return (rv);
408*7532SSean.Ye@Sun.COM }
409*7532SSean.Ye@Sun.COM
4100Sstevel@tonic-gate int
fmd_fmri_contains(nvlist_t * er,nvlist_t * ee)4110Sstevel@tonic-gate fmd_fmri_contains(nvlist_t *er, nvlist_t *ee)
4120Sstevel@tonic-gate {
4130Sstevel@tonic-gate fmd_scheme_t *sp;
4140Sstevel@tonic-gate char *ername, *eename;
4150Sstevel@tonic-gate int rv;
4160Sstevel@tonic-gate
4170Sstevel@tonic-gate if (nvlist_lookup_string(er, FM_FMRI_SCHEME, &ername) != 0 ||
4180Sstevel@tonic-gate nvlist_lookup_string(ee, FM_FMRI_SCHEME, &eename) != 0 ||
4190Sstevel@tonic-gate strcmp(ername, eename) != 0)
4200Sstevel@tonic-gate return (fmd_set_errno(EFMD_FMRI_INVAL));
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate if ((sp = fmd_scheme_hash_lookup(fmd.d_schemes, ername)) == NULL)
4230Sstevel@tonic-gate return (-1); /* errno is set for us */
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate (void) pthread_mutex_lock(&sp->sch_opslock);
4260Sstevel@tonic-gate rv = sp->sch_ops.sop_contains(er, ee);
4270Sstevel@tonic-gate (void) pthread_mutex_unlock(&sp->sch_opslock);
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate fmd_scheme_hash_release(fmd.d_schemes, sp);
4300Sstevel@tonic-gate return (rv);
4310Sstevel@tonic-gate }
4321193Smws
4331193Smws nvlist_t *
fmd_fmri_translate(nvlist_t * fmri,nvlist_t * auth)4341193Smws fmd_fmri_translate(nvlist_t *fmri, nvlist_t *auth)
4351193Smws {
4361193Smws fmd_scheme_t *sp;
4371193Smws nvlist_t *nvl;
4381193Smws
4391193Smws if ((sp = nvl2scheme(fmri)) == NULL)
4401193Smws return (NULL); /* errno is set for us */
4411193Smws
4421193Smws (void) pthread_mutex_lock(&sp->sch_opslock);
4431193Smws nvl = sp->sch_ops.sop_translate(fmri, auth);
4441193Smws (void) pthread_mutex_unlock(&sp->sch_opslock);
4451193Smws
4461193Smws fmd_scheme_hash_release(fmd.d_schemes, sp);
4471193Smws return (nvl);
4481193Smws }
449