Merge pull request #8972 from kjbracey-arm/merge_file_truncate

Merge feature-posix branch (FileHandle::truncate)
pull/9122/head
Cruz Monrreal 2018-12-17 14:49:56 -06:00 committed by GitHub
commit 80c6f5f8ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 220 additions and 2 deletions

View File

@ -30,7 +30,7 @@ public:
~TestFile() {}
enum FunctionName {
fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty
fnNone, fnRead, fnWrite, fnSeek, fnClose, fnIsatty, fnTruncate
};
virtual ssize_t read(void *buffer, size_t size)
@ -107,6 +107,24 @@ public:
return 0;
}
virtual off_t size()
{
return _end;
}
virtual int truncate(off_t length)
{
_fnCalled = fnTruncate;
if (!NEW_POS_IS_VALID(length)) {
return -EINVAL;
}
while (_end < length) {
_data[_end++] = 0;
}
_end = length;
return 0;
}
static void resetFunctionCallHistory()
{

View File

@ -451,6 +451,68 @@ void test_fseek_ftell()
std::fclose(file);
}
/** Test ftruncate and fstat (st_size)
*
* Check we get EBADF for illegal handles
*
* Given already opened file is empty
*
* Check initial size is returned as 0
* Call ftruncate with negative value - check our EINVAL is passed back
* Call ftruncate with positive value to increase size - check no error return
* Check fstat st_size now reads back as the value we set.
* Call ftruncate with smaller positive value to decrease size - check no error return
* Check fstat st_size now reads back as the value we set.
*/
void test_ftruncate_fstat()
{
int fildes;
int ret;
struct stat st;
const uint32_t FS = 128;
TestFile<FS> fh;
ret = ftruncate(12345678, 24);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EBADF, errno);
ret = fstat(12345678, &st);
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EBADF, errno);
fildes = bind_to_fd(&fh);
TEST_ASSERT_TRUE(fildes >= 0);
ret = fstat(fildes, &st);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(0, st.st_size);
TestFile<FS>::resetFunctionCallHistory();
ret = ftruncate(fildes, -3);
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnTruncate));
TEST_ASSERT_EQUAL(-1, ret);
TEST_ASSERT_EQUAL(EINVAL, errno);
TestFile<FS>::resetFunctionCallHistory();
ret = ftruncate(fildes, 24);
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnTruncate));
TEST_ASSERT_EQUAL(0, ret);
ret = fstat(fildes, &st);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(24, st.st_size);
ret = ftruncate(fildes, 12);
TEST_ASSERT_TRUE(TestFile<FS>::functionCalled(TestFile<FS>::fnTruncate));
TEST_ASSERT_EQUAL(0, ret);
ret = fstat(fildes, &st);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL(12, st.st_size);
close(fildes);
}
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(10, "default_auto");
@ -463,7 +525,8 @@ Case cases[] = {
Case("Test fputc/fgetc", test_fputc_fgetc),
Case("Test fputs/fgets", test_fputs_fgets),
Case("Test fprintf/fscanf", test_fprintf_fscanf),
Case("Test fseek/ftell", test_fseek_ftell)
Case("Test fseek/ftell", test_fseek_ftell),
Case("Test ftruncate/fstat", test_ftruncate_fstat)
};
utest::v1::Specification specification(test_setup, cases);

View File

@ -110,4 +110,10 @@ off_t File::size()
return _fs->file_size(_file);
}
int File::truncate(off_t length)
{
MBED_ASSERT(_fs);
return _fs->file_truncate(_file, length);
}
} // namespace mbed

View File

@ -126,6 +126,18 @@ public:
*/
virtual off_t size();
/** Truncate or extend a file.
*
* The file's length is set to the specified value. The seek pointer is
* not changed. If the file is extended, the extended area appears as if
* it were zero-filled.
*
* @param length The requested new length for the file
*
* @return Zero on success, negative error code on failure
*/
virtual int truncate(off_t length);
private:
FileSystem *_fs;
fs_file_t _file;

View File

