mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-30 19:19:21 +00:00
feat(fatfs): Allow expanding files with seeking and truncating functions
Closes https://github.com/espressif/esp-idf/issues/13100
This commit is contained in:
@@ -190,7 +190,14 @@ TEST_CASE("(WL) can lseek", "[fatfs][wear_levelling]")
|
||||
TEST_CASE("(WL) can truncate", "[fatfs][wear_levelling]")
|
||||
{
|
||||
test_setup();
|
||||
test_fatfs_truncate_file("/spiflash/truncate.txt");
|
||||
test_fatfs_truncate_file("/spiflash/truncate.txt", true);
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
TEST_CASE("(WL) can ftruncate", "[fatfs][wear_levelling]")
|
||||
{
|
||||
test_setup();
|
||||
test_fatfs_ftruncate_file("/spiflash/ftrunc.txt", true);
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
|
@@ -186,7 +186,7 @@ TEST_CASE("(SD) can truncate", "[fatfs][sdmmc]")
|
||||
{
|
||||
sdmmc_card_t *card = NULL;
|
||||
test_setup_sdmmc(&card);
|
||||
test_fatfs_truncate_file("/sdcard/truncate.txt");
|
||||
test_fatfs_truncate_file("/sdcard/truncate.txt", true);
|
||||
test_teardown_sdmmc(card);
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ TEST_CASE("(SD) can ftruncate", "[fatfs][sdmmc]")
|
||||
{
|
||||
sdmmc_card_t *card = NULL;
|
||||
test_setup_sdmmc(&card);
|
||||
test_fatfs_ftruncate_file("/sdcard/ftrunc.txt");
|
||||
test_fatfs_ftruncate_file("/sdcard/ftrunc.txt", true);
|
||||
test_teardown_sdmmc(card);
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "test_fatfs_common.h"
|
||||
#include "ff.h"
|
||||
|
||||
const char* fatfs_test_hello_str = "Hello, World!\n";
|
||||
const char* fatfs_test_hello_str_utf = "世界,你好!\n";
|
||||
@@ -252,7 +253,7 @@ void test_fatfs_lseek(const char* filename)
|
||||
|
||||
}
|
||||
|
||||
void test_fatfs_truncate_file(const char* filename)
|
||||
void test_fatfs_truncate_file(const char* filename, bool allow_expanding_files)
|
||||
{
|
||||
int read = 0;
|
||||
int truncated_len = 0;
|
||||
@@ -267,14 +268,44 @@ void test_fatfs_truncate_file(const char* filename)
|
||||
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
|
||||
struct stat st;
|
||||
size_t size;
|
||||
|
||||
// Extending file beyond size is not supported
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(errno, EPERM);
|
||||
stat(filename, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(strlen(input), size);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, -1));
|
||||
TEST_ASSERT_EQUAL(errno, EINVAL);
|
||||
if (allow_expanding_files) {
|
||||
size_t trunc_add = 2;
|
||||
size_t new_size = strlen(input) + trunc_add;
|
||||
TEST_ASSERT_EQUAL(0, truncate(filename, new_size));
|
||||
|
||||
stat(filename, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(new_size, size);
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
TEST_ASSERT_NOT_NULL(f);
|
||||
|
||||
char expanded_output[sizeof(input) + trunc_add];
|
||||
memset(expanded_output, 42, sizeof(expanded_output)); // set to something else than 0 (42)
|
||||
|
||||
read = fread(expanded_output, 1, sizeof(input) + trunc_add, f);
|
||||
TEST_ASSERT_EQUAL(new_size, read);
|
||||
|
||||
TEST_ASSERT_EQUAL('Z', expanded_output[strlen(input) - 1]); // 'Z' character
|
||||
TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 3]); // zeroed expanded space
|
||||
TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 2]); // zeroed expanded space
|
||||
TEST_ASSERT_EQUAL(42, expanded_output[sizeof(input) + trunc_add - 1]); // 42 set with memset, end of the array
|
||||
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
} else {
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(errno, EPERM);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, -1));
|
||||
TEST_ASSERT_EQUAL(errno, EINVAL);
|
||||
}
|
||||
|
||||
// Truncating should succeed
|
||||
const char truncated_1[] = "ABCDEFGHIJ";
|
||||
@@ -282,6 +313,10 @@ void test_fatfs_truncate_file(const char* filename)
|
||||
|
||||
TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len));
|
||||
|
||||
stat(filename, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(strlen(truncated_1), size);
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
TEST_ASSERT_NOT_NULL(f);
|
||||
|
||||
@@ -293,28 +328,34 @@ void test_fatfs_truncate_file(const char* filename)
|
||||
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
|
||||
if (allow_expanding_files) {
|
||||
TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len + 1));
|
||||
} else {
|
||||
// Once truncated, the new file size should be the basis
|
||||
// whether truncation should succeed or not when `allow_expanding_files == false`
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, truncated_len + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
// Once truncated, the new file size should be the basis
|
||||
// whether truncation should succeed or not
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, truncated_len + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input)));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input)));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, truncate(filename, -1));
|
||||
TEST_ASSERT_EQUAL(EINVAL, errno);
|
||||
|
||||
|
||||
// Truncating a truncated file should succeed
|
||||
const char truncated_2[] = "ABCDE";
|
||||
truncated_len = strlen(truncated_2);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, truncate(filename, truncated_len));
|
||||
|
||||
stat(filename, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(strlen(truncated_2), size);
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
TEST_ASSERT_NOT_NULL(f);
|
||||
|
||||
@@ -327,29 +368,63 @@ void test_fatfs_truncate_file(const char* filename)
|
||||
TEST_ASSERT_EQUAL(0, fclose(f));
|
||||
}
|
||||
|
||||
void test_fatfs_ftruncate_file(const char* filename)
|
||||
void test_fatfs_ftruncate_file(const char* filename, bool allow_expanding_files)
|
||||
{
|
||||
int truncated_len = 0;
|
||||
|
||||
const char input[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
char output[sizeof(input)];
|
||||
|
||||
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, fd);
|
||||
|
||||
TEST_ASSERT_EQUAL(strlen(input), write(fd, input, strlen(input)));
|
||||
|
||||
// Extending file beyond size is not supported
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(errno, EPERM);
|
||||
struct stat st;
|
||||
size_t size;
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1));
|
||||
TEST_ASSERT_EQUAL(errno, EINVAL);
|
||||
fstat(fd, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(strlen(input), size);
|
||||
|
||||
if (allow_expanding_files) {
|
||||
size_t trunc_add = 2;
|
||||
size_t new_size = strlen(input) + trunc_add;
|
||||
TEST_ASSERT_EQUAL(0, ftruncate(fd, new_size));
|
||||
|
||||
fstat(fd, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(new_size, size);
|
||||
|
||||
char expanded_output[sizeof(input) + trunc_add];
|
||||
memset(expanded_output, 42, sizeof(expanded_output)); // set to something else than 0 (42)
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
int r = read(fd, expanded_output, sizeof(input) + trunc_add);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, r);
|
||||
TEST_ASSERT_EQUAL(new_size, r);
|
||||
|
||||
TEST_ASSERT_EQUAL('Z', expanded_output[strlen(input) - 1]); // 'Z' character
|
||||
TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 3]); // zeroed expanded space
|
||||
TEST_ASSERT_EQUAL('\0', expanded_output[sizeof(input) + trunc_add - 2]); // zeroed expanded space
|
||||
TEST_ASSERT_EQUAL(42, expanded_output[sizeof(input) + trunc_add - 1]); // 42 set with memset, end of the array
|
||||
} else {
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(errno, EPERM);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1));
|
||||
TEST_ASSERT_EQUAL(errno, EINVAL);
|
||||
}
|
||||
|
||||
// Truncating should succeed
|
||||
const char truncated_1[] = "ABCDEFGHIJ";
|
||||
truncated_len = strlen(truncated_1);
|
||||
TEST_ASSERT_EQUAL(0, ftruncate(fd, truncated_len));
|
||||
|
||||
fstat(fd, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(truncated_len, size);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
|
||||
// open file for reading and validate the content
|
||||
@@ -367,25 +442,35 @@ void test_fatfs_ftruncate_file(const char* filename)
|
||||
// further truncate the file
|
||||
fd = open(filename, O_WRONLY);
|
||||
TEST_ASSERT_NOT_EQUAL(-1, fd);
|
||||
// Once truncated, the new file size should be the basis
|
||||
// whether truncation should succeed or not
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, truncated_len + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input)));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
if (allow_expanding_files) {
|
||||
TEST_ASSERT_EQUAL(0, ftruncate(fd, truncated_len + 1));
|
||||
} else {
|
||||
// Once truncated, the new file size should be the basis
|
||||
// whether truncation should succeed or not when `allow_expanding_files == false`
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, truncated_len + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input)));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1));
|
||||
TEST_ASSERT_EQUAL(EINVAL, errno);
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, strlen(input) + 1));
|
||||
TEST_ASSERT_EQUAL(EPERM, errno);
|
||||
|
||||
TEST_ASSERT_EQUAL(-1, ftruncate(fd, -1));
|
||||
TEST_ASSERT_EQUAL(EINVAL, errno);
|
||||
}
|
||||
|
||||
// Truncating a truncated file should succeed
|
||||
const char truncated_2[] = "ABCDE";
|
||||
truncated_len = strlen(truncated_2);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, ftruncate(fd, truncated_len));
|
||||
|
||||
fstat(fd, &st);
|
||||
size = st.st_size;
|
||||
TEST_ASSERT_EQUAL(truncated_len, size);
|
||||
|
||||
TEST_ASSERT_EQUAL(0, close(fd));
|
||||
|
||||
// open file for reading and validate the content
|
||||
|
@@ -45,9 +45,9 @@ void test_fatfs_open_max_files(const char* filename_prefix, size_t files_count);
|
||||
|
||||
void test_fatfs_lseek(const char* filename);
|
||||
|
||||
void test_fatfs_truncate_file(const char* path);
|
||||
void test_fatfs_truncate_file(const char* path, bool allow_expanding_files);
|
||||
|
||||
void test_fatfs_ftruncate_file(const char* path);
|
||||
void test_fatfs_ftruncate_file(const char* path, bool allow_expanding_files);
|
||||
|
||||
void test_fatfs_stat(const char* filename, const char* root_dir);
|
||||
|
||||
|
Reference in New Issue
Block a user