The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_nvpair.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2009-2013 The FreeBSD Foundation
    3  * All rights reserved.
    4  *
    5  * This software was developed by Pawel Jakub Dawidek under sponsorship from
    6  * the FreeBSD Foundation.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include <sys/param.h>
   34 #include <sys/endian.h>
   35 #include <sys/queue.h>
   36 
   37 #ifdef _KERNEL
   38 
   39 #include <sys/errno.h>
   40 #include <sys/lock.h>
   41 #include <sys/malloc.h>
   42 #include <sys/systm.h>
   43 
   44 #include <machine/stdarg.h>
   45 
   46 #else
   47 #include <errno.h>
   48 #include <fcntl.h>
   49 #include <stdarg.h>
   50 #include <stdbool.h>
   51 #include <stdint.h>
   52 #include <stdlib.h>
   53 #include <string.h>
   54 #include <unistd.h>
   55 
   56 #include "common_impl.h"
   57 #endif
   58 
   59 #ifdef HAVE_PJDLOG
   60 #include <pjdlog.h>
   61 #endif
   62 
   63 #include <sys/nv.h>
   64 #include <sys/nv_impl.h>
   65 #include <sys/nvlist_impl.h>
   66 #include <sys/nvpair_impl.h>
   67 
   68 #ifndef HAVE_PJDLOG
   69 #ifdef _KERNEL
   70 #define PJDLOG_ASSERT(...)              MPASS(__VA_ARGS__)
   71 #define PJDLOG_RASSERT(expr, ...)       KASSERT(expr, (__VA_ARGS__))
   72 #define PJDLOG_ABORT(...)               panic(__VA_ARGS__)
   73 #else
   74 #include <assert.h>
   75 #define PJDLOG_ASSERT(...)              assert(__VA_ARGS__)
   76 #define PJDLOG_RASSERT(expr, ...)       assert(expr)
   77 #define PJDLOG_ABORT(...)               abort()
   78 #endif
   79 #endif
   80 
   81 #define NVPAIR_MAGIC    0x6e7670        /* "nvp" */
   82 struct nvpair {
   83         int              nvp_magic;
   84         char            *nvp_name;
   85         int              nvp_type;
   86         uint64_t         nvp_data;
   87         size_t           nvp_datasize;
   88         nvlist_t        *nvp_list;
   89         TAILQ_ENTRY(nvpair) nvp_next;
   90 };
   91 
   92 #define NVPAIR_ASSERT(nvp)      do {                                    \
   93         PJDLOG_ASSERT((nvp) != NULL);                                   \
   94         PJDLOG_ASSERT((nvp)->nvp_magic == NVPAIR_MAGIC);                \
   95 } while (0)
   96 
   97 struct nvpair_header {
   98         uint8_t         nvph_type;
   99         uint16_t        nvph_namesize;
  100         uint64_t        nvph_datasize;
  101 } __packed;
  102 
  103 
  104 void
  105 nvpair_assert(const nvpair_t *nvp)
  106 {
  107 
  108         NVPAIR_ASSERT(nvp);
  109 }
  110 
  111 nvlist_t *
  112 nvpair_nvlist(const nvpair_t *nvp)
  113 {
  114 
  115         NVPAIR_ASSERT(nvp);
  116 
  117         return (nvp->nvp_list);
  118 }
  119 
  120 nvpair_t *
  121 nvpair_next(const nvpair_t *nvp)
  122 {
  123 
  124         NVPAIR_ASSERT(nvp);
  125         PJDLOG_ASSERT(nvp->nvp_list != NULL);
  126 
  127         return (TAILQ_NEXT(nvp, nvp_next));
  128 }
  129 
  130 nvpair_t *
  131 nvpair_prev(const nvpair_t *nvp)
  132 {
  133 
  134         NVPAIR_ASSERT(nvp);
  135         PJDLOG_ASSERT(nvp->nvp_list != NULL);
  136 
  137         return (TAILQ_PREV(nvp, nvl_head, nvp_next));
  138 }
  139 
  140 void
  141 nvpair_insert(struct nvl_head *head, nvpair_t *nvp, nvlist_t *nvl)
  142 {
  143 
  144         NVPAIR_ASSERT(nvp);
  145         PJDLOG_ASSERT(nvp->nvp_list == NULL);
  146         PJDLOG_ASSERT(!nvlist_exists(nvl, nvpair_name(nvp)));
  147 
  148         TAILQ_INSERT_TAIL(head, nvp, nvp_next);
  149         nvp->nvp_list = nvl;
  150 }
  151 
  152 static void
  153 nvpair_remove_nvlist(nvpair_t *nvp)
  154 {
  155         nvlist_t *nvl;
  156 
  157         /* XXX: DECONST is bad, mkay? */
  158         nvl = __DECONST(nvlist_t *, nvpair_get_nvlist(nvp));
  159         PJDLOG_ASSERT(nvl != NULL);
  160         nvlist_set_parent(nvl, NULL);
  161 }
  162 
  163 void
  164 nvpair_remove(struct nvl_head *head, nvpair_t *nvp, const nvlist_t *nvl)
  165 {
  166 
  167         NVPAIR_ASSERT(nvp);
  168         PJDLOG_ASSERT(nvp->nvp_list == nvl);
  169 
  170         if (nvpair_type(nvp) == NV_TYPE_NVLIST)
  171                 nvpair_remove_nvlist(nvp);
  172 
  173         TAILQ_REMOVE(head, nvp, nvp_next);
  174         nvp->nvp_list = NULL;
  175 }
  176 
  177 nvpair_t *
  178 nvpair_clone(const nvpair_t *nvp)
  179 {
  180         nvpair_t *newnvp;
  181         const char *name;
  182         const void *data;
  183         size_t datasize;
  184 
  185         NVPAIR_ASSERT(nvp);
  186 
  187         name = nvpair_name(nvp);
  188 
  189         switch (nvpair_type(nvp)) {
  190         case NV_TYPE_NULL:
  191                 newnvp = nvpair_create_null(name);
  192                 break;
  193         case NV_TYPE_BOOL:
  194                 newnvp = nvpair_create_bool(name, nvpair_get_bool(nvp));
  195                 break;
  196         case NV_TYPE_NUMBER:
  197                 newnvp = nvpair_create_number(name, nvpair_get_number(nvp));
  198                 break;
  199         case NV_TYPE_STRING:
  200                 newnvp = nvpair_create_string(name, nvpair_get_string(nvp));
  201                 break;
  202         case NV_TYPE_NVLIST:
  203                 newnvp = nvpair_create_nvlist(name, nvpair_get_nvlist(nvp));
  204                 break;
  205 #ifndef _KERNEL
  206         case NV_TYPE_DESCRIPTOR:
  207                 newnvp = nvpair_create_descriptor(name,
  208                     nvpair_get_descriptor(nvp));
  209                 break;
  210 #endif
  211         case NV_TYPE_BINARY:
  212                 data = nvpair_get_binary(nvp, &datasize);
  213                 newnvp = nvpair_create_binary(name, data, datasize);
  214                 break;
  215         default:
  216                 PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
  217         }
  218 
  219         return (newnvp);
  220 }
  221 
  222 size_t
  223 nvpair_header_size(void)
  224 {
  225 
  226         return (sizeof(struct nvpair_header));
  227 }
  228 
  229 size_t
  230 nvpair_size(const nvpair_t *nvp)
  231 {
  232 
  233         NVPAIR_ASSERT(nvp);
  234 
  235         return (nvp->nvp_datasize);
  236 }
  237 
  238 unsigned char *
  239 nvpair_pack_header(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  240 {
  241         struct nvpair_header nvphdr;
  242         size_t namesize;
  243 
  244         NVPAIR_ASSERT(nvp);
  245 
  246         nvphdr.nvph_type = nvp->nvp_type;
  247         namesize = strlen(nvp->nvp_name) + 1;
  248         PJDLOG_ASSERT(namesize > 0 && namesize <= UINT16_MAX);
  249         nvphdr.nvph_namesize = namesize;
  250         nvphdr.nvph_datasize = nvp->nvp_datasize;
  251         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
  252         memcpy(ptr, &nvphdr, sizeof(nvphdr));
  253         ptr += sizeof(nvphdr);
  254         *leftp -= sizeof(nvphdr);
  255 
  256         PJDLOG_ASSERT(*leftp >= namesize);
  257         memcpy(ptr, nvp->nvp_name, namesize);
  258         ptr += namesize;
  259         *leftp -= namesize;
  260 
  261         return (ptr);
  262 }
  263 
  264 unsigned char *
  265 nvpair_pack_null(const nvpair_t *nvp, unsigned char *ptr,
  266     size_t *leftp __unused)
  267 {
  268 
  269         NVPAIR_ASSERT(nvp);
  270         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
  271 
  272         return (ptr);
  273 }
  274 
  275 unsigned char *
  276 nvpair_pack_bool(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  277 {
  278         uint8_t value;
  279 
  280         NVPAIR_ASSERT(nvp);
  281         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
  282 
  283         value = (uint8_t)nvp->nvp_data;
  284 
  285         PJDLOG_ASSERT(*leftp >= sizeof(value));
  286         memcpy(ptr, &value, sizeof(value));
  287         ptr += sizeof(value);
  288         *leftp -= sizeof(value);
  289 
  290         return (ptr);
  291 }
  292 
  293 unsigned char *
  294 nvpair_pack_number(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  295 {
  296         uint64_t value;
  297 
  298         NVPAIR_ASSERT(nvp);
  299         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
  300 
  301         value = (uint64_t)nvp->nvp_data;
  302 
  303         PJDLOG_ASSERT(*leftp >= sizeof(value));
  304         memcpy(ptr, &value, sizeof(value));
  305         ptr += sizeof(value);
  306         *leftp -= sizeof(value);
  307 
  308         return (ptr);
  309 }
  310 
  311 unsigned char *
  312 nvpair_pack_string(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  313 {
  314 
  315         NVPAIR_ASSERT(nvp);
  316         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
  317 
  318         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  319         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
  320         ptr += nvp->nvp_datasize;
  321         *leftp -= nvp->nvp_datasize;
  322 
  323         return (ptr);
  324 }
  325 
  326 unsigned char *
  327 nvpair_pack_nvlist_up(unsigned char *ptr, size_t *leftp)
  328 {
  329         struct nvpair_header nvphdr;
  330         size_t namesize;
  331         const char *name = "";
  332 
  333         namesize = 1;
  334         nvphdr.nvph_type = NV_TYPE_NVLIST_UP;
  335         nvphdr.nvph_namesize = namesize;
  336         nvphdr.nvph_datasize = 0;
  337         PJDLOG_ASSERT(*leftp >= sizeof(nvphdr));
  338         memcpy(ptr, &nvphdr, sizeof(nvphdr));
  339         ptr += sizeof(nvphdr);
  340         *leftp -= sizeof(nvphdr);
  341 
  342         PJDLOG_ASSERT(*leftp >= namesize);
  343         memcpy(ptr, name, namesize);
  344         ptr += namesize;
  345         *leftp -= namesize;
  346 
  347         return (ptr);
  348 }
  349 
  350 #ifndef _KERNEL
  351 unsigned char *
  352 nvpair_pack_descriptor(const nvpair_t *nvp, unsigned char *ptr, int64_t *fdidxp,
  353     size_t *leftp)
  354 {
  355         int64_t value;
  356 
  357         NVPAIR_ASSERT(nvp);
  358         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
  359 
  360         value = (int64_t)nvp->nvp_data;
  361         if (value != -1) {
  362                 /*
  363                  * If there is a real descriptor here, we change its number
  364                  * to position in the array of descriptors send via control
  365                  * message.
  366                  */
  367                 PJDLOG_ASSERT(fdidxp != NULL);
  368 
  369                 value = *fdidxp;
  370                 (*fdidxp)++;
  371         }
  372 
  373         PJDLOG_ASSERT(*leftp >= sizeof(value));
  374         memcpy(ptr, &value, sizeof(value));
  375         ptr += sizeof(value);
  376         *leftp -= sizeof(value);
  377 
  378         return (ptr);
  379 }
  380 #endif
  381 
  382 unsigned char *
  383 nvpair_pack_binary(const nvpair_t *nvp, unsigned char *ptr, size_t *leftp)
  384 {
  385 
  386         NVPAIR_ASSERT(nvp);
  387         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
  388 
  389         PJDLOG_ASSERT(*leftp >= nvp->nvp_datasize);
  390         memcpy(ptr, (const void *)(intptr_t)nvp->nvp_data, nvp->nvp_datasize);
  391         ptr += nvp->nvp_datasize;
  392         *leftp -= nvp->nvp_datasize;
  393 
  394         return (ptr);
  395 }
  396 
  397 void
  398 nvpair_init_datasize(nvpair_t *nvp)
  399 {
  400 
  401         NVPAIR_ASSERT(nvp);
  402 
  403         if (nvp->nvp_type == NV_TYPE_NVLIST) {
  404                 if (nvp->nvp_data == 0) {
  405                         nvp->nvp_datasize = 0;
  406                 } else {
  407                         nvp->nvp_datasize =
  408                             nvlist_size((const nvlist_t *)(intptr_t)nvp->nvp_data);
  409                 }
  410         }
  411 }
  412 
  413 const unsigned char *
  414 nvpair_unpack_header(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  415     size_t *leftp)
  416 {
  417         struct nvpair_header nvphdr;
  418 
  419         if (*leftp < sizeof(nvphdr))
  420                 goto failed;
  421 
  422         memcpy(&nvphdr, ptr, sizeof(nvphdr));
  423         ptr += sizeof(nvphdr);
  424         *leftp -= sizeof(nvphdr);
  425 
  426 #if NV_TYPE_FIRST > 0
  427         if (nvphdr.nvph_type < NV_TYPE_FIRST)
  428                 goto failed;
  429 #endif
  430         if (nvphdr.nvph_type > NV_TYPE_LAST &&
  431             nvphdr.nvph_type != NV_TYPE_NVLIST_UP) {
  432                 goto failed;
  433         }
  434 
  435 #if BYTE_ORDER == BIG_ENDIAN
  436         if (!isbe) {
  437                 nvphdr.nvph_namesize = le16toh(nvphdr.nvph_namesize);
  438                 nvphdr.nvph_datasize = le64toh(nvphdr.nvph_datasize);
  439         }
  440 #else
  441         if (isbe) {
  442                 nvphdr.nvph_namesize = be16toh(nvphdr.nvph_namesize);
  443                 nvphdr.nvph_datasize = be64toh(nvphdr.nvph_datasize);
  444         }
  445 #endif
  446 
  447         if (nvphdr.nvph_namesize > NV_NAME_MAX)
  448                 goto failed;
  449         if (*leftp < nvphdr.nvph_namesize)
  450                 goto failed;
  451         if (nvphdr.nvph_namesize < 1)
  452                 goto failed;
  453         if (strnlen((const char *)ptr, nvphdr.nvph_namesize) !=
  454             (size_t)(nvphdr.nvph_namesize - 1)) {
  455                 goto failed;
  456         }
  457 
  458         memcpy(nvp->nvp_name, ptr, nvphdr.nvph_namesize);
  459         ptr += nvphdr.nvph_namesize;
  460         *leftp -= nvphdr.nvph_namesize;
  461 
  462         if (*leftp < nvphdr.nvph_datasize)
  463                 goto failed;
  464 
  465         nvp->nvp_type = nvphdr.nvph_type;
  466         nvp->nvp_data = 0;
  467         nvp->nvp_datasize = nvphdr.nvph_datasize;
  468 
  469         return (ptr);
  470 failed:
  471         RESTORE_ERRNO(EINVAL);
  472         return (NULL);
  473 }
  474 
  475 const unsigned char *
  476 nvpair_unpack_null(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
  477     size_t *leftp __unused)
  478 {
  479 
  480         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NULL);
  481 
  482         if (nvp->nvp_datasize != 0) {
  483                 RESTORE_ERRNO(EINVAL);
  484                 return (NULL);
  485         }
  486 
  487         return (ptr);
  488 }
  489 
  490 const unsigned char *
  491 nvpair_unpack_bool(bool isbe __unused, nvpair_t *nvp, const unsigned char *ptr,
  492     size_t *leftp)
  493 {
  494         uint8_t value;
  495 
  496         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BOOL);
  497 
  498         if (nvp->nvp_datasize != sizeof(value)) {
  499                 RESTORE_ERRNO(EINVAL);
  500                 return (NULL);
  501         }
  502         if (*leftp < sizeof(value)) {
  503                 RESTORE_ERRNO(EINVAL);
  504                 return (NULL);
  505         }
  506 
  507         memcpy(&value, ptr, sizeof(value));
  508         ptr += sizeof(value);
  509         *leftp -= sizeof(value);
  510 
  511         if (value != 0 && value != 1) {
  512                 RESTORE_ERRNO(EINVAL);
  513                 return (NULL);
  514         }
  515 
  516         nvp->nvp_data = (uint64_t)value;
  517 
  518         return (ptr);
  519 }
  520 
  521 const unsigned char *
  522 nvpair_unpack_number(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  523      size_t *leftp)
  524 {
  525 
  526         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NUMBER);
  527 
  528         if (nvp->nvp_datasize != sizeof(uint64_t)) {
  529                 RESTORE_ERRNO(EINVAL);
  530                 return (NULL);
  531         }
  532         if (*leftp < sizeof(uint64_t)) {
  533                 RESTORE_ERRNO(EINVAL);
  534                 return (NULL);
  535         }
  536 
  537         if (isbe)
  538                 nvp->nvp_data = be64dec(ptr);
  539         else
  540                 nvp->nvp_data = le64dec(ptr);
  541         ptr += sizeof(uint64_t);
  542         *leftp -= sizeof(uint64_t);
  543 
  544         return (ptr);
  545 }
  546 
  547 const unsigned char *
  548 nvpair_unpack_string(bool isbe __unused, nvpair_t *nvp,
  549     const unsigned char *ptr, size_t *leftp)
  550 {
  551 
  552         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
  553 
  554         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
  555                 RESTORE_ERRNO(EINVAL);
  556                 return (NULL);
  557         }
  558 
  559         if (strnlen((const char *)ptr, nvp->nvp_datasize) !=
  560             nvp->nvp_datasize - 1) {
  561                 RESTORE_ERRNO(EINVAL);
  562                 return (NULL);
  563         }
  564 
  565         nvp->nvp_data = (uint64_t)(uintptr_t)nv_strdup((const char *)ptr);
  566         if (nvp->nvp_data == 0)
  567                 return (NULL);
  568 
  569         ptr += nvp->nvp_datasize;
  570         *leftp -= nvp->nvp_datasize;
  571 
  572         return (ptr);
  573 }
  574 
  575 const unsigned char *
  576 nvpair_unpack_nvlist(bool isbe __unused, nvpair_t *nvp,
  577     const unsigned char *ptr, size_t *leftp, size_t nfds, nvlist_t **child)
  578 {
  579         nvlist_t *value;
  580 
  581         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
  582 
  583         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
  584                 RESTORE_ERRNO(EINVAL);
  585                 return (NULL);
  586         }
  587 
  588         value = nvlist_create(0);
  589         if (value == NULL)
  590                 return (NULL);
  591 
  592         ptr = nvlist_unpack_header(value, ptr, nfds, NULL, leftp);
  593         if (ptr == NULL)
  594                 return (NULL);
  595 
  596         nvp->nvp_data = (uint64_t)(uintptr_t)value;
  597         *child = value;
  598 
  599         return (ptr);
  600 }
  601 
  602 #ifndef _KERNEL
  603 const unsigned char *
  604 nvpair_unpack_descriptor(bool isbe, nvpair_t *nvp, const unsigned char *ptr,
  605     size_t *leftp, const int *fds, size_t nfds)
  606 {
  607         int64_t idx;
  608 
  609         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
  610 
  611         if (nvp->nvp_datasize != sizeof(idx)) {
  612                 errno = EINVAL;
  613                 return (NULL);
  614         }
  615         if (*leftp < sizeof(idx)) {
  616                 errno = EINVAL;
  617                 return (NULL);
  618         }
  619 
  620         if (isbe)
  621                 idx = be64dec(ptr);
  622         else
  623                 idx = le64dec(ptr);
  624 
  625         if (idx < 0) {
  626                 errno = EINVAL;
  627                 return (NULL);
  628         }
  629 
  630         if ((size_t)idx >= nfds) {
  631                 errno = EINVAL;
  632                 return (NULL);
  633         }
  634 
  635         nvp->nvp_data = (uint64_t)fds[idx];
  636 
  637         ptr += sizeof(idx);
  638         *leftp -= sizeof(idx);
  639 
  640         return (ptr);
  641 }
  642 #endif
  643 
  644 const unsigned char *
  645 nvpair_unpack_binary(bool isbe __unused, nvpair_t *nvp,
  646     const unsigned char *ptr, size_t *leftp)
  647 {
  648         void *value;
  649 
  650         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
  651 
  652         if (*leftp < nvp->nvp_datasize || nvp->nvp_datasize == 0) {
  653                 RESTORE_ERRNO(EINVAL);
  654                 return (NULL);
  655         }
  656 
  657         value = nv_malloc(nvp->nvp_datasize);
  658         if (value == NULL)
  659                 return (NULL);
  660 
  661         memcpy(value, ptr, nvp->nvp_datasize);
  662         ptr += nvp->nvp_datasize;
  663         *leftp -= nvp->nvp_datasize;
  664 
  665         nvp->nvp_data = (uint64_t)(uintptr_t)value;
  666 
  667         return (ptr);
  668 }
  669 
  670 const unsigned char *
  671 nvpair_unpack(bool isbe, const unsigned char *ptr, size_t *leftp,
  672     nvpair_t **nvpp)
  673 {
  674         nvpair_t *nvp, *tmp;
  675 
  676         nvp = nv_calloc(1, sizeof(*nvp) + NV_NAME_MAX);
  677         if (nvp == NULL)
  678                 return (NULL);
  679         nvp->nvp_name = (char *)(nvp + 1);
  680 
  681         ptr = nvpair_unpack_header(isbe, nvp, ptr, leftp);
  682         if (ptr == NULL)
  683                 goto failed;
  684         tmp = nv_realloc(nvp, sizeof(*nvp) + strlen(nvp->nvp_name) + 1);
  685         if (tmp == NULL)
  686                 goto failed;
  687         nvp = tmp;
  688 
  689         /* Update nvp_name after realloc(). */
  690         nvp->nvp_name = (char *)(nvp + 1);
  691         nvp->nvp_data = 0x00;
  692         nvp->nvp_magic = NVPAIR_MAGIC;
  693         *nvpp = nvp;
  694         return (ptr);
  695 failed:
  696         nv_free(nvp);
  697         return (NULL);
  698 }
  699 
  700 int
  701 nvpair_type(const nvpair_t *nvp)
  702 {
  703 
  704         NVPAIR_ASSERT(nvp);
  705 
  706         return (nvp->nvp_type);
  707 }
  708 
  709 const char *
  710 nvpair_name(const nvpair_t *nvp)
  711 {
  712 
  713         NVPAIR_ASSERT(nvp);
  714 
  715         return (nvp->nvp_name);
  716 }
  717 
  718 static nvpair_t *
  719 nvpair_allocv(const char *name, int type, uint64_t data, size_t datasize)
  720 {
  721         nvpair_t *nvp;
  722         size_t namelen;
  723 
  724         PJDLOG_ASSERT(type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST);
  725 
  726         namelen = strlen(name);
  727         if (namelen >= NV_NAME_MAX) {
  728                 RESTORE_ERRNO(ENAMETOOLONG);
  729                 return (NULL);
  730         }
  731 
  732         nvp = nv_calloc(1, sizeof(*nvp) + namelen + 1);
  733         if (nvp != NULL) {
  734                 nvp->nvp_name = (char *)(nvp + 1);
  735                 memcpy(nvp->nvp_name, name, namelen);
  736                 nvp->nvp_name[namelen + 1] = '\0';
  737                 nvp->nvp_type = type;
  738                 nvp->nvp_data = data;
  739                 nvp->nvp_datasize = datasize;
  740                 nvp->nvp_magic = NVPAIR_MAGIC;
  741         }
  742 
  743         return (nvp);
  744 };
  745 
  746 nvpair_t *
  747 nvpair_create_stringf(const char *name, const char *valuefmt, ...)
  748 {
  749         va_list valueap;
  750         nvpair_t *nvp;
  751 
  752         va_start(valueap, valuefmt);
  753         nvp = nvpair_create_stringv(name, valuefmt, valueap);
  754         va_end(valueap);
  755 
  756         return (nvp);
  757 }
  758 
  759 nvpair_t *
  760 nvpair_create_stringv(const char *name, const char *valuefmt, va_list valueap)
  761 {
  762         nvpair_t *nvp;
  763         char *str;
  764         int len;
  765 
  766         len = nv_vasprintf(&str, valuefmt, valueap);
  767         if (len < 0)
  768                 return (NULL);
  769         nvp = nvpair_create_string(name, str);
  770         if (nvp == NULL)
  771                 nv_free(str);
  772         return (nvp);
  773 }
  774 
  775 nvpair_t *
  776 nvpair_create_null(const char *name)
  777 {
  778 
  779         return (nvpair_allocv(name, NV_TYPE_NULL, 0, 0));
  780 }
  781 
  782 nvpair_t *
  783 nvpair_create_bool(const char *name, bool value)
  784 {
  785 
  786         return (nvpair_allocv(name, NV_TYPE_BOOL, value ? 1 : 0,
  787             sizeof(uint8_t)));
  788 }
  789 
  790 nvpair_t *
  791 nvpair_create_number(const char *name, uint64_t value)
  792 {
  793 
  794         return (nvpair_allocv(name, NV_TYPE_NUMBER, value, sizeof(value)));
  795 }
  796 
  797 nvpair_t *
  798 nvpair_create_string(const char *name, const char *value)
  799 {
  800         nvpair_t *nvp;
  801         size_t size;
  802         char *data;
  803 
  804         if (value == NULL) {
  805                 RESTORE_ERRNO(EINVAL);
  806                 return (NULL);
  807         }
  808 
  809         data = nv_strdup(value);
  810         if (data == NULL)
  811                 return (NULL);
  812         size = strlen(value) + 1;
  813 
  814         nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)data,
  815             size);
  816         if (nvp == NULL)
  817                 nv_free(data);
  818 
  819         return (nvp);
  820 }
  821 
  822 nvpair_t *
  823 nvpair_create_nvlist(const char *name, const nvlist_t *value)
  824 {
  825         nvlist_t *nvl;
  826         nvpair_t *nvp;
  827 
  828         if (value == NULL) {
  829                 RESTORE_ERRNO(EINVAL);
  830                 return (NULL);
  831         }
  832 
  833         nvl = nvlist_clone(value);
  834         if (nvl == NULL)
  835                 return (NULL);
  836 
  837         nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)nvl, 0);
  838         if (nvp == NULL)
  839                 nvlist_destroy(nvl);
  840         else
  841                 nvlist_set_parent(nvl, nvp);
  842 
  843         return (nvp);
  844 }
  845 
  846 #ifndef _KERNEL
  847 nvpair_t *
  848 nvpair_create_descriptor(const char *name, int value)
  849 {
  850         nvpair_t *nvp;
  851 
  852         if (value < 0 || !fd_is_valid(value)) {
  853                 errno = EBADF;
  854                 return (NULL);
  855         }
  856 
  857         value = fcntl(value, F_DUPFD_CLOEXEC, 0);
  858         if (value < 0)
  859                 return (NULL);
  860 
  861         nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
  862             sizeof(int64_t));
  863         if (nvp == NULL)
  864                 close(value);
  865 
  866         return (nvp);
  867 }
  868 #endif
  869 
  870 nvpair_t *
  871 nvpair_create_binary(const char *name, const void *value, size_t size)
  872 {
  873         nvpair_t *nvp;
  874         void *data;
  875 
  876         if (value == NULL || size == 0) {
  877                 RESTORE_ERRNO(EINVAL);
  878                 return (NULL);
  879         }
  880 
  881         data = nv_malloc(size);
  882         if (data == NULL)
  883                 return (NULL);
  884         memcpy(data, value, size);
  885 
  886         nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)data,
  887             size);
  888         if (nvp == NULL)
  889                 nv_free(data);
  890 
  891         return (nvp);
  892 }
  893 
  894 nvpair_t *
  895 nvpair_move_string(const char *name, char *value)
  896 {
  897         nvpair_t *nvp;
  898         int serrno;
  899 
  900         if (value == NULL) {
  901                 RESTORE_ERRNO(EINVAL);
  902                 return (NULL);
  903         }
  904 
  905         nvp = nvpair_allocv(name, NV_TYPE_STRING, (uint64_t)(uintptr_t)value,
  906             strlen(value) + 1);
  907         if (nvp == NULL) {
  908                 SAVE_ERRNO(serrno);
  909                 nv_free(value);
  910                 RESTORE_ERRNO(serrno);
  911         }
  912 
  913         return (nvp);
  914 }
  915 
  916 nvpair_t *
  917 nvpair_move_nvlist(const char *name, nvlist_t *value)
  918 {
  919         nvpair_t *nvp;
  920 
  921         if (value == NULL || nvlist_get_nvpair_parent(value) != NULL) {
  922                 RESTORE_ERRNO(EINVAL);
  923                 return (NULL);
  924         }
  925 
  926         if (nvlist_error(value) != 0) {
  927                 RESTORE_ERRNO(nvlist_error(value));
  928                 nvlist_destroy(value);
  929                 return (NULL);
  930         }
  931 
  932         nvp = nvpair_allocv(name, NV_TYPE_NVLIST, (uint64_t)(uintptr_t)value,
  933             0);
  934         if (nvp == NULL)
  935                 nvlist_destroy(value);
  936         else
  937                 nvlist_set_parent(value, nvp);
  938 
  939         return (nvp);
  940 }
  941 
  942 #ifndef _KERNEL
  943 nvpair_t *
  944 nvpair_move_descriptor(const char *name, int value)
  945 {
  946         nvpair_t *nvp;
  947         int serrno;
  948 
  949         if (value < 0 || !fd_is_valid(value)) {
  950                 errno = EBADF;
  951                 return (NULL);
  952         }
  953 
  954         nvp = nvpair_allocv(name, NV_TYPE_DESCRIPTOR, (uint64_t)value,
  955             sizeof(int64_t));
  956         if (nvp == NULL) {
  957                 serrno = errno;
  958                 close(value);
  959                 errno = serrno;
  960         }
  961 
  962         return (nvp);
  963 }
  964 #endif
  965 
  966 nvpair_t *
  967 nvpair_move_binary(const char *name, void *value, size_t size)
  968 {
  969         nvpair_t *nvp;
  970         int serrno;
  971 
  972         if (value == NULL || size == 0) {
  973                 RESTORE_ERRNO(EINVAL);
  974                 return (NULL);
  975         }
  976 
  977         nvp = nvpair_allocv(name, NV_TYPE_BINARY, (uint64_t)(uintptr_t)value,
  978             size);
  979         if (nvp == NULL) {
  980                 SAVE_ERRNO(serrno);
  981                 nv_free(value);
  982                 RESTORE_ERRNO(serrno);
  983         }
  984 
  985         return (nvp);
  986 }
  987 
  988 bool
  989 nvpair_get_bool(const nvpair_t *nvp)
  990 {
  991 
  992         NVPAIR_ASSERT(nvp);
  993 
  994         return (nvp->nvp_data == 1);
  995 }
  996 
  997 uint64_t
  998 nvpair_get_number(const nvpair_t *nvp)
  999 {
 1000 
 1001         NVPAIR_ASSERT(nvp);
 1002 
 1003         return (nvp->nvp_data);
 1004 }
 1005 
 1006 const char *
 1007 nvpair_get_string(const nvpair_t *nvp)
 1008 {
 1009 
 1010         NVPAIR_ASSERT(nvp);
 1011         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_STRING);
 1012 
 1013         return ((const char *)(intptr_t)nvp->nvp_data);
 1014 }
 1015 
 1016 const nvlist_t *
 1017 nvpair_get_nvlist(const nvpair_t *nvp)
 1018 {
 1019 
 1020         NVPAIR_ASSERT(nvp);
 1021         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_NVLIST);
 1022 
 1023         return ((const nvlist_t *)(intptr_t)nvp->nvp_data);
 1024 }
 1025 
 1026 #ifndef _KERNEL
 1027 int
 1028 nvpair_get_descriptor(const nvpair_t *nvp)
 1029 {
 1030 
 1031         NVPAIR_ASSERT(nvp);
 1032         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_DESCRIPTOR);
 1033 
 1034         return ((int)nvp->nvp_data);
 1035 }
 1036 #endif
 1037 
 1038 const void *
 1039 nvpair_get_binary(const nvpair_t *nvp, size_t *sizep)
 1040 {
 1041 
 1042         NVPAIR_ASSERT(nvp);
 1043         PJDLOG_ASSERT(nvp->nvp_type == NV_TYPE_BINARY);
 1044 
 1045         if (sizep != NULL)
 1046                 *sizep = nvp->nvp_datasize;
 1047         return ((const void *)(intptr_t)nvp->nvp_data);
 1048 }
 1049 
 1050 void
 1051 nvpair_free(nvpair_t *nvp)
 1052 {
 1053 
 1054         NVPAIR_ASSERT(nvp);
 1055         PJDLOG_ASSERT(nvp->nvp_list == NULL);
 1056 
 1057         nvp->nvp_magic = 0;
 1058         switch (nvp->nvp_type) {
 1059 #ifndef _KERNEL
 1060         case NV_TYPE_DESCRIPTOR:
 1061                 close((int)nvp->nvp_data);
 1062                 break;
 1063 #endif
 1064         case NV_TYPE_NVLIST:
 1065                 nvlist_destroy((nvlist_t *)(intptr_t)nvp->nvp_data);
 1066                 break;
 1067         case NV_TYPE_STRING:
 1068                 nv_free((char *)(intptr_t)nvp->nvp_data);
 1069                 break;
 1070         case NV_TYPE_BINARY:
 1071                 nv_free((void *)(intptr_t)nvp->nvp_data);
 1072                 break;
 1073         }
 1074         nv_free(nvp);
 1075 }
 1076 
 1077 void
 1078 nvpair_free_structure(nvpair_t *nvp)
 1079 {
 1080 
 1081         NVPAIR_ASSERT(nvp);
 1082         PJDLOG_ASSERT(nvp->nvp_list == NULL);
 1083 
 1084         nvp->nvp_magic = 0;
 1085         nv_free(nvp);
 1086 }
 1087 
 1088 const char *
 1089 nvpair_type_string(int type)
 1090 {
 1091 
 1092         switch (type) {
 1093         case NV_TYPE_NULL:
 1094                 return ("NULL");
 1095         case NV_TYPE_BOOL:
 1096                 return ("BOOL");
 1097         case NV_TYPE_NUMBER:
 1098                 return ("NUMBER");
 1099         case NV_TYPE_STRING:
 1100                 return ("STRING");
 1101         case NV_TYPE_NVLIST:
 1102                 return ("NVLIST");
 1103         case NV_TYPE_DESCRIPTOR:
 1104                 return ("DESCRIPTOR");
 1105         case NV_TYPE_BINARY:
 1106                 return ("BINARY");
 1107         default:
 1108                 return ("<UNKNOWN>");
 1109         }
 1110 }
 1111 

Cache object: b78ac3f630a785dc466a9b0981aff2ed


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.