From aa07b3fb833b9b006dd7a750b01882ecd9934743 Mon Sep 17 00:00:00 2001 From: Ryan Stone Date: Sat, 17 May 2014 21:16:20 -0400 Subject: [PATCH 13/17] 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. --- lib/libnv/dnvlist.c | 42 +++++-- lib/libnv/nv_impl.h | 8 -- lib/libnv/nv_user.c | 10 +- lib/libnv/nvlist.c | 270 +++++++++++++++++++++++---------------------- lib/libnv/nvlist_getters.h | 121 ++++++++++++-------- 5 files changed, 247 insertions(+), 204 deletions(-) diff --git a/lib/libnv/dnvlist.c b/lib/libnv/dnvlist.c index a0344a0..98a1aa6 100644 --- a/lib/libnv/dnvlist.c +++ b/lib/libnv/dnvlist.c @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "nv.h" #include "nv_impl.h" @@ -49,8 +50,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); } DNVLIST_GETF(bool, bool) @@ -82,18 +91,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); } @@ -106,8 +115,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); } DNVLIST_TAKEF(bool, bool) @@ -139,17 +156,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 0e580fe..460d4c3 100644 --- a/lib/libnv/nv_impl.h +++ b/lib/libnv/nv_impl.h @@ -93,14 +93,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/nv_user.c b/lib/libnv/nv_user.c index 0993aff..04e02cd 100644 --- a/lib/libnv/nv_user.c +++ b/lib/libnv/nv_user.c @@ -146,9 +146,9 @@ nvlist_fdump(const nvlist_t *nvl, FILE *fp) nvlist_dump(nvl, fileno(fp)); } -NVLIST_EXISTS(descriptor) +NVLIST_EXISTS(descriptor, DESCRIPTOR) NVLIST_EXISTSF(descriptor) -NVLIST_EXISTSV(descriptor, DESCRIPTOR) +NVLIST_EXISTSV(descriptor) void nvlist_add_descriptor(nvlist_t *nvl, const char *name, int value) @@ -206,13 +206,13 @@ nvlist_movev_descriptor(nvlist_t *nvl, int value, const char *namefmt, NVLIST_MOVE(int, descriptor) NVLIST_MOVEF(int, descriptor) -NVLIST_GET(int, descriptor) +NVLIST_GET(int, descriptor, DESCRIPTOR) NVLIST_GETF(int, descriptor) NVLIST_GETV(int, descriptor, DESCRIPTOR) -NVLIST_TAKE(int, descriptor) +NVLIST_TAKE(int, descriptor, DESCRIPTOR) NVLIST_TAKEF(int, descriptor) NVLIST_TAKEV(int, descriptor, DESCRIPTOR) -NVLIST_FREE(descriptor) +NVLIST_FREE(descriptor, DESCRIPTOR) NVLIST_FREEF(descriptor) NVLIST_FREEV(descriptor, DESCRIPTOR) diff --git a/lib/libnv/nvlist.c b/lib/libnv/nvlist.c index fcecfaf..8e8d9bd 100644 --- a/lib/libnv/nvlist.c +++ b/lib/libnv/nvlist.c @@ -147,29 +147,23 @@ nvlist_empty(const nvlist_t *nvl) } 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)); } 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) @@ -184,8 +178,6 @@ nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, va_list nameap) break; } - free(name); - if (nvp == NULL) errno = ENOENT; @@ -196,7 +188,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 @@ -216,20 +213,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 (0); - 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_freef_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)); + + nvp = nvlist_find(nvl, type, name); + if (nvp != NULL) + nvlist_free_nvpair(nvl, nvp); + else + nvlist_report_missing(type, name); } void @@ -245,21 +255,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, ""); + nvlist_free_type(nvl, name, type); + free(name); } nvlist_t * @@ -653,15 +655,15 @@ 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); } -NVLIST_EXISTS(null) -NVLIST_EXISTS(bool) -NVLIST_EXISTS(number) -NVLIST_EXISTS(string) -NVLIST_EXISTS(nvlist) -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(binary, BINARY) bool nvlist_existsf(const nvlist_t *nvl, const char *namefmt, ...) @@ -685,42 +687,25 @@ 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); -} - -NVLIST_EXISTSV(null, NULL) -NVLIST_EXISTSV(bool, BOOL) -NVLIST_EXISTSV(number, NUMBER) -NVLIST_EXISTSV(string, STRING) -NVLIST_EXISTSV(nvlist, NVLIST) -NVLIST_EXISTSV(binary, BINARY) - -void -nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp) -{ - nvpair_t *newnvp; - - NVPAIR_ASSERT(nvp); - - if (nvlist_error(nvl) != 0) { - errno = nvlist_error(nvl); - return; - } - if (nvlist_exists(nvl, nvpair_name(nvp))) { - nvl->nvl_error = errno = EEXIST; - return; - } - - newnvp = nvpair_clone(nvp); - if (newnvp == NULL) { - nvl->nvl_error = errno = (errno != 0 ? errno : ENOMEM); - return; - } + vasprintf(&name, namefmt, nameap); + if (name == NULL) + return (0); - nvpair_insert(&nvl->nvl_head, newnvp, nvl); + exists = nvlist_exists(nvl, name); + free(name); + return (exists); } +NVLIST_EXISTSV(null) +NVLIST_EXISTSV(bool) +NVLIST_EXISTSV(number) +NVLIST_EXISTSV(string) +NVLIST_EXISTSV(nvlist) +NVLIST_EXISTSV(binary) + void nvlist_add_null(nvlist_t *nvl, const char *name) { @@ -1064,20 +1049,30 @@ nvlist_movev_binary(nvlist_t *nvl, void *value, size_t size, nvlist_move_nvpair(nvl, 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) +const nvpair_t * +nvlist_get_nvpair(const nvlist_t *nvl, const char *name) +{ + + return (nvlist_find(nvl, NV_TYPE_NONE, name)); +} + +NVLIST_GET(bool, bool, BOOL) +NVLIST_GET(uint64_t, number, NUMBER) +NVLIST_GET(const char *, string, STRING) +NVLIST_GET(const nvlist_t *, nvlist, NVLIST) 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)); } -NVLIST_GETF(const nvpair_t *, nvpair) NVLIST_GETF(bool, bool) NVLIST_GETF(uint64_t, number) NVLIST_GETF(const char *, string) @@ -1096,13 +1091,6 @@ 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)); -} - NVLIST_GETV(bool, bool, BOOL) NVLIST_GETV(uint64_t, number, NUMBER) NVLIST_GETV(const char *, string, STRING) @@ -1112,32 +1100,64 @@ 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, ""); - return (nvpair_get_binary(nvp, sizep)); + binary = nvlist_get_binary(nvl, name, sizep); + free(name); + return (binary); } -NVLIST_TAKE(nvpair_t *, nvpair) -NVLIST_TAKE(bool, bool) -NVLIST_TAKE(uint64_t, number) -NVLIST_TAKE(char *, string) -NVLIST_TAKE(nvlist_t *, nvlist) +nvpair_t * +nvlist_take_nvpair(nvlist_t *nvl, const char *name) +{ + nvpair_t *nvp; + + nvp = nvlist_find(nvl, NV_TYPE_NONE, name); + if (nvp != NULL) + nvlist_remove_nvpair(nvl, nvp); + return (nvp); +} + +NVLIST_TAKE(bool, bool, BOOL) +NVLIST_TAKE(uint64_t, number, NUMBER) +NVLIST_TAKE(char *, string, STRING) + +nvlist_t * +nvlist_take_nvlist(nvlist_t *nvl, const char *name) +{ + nvpair_t *nvp; + nvlist_t *value; + + nvp = nvlist_find(nvl, NV_TYPE_NVLIST, name); + if (nvp == NULL) + nvlist_report_missing(NV_TYPE_NVLIST, name); + value = (nvlist_t *)(intptr_t)nvpair_get_nvlist(nvp); + nvlist_remove_nvpair(nvl, nvp); + nvpair_free_structure(nvp); + return (value); +} void * nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep) { + nvpair_t *nvp; + void *value; - return (nvlist_takef_binary(nvl, sizep, "%s", name)); + nvp = nvlist_find(nvl, NV_TYPE_BINARY, name); + if (nvp == NULL) + nvlist_report_missing(NV_TYPE_BINARY, name); + + value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep); + nvlist_remove_nvpair(nvl, nvp); + nvpair_free_structure(nvp); + return (value); } -NVLIST_TAKEF(nvpair_t *, nvpair) NVLIST_TAKEF(bool, bool) NVLIST_TAKEF(uint64_t, number) NVLIST_TAKEF(char *, string) @@ -1156,17 +1176,6 @@ 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); -} - NVLIST_TAKEV(bool, bool, BOOL) NVLIST_TAKEV(uint64_t, number, NUMBER) NVLIST_TAKEV(char *, string, STRING) @@ -1176,20 +1185,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, ""); - 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 @@ -1207,15 +1212,15 @@ void nvlist_free(nvlist_t *nvl, const char *name) { - nvlist_freef(nvl, "%s", name); + nvlist_free_type(nvl, name, NV_TYPE_NONE); } -NVLIST_FREE(null) -NVLIST_FREE(bool) -NVLIST_FREE(number) -NVLIST_FREE(string) -NVLIST_FREE(nvlist) -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(binary, BINARY) void nvlist_freef(nvlist_t *nvl, const char *namefmt, ...) @@ -1237,8 +1242,13 @@ NVLIST_FREEF(binary) void nvlist_freev(nvlist_t *nvl, const char *namefmt, va_list nameap) { + char *name; - nvlist_freev_type(nvl, NV_TYPE_NONE, namefmt, nameap); + vasprintf(&name, namefmt, nameap); + if (name == NULL) + nvlist_report_missing(NV_TYPE_NONE, ""); + nvlist_free(nvl, name); + free(name); } NVLIST_FREEV(null, NULL) diff --git a/lib/libnv/nvlist_getters.h b/lib/libnv/nvlist_getters.h index 7c00b64..d40e933 100644 --- a/lib/libnv/nvlist_getters.h +++ b/lib/libnv/nvlist_getters.h @@ -32,16 +32,18 @@ #ifndef _NVLIST_GETTERS_H #define _NVLIST_GETTERS_H -nvpair_t * nvlist_findv(const nvlist_t *nvl, int type, const char *namefmt, - va_list nameap); -void nvlist_report_missing(int type, const char *namefmt, va_list nameap); +nvpair_t * nvlist_find(const nvlist_t *nvl, int type, const char *name); +void nvlist_report_missing(int type, const char *name); #define DNVLIST_GET(ftype, type) \ 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); \ } #define DNVLIST_GETF(ftype, type) \ @@ -64,15 +66,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); \ } @@ -81,7 +82,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); \ } #define DNVLIST_TAKEF(ftype, type) \ @@ -104,24 +108,23 @@ 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); \ } -#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); \ } #define NVLIST_EXISTSF(type) \ @@ -137,14 +140,20 @@ nvlist_existsf_##type(const nvlist_t *nvl, const char *namefmt, ...) \ return (ret); \ } -#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); \ + vasprintf(&name, namefmt, nameap); \ + if (name == NULL) \ + return (0); \ + exists = nvlist_exists_##type(nvl, name); \ + free(name); \ + return (exists); \ } #define NVLIST_MOVE(vtype, type) \ @@ -167,12 +176,16 @@ nvlist_movef_##type(nvlist_t *nvl, vtype value, const char *namefmt, \ va_end(nameap); \ } -#define NVLIST_GET(ftype, type) \ +#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)); \ } #define NVLIST_GETF(ftype, type) \ @@ -194,23 +207,32 @@ 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, ""); \ + value = nvlist_get_##type(nvl, name); \ + free(name); \ + \ + return (value); \ } -#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); \ } #define NVLIST_TAKEF(ftype, type) \ @@ -231,27 +253,23 @@ nvlist_takef_##type(nvlist_t *nvl, const char *namefmt, ...) \ 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, ""); \ + value = nvlist_take_##type(nvl, name); \ + free(name); \ return (value); \ } -#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); \ } #define NVLIST_FREEF(type) \ @@ -269,8 +287,13 @@ nvlist_freef_##type(nvlist_t *nvl, const char *namefmt, ...) \ 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, ""); \ + nvlist_free_##type(nvl, name); \ + free(name); \ } #endif -- 1.9.2