Path: blob/main/sys/contrib/openzfs/lib/libzfsbootenv/lzbe_pair.c
48378 views
// SPDX-License-Identifier: CDDL-1.01/*2* This file and its contents are supplied under the terms of the3* Common Development and Distribution License ("CDDL"), version 1.0.4* You may only use this file in accordance with the terms of version5* 1.0 of the CDDL.6*7* A full copy of the text of the CDDL should have accompanied this8* source. A copy of the CDDL is also available via the Internet at9* http://www.illumos.org/license/CDDL.10*/11/*12* Copyright 2020 Toomas Soome <[email protected]>13*/1415#include <sys/types.h>16#include <string.h>17#include <libzfs.h>18#include <libzfsbootenv.h>19#include <sys/zfs_bootenv.h>20#include <sys/vdev_impl.h>2122/*23* Get or create nvlist. If key is not NULL, get nvlist from bootenv,24* otherwise return bootenv.25*/26int27lzbe_nvlist_get(const char *pool, const char *key, void **ptr)28{29libzfs_handle_t *hdl;30zpool_handle_t *zphdl;31nvlist_t *nv;32int rv = -1;3334if (pool == NULL || *pool == '\0')35return (rv);3637if ((hdl = libzfs_init()) == NULL) {38return (rv);39}4041zphdl = zpool_open(hdl, pool);42if (zphdl == NULL) {43libzfs_fini(hdl);44return (rv);45}4647rv = zpool_get_bootenv(zphdl, &nv);48if (rv == 0) {49nvlist_t *nvl, *dup;5051if (key != NULL) {52rv = nvlist_lookup_nvlist(nv, key, &nvl);53if (rv == 0) {54rv = nvlist_dup(nvl, &dup, 0);55nvlist_free(nv);56if (rv == 0)57nv = dup;58else59nv = NULL;60} else {61nvlist_free(nv);62rv = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);63}64}65*ptr = nv;66}6768zpool_close(zphdl);69libzfs_fini(hdl);70return (rv);71}7273int74lzbe_nvlist_set(const char *pool, const char *key, void *ptr)75{76libzfs_handle_t *hdl;77zpool_handle_t *zphdl;78nvlist_t *nv;79uint64_t version;80int rv = -1;8182if (pool == NULL || *pool == '\0')83return (rv);8485if ((hdl = libzfs_init()) == NULL) {86return (rv);87}8889zphdl = zpool_open(hdl, pool);90if (zphdl == NULL) {91libzfs_fini(hdl);92return (rv);93}9495if (key != NULL) {96rv = zpool_get_bootenv(zphdl, &nv);97if (rv == 0) {98/*99* We got the nvlist, check for version.100* if version is missing or is not VB_NVLIST,101* create new list.102*/103rv = nvlist_lookup_uint64(nv, BOOTENV_VERSION,104&version);105if (rv != 0 || version != VB_NVLIST) {106/* Drop this nvlist */107fnvlist_free(nv);108/* Create and prepare new nvlist */109nv = fnvlist_alloc();110fnvlist_add_uint64(nv, BOOTENV_VERSION,111VB_NVLIST);112}113rv = nvlist_add_nvlist(nv, key, ptr);114if (rv == 0)115rv = zpool_set_bootenv(zphdl, nv);116nvlist_free(nv);117}118} else {119rv = zpool_set_bootenv(zphdl, ptr);120}121122zpool_close(zphdl);123libzfs_fini(hdl);124return (rv);125}126127/*128* free nvlist we got via lzbe_nvlist_get()129*/130void131lzbe_nvlist_free(void *ptr)132{133nvlist_free(ptr);134}135136static const char *typenames[] = {137"DATA_TYPE_UNKNOWN",138"DATA_TYPE_BOOLEAN",139"DATA_TYPE_BYTE",140"DATA_TYPE_INT16",141"DATA_TYPE_UINT16",142"DATA_TYPE_INT32",143"DATA_TYPE_UINT32",144"DATA_TYPE_INT64",145"DATA_TYPE_UINT64",146"DATA_TYPE_STRING",147"DATA_TYPE_BYTE_ARRAY",148"DATA_TYPE_INT16_ARRAY",149"DATA_TYPE_UINT16_ARRAY",150"DATA_TYPE_INT32_ARRAY",151"DATA_TYPE_UINT32_ARRAY",152"DATA_TYPE_INT64_ARRAY",153"DATA_TYPE_UINT64_ARRAY",154"DATA_TYPE_STRING_ARRAY",155"DATA_TYPE_HRTIME",156"DATA_TYPE_NVLIST",157"DATA_TYPE_NVLIST_ARRAY",158"DATA_TYPE_BOOLEAN_VALUE",159"DATA_TYPE_INT8",160"DATA_TYPE_UINT8",161"DATA_TYPE_BOOLEAN_ARRAY",162"DATA_TYPE_INT8_ARRAY",163"DATA_TYPE_UINT8_ARRAY"164};165166static int167nvpair_type_from_name(const char *name)168{169unsigned i;170171for (i = 0; i < ARRAY_SIZE(typenames); i++) {172if (strcmp(name, typenames[i]) == 0)173return (i);174}175return (0);176}177178/*179* Add pair defined by key, type and value into nvlist.180*/181int182lzbe_add_pair(void *ptr, const char *key, const char *type, void *value,183size_t size)184{185nvlist_t *nv = ptr;186data_type_t dt;187int rv = 0;188189if (ptr == NULL || key == NULL || value == NULL)190return (rv);191192if (type == NULL)193type = "DATA_TYPE_STRING";194dt = nvpair_type_from_name(type);195if (dt == DATA_TYPE_UNKNOWN)196return (EINVAL);197198switch (dt) {199case DATA_TYPE_BYTE:200if (size != sizeof (uint8_t)) {201rv = EINVAL;202break;203}204rv = nvlist_add_byte(nv, key, *(uint8_t *)value);205break;206207case DATA_TYPE_INT16:208if (size != sizeof (int16_t)) {209rv = EINVAL;210break;211}212rv = nvlist_add_int16(nv, key, *(int16_t *)value);213break;214215case DATA_TYPE_UINT16:216if (size != sizeof (uint16_t)) {217rv = EINVAL;218break;219}220rv = nvlist_add_uint16(nv, key, *(uint16_t *)value);221break;222223case DATA_TYPE_INT32:224if (size != sizeof (int32_t)) {225rv = EINVAL;226break;227}228rv = nvlist_add_int32(nv, key, *(int32_t *)value);229break;230231case DATA_TYPE_UINT32:232if (size != sizeof (uint32_t)) {233rv = EINVAL;234break;235}236rv = nvlist_add_uint32(nv, key, *(uint32_t *)value);237break;238239case DATA_TYPE_INT64:240if (size != sizeof (int64_t)) {241rv = EINVAL;242break;243}244rv = nvlist_add_int64(nv, key, *(int64_t *)value);245break;246247case DATA_TYPE_UINT64:248if (size != sizeof (uint64_t)) {249rv = EINVAL;250break;251}252rv = nvlist_add_uint64(nv, key, *(uint64_t *)value);253break;254255case DATA_TYPE_STRING:256rv = nvlist_add_string(nv, key, value);257break;258259case DATA_TYPE_BYTE_ARRAY:260rv = nvlist_add_byte_array(nv, key, value, size);261break;262263case DATA_TYPE_INT16_ARRAY:264rv = nvlist_add_int16_array(nv, key, value, size);265break;266267case DATA_TYPE_UINT16_ARRAY:268rv = nvlist_add_uint16_array(nv, key, value, size);269break;270271case DATA_TYPE_INT32_ARRAY:272rv = nvlist_add_int32_array(nv, key, value, size);273break;274275case DATA_TYPE_UINT32_ARRAY:276rv = nvlist_add_uint32_array(nv, key, value, size);277break;278279case DATA_TYPE_INT64_ARRAY:280rv = nvlist_add_int64_array(nv, key, value, size);281break;282283case DATA_TYPE_UINT64_ARRAY:284rv = nvlist_add_uint64_array(nv, key, value, size);285break;286287case DATA_TYPE_STRING_ARRAY:288rv = nvlist_add_string_array(nv, key, value, size);289break;290291case DATA_TYPE_NVLIST:292rv = nvlist_add_nvlist(nv, key, (nvlist_t *)value);293break;294295case DATA_TYPE_NVLIST_ARRAY:296rv = nvlist_add_nvlist_array(nv, key, (const nvlist_t **)value,297size);298break;299300case DATA_TYPE_BOOLEAN_VALUE:301if (size != sizeof (boolean_t)) {302rv = EINVAL;303break;304}305rv = nvlist_add_boolean_value(nv, key, *(boolean_t *)value);306break;307308case DATA_TYPE_INT8:309if (size != sizeof (int8_t)) {310rv = EINVAL;311break;312}313rv = nvlist_add_int8(nv, key, *(int8_t *)value);314break;315316case DATA_TYPE_UINT8:317if (size != sizeof (uint8_t)) {318rv = EINVAL;319break;320}321rv = nvlist_add_uint8(nv, key, *(uint8_t *)value);322break;323324case DATA_TYPE_BOOLEAN_ARRAY:325rv = nvlist_add_boolean_array(nv, key, value, size);326break;327328case DATA_TYPE_INT8_ARRAY:329rv = nvlist_add_int8_array(nv, key, value, size);330break;331332case DATA_TYPE_UINT8_ARRAY:333rv = nvlist_add_uint8_array(nv, key, value, size);334break;335336default:337return (ENOTSUP);338}339340return (rv);341}342343int344lzbe_remove_pair(void *ptr, const char *key)345{346347return (nvlist_remove_all(ptr, key));348}349350351