@ -84,6 +84,11 @@ off_t FileSystem::file_size(fs_file_t file)
return size;
}
int FileSystem::file_truncate(fs_file_t file, off_t length)
{
return -ENOSYS;
}
int FileSystem::dir_open(fs_dir_t *dir, const char *path)
{
return -ENOSYS;

View File

@ -220,6 +220,19 @@ protected:
*/
virtual off_t file_size(fs_file_t file);
/** Truncate or extend a file.
*
* The file's length is set to the specified value. The seek pointer is
* not changed. If the file is extended, the extended area appears as if
* it were zero-filled.
*
* @param file File handle
* @param length The requested new length for the file
*
* @return Zero on success, negative error code on failure
*/
virtual int file_truncate(fs_file_t file, off_t length);
/** Open a directory on the filesystem
*
* @param dir Destination for the handle to the directory

View File

@ -721,6 +721,37 @@ off_t FATFileSystem::file_size(fs_file_t file)
return res;
}
int FATFileSystem::file_truncate(fs_file_t file, off_t length)
{
FIL *fh = static_cast<FIL *>(file);
lock();
// save current position
FSIZE_t oldoff = f_tell(fh);
// seek to new file size and truncate
FRESULT res = f_lseek(fh, length);
if (res) {
unlock();
return fat_error_remap(res);
}
res = f_truncate(fh);
if (res) {
unlock();
return fat_error_remap(res);
}
// restore old position
res = f_lseek(fh, oldoff);
if (res) {
unlock();
return fat_error_remap(res);
}
return 0;
}
////// Dir operations //////
int FATFileSystem::dir_open(fs_dir_t *dir, const char *path)

View File

@ -222,6 +222,19 @@ protected:
*/
virtual off_t file_size(fs_file_t file);
/** Truncate or extend a file.
*
* The file's length is set to the specified value. The seek pointer is
* not changed. If the file is extended, the extended area appears as if
* it were zero-filled.
*
* @param file File handle
* @param length The requested new length for the file
*
* @return Zero on success, negative error code on failure
*/
virtual int file_truncate(mbed::fs_file_t file, off_t length);
/** Open a directory on the filesystem
*
* @param dir Destination for the handle to the directory

View File

@ -500,6 +500,17 @@ off_t LittleFileSystem::file_size(fs_file_t file)
return lfs_toerror(res);
}
int LittleFileSystem::file_truncate(fs_file_t file, off_t length)
{
lfs_file_t *f = (lfs_file_t *)file;
_mutex.lock();
LFS_INFO("file_truncate(%p)", file);
int err = lfs_file_truncate(&_lfs, f, length);
LFS_INFO("file_truncate -> %d", lfs_toerror(err));
_mutex.unlock();
return lfs_toerror(err);
}
////// Dir operations //////
int LittleFileSystem::dir_open(fs_dir_t *dir, const char *path)

View File

@ -227,6 +227,19 @@ protected:
*/
virtual off_t file_size(mbed::fs_file_t file);
/** Truncate or extend a file.
*
* The file's length is set to the specified value. The seek pointer is
* not changed. If the file is extended, the extended area appears as if
* it were zero-filled.
*
* @param file File handle
* @param length The requested new length for the file
*
* @return Zero on success, negative error code on failure
*/
virtual int file_truncate(mbed::fs_file_t file, off_t length);
/** Open a directory on the filesystem
*
* @param dir Destination for the handle to the directory

View File

@ -138,6 +138,21 @@ public:
*/
virtual off_t size();
/** Truncate or extend a file.
*
* The file's length is set to the specified value. The seek pointer is
* not changed. If the file is extended, the extended area appears as if
* it were zero-filled.
*
* @param length The requested new length for the file
*
* @return Zero on success, negative error code on failure
*/
virtual int truncate(off_t length)
{
return -EINVAL;
}
/** Move the file position to a given offset from a given location.
*
* @param offset The offset from whence to move to

View File

@ -842,6 +842,23 @@ extern "C" off_t lseek(int fildes, off_t offset, int whence)
return off;
}
extern "C" int ftruncate(int fildes, off_t length)
{
FileHandle *fhc = get_fhc(fildes);
if (fhc == NULL) {
errno = EBADF;
return -1;
}
int err = fhc->truncate(length);
if (err < 0) {
errno = -err;
return -1;
} else {
return 0;
}
}
#ifdef __ARMCC_VERSION
extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
{

View File

@ -524,6 +524,7 @@ extern "C" {
ssize_t write(int fildes, const void *buf, size_t nbyte);
ssize_t read(int fildes, void *buf, size_t nbyte);
off_t lseek(int fildes, off_t offset, int whence);
int ftruncate(int fildes, off_t length);
int isatty(int fildes);
int fsync(int fildes);
int fstat(int fildes, struct stat *st);