diff options
author | rstone <rstone@FreeBSD.org> | 2015-03-01 00:22:31 +0000 |
---|---|---|
committer | rstone <rstone@FreeBSD.org> | 2015-03-01 00:22:31 +0000 |
commit | 82f396d1056e72b527e0fb7a04bafb6c8cb1f490 (patch) | |
tree | 0e1de0c66942e5907662e1732dd48d5bf9a9c667 | |
parent | 8c5d4c9ca27df87867fa8736af38f34923b1be9f (diff) | |
download | FreeBSD-src-82f396d1056e72b527e0fb7a04bafb6c8cb1f490.zip FreeBSD-src-82f396d1056e72b527e0fb7a04bafb6c8cb1f490.tar.gz |
Don't allocate memory for operations that do not insert
Almost every operation performed on an nvlist was allocating a
new string to hold the key name. The nvlist_exists* family of
functions would always return false if they failed to allocate
the string. The rest of the functions would outright abort().
Fix the non-varargs variants of the functions to perform the
requested operations directly and the varargs versions to
allocate the string and call into the non-varargs versions.
The varargs versions are still broken and really can't be fixed,
so we might consider axing them entirely. However, now the non-
varargs functions are always safe to call.
Differential Revision: https://reviews.freebsd.org/D1879
Reviewed by: pjd, jfv
MFC after: 1 month
Sponsored by: Sandvine Inc.
-rw-r--r-- | lib/libnv/dnvlist.c | 78 | ||||
-rw-r--r-- | lib/libnv/nv_impl.h | 8 | ||||
-rw-r--r-- | lib/libnv/nvlist.c | 309 |
3 files changed, 217 insertions, 178 deletions
diff --git a/lib/libnv/dnvlist.c b/lib/libnv/dnvlist.c index b758bbf..582d19b 100644 --- a/lib/libnv/dnvlist.c +++ b/lib/libnv/dnvlist.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include <stdarg.h> #include <stdbool.h> #include <stdint.h> +#include <stdlib.h> #include "nv.h" #include "nv_impl.h" @@ -44,7 +45,10 @@ ftype \ dnvlist_get_##type(const nvlist_t *nvl, const char *name, ftype defval) \ { \ \ - return (dnvlist_getf_##type(nvl, defval, "%s", name)); \ + if (nvlist_exists_##type(nvl, name)) \ + return (nvlist_get_##type(nvl, name)); \ + else \ + return (defval); \ } DNVLIST_GET(bool, bool) @@ -59,8 +63,16 @@ const void * dnvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep, const void *defval, size_t defsize) { + const void *value; - return (dnvlist_getf_binary(nvl, sizep, defval, defsize, "%s", name)); + if (nvlist_exists_binary(nvl, name)) + value = nvlist_get_binary(nvl, name, sizep); + else { + if (sizep != NULL) + *sizep = defsize; + value = defval; + } + return (value); } #define DNVLIST_GETF(ftype, type) \ @@ -106,15 +118,14 @@ ftype \ dnvlist_getv_##type(const nvlist_t *nvl, ftype defval, \ const char *namefmt, va_list nameap) \ { \ - va_list cnameap; \ + char *name; \ ftype value; \ \ - va_copy(cnameap, nameap); \ - if (nvlist_existsv_##type(nvl, namefmt, cnameap)) \ - value = nvlist_getv_##type(nvl, namefmt, nameap); \ - else \ - value = defval; \ - va_end(cnameap); \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (defval); \ + value = dnvlist_get_##type(nvl, name, defval); \ + free(name); \ return (value); \ } @@ -130,18 +141,18 @@ const void * dnvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const void *defval, size_t defsize, const char *namefmt, va_list nameap) { - va_list cnameap; + char *name; const void *value; - va_copy(cnameap, nameap); - if (nvlist_existsv_binary(nvl, namefmt, cnameap)) { - value = nvlist_getv_binary(nvl, sizep, namefmt, nameap); + vasprintf(&name, namefmt, nameap); + if (name != NULL) { + value = dnvlist_get_binary(nvl, name, sizep, defval, defsize); + free(name); } else { if (sizep != NULL) *sizep = defsize; value = defval; } - va_end(cnameap); return (value); } @@ -150,7 +161,10 @@ ftype \ dnvlist_take_##type(nvlist_t *nvl, const char *name, ftype defval) \ { \ \ - return (dnvlist_takef_##type(nvl, defval, "%s", name)); \ + if (nvlist_exists_##type(nvl, name)) \ + return (nvlist_take_##type(nvl, name)); \ + else \ + return (defval); \ } DNVLIST_TAKE(bool, bool) @@ -165,8 +179,16 @@ void * dnvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep, void *defval, size_t defsize) { + void *value; - return (dnvlist_takef_binary(nvl, sizep, defval, defsize, "%s", name)); + if (nvlist_exists_binary(nvl, name)) + value = nvlist_take_binary(nvl, name, sizep); + else { + if (sizep != NULL) + *sizep = defsize; + value = defval; + } + return (value); } #define DNVLIST_TAKEF(ftype, type) \ @@ -212,15 +234,14 @@ ftype \ dnvlist_takev_##type(nvlist_t *nvl, ftype defval, const char *namefmt, \ va_list nameap) \ { \ - va_list cnameap; \ + char *name; \ ftype value; \ \ - va_copy(cnameap, nameap); \ - if (nvlist_existsv_##type(nvl, namefmt, cnameap)) \ - value = nvlist_takev_##type(nvl, namefmt, nameap); \ - else \ - value = defval; \ - va_end(cnameap); \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (defval); \ + value = dnvlist_take_##type(nvl, name, defval); \ + free(name); \ return (value); \ } @@ -236,17 +257,18 @@ void * dnvlist_takev_binary(nvlist_t *nvl, size_t *sizep, void *defval, size_t defsize, const char *namefmt, va_list nameap) { - va_list cnameap; + char *name; void *value; - va_copy(cnameap, nameap); - if (nvlist_existsv_binary(nvl, namefmt, cnameap)) { - value = nvlist_takev_binary(nvl, sizep, namefmt, nameap); + vasprintf(&name, namefmt, nameap); + if (name != NULL) { + value = dnvlist_take_binary(nvl, name, sizep, defval, defsize); + free(name); } else { if (sizep != NULL) *sizep = defsize; value = defval; } - va_end(cnameap); + return (value); } diff --git a/lib/libnv/nv_impl.h b/lib/libnv/nv_impl.h index 3ed45b3..ce97dd0 100644 --- a/lib/libnv/nv_impl.h +++ b/lib/libnv/nv_impl.h @@ -97,14 +97,6 @@ const void *nvpair_get_binary(const nvpair_t *nvp, size_t *sizep); void nvpair_free(nvpair_t *nvp); -const nvpair_t *nvlist_getf_nvpair(const nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); - -const nvpair_t *nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); - -nvpair_t *nvlist_takef_nvpair(nvlist_t *nvl, const char *namefmt, ...) __printflike(2, 3); - -nvpair_t *nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap) __printflike(2, 0); - nvpair_t *nvpair_createf_null(const char *namefmt, ...) __printflike(1, 2); nvpair_t *nvpair_createf_bool(bool value, const char *namefmt, ...) __printflike(2, 3); nvpair_t *nvpair_createf_number(uint64_t value, const char *namefmt, ...) __printflike(2, 3); diff --git a/lib/libnv/nvlist.c b/lib/libnv/nvlist.c index 90fcde3..7a07813 100644 --- a/lib/libnv/nvlist.c +++ b/lib/libnv/nvlist.c @@ -208,29 +208,23 @@ nvlist_empty(const nvlist_t *nvl) } static void -nvlist_report_missing(int type, const char *namefmt, va_list nameap) +nvlist_report_missing(int type, const char *name) { - char *name; - vasprintf(&name, namefmt, nameap); PJDLOG_ABORT("Element '%s' of type %s doesn't exist.", - name != NULL ? name : "N/A", nvpair_type_string(type)); + name, nvpair_type_string(type)); } static nvpair_t * -nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) +nvlist_find(const nvlist_t *nvl, int type, const char *name) { nvpair_t *nvp; - char *name; NVLIST_ASSERT(nvl); PJDLOG_ASSERT(nvl->nvl_error == 0); PJDLOG_ASSERT(type == NV_TYPE_NONE || (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - if (vasprintf(&name, namefmt, nameap) < 0) - return (NULL); - for (nvp = nvlist_first_nvpair(nvl); nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) { if (type != NV_TYPE_NONE && nvpair_type(nvp) != type) @@ -245,8 +239,6 @@ nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) break; } - free(name); - if (nvp == NULL) errno = ENOENT; @@ -257,7 +249,12 @@ bool nvlist_exists_type(const nvlist_t *nvl, const char *name, int type) { - return (nvlist_existsf_type(nvl, type, "%s", name)); + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + + return (nvlist_find(nvl, type, name) != NULL); } bool @@ -277,20 +274,33 @@ bool nvlist_existsv_type(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) { + char *name; + bool exists; - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + vasprintf(&name, namefmt, nameap); + if (name == NULL) + return (false); - return (nvlist_findv(nvl, type, namefmt, nameap) != NULL); + exists = nvlist_exists_type(nvl, name, type); + free(name); + return (exists); } void nvlist_free_type(nvlist_t *nvl, const char *name, int type) { + nvpair_t *nvp; + + NVLIST_ASSERT(nvl); + PJDLOG_ASSERT(nvl->nvl_error == 0); + PJDLOG_ASSERT(type == NV_TYPE_NONE || + (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); - nvlist_freef_type(nvl, type, "%s", name); + nvp = nvlist_find(nvl, type, name); + if (nvp != NULL) + nvlist_free_nvpair(nvl, nvp); + else + nvlist_report_missing(type, name); } void @@ -306,21 +316,13 @@ nvlist_freef_type(nvlist_t *nvl, int type, const char *namefmt, ...) void nvlist_freev_type(nvlist_t *nvl, int type, const char *namefmt, va_list nameap) { - va_list cnameap; - nvpair_t *nvp; - - NVLIST_ASSERT(nvl); - PJDLOG_ASSERT(nvl->nvl_error == 0); - PJDLOG_ASSERT(type == NV_TYPE_NONE || - (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST)); + char *name; - va_copy(cnameap, nameap); - nvp = nvlist_findv(nvl, type, namefmt, cnameap); - va_end(cnameap); - if (nvp != NULL) - nvlist_free_nvpair(nvl, nvp); - else - nvlist_report_missing(type, namefmt, nameap); + vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(type, "<unknown>"); + nvlist_free_type(nvl, name, type); + free(name); } nvlist_t * @@ -1031,24 +1033,24 @@ bool nvlist_exists(const nvlist_t *nvl, const char *name) { - return (nvlist_existsf(nvl, "%s", name)); + return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL); } -#define NVLIST_EXISTS(type) \ +#define NVLIST_EXISTS(type, TYPE) \ bool \ nvlist_exists_##type(const nvlist_t *nvl, const char *name) \ { \ \ - return (nvlist_existsf_##type(nvl, "%s", name)); \ + return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL); \ } -NVLIST_EXISTS(null) -NVLIST_EXISTS(bool) -NVLIST_EXISTS(number) -NVLIST_EXISTS(string) -NVLIST_EXISTS(nvlist) -NVLIST_EXISTS(descriptor) -NVLIST_EXISTS(binary) +NVLIST_EXISTS(null, NULL) +NVLIST_EXISTS(bool, BOOL) +NVLIST_EXISTS(number, NUMBER) +NVLIST_EXISTS(string, STRING) +NVLIST_EXISTS(nvlist, NVLIST) +NVLIST_EXISTS(descriptor, DESCRIPTOR) +NVLIST_EXISTS(binary, BINARY) #undef NVLIST_EXISTS @@ -1090,27 +1092,41 @@ NVLIST_EXISTSF(binary) bool nvlist_existsv(const nvlist_t *nvl, const char *namefmt, va_list nameap) { + char *name; + bool exists; - return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap) != NULL); + vasprintf(&name, namefmt, nameap); + if (name == NULL) + return (false); + + exists = nvlist_exists(nvl, name); + free(name); + return (exists); } -#define NVLIST_EXISTSV(type, TYPE) \ +#define NVLIST_EXISTSV(type) \ bool \ nvlist_existsv_##type(const nvlist_t *nvl, const char *namefmt, \ va_list nameap) \ { \ + char *name; \ + bool exists; \ \ - return (nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, nameap) != \ - NULL); \ -} - -NVLIST_EXISTSV(null, NULL) -NVLIST_EXISTSV(bool, BOOL) -NVLIST_EXISTSV(number, NUMBER) -NVLIST_EXISTSV(string, STRING) -NVLIST_EXISTSV(nvlist, NVLIST) -NVLIST_EXISTSV(descriptor, DESCRIPTOR) -NVLIST_EXISTSV(binary, BINARY) + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (false); \ + exists = nvlist_exists_##type(nvl, name); \ + free(name); \ + return (exists); \ +} + +NVLIST_EXISTSV(null) +NVLIST_EXISTSV(bool) +NVLIST_EXISTSV(number) +NVLIST_EXISTSV(string) +NVLIST_EXISTSV(nvlist) +NVLIST_EXISTSV(descriptor) +NVLIST_EXISTSV(binary) #undef NVLIST_EXISTSV @@ -1561,28 +1577,43 @@ nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, nvlist_move_nvpair(nvl, nvp); } -#define NVLIST_GET(ftype, type) \ +const nvpair_t * +nvlist_get_nvpair(const nvlist_t *nvl, const char *name) +{ + + return (nvlist_find(nvl, NV_TYPE_NONE, name)); +} + +#define NVLIST_GET(ftype, type, TYPE) \ ftype \ nvlist_get_##type(const nvlist_t *nvl, const char *name) \ { \ + const nvpair_t *nvp; \ \ - return (nvlist_getf_##type(nvl, "%s", name)); \ + nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ + if (nvp == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, name); \ + return (nvpair_get_##type(nvp)); \ } -NVLIST_GET(const nvpair_t *, nvpair) -NVLIST_GET(bool, bool) -NVLIST_GET(uint64_t, number) -NVLIST_GET(const char *, string) -NVLIST_GET(const nvlist_t *, nvlist) -NVLIST_GET(int, descriptor) +NVLIST_GET(bool, bool, BOOL) +NVLIST_GET(uint64_t, number, NUMBER) +NVLIST_GET(const char *, string, STRING) +NVLIST_GET(const nvlist_t *, nvlist, NVLIST) +NVLIST_GET(int, descriptor, DESCRIPTOR) #undef NVLIST_GET const void * nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep) { + nvpair_t *nvp; + + nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); + if (nvp == NULL) + nvlist_report_missing(NV_TYPE_BINARY, name); - return (nvlist_getf_binary(nvl, sizep, "%s", name)); + return (nvpair_get_binary(nvp, sizep)); } #define NVLIST_GETF(ftype, type) \ @@ -1599,7 +1630,6 @@ nvlist_getf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ return (value); \ } -NVLIST_GETF(const nvpair_t *, nvpair) NVLIST_GETF(bool, bool) NVLIST_GETF(uint64_t, number) NVLIST_GETF(const char *, string) @@ -1621,27 +1651,21 @@ nvlist_getf_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) return (value); } -const nvpair_t * -nvlist_getv_nvpair(const nvlist_t *nvl, const char *namefmt, va_list nameap) -{ - - return (nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap)); -} - #define NVLIST_GETV(ftype, type, TYPE) \ ftype \ nvlist_getv_##type(const nvlist_t *nvl, const char *namefmt, \ va_list nameap) \ { \ - va_list cnameap; \ - const nvpair_t *nvp; \ + char *name; \ + ftype value; \ \ - va_copy(cnameap, nameap); \ - nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ - va_end(cnameap); \ - if (nvp == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ - return (nvpair_get_##type(nvp)); \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \ + value = nvlist_get_##type(nvl, name); \ + free(name); \ + \ + return (value); \ } NVLIST_GETV(bool, bool, BOOL) @@ -1656,40 +1680,56 @@ const void * nvlist_getv_binary(const nvlist_t *nvl, size_t *sizep, const char *namefmt, va_list nameap) { - va_list cnameap; - const nvpair_t *nvp; + char *name; + const void *binary; - va_copy(cnameap, nameap); - nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap); - va_end(cnameap); - if (nvp == NULL) - nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap); + vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(NV_TYPE_BINARY, "<unknown>"); - return (nvpair_get_binary(nvp, sizep)); + binary = nvlist_get_binary(nvl, name, sizep); + free(name); + return (binary); } -#define NVLIST_TAKE(ftype, type) \ +#define NVLIST_TAKE(ftype, type, TYPE) \ ftype \ nvlist_take_##type(nvlist_t *nvl, const char *name) \ { \ + nvpair_t *nvp; \ + ftype value; \ \ - return (nvlist_takef_##type(nvl, "%s", name)); \ + nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name); \ + if (nvp == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, name); \ + value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ + nvlist_remove_nvpair(nvl, nvp); \ + nvpair_free_structure(nvp); \ + return (value); \ } -NVLIST_TAKE(nvpair_t *, nvpair) -NVLIST_TAKE(bool, bool) -NVLIST_TAKE(uint64_t, number) -NVLIST_TAKE(char *, string) -NVLIST_TAKE(nvlist_t *, nvlist) -NVLIST_TAKE(int, descriptor) +NVLIST_TAKE(bool, bool, BOOL) +NVLIST_TAKE(uint64_t, number, NUMBER) +NVLIST_TAKE(char *, string, STRING) +NVLIST_TAKE(nvlist_t *, nvlist, NVLIST) +NVLIST_TAKE(int, descriptor, DESCRIPTOR) #undef NVLIST_TAKE void * nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) { + nvpair_t *nvp; + void *value; + + nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); + if (nvp == NULL) + nvlist_report_missing(NV_TYPE_BINARY, name); - return (nvlist_takef_binary(nvl, sizep, "%s", name)); + value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); + nvlist_remove_nvpair(nvl, nvp); + nvpair_free_structure(nvp); + return (value); } #define NVLIST_TAKEF(ftype, type) \ @@ -1706,7 +1746,6 @@ nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \ return (value); \ } -NVLIST_TAKEF(nvpair_t *, nvpair) NVLIST_TAKEF(bool, bool) NVLIST_TAKEF(uint64_t, number) NVLIST_TAKEF(char *, string) @@ -1728,33 +1767,18 @@ nvlist_takef_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, ...) return (value); } -nvpair_t * -nvlist_takev_nvpair(nvlist_t *nvl, const char *namefmt, va_list nameap) -{ - nvpair_t *nvp; - - nvp = nvlist_findv(nvl, NV_TYPE_NONE, namefmt, nameap); - if (nvp != NULL) - nvlist_remove_nvpair(nvl, nvp); - return (nvp); -} - #define NVLIST_TAKEV(ftype, type, TYPE) \ ftype \ nvlist_takev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ { \ - va_list cnameap; \ - nvpair_t *nvp; \ + char *name; \ ftype value; \ \ - va_copy(cnameap, nameap); \ - nvp = nvlist_findv(nvl, NV_TYPE_##TYPE, namefmt, cnameap); \ - va_end(cnameap); \ - if (nvp == NULL) \ - nvlist_report_missing(NV_TYPE_##TYPE, namefmt, nameap); \ - value = (ftype)(intptr_t)nvpair_get_##type(nvp); \ - nvlist_remove_nvpair(nvl, nvp); \ - nvpair_free_structure(nvp); \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \ + value = nvlist_take_##type(nvl, name); \ + free(name); \ return (value); \ } @@ -1770,20 +1794,16 @@ void * nvlist_takev_binary(nvlist_t *nvl, size_t *sizep, const char *namefmt, va_list nameap) { - va_list cnameap; - nvpair_t *nvp; - void *value; + char *name; + void *binary; - va_copy(cnameap, nameap); - nvp = nvlist_findv(nvl, NV_TYPE_BINARY, namefmt, cnameap); - va_end(cnameap); - if (nvp == NULL) - nvlist_report_missing(NV_TYPE_BINARY, namefmt, nameap); + vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(NV_TYPE_BINARY, "<unknown>"); - value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); - nvlist_remove_nvpair(nvl, nvp); - nvpair_free_structure(nvp); - return (value); + binary = nvlist_take_binary(nvl, name, sizep); + free(name); + return (binary); } void @@ -1801,24 +1821,24 @@ void nvlist_free(nvlist_t *nvl, const char *name) { - nvlist_freef(nvl, "%s", name); + nvlist_free_type(nvl, name, NV_TYPE_NONE); } -#define NVLIST_FREE(type) \ +#define NVLIST_FREE(type, TYPE) \ void \ nvlist_free_##type(nvlist_t *nvl, const char *name) \ { \ \ - nvlist_freef_##type(nvl, "%s", name); \ + nvlist_free_type(nvl, name, NV_TYPE_##TYPE); \ } -NVLIST_FREE(null) -NVLIST_FREE(bool) -NVLIST_FREE(number) -NVLIST_FREE(string) -NVLIST_FREE(nvlist) -NVLIST_FREE(descriptor) -NVLIST_FREE(binary) +NVLIST_FREE(null, NULL) +NVLIST_FREE(bool, BOOL) +NVLIST_FREE(number, NUMBER) +NVLIST_FREE(string, STRING) +NVLIST_FREE(nvlist, NVLIST) +NVLIST_FREE(descriptor, DESCRIPTOR) +NVLIST_FREE(binary, BINARY) #undef NVLIST_FREE @@ -1864,8 +1884,13 @@ nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) void \ nvlist_freev_##type(nvlist_t *nvl, const char *namefmt, va_list nameap) \ { \ + char *name; \ \ - nvlist_freev_type(nvl, NV_TYPE_##TYPE, namefmt, nameap); \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + nvlist_report_missing(NV_TYPE_##TYPE, "<unknown>"); \ + nvlist_free_##type(nvl, name); \ + free(name); \ } NVLIST_FREEV(null, NULL) |