Skip to content

Commit 80c6f5f

Browse files
author
Cruz Monrreal
authored
Merge pull request #8972 from kjbracey-arm/merge_file_truncate
Merge feature-posix branch (FileHandle::truncate)
2 parents 7bf2fbd + 8db2c0d commit 80c6f5f

File tree

13 files changed

+220
-2
lines changed

13 files changed

+220
-2
lines changed

TESTS/mbed_platform/FileHandle/TestFile.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class TestFile : public mbed::FileHandle {
3030
~TestFile() {}
3131

3232
enum FunctionName {
33-
fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty
33+
fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty, fnTruncate
3434
};
3535

3636
virtual ssize_t read(void *buffer, size_t size)
@@ -107,6 +107,24 @@ class TestFile : public mbed::FileHandle {
107107
return 0;
108108
}
109109

110+
virtual off_t size()
111+
{
112+
return _end;
113+
}
114+
115+
virtual int truncate(off_t length)
116+
{
117+
_fnCalled = fnTruncate;
118+
if (!NEW_POS_IS_VALID(length)) {
119+
return -EINVAL;
120+
}
121+
while (_end < length) {
122+
_data[_end++] = 0;
123+
}
124+
_end = length;
125+
return 0;
126+
}
127+
110128

111129
static void resetFunctionCallHistory()
112130
{

TESTS/mbed_platform/FileHandle/main.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,68 @@ void test_fseek_ftell()
451451
std::fclose(file);
452452
}
453453

454+
/** Test ftruncate and fstat (st_size)
455+
*
456+
* Check we get EBADF for illegal handles
457+
*
458+
* Given already opened file is empty
459+
*
460+
* Check initial size is returned as 0
461+
* Call ftruncate with negative value - check our EINVAL is passed back
462+
* Call ftruncate with positive value to increase size - check no error return
463+
* Check fstat st_size now reads back as the value we set.
464+
* Call ftruncate with smaller positive value to decrease size - check no error return
465+
* Check fstat st_size now reads back as the value we set.
466+
*/
467+
void test_ftruncate_fstat()
468+
{
469+
int fildes;
470+
int ret;
471+
struct stat st;
472+
const uint32_t FS = 128;
473+
TestFile<FS> fh;
474+
475+
ret = ftruncate(12345678, 24);
476+
TEST_ASSERT_EQUAL(-1, ret);
477+
TEST_ASSERT_EQUAL(EBADF, errno);
478+
479+
ret = fstat(12345678, &st);
480+
TEST_ASSERT_EQUAL(-1, ret);
481+
TEST_ASSERT_EQUAL(EBADF, errno);
482+
483+
fildes = bind_to_fd(&fh);
484+
TEST_ASSERT_TRUE(fildes >= 0);
485+
486+
ret = fstat(fildes, &st);
487+
TEST_ASSERT_EQUAL(0, ret);
488+
TEST_ASSERT_EQUAL(0, st.st_size);
489+
490+
TestFile<FS>::resetFunctionCallHistory();
491+
ret = ftruncate(fildes, -3);
492+
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnTruncate));
493+
TEST_ASSERT_EQUAL(-1, ret);
494+
TEST_ASSERT_EQUAL(EINVAL, errno);
495+
496+
TestFile<FS>::resetFunctionCallHistory();
497+
ret = ftruncate(fildes, 24);
498+
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnTruncate));
499+
TEST_ASSERT_EQUAL(0, ret);
500+
501+
ret = fstat(fildes, &st);
502+
TEST_ASSERT_EQUAL(0, ret);
503+
TEST_ASSERT_EQUAL(24, st.st_size);
504+
505+
ret = ftruncate(fildes, 12);
506+
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnTruncate));
507+
TEST_ASSERT_EQUAL(0, ret);
508+
509+
ret = fstat(fildes, &st);
510+
TEST_ASSERT_EQUAL(0, ret);
511+
TEST_ASSERT_EQUAL(12, st.st_size);
512+
513+
close(fildes);
514+
}
515+
454516
utest::v1::status_t test_setup(const size_t number_of_cases)
455517
{
456518
GREENTEA_SETUP(10, "default_auto");
@@ -463,7 +525,8 @@ Case cases[] = {
463525
Case("Test fputc/fgetc", test_fputc_fgetc),
464526
Case("Test fputs/fgets", test_fputs_fgets),
465527
Case("Test fprintf/fscanf", test_fprintf_fscanf),
466-
Case("Test fseek/ftell", test_fseek_ftell)
528+
Case("Test fseek/ftell", test_fseek_ftell),
529+
Case("Test ftruncate/fstat", test_ftruncate_fstat)
467530
};
468531

469532
utest::v1::Specification specification(test_setup, cases);

features/storage/filesystem/File.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,10 @@ off_t File::size()
110110
return _fs->file_size(_file);
111111
}
112112

