diff --git a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp index 413558a9563..bf1b66a3f6f 100644 --- a/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp +++ b/components/nvs_flash/host_test/nvs_host_test/main/test_nvs.cpp @@ -3310,7 +3310,92 @@ TEST_CASE("nvs multiple write with same key but different types", "[nvs][xxx]") TEST_ESP_OK(nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME)); } +TEST_CASE("nvs find key tests", "[nvs]") +{ + const size_t buff_len = 4096; + + PartitionEmulationFixture f(0, 20); + f.randomize(100); + nvs_handle_t handle_1; + nvs_handle_t handle_2; + + const uint32_t NVS_FLASH_SECTOR = 6; + const uint32_t NVS_FLASH_SECTOR_COUNT_MIN = 13; + + + TEST_ESP_ERR(nvs_open("namespace1", NVS_READWRITE, &handle_1), ESP_ERR_NVS_NOT_INITIALIZED); + for (uint16_t i = NVS_FLASH_SECTOR; i < NVS_FLASH_SECTOR + NVS_FLASH_SECTOR_COUNT_MIN; ++i) { + f.erase(i); + } + TEST_ESP_OK(nvs::NVSPartitionManager::get_instance()->init_custom(f.part(), + NVS_FLASH_SECTOR, + NVS_FLASH_SECTOR_COUNT_MIN)); + + nvs_type_t datatype_found; // datatype of entry found + + // open writeable namespace + TEST_ESP_OK(nvs_open("namespace1", NVS_READWRITE, &handle_1)); + + // set value, erease value, test find before and after each of steps + TEST_ESP_ERR(nvs_find_key(handle_1, "foo", &datatype_found), ESP_ERR_NVS_NOT_FOUND); + // write "foo" as I32, should find it, first attempt without pointer to type variable + TEST_ESP_OK(nvs_set_i32(handle_1, "foo", 0x12345678)); + TEST_ESP_OK(nvs_find_key(handle_1, "foo", nullptr)); + // second search attempt with pointer to type variable specified + TEST_ESP_OK(nvs_find_key(handle_1, "foo", &datatype_found)); + CHECK(datatype_found == NVS_TYPE_I32); + TEST_ESP_OK(nvs_erase_key(handle_1, "foo")); + TEST_ESP_ERR(nvs_find_key(handle_1, "foo", &datatype_found), ESP_ERR_NVS_NOT_FOUND); + + // set value, rewrite value, erease value, test find before and after each of steps + TEST_ESP_ERR(nvs_find_key(handle_1, "foo1", &datatype_found), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_OK(nvs_set_i16(handle_1, "foo1", 0x1234)); + TEST_ESP_OK(nvs_find_key(handle_1, "foo1", &datatype_found)); + CHECK(datatype_found == NVS_TYPE_I16); + TEST_ESP_OK(nvs_set_i16(handle_1, "foo1", 0x4321)); + TEST_ESP_OK(nvs_find_key(handle_1, "foo1", &datatype_found)); + CHECK(datatype_found == NVS_TYPE_I16); + TEST_ESP_OK(nvs_erase_key(handle_1, "foo1")); + TEST_ESP_ERR(nvs_find_key(handle_1, "foo1", &datatype_found), ESP_ERR_NVS_NOT_FOUND); + + // set blob value, rewrite blob, delete blob, test find before and after each of steps + uint8_t *p_buff = (uint8_t *) malloc(buff_len); + CHECK(p_buff != nullptr); + TEST_ESP_ERR(nvs_find_key(handle_1, "foo2", &datatype_found), ESP_ERR_NVS_NOT_FOUND); + for(size_t i=0; i(it); } +extern "C" esp_err_t nvs_find_key(nvs_handle_t c_handle, const char* key, nvs_type_t* out_type) +{ + Lock lock; + ESP_LOGD(TAG, "%s %s", __func__, key); + NVSHandleSimple *handle; + auto err = nvs_find_ns_handle(c_handle, &handle); + if (err != ESP_OK) { + return err; + } + + nvs_type_t nvstype; + err = handle->find_key(key, nvstype); + + if(err == ESP_OK && out_type != nullptr) + *out_type = nvstype; + + return err; +} + extern "C" esp_err_t nvs_erase_key(nvs_handle_t c_handle, const char* key) { Lock lock; diff --git a/components/nvs_flash/src/nvs_handle_locked.cpp b/components/nvs_flash/src/nvs_handle_locked.cpp index 39218874488..898c8fed990 100644 --- a/components/nvs_flash/src/nvs_handle_locked.cpp +++ b/components/nvs_flash/src/nvs_handle_locked.cpp @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "nvs_handle_locked.hpp" namespace nvs { @@ -47,6 +39,12 @@ esp_err_t NVSHandleLocked::get_item_size(ItemType datatype, const char *key, siz return handle->get_item_size(datatype, key, size); } +esp_err_t NVSHandleLocked::find_key(const char* key, nvs_type_t &nvstype) +{ + Lock lock; + return handle->find_key(key, nvstype); +} + esp_err_t NVSHandleLocked::erase_item(const char* key) { Lock lock; return handle->erase_item(key); diff --git a/components/nvs_flash/src/nvs_handle_locked.hpp b/components/nvs_flash/src/nvs_handle_locked.hpp index b9b0cb56209..8a0f87663a4 100644 --- a/components/nvs_flash/src/nvs_handle_locked.hpp +++ b/components/nvs_flash/src/nvs_handle_locked.hpp @@ -1,16 +1,8 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef NVS_HANDLE_LOCKED_HPP_ #define NVS_HANDLE_LOCKED_HPP_ @@ -49,6 +41,8 @@ class NVSHandleLocked : public NVSHandle { esp_err_t get_item_size(ItemType datatype, const char *key, size_t &size) override; + esp_err_t find_key(const char* key, nvs_type_t &nvstype) override; + esp_err_t erase_item(const char* key) override; esp_err_t erase_all() override; diff --git a/components/nvs_flash/src/nvs_handle_simple.cpp b/components/nvs_flash/src/nvs_handle_simple.cpp index 658c811aadc..d6423eb2761 100644 --- a/components/nvs_flash/src/nvs_handle_simple.cpp +++ b/components/nvs_flash/src/nvs_handle_simple.cpp @@ -65,6 +65,23 @@ esp_err_t NVSHandleSimple::get_item_size(ItemType datatype, const char *key, siz return mStoragePtr->getItemDataSize(mNsIndex, datatype, key, size); } +esp_err_t NVSHandleSimple::find_key(const char* key, nvs_type_t &nvstype) +{ + if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; + + nvs::ItemType datatype; + esp_err_t err = mStoragePtr->findKey(mNsIndex, key, &datatype); + if(err != ESP_OK) + return err; + + if(datatype == ItemType::BLOB_IDX || datatype == ItemType::BLOB) + datatype = ItemType::BLOB_DATA; + + nvstype = (nvs_type_t) datatype; + + return err; +} + esp_err_t NVSHandleSimple::erase_item(const char* key) { if (!valid) return ESP_ERR_NVS_INVALID_HANDLE; diff --git a/components/nvs_flash/src/nvs_handle_simple.hpp b/components/nvs_flash/src/nvs_handle_simple.hpp index fe93f9f706b..f7ccb31d27d 100644 --- a/components/nvs_flash/src/nvs_handle_simple.hpp +++ b/components/nvs_flash/src/nvs_handle_simple.hpp @@ -51,6 +51,8 @@ class NVSHandleSimple : public intrusive_list_node, esp_err_t get_item_size(ItemType datatype, const char *key, size_t &size) override; + esp_err_t find_key(const char *key, nvs_type_t &nvstype) override; + esp_err_t erase_item(const char *key) override; esp_err_t erase_all() override; diff --git a/components/nvs_flash/src/nvs_storage.cpp b/components/nvs_flash/src/nvs_storage.cpp index bac19955807..194bfe2b0c2 100644 --- a/components/nvs_flash/src/nvs_storage.cpp +++ b/components/nvs_flash/src/nvs_storage.cpp @@ -683,6 +683,26 @@ esp_err_t Storage::eraseNamespace(uint8_t nsIndex) } +esp_err_t Storage::findKey(const uint8_t nsIndex, const char* key, ItemType* datatype) +{ + if (mState != StorageState::ACTIVE) { + return ESP_ERR_NVS_NOT_INITIALIZED; + } + + Item item; + Page* findPage = nullptr; + auto err = findItem(nsIndex, ItemType::ANY, key, findPage, item); + if (err != ESP_OK) { + return err; + } + + if(datatype != nullptr) { + *datatype = item.datatype; + } + + return err; +} + esp_err_t Storage::getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize) { if (mState != StorageState::ACTIVE) { diff --git a/components/nvs_flash/src/nvs_storage.hpp b/components/nvs_flash/src/nvs_storage.hpp index 9e64ac9bb58..7c19d6fb9aa 100644 --- a/components/nvs_flash/src/nvs_storage.hpp +++ b/components/nvs_flash/src/nvs_storage.hpp @@ -71,6 +71,8 @@ class Storage : public intrusive_list_node, public ExceptionlessAllocat esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize); + esp_err_t findKey(const uint8_t nsIndex, const char* key, ItemType* datatype); + esp_err_t getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize); esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key); diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 4acc9778059..13fb791f2c1 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -582,8 +582,6 @@ components/mbedtls/port/sha/parallel_engine/sha.c components/nvs_flash/include/nvs_handle.hpp components/nvs_flash/src/nvs_cxx_api.cpp components/nvs_flash/src/nvs_encrypted_partition.hpp -components/nvs_flash/src/nvs_handle_locked.cpp -components/nvs_flash/src/nvs_handle_locked.hpp components/nvs_flash/src/nvs_item_hash_list.cpp components/nvs_flash/src/nvs_pagemanager.hpp components/nvs_flash/src/nvs_partition_lookup.cpp