From 60f2ae4d3cee0cbf200a89df21a3949c92125cf4 Mon Sep 17 00:00:00 2001 From: zhangjun <2281979437@qq.com> Date: Thu, 26 Sep 2019 10:22:33 +0800 Subject: [PATCH] =?UTF-8?q?[components][dfs]=E6=B7=BB=E5=8A=A0ftruncate?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/dfs/filesystems/elmfat/dfs_elm.c | 25 +++++++++++ components/dfs/include/dfs_file.h | 4 ++ components/dfs/include/dfs_posix.h | 1 + components/dfs/src/dfs_file.c | 29 +++++++++++++ components/dfs/src/dfs_posix.c | 46 +++++++++++++++++++++ 5 files changed, 105 insertions(+) diff --git a/components/dfs/filesystems/elmfat/dfs_elm.c b/components/dfs/filesystems/elmfat/dfs_elm.c index 3825fd9108..b6d2c2388a 100644 --- a/components/dfs/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/filesystems/elmfat/dfs_elm.c @@ -478,6 +478,31 @@ int dfs_elm_close(struct dfs_fd *file) int dfs_elm_ioctl(struct dfs_fd *file, int cmd, void *args) { + switch (cmd) + { + case RT_FIOFTRUNCATE: + { + FIL *fd; + FSIZE_t fptr, length; + FRESULT result = FR_OK; + fd = (FIL *)(file->data); + RT_ASSERT(fd != RT_NULL); + + /* save file read/write point */ + fptr = fd->fptr; + length = *(off_t*)args; + if (length <= fd->obj.objsize) + { + fd->fptr = length; + result = f_truncate(fd); + }else{ + result = f_lseek(fd, length); + } + /* restore file read/write point */ + fd->fptr = fptr; + return elm_result_to_dfs(result); + } + } return -ENOSYS; } diff --git a/components/dfs/include/dfs_file.h b/components/dfs/include/dfs_file.h index aaff3f6e9c..2dfacd653e 100644 --- a/components/dfs/include/dfs_file.h +++ b/components/dfs/include/dfs_file.h @@ -66,6 +66,10 @@ int dfs_file_lseek(struct dfs_fd *fd, off_t offset); int dfs_file_stat(const char *path, struct stat *buf); int dfs_file_rename(const char *oldpath, const char *newpath); +int dfs_file_ftruncate(struct dfs_fd *fd, off_t length); + +/* 0x5254 is just a magic number to make these relatively unique ("RT") */ +#define RT_FIOFTRUNCATE 0x52540000U #ifdef __cplusplus } diff --git a/components/dfs/include/dfs_posix.h b/components/dfs/include/dfs_posix.h index 9fd76debe2..87d5f0771e 100644 --- a/components/dfs/include/dfs_posix.h +++ b/components/dfs/include/dfs_posix.h @@ -58,6 +58,7 @@ int fstat(int fildes, struct stat *buf); int fsync(int fildes); int fcntl(int fildes, int cmd, ...); int ioctl(int fildes, int cmd, ...); +int ftruncate(int fd, off_t length); /* directory api*/ int rmdir(const char *path); diff --git a/components/dfs/src/dfs_file.c b/components/dfs/src/dfs_file.c index 5f090a7f6b..1063a278ab 100644 --- a/components/dfs/src/dfs_file.c +++ b/components/dfs/src/dfs_file.c @@ -482,6 +482,35 @@ __exit: return result; } +/** + * this function is will cause the regular file referenced by fd + * to be truncated to a size of precisely length bytes. + * + * @param fd the file descriptor. + * @param length the length to be truncated. + * + * @return the status of truncated. + */ +int dfs_file_ftruncate(struct dfs_fd *fd, off_t length) +{ + int result; + + /* fd is null or not a regular file system fd, or length is invalid */ + if (fd == NULL || fd->type != FT_REGULAR || length < 0) + return -EINVAL; + + if (fd->fops->ioctl == NULL) + return -ENOSYS; + + result = fd->fops->ioctl(fd, RT_FIOFTRUNCATE, (void*)&length); + + /* update current size */ + if (result == 0) + fd->size = length; + + return result; +} + #ifdef RT_USING_FINSH #include diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c index 69fe56a84e..fc603df437 100644 --- a/components/dfs/src/dfs_posix.c +++ b/components/dfs/src/dfs_posix.c @@ -471,6 +471,52 @@ int ioctl(int fildes, int cmd, ...) } RTM_EXPORT(ioctl); +/** + * + * this function is a POSIX compliant version, which cause the regular file + * referenced by fd to be truncated to a size of precisely length bytes. + * @param fd the file descriptor. + * @param length the length to be truncated. + * + * @return Upon successful completion, ftruncate() shall return 0; + * otherwise, -1 shall be returned and errno set to indicate the error. + */ +int ftruncate(int fd, off_t length) +{ + int result; + struct dfs_fd *d; + + d = fd_get(fd); + if (d == NULL) + { + rt_set_errno(-EBADF); + + return -1; + } + + if (length < 0) + { + fd_put(d); + rt_set_errno(-EINVAL); + + return -1; + } + result = dfs_file_ftruncate(d, length); + if (result < 0) + { + fd_put(d); + rt_set_errno(result); + + return -1; + } + + /* release the ref-count of fd */ + fd_put(d); + + return 0; +} +RTM_EXPORT(ftruncate); + /** * this function is a POSIX compliant version, which will return the * information about a mounted file system.