113+
int File::truncate(off_t length)
114+
{
115+
MBED_ASSERT(_fs);
116+
return _fs->file_truncate(_file, length);
117+
}
118+
113119
} // namespace mbed

features/storage/filesystem/File.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,18 @@ class File : public FileHandle {
126126
*/
127127
virtual off_t size();
128128

129+
/** Truncate or extend a file.
130+
*
131+
* The file's length is set to the specified value. The seek pointer is
132+
* not changed. If the file is extended, the extended area appears as if
133+
* it were zero-filled.
134+
*
135+
* @param length The requested new length for the file
136+
*
137+
* @return Zero on success, negative error code on failure
138+
*/
139+
virtual int truncate(off_t length);
140+
129141
private:
130142
FileSystem *_fs;
131143
fs_file_t _file;

features/storage/filesystem/FileSystem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ off_t FileSystem::file_size(fs_file_t file)
8484
return size;
8585
}
8686

87+
int FileSystem::file_truncate(fs_file_t file, off_t length)
88+
{
89+
return -ENOSYS;
90+
}
91+
8792
int FileSystem::dir_open(fs_dir_t *dir, const char *path)
8893
{
8994
return -ENOSYS;

features/storage/filesystem/FileSystem.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,19 @@ class FileSystem : public FileSystemLike {
220220
*/
221221
virtual off_t file_size(fs_file_t file);
222222

223+
/** Truncate or extend a file.
224+
*
225+
* The file's length is set to the specified value. The seek pointer is
226+
* not changed. If the file is extended, the extended area appears as if
227+
* it were zero-filled.
228+
*
229+
* @param file File handle
230+
* @param length The requested new length for the file
231+
*
232+
* @return Zero on success, negative error code on failure
233+
*/
234+
virtual int file_truncate(fs_file_t file, off_t length);
235+
223236
/** Open a directory on the filesystem
224237
*
225238
* @param dir Destination for the handle to the directory

features/storage/filesystem/fat/FATFileSystem.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,37 @@ off_t FATFileSystem::file_size(fs_file_t file)
721721
return res;
722722
}
723723

724+
int FATFileSystem::file_truncate(fs_file_t file, off_t length)
725+
{
726+
FIL *fh = static_cast<FIL *>(file);
727+
728+
lock();
729+
// save current position
730+
FSIZE_t oldoff = f_tell(fh);
731+
732+
// seek to new file size and truncate
733+
FRESULT res = f_lseek(fh, length);
734+
if (res) {
735+
unlock();
736+
return fat_error_remap(res);
737+
}
738+
739+
res = f_truncate(fh);
740+
if (res) {
741+
unlock();
742+
return fat_error_remap(res);
743+
}
744+
745+
// restore old position
746+
res = f_lseek(fh, oldoff);
747+
if (res) {
748+
unlock();
749+
return fat_error_remap(res);
750+
}
751+
752+
return 0;
753+
}
754+
724755

725756
////// Dir operations //////
726757
int FATFileSystem::dir_open(fs_dir_t *dir, const char *path)

features/storage/filesystem/fat/FATFileSystem.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,19 @@ class FATFileSystem : public FileSystem {
222222
*/
223223
virtual off_t file_size(fs_file_t file);
224224

225+
/** Truncate or extend a file.
226+
*
227+
* The file's length is set to the specified value. The seek pointer is
228+
* not changed. If the file is extended, the extended area appears as if
229+
* it were zero-filled.
230+
*
231+
* @param file File handle
232+
* @param length The requested new length for the file
233+
*
234+
* @return Zero on success, negative error code on failure
235+
*/
236+
virtual int file_truncate(mbed::fs_file_t file, off_t length);
237+
225238
/** Open a directory on the filesystem
226239
*
227240
* @param dir Destination for the handle to the directory

features/storage/filesystem/littlefs/LittleFileSystem.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,17 @@ off_t LittleFileSystem::file_size(fs_file_t file)
500500
return lfs_toerror(res);
501501
}
502502

503+
int LittleFileSystem::file_truncate(fs_file_t file, off_t length)
504+
{
505+
lfs_file_t *f = (lfs_file_t *)file;
506+
_mutex.lock();
507+
LFS_INFO("file_truncate(%p)", file);
508+
int err = lfs_file_truncate(&_lfs, f, length);
509+
LFS_INFO("file_truncate -> %d", lfs_toerror(err));
510+
_mutex.unlock();
511+
return lfs_toerror(err);
512+
}
513+
503514

504515
////// Dir operations //////
505516
int LittleFileSystem::dir_open(fs_dir_t *dir, const char *path)

features/storage/filesystem/littlefs/LittleFileSystem.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,19 @@ class LittleFileSystem : public mbed::FileSystem {
227227
*/
228228
virtual off_t file_size(mbed::fs_file_t file);
229229

230+
/** Truncate or extend a file.
231+
*
232+
* The file's length is set to the specified value. The seek pointer is
233+
* not changed. If the file is extended, the extended area appears as if
234+
* it were zero-filled.
235+
*
236+
* @param file File handle
237+
* @param length The requested new length for the file
238+
*
239+
* @return Zero on success, negative error code on failure
240+
*/
241+
virtual int file_truncate(mbed::fs_file_t file, off_t length);
242+
230243
/** Open a directory on the filesystem
231244
*
232245
* @param dir Destination for the handle to the directory

platform/FileHandle.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ class FileHandle : private NonCopyable<FileHandle> {
138138
*/
139139
virtual off_t size();
140140

141+
/** Truncate or extend a file.
142+
*
143+
* The file's length is set to the specified value. The seek pointer is
144+
* not changed. If the file is extended, the extended area appears as if
145+
* it were zero-filled.
146+
*
147+
* @param length The requested new length for the file
148+
*
149+
* @return Zero on success, negative error code on failure
150+
*/
151+
virtual int truncate(off_t length)
152+
{
153+
return -EINVAL;
154+
}
155+
141156
/** Move the file position to a given offset from a given location.
142157
*
143158
* @param offset The offset from whence to move to

platform/mbed_retarget.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,23 @@ extern "C" off_t lseek(int fildes, off_t offset, int whence)
842842
return off;
843843
}
844844

845+
extern "C" int ftruncate(int fildes, off_t length)
846+
{
847+
FileHandle *fhc = get_fhc(fildes);
848+
if (fhc == NULL) {
849+
errno = EBADF;
850+
return -1;
851+
}
852+
853+
int err = fhc->truncate(length);
854+
if (err < 0) {
855+
errno = -err;
856+
return -1;
857+
} else {
858+
return 0;
859+
}
860+
}
861+
845862
#ifdef __ARMCC_VERSION
846863
extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
847864
{

platform/mbed_retarget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ extern "C" {
524524
ssize_t write(int fildes, const void *buf, size_t nbyte);
525525
ssize_t read(int fildes, void *buf, size_t nbyte);
526526
off_t lseek(int fildes, off_t offset, int whence);
527+
int ftruncate(int fildes, off_t length);
527528
int isatty(int fildes);
528529
int fsync(int fildes);
529530
int fstat(int fildes, struct stat *st);

0 commit comments

Comments
 (0)