diff --git a/port/android/storage.c b/port/android/storage.c index 58fdae331c..ed2788905a 100644 --- a/port/android/storage.c +++ b/port/android/storage.c @@ -90,8 +90,8 @@ oc_storage_reset(void) return 0; } -long -oc_storage_read(const char *store, uint8_t *buf, size_t size) +static int +storage_open(const char *store, FILE **fp) { if (g_store_path_len == 0) { return -ENOENT; @@ -105,10 +105,44 @@ oc_storage_read(const char *store, uint8_t *buf, size_t size) memcpy(g_store_path + g_store_path_len, store, store_len); g_store_path[g_store_path_len + store_len] = '\0'; - FILE *fp = fopen(g_store_path, "rb"); - if (fp == NULL) { + FILE *file = fopen(g_store_path, "rb"); + if (file == NULL) { return -EINVAL; } + *fp = file; + return 0; +} + +long +oc_storage_size(const char *store) +{ + FILE *fp = NULL; + int ret = storage_open(store, &fp); + if (ret != 0) { + return ret; + } + + if (fseek(fp, 0, SEEK_END) != 0) { + fclose(fp); + return -errno; + } + long fsize = ftell(fp); + if (fsize < 0) { + fclose(fp); + return -errno; + } + fclose(fp); + return fsize; +} + +long +oc_storage_read(const char *store, uint8_t *buf, size_t size) +{ + FILE *fp = NULL; + int ret = storage_open(store, &fp); + if (ret != 0) { + return ret; + } if (fseek(fp, 0, SEEK_END) != 0) { goto error; diff --git a/port/arduino/adapter/storage.c b/port/arduino/adapter/storage.c index 6e90ec6c71..8dc8602606 100644 --- a/port/arduino/adapter/storage.c +++ b/port/arduino/adapter/storage.c @@ -104,6 +104,12 @@ oc_storage_write(const char *store, const uint8_t *buf, size_t len) return len; } +long +oc_storage_size(const char *store) +{ + return -1; +} + long oc_storage_read(const char *store, uint8_t *buf, size_t len) { diff --git a/port/esp32/adapter/src/storage.c b/port/esp32/adapter/src/storage.c index 40aa9779d2..bc3cd5db57 100644 --- a/port/esp32/adapter/src/storage.c +++ b/port/esp32/adapter/src/storage.c @@ -92,31 +92,61 @@ oc_storage_reset(void) return 0; } -long -oc_storage_read(const char *store, uint8_t *buf, size_t size) +static int +storage_open(const char *store, nvs_handle_t *handle) { - OC_DBG("oc_storage_read: %s", store); if (!g_path_set) { return -ENOENT; } - nvs_handle_t handle; + esp_err_t err = - nvs_open_from_partition(NVS_PARTITION, g_store_path, NVS_READONLY, &handle); + nvs_open_from_partition(NVS_PARTITION, g_store_path, NVS_READWRITE, handle); if (err != ESP_OK) { OC_ERR("oc_storage_read cannot nvs_open_from_partition %s: %s", store, esp_err_to_name(err)); return -EINVAL; } + return 0; +} + +long +oc_storage_size(const char *store) +{ + nvs_handle_t handle; + int ret = storage_open(store, &handle); + if (ret < 0) { + return ret; + } - err = nvs_get_blob(handle, store, buf, &size); + size_t required_size; + esp_err_t err = nvs_get_blob(handle, store, NULL, &required_size); if (err != ESP_OK) { OC_ERR("oc_storage_read cannot nvs_get_blob %s: %s", store, esp_err_to_name(err)); nvs_close(handle); return -EINVAL; } - // TODO: check for overflow of buffer + nvs_close(handle); + return (long)required_size; +} +long +oc_storage_read(const char *store, uint8_t *buf, size_t size) +{ + OC_DBG("oc_storage_read: %s", store); + nvs_handle_t handle; + int ret = storage_open(store, &handle); + if (ret < 0) { + return ret; + } + + esp_err_t err = nvs_get_blob(handle, store, buf, &size); + if (err != ESP_OK) { + OC_ERR("oc_storage_read cannot nvs_get_blob %s: %s", store, + esp_err_to_name(err)); + nvs_close(handle); + return -EINVAL; + } nvs_close(handle); return size; } diff --git a/port/linux/storage.c b/port/linux/storage.c index 42a3bbbe5f..80f45fc4b2 100644 --- a/port/linux/storage.c +++ b/port/linux/storage.c @@ -100,18 +100,18 @@ oc_storage_reset(void) return 0; } -long -oc_storage_read(const char *store, uint8_t *buf, size_t size) +static int +storage_open(const char *store, FILE **fp) { if (g_store_path_len == 0) { - OC_ERR("failed to read from storage: store path is empty"); + OC_ERR("failed to open storage: store path is empty"); return -ENOENT; } size_t store_len = oc_strnlen_s(store, OC_STORE_PATH_SIZE); if ((store_len == 0) || (store_len + g_store_path_len >= OC_STORE_PATH_SIZE)) { - OC_ERR("failed to read from storage: %s", + OC_ERR("failed to open storage: %s", store_len == 0 ? "store path is empty" : "store path length is greater than " OC_EXPAND_TO_STR( @@ -121,8 +121,8 @@ oc_storage_read(const char *store, uint8_t *buf, size_t size) memcpy(g_store_path + g_store_path_len, store, store_len); g_store_path[g_store_path_len + store_len] = '\0'; - FILE *fp = fopen(g_store_path, "rb"); - if (fp == NULL) { + FILE *file = fopen(g_store_path, "rb"); + if (file == NULL) { #if OC_ERR_IS_ENABLED if (errno != ENOENT) { OC_ERR("failed to open %s for read: %d", g_store_path, errno); @@ -133,6 +133,41 @@ oc_storage_read(const char *store, uint8_t *buf, size_t size) return -errno; } + *fp = file; + return 0; +} + +long +oc_storage_size(const char *store) +{ + FILE *fp = NULL; + int ret = storage_open(store, &fp); + if (ret != 0) { + return ret; + } + + if (fseek(fp, 0, SEEK_END) != 0) { + fclose(fp); + return -errno; + } + long fsize = ftell(fp); + if (fsize < 0) { + fclose(fp); + return -errno; + } + fclose(fp); + return fsize; +} + +long +oc_storage_read(const char *store, uint8_t *buf, size_t size) +{ + FILE *fp = NULL; + int ret = storage_open(store, &fp); + if (ret < 0) { + return ret; + } + if (fseek(fp, 0, SEEK_END) != 0) { OC_ERR("failed to fseek to the end of file %s: %d", g_store_path, errno); goto error; diff --git a/port/oc_storage_internal.h b/port/oc_storage_internal.h index 9e705678e7..a50ffa530f 100644 --- a/port/oc_storage_internal.h +++ b/port/oc_storage_internal.h @@ -19,6 +19,8 @@ #ifndef OC_PORT_STORAGE_INTERNAL_H #define OC_PORT_STORAGE_INTERNAL_H +#include "util/oc_compiler.h" + #include #include @@ -44,6 +46,15 @@ int oc_storage_reset(void); */ bool oc_storage_path(char *buffer, size_t buffer_size); +/** + * @brief get size (in bytes) of the data written to store + * + * @param store the path to be read (cannot be NULL) + * @return <0 on failure + * @return >=0 size of the store + */ +long oc_storage_size(const char *store) OC_NONNULL(); + #ifdef __cplusplus } #endif diff --git a/port/unittest/storagetest.cpp b/port/unittest/storagetest.cpp index 686a70f876..fc6adda893 100644 --- a/port/unittest/storagetest.cpp +++ b/port/unittest/storagetest.cpp @@ -55,19 +55,19 @@ class TestStorage : public testing::Test { void TearDown() override { ASSERT_EQ(0, oc_storage_reset()); } }; -TEST_F(TestStorage, oc_storage_config_fail) +TEST_F(TestStorage, Config_Fail) { EXPECT_NE(0, oc_storage_config(nullptr)); EXPECT_NE(0, oc_storage_config("")); } -TEST_F(TestStorage, oc_storage_config_fail_append_slash) +TEST_F(TestStorage, Config_FailAppendSlash) { auto path = std::string(OC_STORE_PATH_SIZE - 1, 'a'); EXPECT_NE(0, oc_storage_config(path.c_str())); } -TEST_F(TestStorage, oc_storage_config_fail_with_length_over) +TEST_F(TestStorage, Config_FailWithLengthOver) { EXPECT_NE( 0, oc_storage_config("./" @@ -77,7 +77,7 @@ TEST_F(TestStorage, oc_storage_config_fail_with_length_over) EXPECT_FALSE(oc_storage_path(nullptr, 0)); } -TEST_F(TestStorage, oc_storage_config) +TEST_F(TestStorage, Config) { EXPECT_EQ(0, oc_storage_config(testStorage.c_str())); @@ -90,7 +90,7 @@ TEST_F(TestStorage, oc_storage_config) EXPECT_FALSE(oc_storage_path(nullptr, 0)); } -TEST_F(TestStorage, oc_storage_config_strip_trailing_slashes) +TEST_F(TestStorage, Config_StripTrailingSlashes) { EXPECT_EQ(0, oc_storage_config( (testStorage + std::string(5, kPathSeparator)).c_str())); @@ -103,7 +103,7 @@ TEST_F(TestStorage, oc_storage_config_strip_trailing_slashes) EXPECT_FALSE(oc_storage_path(nullptr, 0)); } -TEST_F(TestStorage, oc_storage_path_fail) +TEST_F(TestStorage, Path_Fail) { ASSERT_EQ(0, oc_storage_config(testStorage.c_str())); @@ -111,7 +111,12 @@ TEST_F(TestStorage, oc_storage_path_fail) EXPECT_FALSE(oc_storage_path(too_small.data(), too_small.size())); } -TEST_F(TestStorage, oc_storage_read_fail) +TEST_F(TestStorage, Size) +{ + // TODO +} + +TEST_F(TestStorage, Read_Fail) { // not configured std::array buf{}; @@ -126,7 +131,7 @@ TEST_F(TestStorage, oc_storage_read_fail) EXPECT_NE(0, oc_storage_read(store.c_str(), buf.data(), buf.size())); } -TEST_F(TestStorage, oc_storage_write_fail) +TEST_F(TestStorage, Write_Fail) { // not configured std::array buf{}; @@ -141,7 +146,7 @@ TEST_F(TestStorage, oc_storage_write_fail) EXPECT_NE(0, oc_storage_write(store.c_str(), buf.data(), buf.size())); } -TEST_F(TestStorage, oc_storage_write) +TEST_F(TestStorage, Write) { EXPECT_EQ(0, oc_storage_config(testStorage.c_str())); diff --git a/port/windows/storage.c b/port/windows/storage.c index 40e7a82562..837dcc79c7 100644 --- a/port/windows/storage.c +++ b/port/windows/storage.c @@ -92,8 +92,8 @@ oc_storage_reset(void) return 0; } -long -oc_storage_read(const char *store, uint8_t *buf, size_t size) +static int +storage_open(const char *store, FILE **fp) { if (g_store_path_len == 0) { return -ENOENT; @@ -107,10 +107,44 @@ oc_storage_read(const char *store, uint8_t *buf, size_t size) memcpy(g_store_path + g_store_path_len, store, store_len); g_store_path[g_store_path_len + store_len] = '\0'; - FILE *fp = fopen(g_store_path, "rb"); - if (fp == NULL) { + FILE *file = fopen(g_store_path, "rb"); + if (file == NULL) { return -EINVAL; } + *fp = file; + return 0; +} + +long +oc_storage_size(const char *store) +{ + FILE *fp = NULL; + int ret = storage_open(store, &fp); + if (ret != 0) { + return ret; + } + + if (fseek(fp, 0, SEEK_END) != 0) { + fclose(fp); + return -errno; + } + long fsize = ftell(fp); + if (fsize < 0) { + fclose(fp); + return -errno; + } + fclose(fp); + return fsize; +} + +long +oc_storage_read(const char *store, uint8_t *buf, size_t size) +{ + FILE *fp = NULL; + int ret = storage_open(store, &fp); + if (ret != 0) { + return ret; + } if (fseek(fp, 0, SEEK_END) != 0) { goto error; diff --git a/port/zephyr/src/storage.c b/port/zephyr/src/storage.c index 297a93033f..4cd6f7136a 100644 --- a/port/zephyr/src/storage.c +++ b/port/zephyr/src/storage.c @@ -290,6 +290,12 @@ find_key(const char *store) return NULL; } +long +oc_storage_size(const char *store) +{ + return -1; +} + /* * store should contains the memory position to read. * The value should be multiple of the flash sector size.