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 <libintl.h>
30 #include <string.h>
31 #include "volume_nvpair.h"
32 #include "volume_error.h"
33
34 /*
35 * ******************************************************************
36 *
37 * Function prototypes
38 *
39 * ******************************************************************
40 */
41
42 static nvpair_t *nvlist_walk_nvpair(nvlist_t *nvl,
43 const char *name, data_type_t type, nvpair_t *nvp);
44
45 /*
46 * ******************************************************************
47 *
48 * External functions
49 *
50 * ******************************************************************
51 */
52
53 /*
54 * Get the named uint16 from the given nvlist_t.
55 *
56 * @param attrs
57 * the nvlist_t to search
58 *
59 * @param which
60 * the string key for this element in the list
61 *
62 * @param val
63 * RETURN: the value of the requested uint16
64 *
65 * @return 0
66 * if successful
67 *
68 * @return ENOENT
69 * if no matching name-value pair is found
70 */
71 int
get_uint16(nvlist_t * attrs,char * which,uint16_t * val)72 get_uint16(
73 nvlist_t *attrs,
74 char *which,
75 uint16_t *val)
76 {
77 int error;
78 nvpair_t *match =
79 nvlist_walk_nvpair(attrs, which, DATA_TYPE_UINT16, NULL);
80
81 if (match == NULL) {
82 error = ENOENT;
83 } else {
84 error = nvpair_value_uint16(match, val);
85 }
86
87 return (error);
88 }
89
90 /*
91 * Set the named uint16 in the given nvlist_t.
92 *
93 * @param attrs
94 * the nvlist_t to search
95 *
96 * @param which
97 * the string key for this element in the list
98 *
99 * @param val
100 * the value to set
101 *
102 * @return 0
103 * if successful
104 *
105 * @return EINVAL
106 * if there is an invalid argument
107 *
108 * @return ENOMEM
109 * if there is insufficient memory
110 */
111 int
set_uint16(nvlist_t * attrs,char * which,uint16_t val)112 set_uint16(
113 nvlist_t *attrs,
114 char *which,
115 uint16_t val)
116 {
117 int error = 0;
118
119 if ((error = nvlist_add_uint16(attrs, which, val)) != 0) {
120 volume_set_error(
121 gettext("nvlist_add_int16(%s) failed: %d\n"), which, error);
122 }
123
124 return (error);
125 }
126
127 /*
128 * Get the named uint32 from the given nvlist_t.
129 *
130 * @param attrs
131 * the nvlist_t to search
132 *
133 * @param which
134 * the string key for this element in the list
135 *
136 * @param val
137 * RETURN: the value of the requested uint32
138 *
139 * @return 0
140 * if successful
141 *
142 * @return ENOENT
143 * if no matching name-value pair is found
144 */
145 int
get_uint32(nvlist_t * attrs,char * which,uint32_t * val)146 get_uint32(
147 nvlist_t *attrs,
148 char *which,
149 uint32_t *val)
150 {
151 int error;
152 nvpair_t *match =
153 nvlist_walk_nvpair(attrs, which, DATA_TYPE_UINT32, NULL);
154
155 if (match == NULL) {
156 error = ENOENT;
157 } else {
158 error = nvpair_value_uint32(match, val);
159 }
160
161 return (error);
162 }
163
164 /*
165 * Set the named uint32 in the given nvlist_t.
166 *
167 * @param attrs
168 * the nvlist_t to search
169 *
170 * @param which
171 * the string key for this element in the list
172 *
173 * @param val
174 * the value to set
175 *
176 * @return 0
177 * if successful
178 *
179 * @return EINVAL
180 * if there is an invalid argument
181 *
182 * @return ENOMEM
183 * if there is insufficient memory
184 */
185 int
set_uint32(nvlist_t * attrs,char * which,uint32_t val)186 set_uint32(
187 nvlist_t *attrs,
188 char *which,
189 uint32_t val)
190 {
191 int error = 0;
192
193 if ((error = nvlist_add_uint32(attrs, which, val)) != 0) {
194 volume_set_error(
195 gettext("nvlist_add_int32(%s) failed: %d\n"), which, error);
196 }
197
198 return (error);
199 }
200
201 /*
202 * Get the named uint64 from the given nvlist_t.
203 *
204 * @param attrs
205 * the nvlist_t to search
206 *
207 * @param which
208 * the string key for this element in the list
209 *
210 * @param val
211 * RETURN: the value of the requested uint64
212 *
213 * @return 0
214 * if successful
215 *
216 * @return ENOENT
217 * if no matching name-value pair is found
218 */
219 int
get_uint64(nvlist_t * attrs,char * which,uint64_t * val)220 get_uint64(
221 nvlist_t *attrs,
222 char *which,
223 uint64_t *val)
224 {
225 int error;
226 nvpair_t *match =
227 nvlist_walk_nvpair(attrs, which, DATA_TYPE_UINT64, NULL);
228
229 if (match == NULL) {
230 error = ENOENT;
231 } else {
232 error = nvpair_value_uint64(match, val);
233 }
234
235 return (error);
236 }
237
238 /*
239 * Set the named uint64 in the given nvlist_t.
240 *
241 * @param attrs
242 * the nvlist_t to search
243 *
244 * @param which
245 * the string key for this element in the list
246 *
247 * @param val
248 * the value to set
249 *
250 * @return 0
251 * if successful
252 *
253 * @return EINVAL
254 * if there is an invalid argument
255 *
256 * @return ENOMEM
257 * if there is insufficient memory
258 */
259 int
set_uint64(nvlist_t * attrs,char * which,uint64_t val)260 set_uint64(
261 nvlist_t *attrs,
262 char *which,
263 uint64_t val)
264 {
265 int error = 0;
266
267 if ((error = nvlist_add_uint64(attrs, which, val)) != 0) {
268 volume_set_error(
269 gettext("nvlist_add_int64(%s) failed: %d\n"), which, error);
270 }
271
272 return (error);
273 }
274
275 /*
276 * Set the named boolean in the given nvlist_t.
277 *
278 * @param attrs
279 * the nvlist_t to search
280 *
281 * @param which
282 * the string key for this element in the list
283 *
284 * @param val
285 * the value to set
286 *
287 * @return 0
288 * if successful
289 *
290 * @return EINVAL
291 * if there is an invalid argument
292 *
293 * @return ENOMEM
294 * if there is insufficient memory
295 */
296 int
set_boolean(nvlist_t * attrs,char * which,boolean_t val)297 set_boolean(
298 nvlist_t *attrs,
299 char *which,
300 boolean_t val)
301 {
302 /*
303 * Use set_uint16 to distinguish "attr = B_FALSE" from
304 * "attribute unset".
305 */
306 return (set_uint16(attrs, which, val == B_TRUE ? 1 : 0));
307 }
308
309 /*
310 * Get the named boolean from the given nvlist_t.
311 *
312 * @param attrs
313 * the nvlist_t to search
314 *
315 * @param which
316 * the string key for this element in the list
317 *
318 * @param boolval
319 * RETURN: the value of the requested boolean
320 *
321 * @return 0
322 * if successful
323 *
324 * @return ENOENT
325 * if no matching name-value pair is found
326 */
327 int
get_boolean(nvlist_t * attrs,char * which,boolean_t * boolval)328 get_boolean(
329 nvlist_t *attrs,
330 char *which,
331 boolean_t *boolval)
332 {
333 int error;
334 uint16_t val;
335
336 /*
337 * Use get_uint16 to distinguish "attr = B_FALSE" from
338 * "attribute unset".
339 */
340 if ((error = get_uint16(attrs, which, &val)) == 0) {
341 *boolval = (val ? B_TRUE : B_FALSE);
342 }
343
344 return (error);
345 }
346
347 /*
348 * Get the named string from the given nvlist_t.
349 *
350 * @param attrs
351 * the nvlist_t to search
352 *
353 * @param which
354 * the string key for this element in the list
355 *
356 * @param str
357 * RETURN: the requested string
358 *
359 * @return 0
360 * if successful
361 *
362 * @return ENOENT
363 * if no matching name-value pair is found
364 */
365 int
get_string(nvlist_t * attrs,char * which,char ** str)366 get_string(
367 nvlist_t *attrs,
368 char *which,
369 char **str)
370 {
371 int error;
372 nvpair_t *match =
373 nvlist_walk_nvpair(attrs, which, DATA_TYPE_STRING, NULL);
374
375 if (match == NULL) {
376 error = ENOENT;
377 } else {
378 error = nvpair_value_string(match, str);
379 }
380
381 return (error);
382 }
383
384 /*
385 * Set the named string in the given nvlist_t.
386 *
387 * @param attrs
388 * the nvlist_t to search
389 *
390 * @param which
391 * the string key for this element in the list
392 *
393 * @param val
394 * the value to set
395 *
396 * @return 0
397 * if successful
398 *
399 * @return EINVAL
400 * if there is an invalid argument
401 *
402 * @return ENOMEM
403 * if there is insufficient memory
404 */
405 int
set_string(nvlist_t * attrs,char * which,char * val)406 set_string(
407 nvlist_t *attrs,
408 char *which,
409 char *val)
410 {
411 int error = 0;
412
413 if ((error = nvlist_add_string(attrs, which, val)) != 0) {
414 volume_set_error(
415 gettext("nvlist_add_string(%s) failed: %d\n"), which, error);
416 }
417
418 return (error);
419 }
420
421 /*
422 * Get the named uint16 array from the given nvlist_t.
423 *
424 * @param attrs
425 * the nvlist_t to search
426 *
427 * @param which
428 * the string key for this element in the list
429 *
430 * @param val
431 * RETURN: the value of the requested uint16 array
432 *
433 * @param nelem
434 * RETURN: the number of elements in the array
435 *
436 * @return 0
437 * if successful
438 *
439 * @return ENOENT
440 * if no matching name-value pair is found
441 */
442 int
get_uint16_array(nvlist_t * attrs,char * which,uint16_t ** val,uint_t * nelem)443 get_uint16_array(
444 nvlist_t *attrs,
445 char *which,
446 uint16_t **val,
447 uint_t *nelem)
448 {
449 int error;
450 nvpair_t *match =
451 nvlist_walk_nvpair(attrs, which, DATA_TYPE_UINT16_ARRAY, NULL);
452
453 if (match == NULL) {
454 error = ENOENT;
455 } else {
456 error = nvpair_value_uint16_array(match, val, nelem);
457 }
458
459 return (error);
460 }
461
462 /*
463 * Set the named uint16 array from the given nvlist_t.
464 *
465 * @param attrs
466 * the nvlist_t to search
467 *
468 * @param which
469 * the string key for this element in the list
470 *
471 * @param val
472 * the value of the requested uint16 array
473 *
474 * @param nelem
475 * the number of elements in the array
476 *
477 * @return 0
478 * if successful
479 *
480 * @return EINVAL
481 * if there is an invalid argument
482 *
483 * @return ENOMEM
484 * if there is insufficient memory
485 */
486 int
set_uint16_array(nvlist_t * attrs,char * which,uint16_t * val,uint_t nelem)487 set_uint16_array(
488 nvlist_t *attrs,
489 char *which,
490 uint16_t *val,
491 uint_t nelem)
492 {
493 int error = 0;
494
495 if ((error = nvlist_add_uint16_array(
496 attrs, which, val, nelem)) != 0) {
497 volume_set_error(
498 gettext("nvlist_add_uint16_array(%s) failed: %d.\n"),
499 which, error);
500 }
501
502 return (error);
503 }
504
505 /*
506 * Get the named uint64 array from the given nvlist_t.
507 *
508 * @param attrs
509 * the nvlist_t to search
510 *
511 * @param which
512 * the string key for this element in the list
513 *
514 * @param val
515 * RETURN: the value of the requested uint64 array
516 *
517 * @param nelem
518 * RETURN: the number of elements in the array
519 *
520 * @return 0
521 * if successful
522 *
523 * @return ENOENT
524 * if no matching name-value pair is found
525 */
526 int
get_uint64_array(nvlist_t * attrs,char * which,uint64_t ** val,uint_t * nelem)527 get_uint64_array(
528 nvlist_t *attrs,
529 char *which,
530 uint64_t **val,
531 uint_t *nelem)
532 {
533 int error;
534 nvpair_t *match =
535 nvlist_walk_nvpair(attrs, which, DATA_TYPE_UINT64_ARRAY, NULL);
536
537 if (match == NULL) {
538 error = ENOENT;
539 } else {
540 error = nvpair_value_uint64_array(match, val, nelem);
541 }
542
543 return (error);
544 }
545
546 /*
547 * Set the named uint64 array from the given nvlist_t.
548 *
549 * @param attrs
550 * the nvlist_t to search
551 *
552 * @param which
553 * the string key for this element in the list
554 *
555 * @param val
556 * the value of the requested uint64 array
557 *
558 * @param nelem
559 * the number of elements in the array
560 *
561 * @return 0
562 * if successful
563 *
564 * @return EINVAL
565 * if there is an invalid argument
566 *
567 * @return ENOMEM
568 * if there is insufficient memory
569 */
570 int
set_uint64_array(nvlist_t * attrs,char * which,uint64_t * val,uint_t nelem)571 set_uint64_array(
572 nvlist_t *attrs,
573 char *which,
574 uint64_t *val,
575 uint_t nelem)
576 {
577 int error = 0;
578
579 if ((error = nvlist_add_uint64_array(
580 attrs, which, val, nelem)) != 0) {
581 volume_set_error(
582 gettext("nvlist_add_uint64_array(%s) failed: %d.\n"),
583 which, error);
584 }
585
586 return (error);
587 }
588
589 /*
590 * Get the named string array from the given nvlist_t.
591 *
592 * @param attrs
593 * the nvlist_t to search
594 *
595 * @param which
596 * the string key for this element in the list
597 *
598 * @param val
599 * RETURN: the value of the requested string array
600 *
601 * @param nelem
602 * RETURN: the number of elements in the array
603 *
604 * @return 0
605 * if successful
606 *
607 * @return ENOENT
608 * if no matching name-value pair is found
609 */
610 int
get_string_array(nvlist_t * attrs,char * which,char *** val,uint_t * nelem)611 get_string_array(
612 nvlist_t *attrs,
613 char *which,
614 char ***val,
615 uint_t *nelem)
616 {
617 int error;
618 nvpair_t *match =
619 nvlist_walk_nvpair(attrs, which, DATA_TYPE_STRING_ARRAY, NULL);
620
621 if (match == NULL) {
622 error = ENOENT;
623 } else {
624 error = nvpair_value_string_array(match, val, nelem);
625 }
626
627 return (error);
628 }
629
630 /*
631 * Set the named string array from the given nvlist_t.
632 *
633 * @param attrs
634 * the nvlist_t to search
635 *
636 * @param which
637 * the string key for this element in the list
638 *
639 * @param val
640 * the value of the requested string array
641 *
642 * @param nelem
643 * the number of elements in the array
644 *
645 * @return 0
646 * if successful
647 *
648 * @return EINVAL
649 * if there is an invalid argument
650 *
651 * @return ENOMEM
652 * if there is insufficient memory
653 */
654 int
set_string_array(nvlist_t * attrs,char * which,char ** val,uint_t nelem)655 set_string_array(
656 nvlist_t *attrs,
657 char *which,
658 char **val,
659 uint_t nelem)
660 {
661 int error = 0;
662
663 if ((error = nvlist_add_string_array(
664 attrs, which, val, nelem)) != 0) {
665 volume_set_error(
666 gettext("nvlist_add_string_array(%s) failed: %d.\n"),
667 which, error);
668 }
669
670 return (error);
671 }
672
673 /*
674 * ******************************************************************
675 *
676 * Static functions
677 *
678 * ******************************************************************
679 */
680
681 /*
682 * Get a handle to the next nvpair with the specified name and data
683 * type in the list following the given nvpair.
684 *
685 * Some variation of this function will likely appear in the libnvpair
686 * library per 4981923.
687 *
688 * @param nvl
689 * the nvlist_t to search
690 *
691 * @param name
692 * the string key for the pair to find in the list, or
693 * NULL to match any name
694 *
695 * @param type
696 * the data type for the pair to find in the list, or
697 * DATA_TYPE_UNKNOWN to match any type
698 *
699 * @param nvp
700 * the pair to search from in the list, or NULL to search
701 * from the beginning of the list
702 *
703 * @return the next nvpair in the list matching the given
704 * criteria, or NULL if no matching nvpair is found
705 */
706 static nvpair_t *
nvlist_walk_nvpair(nvlist_t * nvl,const char * name,data_type_t type,nvpair_t * nvp)707 nvlist_walk_nvpair(
708 nvlist_t *nvl,
709 const char *name,
710 data_type_t type,
711 nvpair_t *nvp)
712 {
713 /* For each nvpair in the list following nvp... */
714 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
715
716 /* Does this pair's name match the given name? */
717 if ((name == NULL || strcmp(nvpair_name(nvp), name) == 0) &&
718
719 /* Does this pair's type match the given type? */
720 (type == DATA_TYPE_UNKNOWN || type == nvpair_type(nvp))) {
721 return (nvp);
722 }
723 }
724
725 return (NULL);
726 }
727