Skip to content
3 changes: 3 additions & 0 deletions features/storage/TESTS/kvstore/filesystemstore_tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ void test_file_system_store_functionality_unit_test()

FileSystemStore *fsst = new FileSystemStore(fs);

err = fsst->init(InitMode::ExclusiveCreation | InitMode::ReadWrite);
TEST_ASSER_EQUAL_ERROR_CODE(MBED_ERROR_INITIALIZATION_FAILED, err);

err = fsst->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);

Expand Down
6 changes: 6 additions & 0 deletions features/storage/TESTS/kvstore/securestore_whitebox/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ static void white_box_test()
SecureStore *sec_kv = new SecureStore(ul_kv, rbp_kv);

for (int i = 0; i < 2; i++) {
timer.reset();
result = tdbs->init(InitMode::ExclusiveCreation | InitMode::ReadWrite);
elapsed = timer.read_ms();
TEST_ASSER_EQUAL_ERROR_CODE(MBED_ERROR_INITIALIZATION_FAILED, result);
printf("Elapsed time for exclusive init failure %d ms\n", elapsed);

timer.reset();
result = sec_kv->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
Expand Down
6 changes: 6 additions & 0 deletions features/storage/TESTS/kvstore/tdbstore_whitebox/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ static void white_box_test()

TDBStore *tdbs = new TDBStore(test_bd);

timer.reset();
result = tdbs->init(InitMode::ExclusiveCreation | InitMode::ReadWrite);
elapsed = timer.read_ms();
TEST_ASSER_EQUAL_ERROR_CODE(MBED_ERROR_INITIALIZATION_FAILED, result);
printf("Elapsed time for exclusive init failure %d ms\n", elapsed);

timer.reset();
result = tdbs->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
Expand Down
45 changes: 44 additions & 1 deletion features/storage/kvstore/filesystemstore/FileSystemStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,19 @@ FileSystemStore::FileSystemStore(FileSystem *fs) : _fs(fs),

}

