mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #8972 from kjbracey-arm/merge_file_truncate
Merge feature-posix branch (FileHandle::truncate)pull/9122/head
commit
80c6f5f8ee
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue