]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - cddl/contrib/opensolaris/lib/libnvpair/libnvpair.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / cddl / contrib / opensolaris / lib / libnvpair / libnvpair.c
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25
26 #pragma ident   "%Z%%M% %I%     %E% SMI"
27
28 #include <inttypes.h>
29 #include <unistd.h>
30 #include <strings.h>
31 #include "libnvpair.h"
32
33 /*
34  * libnvpair - A tools library for manipulating <name, value> pairs.
35  *
36  *      This library provides routines packing an unpacking nv pairs
37  *      for transporting data across process boundaries, transporting
38  *      between kernel and userland, and possibly saving onto disk files.
39  */
40
41 static void
42 indent(FILE *fp, int depth)
43 {
44         while (depth-- > 0)
45                 (void) fprintf(fp, "\t");
46 }
47
48 /*
49  * nvlist_print - Prints elements in an event buffer
50  */
51 static
52 void
53 nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
54 {
55         int i;
56         char *name;
57         uint_t nelem;
58         nvpair_t *nvp;
59
60         if (nvl == NULL)
61                 return;
62
63         indent(fp, depth);
64         (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl));
65
66         nvp = nvlist_next_nvpair(nvl, NULL);
67
68         while (nvp) {
69                 data_type_t type = nvpair_type(nvp);
70
71                 indent(fp, depth);
72                 name = nvpair_name(nvp);
73                 (void) fprintf(fp, "\t%s =", name);
74                 nelem = 0;
75                 switch (type) {
76                 case DATA_TYPE_BOOLEAN: {
77                         (void) fprintf(fp, " 1");
78                         break;
79                 }
80                 case DATA_TYPE_BOOLEAN_VALUE: {
81                         boolean_t val;
82                         (void) nvpair_value_boolean_value(nvp, &val);
83                         (void) fprintf(fp, " %d", val);
84                         break;
85                 }
86                 case DATA_TYPE_BYTE: {
87                         uchar_t val;
88                         (void) nvpair_value_byte(nvp, &val);
89                         (void) fprintf(fp, " 0x%2.2x", val);
90                         break;
91                 }
92                 case DATA_TYPE_INT8: {
93                         int8_t val;
94                         (void) nvpair_value_int8(nvp, &val);
95                         (void) fprintf(fp, " %d", val);
96                         break;
97                 }
98                 case DATA_TYPE_UINT8: {
99                         uint8_t val;
100                         (void) nvpair_value_uint8(nvp, &val);
101                         (void) fprintf(fp, " 0x%x", val);
102                         break;
103                 }
104                 case DATA_TYPE_INT16: {
105                         int16_t val;
106                         (void) nvpair_value_int16(nvp, &val);
107                         (void) fprintf(fp, " %d", val);
108                         break;
109                 }
110                 case DATA_TYPE_UINT16: {
111                         uint16_t val;
112                         (void) nvpair_value_uint16(nvp, &val);
113                         (void) fprintf(fp, " 0x%x", val);
114                         break;
115                 }
116                 case DATA_TYPE_INT32: {
117                         int32_t val;
118                         (void) nvpair_value_int32(nvp, &val);
119                         (void) fprintf(fp, " %d", val);
120                         break;
121                 }
122                 case DATA_TYPE_UINT32: {
123                         uint32_t val;
124                         (void) nvpair_value_uint32(nvp, &val);
125                         (void) fprintf(fp, " 0x%x", val);
126                         break;
127                 }
128                 case DATA_TYPE_INT64: {
129                         int64_t val;
130                         (void) nvpair_value_int64(nvp, &val);
131                         (void) fprintf(fp, " %lld", (longlong_t)val);
132                         break;
133                 }
134                 case DATA_TYPE_UINT64: {
135                         uint64_t val;
136                         (void) nvpair_value_uint64(nvp, &val);
137                         (void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
138                         break;
139                 }
140                 case DATA_TYPE_DOUBLE: {
141                         double val;
142                         (void) nvpair_value_double(nvp, &val);
143                         (void) fprintf(fp, " 0x%llf", val);
144                         break;
145                 }
146                 case DATA_TYPE_STRING: {
147                         char *val;
148                         (void) nvpair_value_string(nvp, &val);
149                         (void) fprintf(fp, " %s", val);
150                         break;
151                 }
152                 case DATA_TYPE_BOOLEAN_ARRAY: {
153                         boolean_t *val;
154                         (void) nvpair_value_boolean_array(nvp, &val, &nelem);
155                         for (i = 0; i < nelem; i++)
156                                 (void) fprintf(fp, " %d", val[i]);
157                         break;
158                 }
159                 case DATA_TYPE_BYTE_ARRAY: {
160                         uchar_t *val;
161                         (void) nvpair_value_byte_array(nvp, &val, &nelem);
162                         for (i = 0; i < nelem; i++)
163                                 (void) fprintf(fp, " 0x%2.2x", val[i]);
164                         break;
165                 }
166                 case DATA_TYPE_INT8_ARRAY: {
167                         int8_t *val;
168                         (void) nvpair_value_int8_array(nvp, &val, &nelem);
169                         for (i = 0; i < nelem; i++)
170                                 (void) fprintf(fp, " %d", val[i]);
171                         break;
172                 }
173                 case DATA_TYPE_UINT8_ARRAY: {
174                         uint8_t *val;
175                         (void) nvpair_value_uint8_array(nvp, &val, &nelem);
176                         for (i = 0; i < nelem; i++)
177                                 (void) fprintf(fp, " 0x%x", val[i]);
178                         break;
179                 }
180                 case DATA_TYPE_INT16_ARRAY: {
181                         int16_t *val;
182                         (void) nvpair_value_int16_array(nvp, &val, &nelem);
183                         for (i = 0; i < nelem; i++)
184                                 (void) fprintf(fp, " %d", val[i]);
185                         break;
186                 }
187                 case DATA_TYPE_UINT16_ARRAY: {
188                         uint16_t *val;
189                         (void) nvpair_value_uint16_array(nvp, &val, &nelem);
190                         for (i = 0; i < nelem; i++)
191                                 (void) fprintf(fp, " 0x%x", val[i]);
192                         break;
193                 }
194                 case DATA_TYPE_INT32_ARRAY: {
195                         int32_t *val;
196                         (void) nvpair_value_int32_array(nvp, &val, &nelem);
197                         for (i = 0; i < nelem; i++)
198                                 (void) fprintf(fp, " %d", val[i]);
199                         break;
200                 }
201                 case DATA_TYPE_UINT32_ARRAY: {
202                         uint32_t *val;
203                         (void) nvpair_value_uint32_array(nvp, &val, &nelem);
204                         for (i = 0; i < nelem; i++)
205                                 (void) fprintf(fp, " 0x%x", val[i]);
206                         break;
207                 }
208                 case DATA_TYPE_INT64_ARRAY: {
209                         int64_t *val;
210                         (void) nvpair_value_int64_array(nvp, &val, &nelem);
211                         for (i = 0; i < nelem; i++)
212                                 (void) fprintf(fp, " %lld", (longlong_t)val[i]);
213                         break;
214                 }
215                 case DATA_TYPE_UINT64_ARRAY: {
216                         uint64_t *val;
217                         (void) nvpair_value_uint64_array(nvp, &val, &nelem);
218                         for (i = 0; i < nelem; i++)
219                                 (void) fprintf(fp, " 0x%llx",
220                                     (u_longlong_t)val[i]);
221                         break;
222                 }
223                 case DATA_TYPE_STRING_ARRAY: {
224                         char **val;
225                         (void) nvpair_value_string_array(nvp, &val, &nelem);
226                         for (i = 0; i < nelem; i++)
227                                 (void) fprintf(fp, " %s", val[i]);
228                         break;
229                 }
230                 case DATA_TYPE_HRTIME: {
231                         hrtime_t val;
232                         (void) nvpair_value_hrtime(nvp, &val);
233                         (void) fprintf(fp, " 0x%llx", val);
234                         break;
235                 }
236                 case DATA_TYPE_NVLIST: {
237                         nvlist_t *val;
238                         (void) nvpair_value_nvlist(nvp, &val);
239                         (void) fprintf(fp, " (embedded nvlist)\n");
240                         nvlist_print_with_indent(fp, val, depth + 1);
241                         indent(fp, depth + 1);
242                         (void) fprintf(fp, "(end %s)\n", name);
243                         break;
244                 }
245                 case DATA_TYPE_NVLIST_ARRAY: {
246                         nvlist_t **val;
247                         (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
248                         (void) fprintf(fp, " (array of embedded nvlists)\n");
249                         for (i = 0; i < nelem; i++) {
250                                 indent(fp, depth + 1);
251                                 (void) fprintf(fp,
252                                     "(start %s[%d])\n", name, i);
253                                 nvlist_print_with_indent(fp, val[i], depth + 1);
254                                 indent(fp, depth + 1);
255                                 (void) fprintf(fp, "(end %s[%d])\n", name, i);
256                         }
257                         break;
258                 }
259                 default:
260                         (void) fprintf(fp, " unknown data type (%d)", type);
261                         break;
262                 }
263                 (void) fprintf(fp, "\n");
264                 nvp = nvlist_next_nvpair(nvl, nvp);
265         }
266 }
267
268 void
269 nvlist_print(FILE *fp, nvlist_t *nvl)
270 {
271         nvlist_print_with_indent(fp, nvl, 0);
272 }
273
274 /*
275  * Determine if string 'value' matches 'nvp' value.  The 'value' string is
276  * converted, depending on the type of 'nvp', prior to match.  For numeric
277  * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
278  * is an array type, 'ai' is the index into the array against which we are
279  * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
280  * in a regex_t compilation of value in 'value_regex' to trigger regular
281  * expression string match instead of simple strcmp().
282  *
283  * Return 1 on match, 0 on no-match, and -1 on error.  If the error is
284  * related to value syntax error and 'ep' is non-NULL, *ep will point into
285  * the 'value' string at the location where the error exists.
286  *
287  * NOTE: It may be possible to move the non-regex_t version of this into
288  * common code used by library/kernel/boot.
289  */
290 int
291 nvpair_value_match_regex(nvpair_t *nvp, int ai,
292     char *value, regex_t *value_regex, char **ep)
293 {
294         char    *evalue;
295         uint_t  a_len;
296         int     sr;
297
298         if (ep)
299                 *ep = NULL;
300
301         if ((nvp == NULL) || (value == NULL))
302                 return (-1);            /* error fail match - invalid args */
303
304         /* make sure array and index combination make sense */
305         if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
306             (!nvpair_type_is_array(nvp) && (ai >= 0)))
307                 return (-1);            /* error fail match - bad index */
308
309         /* non-string values should be single 'chunk' */
310         if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
311             (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
312                 value += strspn(value, " \t");
313                 evalue = value + strcspn(value, " \t");
314                 if (*evalue) {
315                         if (ep)
316                                 *ep = evalue;
317                         return (-1);    /* error fail match - syntax */
318                 }
319         }
320
321         sr = EOF;
322         switch (nvpair_type(nvp)) {
323         case DATA_TYPE_STRING: {
324                 char    *val;
325
326                 /* check string value for match */
327                 if (nvpair_value_string(nvp, &val) == 0) {
328                         if (value_regex) {
329                                 if (regexec(value_regex, val,
330                                     (size_t)0, NULL, 0) == 0)
331                                         return (1);     /* match */
332                         } else {
333                                 if (strcmp(value, val) == 0)
334                                         return (1);     /* match */
335                         }
336                 }
337                 break;
338         }
339         case DATA_TYPE_STRING_ARRAY: {
340                 char **val_array;
341
342                 /* check indexed string value of array for match */
343                 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
344                     (ai < a_len)) {
345                         if (value_regex) {
346                                 if (regexec(value_regex, val_array[ai],
347                                     (size_t)0, NULL, 0) == 0)
348                                         return (1);
349                         } else {
350                                 if (strcmp(value, val_array[ai]) == 0)
351                                         return (1);
352                         }
353                 }
354                 break;
355         }
356         case DATA_TYPE_BYTE: {
357                 uchar_t val, val_arg;
358
359                 /* scanf uchar_t from value and check for match */
360                 sr = sscanf(value, "%c", &val_arg);
361                 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
362                     (val == val_arg))
363                         return (1);
364                 break;
365         }
366         case DATA_TYPE_BYTE_ARRAY: {
367                 uchar_t *val_array, val_arg;
368
369
370                 /* check indexed value of array for match */
371                 sr = sscanf(value, "%c", &val_arg);
372                 if ((sr == 1) &&
373                     (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
374                     (ai < a_len) &&
375                     (val_array[ai] == val_arg))
376                         return (1);
377                 break;
378         }
379         case DATA_TYPE_INT8: {
380                 int8_t val, val_arg;
381
382                 /* scanf int8_t from value and check for match */
383                 sr = sscanf(value, "%"SCNi8, &val_arg);
384                 if ((sr == 1) &&
385                     (nvpair_value_int8(nvp, &val) == 0) &&
386                     (val == val_arg))
387                         return (1);
388                 break;
389         }
390         case DATA_TYPE_INT8_ARRAY: {
391                 int8_t *val_array, val_arg;
392
393                 /* check indexed value of array for match */
394                 sr = sscanf(value, "%"SCNi8, &val_arg);
395                 if ((sr == 1) &&
396                     (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
397                     (ai < a_len) &&
398                     (val_array[ai] == val_arg))
399                         return (1);
400                 break;
401         }
402         case DATA_TYPE_UINT8: {
403                 uint8_t val, val_arg;
404
405                 /* scanf uint8_t from value and check for match */
406                 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
407                 if ((sr == 1) &&
408                     (nvpair_value_uint8(nvp, &val) == 0) &&
409                     (val == val_arg))
410                         return (1);
411                 break;
412         }
413         case DATA_TYPE_UINT8_ARRAY: {
414                 uint8_t *val_array, val_arg;
415
416                 /* check indexed value of array for match */
417                 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
418                 if ((sr == 1) &&
419                     (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
420                     (ai < a_len) &&
421                     (val_array[ai] == val_arg))
422                         return (1);
423                 break;
424         }
425         case DATA_TYPE_INT16: {
426                 int16_t val, val_arg;
427
428                 /* scanf int16_t from value and check for match */
429                 sr = sscanf(value, "%"SCNi16, &val_arg);
430                 if ((sr == 1) &&
431                     (nvpair_value_int16(nvp, &val) == 0) &&
432                     (val == val_arg))
433                         return (1);
434                 break;
435         }
436         case DATA_TYPE_INT16_ARRAY: {
437                 int16_t *val_array, val_arg;
438
439                 /* check indexed value of array for match */
440                 sr = sscanf(value, "%"SCNi16, &val_arg);
441                 if ((sr == 1) &&
442                     (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
443                     (ai < a_len) &&
444                     (val_array[ai] == val_arg))
445                         return (1);
446                 break;
447         }
448         case DATA_TYPE_UINT16: {
449                 uint16_t val, val_arg;
450
451                 /* scanf uint16_t from value and check for match */
452                 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
453                 if ((sr == 1) &&
454                     (nvpair_value_uint16(nvp, &val) == 0) &&
455                     (val == val_arg))
456                         return (1);
457                 break;
458         }
459         case DATA_TYPE_UINT16_ARRAY: {
460                 uint16_t *val_array, val_arg;
461
462                 /* check indexed value of array for match */
463                 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
464                 if ((sr == 1) &&
465                     (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
466                     (ai < a_len) &&
467                     (val_array[ai] == val_arg))
468                         return (1);
469                 break;
470         }
471         case DATA_TYPE_INT32: {
472                 int32_t val, val_arg;
473
474                 /* scanf int32_t from value and check for match */
475                 sr = sscanf(value, "%"SCNi32, &val_arg);
476                 if ((sr == 1) &&
477                     (nvpair_value_int32(nvp, &val) == 0) &&
478                     (val == val_arg))
479                         return (1);
480                 break;
481         }
482         case DATA_TYPE_INT32_ARRAY: {
483                 int32_t *val_array, val_arg;
484
485                 /* check indexed value of array for match */
486                 sr = sscanf(value, "%"SCNi32, &val_arg);
487                 if ((sr == 1) &&
488                     (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
489                     (ai < a_len) &&
490                     (val_array[ai] == val_arg))
491                         return (1);
492                 break;
493         }
494         case DATA_TYPE_UINT32: {
495                 uint32_t val, val_arg;
496
497                 /* scanf uint32_t from value and check for match */
498                 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
499                 if ((sr == 1) &&
500                     (nvpair_value_uint32(nvp, &val) == 0) &&
501                     (val == val_arg))
502                         return (1);
503                 break;
504         }
505         case DATA_TYPE_UINT32_ARRAY: {
506                 uint32_t *val_array, val_arg;
507
508                 /* check indexed value of array for match */
509                 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
510                 if ((sr == 1) &&
511                     (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
512                     (ai < a_len) &&
513                     (val_array[ai] == val_arg))
514                         return (1);
515                 break;
516         }
517         case DATA_TYPE_INT64: {
518                 int64_t val, val_arg;
519
520                 /* scanf int64_t from value and check for match */
521                 sr = sscanf(value, "%"SCNi64, &val_arg);
522                 if ((sr == 1) &&
523                     (nvpair_value_int64(nvp, &val) == 0) &&
524                     (val == val_arg))
525                         return (1);
526                 break;
527         }
528         case DATA_TYPE_INT64_ARRAY: {
529                 int64_t *val_array, val_arg;
530
531                 /* check indexed value of array for match */
532                 sr = sscanf(value, "%"SCNi64, &val_arg);
533                 if ((sr == 1) &&
534                     (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
535                     (ai < a_len) &&
536                     (val_array[ai] == val_arg))
537                                 return (1);
538                 break;
539         }
540         case DATA_TYPE_UINT64: {
541                 uint64_t val_arg, val;
542
543                 /* scanf uint64_t from value and check for match */
544                 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
545                 if ((sr == 1) &&
546                     (nvpair_value_uint64(nvp, &val) == 0) &&
547                     (val == val_arg))
548                         return (1);
549                 break;
550         }
551         case DATA_TYPE_UINT64_ARRAY: {
552                 uint64_t *val_array, val_arg;
553
554                 /* check indexed value of array for match */
555                 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
556                 if ((sr == 1) &&
557                     (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
558                     (ai < a_len) &&
559                     (val_array[ai] == val_arg))
560                         return (1);
561                 break;
562         }
563         case DATA_TYPE_BOOLEAN_VALUE: {
564                 boolean_t val, val_arg;
565
566                 /* scanf boolean_t from value and check for match */
567                 sr = sscanf(value, "%"SCNi32, &val_arg);
568                 if ((sr == 1) &&
569                     (nvpair_value_boolean_value(nvp, &val) == 0) &&
570                     (val == val_arg))
571                         return (1);
572                 break;
573         }
574         case DATA_TYPE_BOOLEAN_ARRAY: {
575                 boolean_t *val_array, val_arg;
576
577                 /* check indexed value of array for match */
578                 sr = sscanf(value, "%"SCNi32, &val_arg);
579                 if ((sr == 1) &&
580                     (nvpair_value_boolean_array(nvp,
581                     &val_array, &a_len) == 0) &&
582                     (ai < a_len) &&
583                     (val_array[ai] == val_arg))
584                         return (1);
585                 break;
586         }
587         case DATA_TYPE_HRTIME:
588         case DATA_TYPE_NVLIST:
589         case DATA_TYPE_NVLIST_ARRAY:
590         case DATA_TYPE_BOOLEAN:
591         case DATA_TYPE_DOUBLE:
592         case DATA_TYPE_UNKNOWN:
593         default:
594                 /*
595                  * unknown/unsupported data type
596                  */
597                 return (-1);            /* error fail match */
598         }
599
600         /*
601          * check to see if sscanf failed conversion, return approximate
602          * pointer to problem
603          */
604         if (sr != 1) {
605                 if (ep)
606                         *ep = value;
607                 return (-1);            /* error fail match  - syntax */
608         }
609
610         return (0);                     /* fail match */
611 }
612
613 int
614 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
615 {
616         return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
617 }