Print this page
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/fm/topo/libtopo/common/sw.c
+++ new/usr/src/lib/fm/topo/libtopo/common/sw.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <libnvpair.h>
27 27 #include <fm/topo_mod.h>
28 28
29 29 #include <sys/fm/protocol.h>
30 30 #include <sys/types.h>
31 31
32 32 #include <topo_method.h>
33 33 #include <topo_subr.h>
34 34 #include <sw.h>
35 35
36 36 static int sw_fmri_nvl2str(topo_mod_t *, tnode_t *, topo_version_t,
37 37 nvlist_t *, nvlist_t **);
38 38 static int sw_fmri_create(topo_mod_t *, tnode_t *, topo_version_t,
39 39 nvlist_t *, nvlist_t **);
40 40
41 41 static const topo_method_t sw_methods[] = {
42 42 { TOPO_METH_NVL2STR, TOPO_METH_NVL2STR_DESC, TOPO_METH_NVL2STR_VERSION,
43 43 TOPO_STABILITY_INTERNAL, sw_fmri_nvl2str },
44 44 { TOPO_METH_FMRI, TOPO_METH_FMRI_DESC, TOPO_METH_FMRI_VERSION,
45 45 TOPO_STABILITY_INTERNAL, sw_fmri_create },
46 46 { NULL }
47 47 };
48 48
49 49 static int sw_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
50 50 topo_instance_t, void *, void *);
51 51 static void sw_release(topo_mod_t *, tnode_t *);
52 52
53 53 static const topo_modops_t sw_ops =
54 54 { sw_enum, sw_release };
55 55
56 56 static const topo_modinfo_t sw_info =
57 57 { "sw", FM_FMRI_SCHEME_SW, SW_VERSION, &sw_ops };
58 58
59 59 int
60 60 sw_init(topo_mod_t *mod, topo_version_t version)
61 61 {
62 62 if (getenv("TOPOSWDEBUG"))
63 63 topo_mod_setdebug(mod);
64 64 topo_mod_dprintf(mod, "initializing sw builtin\n");
65 65
66 66 if (version != SW_VERSION)
67 67 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
68 68
69 69 if (topo_mod_register(mod, &sw_info, TOPO_VERSION) != 0) {
70 70 topo_mod_dprintf(mod, "failed to register sw_info: "
71 71 "%s\n", topo_mod_errmsg(mod));
72 72 return (-1);
73 73 }
74 74
75 75 return (0);
76 76 }
77 77
78 78 void
79 79 sw_fini(topo_mod_t *mod)
80 80 {
81 81 topo_mod_unregister(mod);
82 82 }
83 83
84 84 static int
85 85 sw_get_optl_string(nvlist_t *nvl, char *name, char **dest)
86 86 {
87 87 if (nvlist_lookup_string(nvl, name, dest) == 0) {
88 88 return (0);
89 89 } else {
90 90 *dest = NULL;
91 91 return (errno == ENOENT ? 0 : 1);
92 92 }
93 93 }
94 94
95 95 static int
96 96 sw_get_optl_int64(nvlist_t *nvl, char *name, int64_t *dest)
97 97 {
98 98 if (nvlist_lookup_int64(nvl, name, dest) == 0) {
99 99 return (0);
100 100 } else {
101 101 *dest = -1;
102 102 return (errno == ENOENT ? 0 : 1);
103 103 }
104 104 }
105 105
106 106 static int
107 107 sw_get_optl_nvlist(nvlist_t *nvl, char *name, nvlist_t **dest)
108 108 {
109 109 if (nvlist_lookup_nvlist(nvl, name, dest) == 0) {
110 110 return (0);
111 111 } else {
112 112 *dest = NULL;
113 113 return (errno == ENOENT ? 0 : 1);
114 114 }
115 115 }
116 116
117 117 static int
118 118 sw_add_optl_string(nvlist_t *nvl, char *name, char *val)
119 119 {
120 120 if (val)
121 121 return (nvlist_add_string(nvl, name, val) != 0);
122 122 else
123 123 return (0);
124 124 }
125 125
126 126 /*ARGSUSED*/
127 127 static int
128 128 sw_fmri_create(topo_mod_t *mod, tnode_t *node, topo_version_t version,
129 129 nvlist_t *in, nvlist_t **out)
130 130 {
131 131 nvlist_t *args, *fmri = NULL, *obj = NULL, *site = NULL, *ctxt = NULL;
132 132 topo_mod_errno_t moderr;
133 133 int err = 0;
134 134
135 135 char *obj_path, *obj_root;
136 136 nvlist_t *obj_pkg;
137 137
138 138 char *site_token, *site_module, *site_file, *site_func;
139 139 int64_t site_line;
140 140
141 141 char *ctxt_origin, *ctxt_execname, *ctxt_zone;
142 142 int64_t ctxt_pid, ctxt_ctid;
143 143 char **ctxt_stack;
144 144 uint_t ctxt_stackdepth;
145 145
146 146
147 147 if (version > TOPO_METH_FMRI_VERSION)
148 148 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
149 149
150 150 if (nvlist_lookup_nvlist(in, TOPO_METH_FMRI_ARG_NVL, &args) != 0)
151 151 return (topo_mod_seterrno(mod, EMOD_METHOD_INVAL));
152 152
153 153 if (nvlist_lookup_string(args, "obj_path", &obj_path) != 0)
154 154 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL));
155 155 err |= sw_get_optl_string(args, "obj_root", &obj_root);
156 156 err |= sw_get_optl_nvlist(args, "obj-pkg", &obj_pkg);
157 157
158 158 err |= sw_get_optl_string(args, "site_token", &site_token);
159 159 err |= sw_get_optl_string(args, "site_module", &site_module);
160 160 err |= sw_get_optl_string(args, "site_file", &site_file);
161 161 err |= sw_get_optl_string(args, "site_func", &site_func);
162 162 err |= sw_get_optl_int64(args, "site_line", &site_line);
163 163
164 164 err |= sw_get_optl_string(args, "ctxt_origin", &ctxt_origin);
165 165 err |= sw_get_optl_string(args, "ctxt_execname", &ctxt_execname);
166 166 err |= sw_get_optl_string(args, "ctxt_zone", &ctxt_zone);
167 167 err |= sw_get_optl_int64(args, "ctxt_pid", &ctxt_pid);
168 168 err |= sw_get_optl_int64(args, "ctxt_ctid", &ctxt_ctid);
169 169
170 170 if (nvlist_lookup_string_array(args, "stack", &ctxt_stack,
171 171 &ctxt_stackdepth) != 0) {
172 172 if (errno == ENOENT)
173 173 ctxt_stack = NULL;
174 174 else
175 175 err++;
176 176 }
177 177
178 178 if (err)
179 179 (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
180 180
181 181 if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0 ||
182 182 topo_mod_nvalloc(mod, &obj, NV_UNIQUE_NAME) != 0) {
183 183 moderr = EMOD_NOMEM;
184 184 goto out;
185 185 }
186 186
187 187 /*
188 188 * Add standard FMRI members 'version' and 'scheme'.
189 189 */
190 190 err |= nvlist_add_uint8(fmri, FM_VERSION, FM_SW_SCHEME_VERSION);
191 191 err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);
192 192
193 193 /*
194 194 * Build up the 'object' nvlist.
195 195 */
196 196 err |= nvlist_add_string(obj, FM_FMRI_SW_OBJ_PATH, obj_path);
197 197 err |= sw_add_optl_string(obj, FM_FMRI_SW_OBJ_ROOT, obj_root);
198 198 if (obj_pkg)
199 199 err |= nvlist_add_nvlist(obj, FM_FMRI_SW_OBJ_PKG, obj_pkg);
200 200
201 201 /*
202 202 * Add 'object' to the fmri.
203 203 */
204 204 if (err == 0)
205 205 err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_OBJ, obj);
206 206
207 207 if (err) {
208 208 moderr = EMOD_NOMEM;
209 209 goto out;
210 210 }
211 211
212 212 /*
213 213 * Do we have anything for a 'site' nvlist?
214 214 */
215 215 if (site_token == NULL && site_module == NULL && site_file == NULL &&
216 216 site_func == NULL && site_line == -1)
217 217 goto context;
218 218
219 219 /*
220 220 * Allocate and build 'site' nvlist.
221 221 */
222 222 if (topo_mod_nvalloc(mod, &site, NV_UNIQUE_NAME) != 0) {
223 223 moderr = EMOD_NOMEM;
224 224 goto out;
225 225 }
226 226
227 227 err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_TOKEN, site_token);
228 228 err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_MODULE, site_module);
229 229 err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_FILE, site_file);
230 230 err |= sw_add_optl_string(site, FM_FMRI_SW_SITE_FUNC, site_func);
231 231 if ((site_token || site_module || site_file || site_func) &&
232 232 site_line != -1)
233 233 err |= nvlist_add_int64(site, FM_FMRI_SW_SITE_LINE, site_line);
234 234
235 235 /*
236 236 * Add 'site' to the fmri.
237 237 */
238 238 if (err == 0)
239 239 err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_SITE, site);
240 240
241 241 if (err) {
242 242 moderr = EMOD_NOMEM;
243 243 goto out;
244 244 }
245 245
246 246 context:
247 247 /*
248 248 * Do we have anything for a 'context' nvlist?
249 249 */
250 250 if (ctxt_origin || ctxt_execname || ctxt_zone ||
251 251 ctxt_pid != -1 || ctxt_ctid != -1 || ctxt_stack != NULL)
252 252 goto out;
253 253
254 254 /*
255 255 * Allocate and build 'context' nvlist.
256 256 */
257 257 if (topo_mod_nvalloc(mod, &ctxt, NV_UNIQUE_NAME) != 0) {
258 258 moderr = EMOD_NOMEM;
259 259 goto out;
260 260 }
261 261
262 262 err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_ORIGIN, ctxt_origin);
263 263 err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_EXECNAME,
264 264 ctxt_execname);
265 265 err |= sw_add_optl_string(ctxt, FM_FMRI_SW_CTXT_ZONE, ctxt_zone);
266 266 if (ctxt_pid != -1)
267 267 err |= nvlist_add_int64(ctxt, FM_FMRI_SW_CTXT_PID, ctxt_pid);
268 268 if (ctxt_ctid != -1)
269 269 err |= nvlist_add_int64(ctxt, FM_FMRI_SW_CTXT_CTID, ctxt_ctid);
270 270 if (ctxt_stack != NULL)
271 271 err |= nvlist_add_string_array(ctxt, FM_FMRI_SW_CTXT_STACK,
272 272 ctxt_stack, ctxt_stackdepth);
273 273
↓ open down ↓ |
273 lines elided |
↑ open up ↑ |
274 274 /*
275 275 * Add 'context' to the fmri.
276 276 */
277 277 if (err == 0)
278 278 err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_CTXT, ctxt);
279 279
280 280 moderr = err ? EMOD_NOMEM : 0;
281 281 out:
282 282 if (moderr == 0)
283 283 *out = fmri;
284 -
285 - if (moderr != 0 && fmri)
284 + else
286 285 nvlist_free(fmri);
287 286
288 - if (obj)
289 - nvlist_free(obj);
290 -
291 - if (site)
292 - nvlist_free(site);
293 -
294 - if (ctxt)
295 - nvlist_free(ctxt);
287 + nvlist_free(obj);
288 + nvlist_free(site);
289 + nvlist_free(ctxt);
296 290
297 291 return (moderr == 0 ? 0 : topo_mod_seterrno(mod, moderr));
298 292 }
299 293
300 294
301 295 /*ARGSUSED*/
302 296 static int
303 297 sw_enum(topo_mod_t *mod, tnode_t *pnode, const char *name,
304 298 topo_instance_t min, topo_instance_t max, void *notused1, void *notused2)
305 299 {
306 300 (void) topo_method_register(mod, pnode, sw_methods);
307 301 return (0);
308 302 }
309 303
310 304 static void
311 305 sw_release(topo_mod_t *mod, tnode_t *node)
312 306 {
313 307 topo_method_unregister_all(mod, node);
314 308 }
315 309
316 310 /*
317 311 * Lookup a string in an nvlist. Possible return values:
318 312 * if 'required' is B_TRUE:
319 313 * 1 = found
320 314 * 0 = not found
321 315 * if 'required' is B_FALSE:
322 316 * 1 = found
323 317 * 0 = not found, but some error other than ENOENT encountered
324 318 * -1 = not found, with ENOENT
325 319 *
326 320 * So 0 is an error condition in both cases.
327 321 *
328 322 * In all "not found" cases, *valp is NULLed.
329 323 */
330 324 static int
331 325 lookup_string(nvlist_t *nvl, char *name, char **valp, boolean_t required)
332 326 {
333 327 int err;
334 328
335 329 err = nvlist_lookup_string(nvl, name, valp);
336 330
337 331 /*
338 332 * A return value of 1 always means "found"
339 333 */
340 334 if (err == 0)
341 335 return (1);
342 336
343 337 /*
344 338 * Failure to lookup for whatever reason NULLs valp
345 339 */
346 340 *valp = NULL;
347 341
348 342 /*
349 343 * Return 0 if not found but required, or optional but some error
350 344 * other than ENOENT was returned.
351 345 */
352 346 if (required == B_TRUE || err != ENOENT)
353 347 return (0);
354 348
355 349 /*
356 350 * Return -1 if not found but was optional (and got ENOENT).
357 351 */
358 352 return (-1);
359 353 }
360 354
361 355 /*ARGSUSED*/
362 356 static int
363 357 sw_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version,
364 358 nvlist_t *nvl, nvlist_t **out)
365 359 {
366 360 nvlist_t *object, *site = NULL, *anvl = NULL;
367 361 char *file, *func, *token;
368 362 uint8_t scheme_version;
369 363 char *path, *root;
370 364 nvlist_t *fmristr;
371 365 size_t buflen = 0;
372 366 int linevalid = 0;
373 367 char *buf = NULL;
374 368 ssize_t size = 0;
375 369 char linebuf[32];
376 370 int64_t line;
377 371 int pass;
378 372 int err;
379 373
380 374 if (version > TOPO_METH_NVL2STR_VERSION)
381 375 return (topo_mod_seterrno(mod, EMOD_VER_NEW));
382 376
383 377 if (nvlist_lookup_uint8(nvl, FM_VERSION, &scheme_version) != 0 ||
384 378 scheme_version > FM_SW_SCHEME_VERSION)
385 379 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
386 380
387 381 /* Get authority, if present */
388 382 err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl);
389 383 if (err != 0 && err != ENOENT)
390 384 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
391 385
392 386 /*
393 387 * The 'object' nvlist is required. It must include the path,
394 388 * but the root is optional.
395 389 */
396 390 if (nvlist_lookup_nvlist(nvl, FM_FMRI_SW_OBJ, &object) != 0 ||
397 391 !lookup_string(object, FM_FMRI_SW_OBJ_PATH, &path, B_TRUE) ||
398 392 !lookup_string(object, FM_FMRI_SW_OBJ_ROOT, &root, B_FALSE))
399 393 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
400 394
401 395 /* The 'site' nvlist is optional */
402 396 file = func = token = NULL;
403 397 linevalid = 0;
404 398 if ((err = nvlist_lookup_nvlist(nvl, FM_FMRI_SW_SITE, &site)) == 0) {
405 399 /*
406 400 * Prefer 'token' to file/func/line
407 401 */
408 402 if (lookup_string(site, FM_FMRI_SW_SITE_TOKEN, &token,
409 403 B_FALSE) <= 0) {
410 404 /*
411 405 * If no token then try file, func, line - but
412 406 * func and line are meaningless without file.
413 407 */
414 408 if (lookup_string(site, FM_FMRI_SW_SITE_FILE,
415 409 &file, B_FALSE) == 1) {
416 410 (void) lookup_string(site, FM_FMRI_SW_SITE_FUNC,
417 411 &func, B_FALSE);
418 412 if (nvlist_lookup_int64(site,
419 413 FM_FMRI_SW_SITE_LINE, &line) == 0)
420 414 linevalid = 1;
421 415 }
422 416 }
423 417 } else if (err != ENOENT) {
424 418 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL));
425 419 }
426 420
427 421 /* On the first pass buf is NULL and size and buflen are 0 */
428 422 pass = 1;
429 423 again:
430 424 /*
431 425 * sw://[<authority>]/
432 426 * [:root=<object.root]
433 427 * :path=<object.path>
434 428 * [#<fragment-identifier>]
435 429 *
436 430 * <fragment-identifier> is one of
437 431 *
438 432 * :token=<site.token>
439 433 * or
440 434 * :file=<site.file>[:func=<site.func>][:line=<site.line>]
441 435 */
442 436
443 437 /* sw:// */
444 438 topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_SW,
445 439 NULL, "://");
446 440
447 441 /* authority, if any */
448 442 if (anvl != NULL) {
449 443 nvpair_t *apair;
450 444 char *aname, *aval;
451 445
452 446 for (apair = nvlist_next_nvpair(anvl, NULL);
453 447 apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) {
454 448 if (nvpair_type(apair) != DATA_TYPE_STRING ||
455 449 nvpair_value_string(apair, &aval) != 0)
456 450 continue;
457 451 aname = nvpair_name(apair);
458 452 topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL);
459 453 topo_fmristr_build(&size, buf, buflen, "=",
460 454 aname, aval);
461 455 }
462 456 }
463 457
464 458 /* separating slash */
465 459 topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL);
466 460
467 461 /* :root=... */
468 462 if (root) {
469 463 topo_fmristr_build(&size, buf, buflen, root,
470 464 ":" FM_FMRI_SW_OBJ_ROOT "=", NULL);
471 465 }
472 466
473 467 /* :path=... */
474 468 topo_fmristr_build(&size, buf, buflen, path,
475 469 ":" FM_FMRI_SW_OBJ_PATH "=", NULL);
476 470
477 471 if (token) {
478 472 /* #:token=... */
479 473 topo_fmristr_build(&size, buf, buflen, token,
480 474 "#:" FM_FMRI_SW_SITE_TOKEN "=", NULL);
481 475 } else if (file) {
482 476 /* #:file=... */
483 477 topo_fmristr_build(&size, buf, buflen, file,
484 478 "#:" FM_FMRI_SW_SITE_FILE "=", NULL);
485 479
486 480 /* :func=... */
487 481 if (func) {
488 482 topo_fmristr_build(&size, buf, buflen, func,
489 483 ":" FM_FMRI_SW_SITE_FUNC "=", NULL);
490 484 }
491 485
492 486 /* :line=... */
493 487 if (linevalid) {
494 488 if (pass == 1)
495 489 (void) snprintf(linebuf, sizeof (linebuf),
496 490 "%lld", line);
497 491
498 492 topo_fmristr_build(&size, buf, buflen, linebuf,
499 493 ":" FM_FMRI_SW_SITE_LINE "=", NULL);
500 494 }
501 495 }
502 496
503 497 if (buf == NULL) {
504 498 if ((buf = topo_mod_alloc(mod, size + 1)) == NULL)
505 499 return (topo_mod_seterrno(mod, EMOD_NOMEM));
506 500
507 501 buflen = size + 1;
508 502 size = 0;
509 503 pass = 2;
510 504 goto again;
511 505 }
512 506
513 507 /*
514 508 * Construct the nvlist to return as the result.
515 509 */
516 510 if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) {
517 511 topo_mod_strfree(mod, buf);
518 512 return (topo_mod_seterrno(mod, EMOD_NOMEM));
519 513 }
520 514
521 515 if (nvlist_add_string(fmristr, "fmri-string", buf) != 0) {
522 516 topo_mod_strfree(mod, buf);
523 517 nvlist_free(fmristr);
524 518 return (topo_mod_seterrno(mod, EMOD_NOMEM));
525 519 }
526 520 topo_mod_strfree(mod, buf);
527 521 *out = fmristr;
528 522
529 523 return (0);
530 524 }
↓ open down ↓ |
225 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX