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