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