int FileSystemStore::init()
int FileSystemStore::init(InitMode flags)
{
// Check for implemented flags
if (!KVStore::_is_valid_flags(flags)) {
return MBED_ERROR_INVALID_ARGUMENT;
}
if (!((flags & InitMode::Append) == InitMode::Append ||
(flags & InitMode::ExclusiveCreation) == InitMode::ExclusiveCreation)) {
return MBED_ERROR_UNSUPPORTED;
}

_flags = flags;

int status = MBED_SUCCESS;

_mutex.lock();
Expand All @@ -93,6 +104,10 @@ int FileSystemStore::init()
Dir kv_dir;

if (kv_dir.open(_fs, _cfg_fs_path) != 0) {
if ((flags & InitMode::ExclusiveCreation) == InitMode::ExclusiveCreation) {
status = MBED_ERROR_INITIALIZATION_FAILED;
goto exit_point;
}
tr_info("KV Dir: %s, doesnt exist - creating new.. ", _cfg_fs_path); //TBD verify ERRNO NOEXIST
if (_fs->mkdir(_cfg_fs_path,/* which flags ? */0777) != 0) {
tr_error("KV Dir: %s, mkdir failed.. ", _cfg_fs_path); //TBD verify ERRNO NOEXIST
Expand Down Expand Up @@ -132,6 +147,10 @@ int FileSystemStore::reset()
Dir kv_dir;
struct dirent dir_ent;

if (!KVStore::_has_flags_any(InitMode::Write)) {
return MBED_ERROR_INVALID_OPERATION;
}

_mutex.lock();
if (false == _is_initialized) {
status = MBED_ERROR_NOT_READY;
Expand Down Expand Up @@ -166,6 +185,10 @@ int FileSystemStore::set(const char *key, const void *buffer, size_t size, uint3
goto exit_point;
}

if (!KVStore::_has_flags_any(InitMode::Write)) {
return MBED_ERROR_INVALID_OPERATION;
}

if ((!is_valid_key(key)) || ((buffer == NULL) && (size > 0))) {
status = MBED_ERROR_INVALID_ARGUMENT;
goto exit_point;
Expand Down Expand Up @@ -210,6 +233,10 @@ int FileSystemStore::get(const char *key, void *buffer, size_t buffer_size, size
goto exit_point;
}

if (!KVStore::_has_flags_any(InitMode::Read)) {
return MBED_ERROR_INVALID_OPERATION;
}

key_metadata_t key_metadata;

if ((status = _verify_key_file(key, &key_metadata, &kv_file)) != MBED_SUCCESS) {
Expand Down Expand Up @@ -255,6 +282,10 @@ int FileSystemStore::get_info(const char *key, info_t *info)
int status = MBED_SUCCESS;
File kv_file;

if (!KVStore::_has_flags_any(InitMode::Read)) {
return MBED_ERROR_INVALID_OPERATION;
}

_mutex.lock();

if (false == _is_initialized) {
Expand Down Expand Up @@ -289,6 +320,10 @@ int FileSystemStore::remove(const char *key)
File kv_file;
key_metadata_t key_metadata;

if (!KVStore::_has_flags_any(InitMode::Write)) {
return MBED_ERROR_INVALID_OPERATION;
}

_mutex.lock();

int status = MBED_SUCCESS;
Expand Down Expand Up @@ -331,6 +366,10 @@ int FileSystemStore::set_start(set_handle_t *handle, const char *key, size_t fin
key_metadata_t key_metadata;
int key_len = 0;

if (!KVStore::_has_flags_any(InitMode::Write)) {
return MBED_ERROR_INVALID_OPERATION;
}

if (create_flags & ~supported_flags) {
return MBED_ERROR_INVALID_ARGUMENT;
}
Expand Down Expand Up @@ -478,6 +517,10 @@ int FileSystemStore::iterator_open(iterator_t *it, const char *prefix)
Dir *kv_dir = NULL;
key_iterator_handle_t *key_it = NULL;

if (!KVStore::_has_flags_any(InitMode::Read | InitMode::WriteOnlyAllowKeyRead)) {
return MBED_ERROR_INVALID_OPERATION;
}

if (it == NULL) {
return MBED_ERROR_INVALID_ARGUMENT;
}
Expand Down
32 changes: 22 additions & 10 deletions features/storage/kvstore/filesystemstore/FileSystemStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,18 @@ class FileSystemStore : public KVStore {
virtual ~FileSystemStore() {}

/**
* @brief Initialize FileSystemStore, checking validity of
* KVStore writing folder and if it doesn't exist, creating it.
* @brief Initialize FileSystemStore, checking validity of KVStore writing folder and
* if it doesn't exist, creating it by default. If other init modes are desired,
* set the flags as necessary.
*
* @param[in] flags Flags that determine how the FileSystemStore allows KV
* read/write and store creation.
*
* @returns MBED_SUCCESS Success.
* MBED_ERROR_INITIALIZATION_FAILED No valid FileSystemStore found on the device.
* MBED_ERROR_FAILED_OPERATION Underlying file system failed operation.
*/
virtual int init();
virtual int init(InitMode flags = DEFAULT_INIT_FLAGS);

/**
* @brief Deinitialize FileSystemStore, release and free resources.
Expand All @@ -67,6 +72,7 @@ class FileSystemStore : public KVStore {
* @returns MBED_SUCCESS Success.
* MBED_ERROR_NOT_READY Not initialized.
* MBED_ERROR_FAILED_OPERATION Underlying file system failed operation.
* MBED_ERROR_INVALID_OPERATION InitMode does not include write permission.
*/
virtual int reset();

Expand All @@ -84,6 +90,7 @@ class FileSystemStore : public KVStore {
* MBED_ERROR_INVALID_ARGUMENT Invalid argument given in function arguments.
* MBED_ERROR_INVALID_SIZE Invalid size given in function arguments.
* MBED_ERROR_WRITE_PROTECTED Already stored with "write once" flag.
* MBED_ERROR_INVALID_OPERATION InitMode do not include write permission.
*/
virtual int set(const char *key, const void *buffer, size_t size, uint32_t create_flags);

Expand All @@ -103,6 +110,7 @@ class FileSystemStore : public KVStore {
* MBED_ERROR_INVALID_SIZE Invalid size given in function arguments.
* MBED_ERROR_INVALID_DATA_DETECTED Data is corrupted.
* MBED_ERROR_ITEM_NOT_FOUND No such key.
* MBED_ERROR_INVALID_OPERATION InitMode do not include write permission.
*/
virtual int get(const char *key, void *buffer, size_t buffer_size, size_t *actual_size = NULL, size_t offset = 0);

Expand All @@ -112,13 +120,14 @@ class FileSystemStore : public KVStore {
* @param[in] key Key - must not include '*' '/' '?' ':' ';' '\' '"' '|' ' ' '<' '>' '\'.
* @param[out] info Returned information structure.
*
* @returns MBED_SUCCESS Success.
* MBED_ERROR_NOT_READY Not initialized.
* MBED_ERROR_FAILED_OPERATION Underlying file system failed operation.
* MBED_ERROR_INVALID_ARGUMENT Invalid argument given in function arguments.
* MBED_ERROR_INVALID_SIZE Invalid size given in function arguments.
* MBED_ERROR_INVALID_DATA_DETECTED Data is corrupted.
* MBED_ERROR_ITEM_NOT_FOUND No such key.
* @returns MBED_SUCCESS Success.
* MBED_ERROR_NOT_READY Not initialized.
* MBED_ERROR_FAILED_OPERATION Underlying file system failed operation.
* MBED_ERROR_INVALID_ARGUMENT Invalid argument given in function arguments.
* MBED_ERROR_INVALID_SIZE Invalid size given in function arguments.
* MBED_ERROR_INVALID_DATA_DETECTED Data is corrupted.
* MBED_ERROR_ITEM_NOT_FOUND No such key.
* MBED_ERROR_INVALID_OPERATION InitMode do not include read permission.
*/
virtual int get_info(const char *key, info_t *info);

Expand All @@ -133,6 +142,7 @@ class FileSystemStore : public KVStore {
* MBED_ERROR_INVALID_ARGUMENT Invalid argument given in function arguments.
* MBED_ERROR_ITEM_NOT_FOUND No such key.
* MBED_ERROR_WRITE_PROTECTED Already stored with "write once" flag.
* MBED_ERROR_INVALID_OPERATION InitMode do not include write permission.
*/
virtual int remove(const char *key);

Expand All @@ -151,6 +161,7 @@ class FileSystemStore : public KVStore {
* MBED_ERROR_INVALID_ARGUMENT Invalid argument given in function arguments.
* MBED_ERROR_INVALID_SIZE Invalid size given in function arguments.
* MBED_ERROR_WRITE_PROTECTED Already stored with "write once" flag.
* MBED_ERROR_INVALID_OPERATION InitMode do not include write permission.
*/
virtual int set_start(set_handle_t *handle, const char *key, size_t final_data_size, uint32_t create_flags);

Expand Down Expand Up @@ -193,6 +204,7 @@ class FileSystemStore : public KVStore {
* @returns MBED_SUCCESS Success.
* MBED_ERROR_NOT_READY Not initialized.
* MBED_ERROR_INVALID_ARGUMENT Invalid argument given in function arguments.
* MBED_ERROR_INVALID_OPERATION InitMode do not include read or write-only read key permissions.
*/
virtual int iterator_open(iterator_t *it, const char *prefix = NULL);

Expand Down
60 changes: 60 additions & 0 deletions features/storage/kvstore/include/InitModeFlags.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* 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.
*/

#ifndef MBED_INIT_MODE_FLAGS_H
#define MBED_INIT_MODE_FLAGS_H

#include <stdint.h>
#include "mbed_enum_flags.h"

namespace mbed {

/**
* @brief A set of creation flags for the KVStore instance.
*
* The Read, Write, and ReadWrite flags may be OR-ed to produce the correct initialization
* sequence. This is similar to how a file is opened.
*
* By default, the init mode opens in ReadWrite and Append mode as the default argument.
*
* At least one of Read, Write, or ReadWrite must be specified. Additionally, at least one
* of the following must be specified with write access: Append, Truncate, CreateNewOnly, or
* ExclusiveCreation.
*
*/
MBED_SCOPED_ENUM_FLAGS(InitMode)
{
Read = (1 << 0), //!< Enable read access from the KVStore
Write = (1 << 1), //!< Enable write access to the KVStore
ReadWrite = (Read | Write), //!< Enable read and write access to the KVSTore. This is the default.
WriteOnlyAllowKeyRead = (1 << 3), //!< Allow reading KVStore keys even in write only mode
Append = (1 << 8), //!< Allow adding to the the KVStore and create from new if necessary. This is the default.
Truncate = (1 << 9), //!< Erase all key/value pairs before using.
CreateNewOnly = (1 << 10), //!< Only open the KVStore if it does not already exist.
ExclusiveCreation = (1 << 11), //!< Only open the KVStore if it already exists.

#if !defined(DOXYGEN_ONLY)
// These are for interal use only
WriteOpenFlags = 0xf00,
NoFlags = 0,
AllFlags = 0xf07

#endif // DOXYGEN_ONLY
};

}

#endif // MBED_INIT_MODE_FLAGS_H
66 changes: 66 additions & 0 deletions features/storage/kvstore/include/KVStore.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* 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.
*/

// ----------------------------------------------------------- Includes -----------------------------------------------------------

#include "KVStore.h"
namespace mbed {


bool KVStore::is_valid_key(const char *key) const
{
if (!key || !strlen(key) || (strlen(key) > MAX_KEY_SIZE)) {
return false;
}

if (strpbrk(key, " */?:;\"|<>\\")) {
return false;
}
return true;
}

bool KVStore::_is_valid_flags(InitMode flags)
{
// Check that only valid bits are here at all
if ((~(InitMode::AllFlags) & flags) == InitMode::NoFlags) {
return false;
}

// Need at least one of the Read or Write bits set
if ((flags & InitMode::ReadWrite) == InitMode::NoFlags) {
return false;
}

// Check for only one set of the WriteOpenFlags
const uint32_t wo_flags = static_cast<uint32_t>(flags & InitMode::WriteOpenFlags);
// Fails for zero, the conditional afterwards finds this
if (wo_flags & (wo_flags - 1)) {
return false;
}
// Only allow blank Append, etc. if no writing
if (((flags & InitMode::Write) == InitMode::Write) && (wo_flags == 0)) {
return false;
}

return true;
}

bool KVStore::_has_flags_any(InitMode flags) const
{
return !(((_flags & flags)) == InitMode::NoFlags);
}

}
Loading