diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 4d1418b8085..315671ff64b 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -16,6 +16,16 @@ if RT_USING_DFS bool "Using working directory" default y + config RT_USING_DFS_LARGE_FILE + bool "Enable large file support with 64-bit file offsets" + default n + select RT_KLIBC_USING_VSNPRINTF_LONGLONG if !RT_KLIBC_USING_LIBC_VSNPRINTF + help + Enable 64-bit signed off_t for DFS/POSIX file offsets and + file sizes. This is required to access FAT32 files larger + than 2GB on 32-bit platforms. Enabling this option changes + the ABI of file offset related APIs and structures. + if RT_USING_DFS_V1 config RT_USING_DFS_MNTTABLE bool "Using mount table for file system" diff --git a/components/dfs/dfs_v1/filesystems/cromfs/dfs_cromfs.c b/components/dfs/dfs_v1/filesystems/cromfs/dfs_cromfs.c index fee8b8dbd15..0a09a7a5adf 100644 --- a/components/dfs/dfs_v1/filesystems/cromfs/dfs_cromfs.c +++ b/components/dfs/dfs_v1/filesystems/cromfs/dfs_cromfs.c @@ -788,7 +788,7 @@ static int dfs_cromfs_read(struct dfs_file *file, void *buf, size_t count) return length; } -static int dfs_cromfs_lseek(struct dfs_file *file, off_t offset) +static off_t dfs_cromfs_lseek(struct dfs_file *file, off_t offset) { if (offset <= file->vnode->size) { diff --git a/components/dfs/dfs_v1/filesystems/elmfat/dfs_elm.c b/components/dfs/dfs_v1/filesystems/elmfat/dfs_elm.c index effd1bcd7c7..826c5c0e653 100644 --- a/components/dfs/dfs_v1/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/dfs_v1/filesystems/elmfat/dfs_elm.c @@ -86,6 +86,18 @@ static int elm_result_to_dfs(FRESULT result) return status; } +static int dfs_elm_off_to_fsize(off_t offset, FSIZE_t *fsize) +{ + if (offset < 0) + return -EINVAL; + + if ((uint64_t)offset > (uint64_t)(FSIZE_t)-1) + return -EFBIG; + + *fsize = (FSIZE_t)offset; + return 0; +} + /* results: * -1, no space to install fatfs driver * >= 0, there is an space to install fatfs driver @@ -505,12 +517,16 @@ int dfs_elm_ioctl(struct dfs_file *file, int cmd, void *args) FIL *fd; FSIZE_t fptr, length; FRESULT result = FR_OK; + int ret; fd = (FIL *)(file->data); RT_ASSERT(fd != RT_NULL); /* save file read/write point */ fptr = fd->fptr; - length = *(off_t*)args; + ret = dfs_elm_off_to_fsize(*(off_t *)args, &length); + if (ret < 0) + return ret; + if (length <= fd->obj.objsize) { fd->fptr = length; @@ -597,12 +613,18 @@ off_t dfs_elm_lseek(struct dfs_file *file, off_t offset) if (file->vnode->type == FT_REGULAR) { FIL *fd; + FSIZE_t fsize; + int ret; /* regular file type */ fd = (FIL *)(file->data); RT_ASSERT(fd != RT_NULL); - result = f_lseek(fd, offset); + ret = dfs_elm_off_to_fsize(offset, &fsize); + if (ret < 0) + return ret; + + result = f_lseek(fd, fsize); if (result == FR_OK) { /* return current position */ diff --git a/components/dfs/dfs_v1/filesystems/nfs/dfs_nfs.c b/components/dfs/dfs_v1/filesystems/nfs/dfs_nfs.c index b24e6361845..815b45e4c74 100644 --- a/components/dfs/dfs_v1/filesystems/nfs/dfs_nfs.c +++ b/components/dfs/dfs_v1/filesystems/nfs/dfs_nfs.c @@ -685,7 +685,7 @@ int nfs_write(struct dfs_file *file, const void *buf, size_t count) return total; } -int nfs_lseek(struct dfs_file *file, off_t offset) +off_t nfs_lseek(struct dfs_file *file, off_t offset) { nfs_file *fd; nfs_filesystem *nfs; diff --git a/components/dfs/dfs_v1/filesystems/skeleton/skeleton.c b/components/dfs/dfs_v1/filesystems/skeleton/skeleton.c index 5c35cd1ffc3..d6feafa3ef8 100644 --- a/components/dfs/dfs_v1/filesystems/skeleton/skeleton.c +++ b/components/dfs/dfs_v1/filesystems/skeleton/skeleton.c @@ -34,7 +34,7 @@ int dfs_skt_read(struct dfs_file *file, void *buf, rt_size_t count) return count; } -int dfs_skt_lseek(struct dfs_file *file, rt_off_t offset) +off_t dfs_skt_lseek(struct dfs_file *file, off_t offset) { return -RT_EIO; } diff --git a/components/dfs/dfs_v1/include/dfs_file.h b/components/dfs/dfs_v1/include/dfs_file.h index 26c74c8f161..fc4d78365ee 100644 --- a/components/dfs/dfs_v1/include/dfs_file.h +++ b/components/dfs/dfs_v1/include/dfs_file.h @@ -50,7 +50,11 @@ struct dfs_vnode const struct dfs_file_ops *fops; uint32_t flags; /* self flags, is dir etc.. */ +#ifdef RT_USING_DFS_LARGE_FILE + off_t size; /* Size in bytes */ +#else size_t size; /* Size in bytes */ +#endif void *data; /* Specific file system data */ }; diff --git a/components/dfs/dfs_v1/src/dfs_file.c b/components/dfs/dfs_v1/src/dfs_file.c index f1c4e7ee4d2..33efc94bb00 100644 --- a/components/dfs/dfs_v1/src/dfs_file.c +++ b/components/dfs/dfs_v1/src/dfs_file.c @@ -580,7 +580,7 @@ int dfs_file_flush(struct dfs_file *fd) */ off_t dfs_file_lseek(struct dfs_file *fd, off_t offset) { - int result; + off_t result; if (fd == NULL) return -EINVAL; @@ -783,6 +783,48 @@ int dfs_file_mmap2(struct dfs_file *fd, struct dfs_mmap2_args *mmap2) #ifdef RT_USING_FINSH #include +#ifdef RT_USING_DFS_LARGE_FILE +static void dfs_print_file_size(off_t size) +{ + char tmp[21]; + char buf[22]; + int index = 0; + int out = 0; + uint64_t value; + + if (size < 0) + { + value = (uint64_t)(-(size + 1)) + 1; + buf[out++] = '-'; + } + else + { + value = (uint64_t)size; + } + + if (value == 0) + { + tmp[index++] = '0'; + } + else + { + while ((value != 0) && (index < (int)sizeof(tmp))) + { + tmp[index++] = (char)('0' + (value % 10)); + value /= 10; + } + } + + while ((index > 0) && (out + 1 < (int)sizeof(buf))) + { + buf[out++] = tmp[--index]; + } + buf[out] = '\0'; + + rt_kprintf(" %-25s\n", buf); +} +#endif + void ls(const char *pathname) { struct dfs_file fd; @@ -835,7 +877,11 @@ void ls(const char *pathname) } else { +#ifdef RT_USING_DFS_LARGE_FILE + dfs_print_file_size(stat.st_size); +#else rt_kprintf(" %-25lu\n", (unsigned long)stat.st_size); +#endif } } else diff --git a/components/dfs/dfs_v1/src/dfs_posix.c b/components/dfs/dfs_v1/src/dfs_posix.c index f3d7b70c318..4350deaa1e4 100644 --- a/components/dfs/dfs_v1/src/dfs_posix.c +++ b/components/dfs/dfs_v1/src/dfs_posix.c @@ -286,7 +286,7 @@ RTM_EXPORT(write); */ off_t lseek(int fd, off_t offset, int whence) { - int result; + off_t result; struct dfs_file *d; d = fd_get(fd); diff --git a/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c b/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c index 90b87a178b4..b1f671e445d 100644 --- a/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c +++ b/components/dfs/dfs_v2/filesystems/elmfat/dfs_elm.c @@ -109,6 +109,18 @@ static int elm_result_to_dfs(FRESULT result) return status; } +static int dfs_elm_off_to_fsize(off_t offset, FSIZE_t *fsize) +{ + if (offset < 0) + return -EINVAL; + + if ((uint64_t)offset > (uint64_t)(FSIZE_t)-1) + return -EFBIG; + + *fsize = (FSIZE_t)offset; + return 0; +} + /* results: * -1, no space to install fatfs driver * >= 0, there is an space to install fatfs driver @@ -549,7 +561,7 @@ int dfs_elm_ioctl(struct dfs_file *file, int cmd, void *args) { case RT_FIOFTRUNCATE: { - off_t offset = (off_t)(size_t)(args); + off_t offset = *(off_t *)args; return dfs_elm_truncate(file, offset); } case F_GETLK: @@ -565,6 +577,8 @@ ssize_t dfs_elm_read(struct dfs_file *file, void *buf, size_t len, off_t *pos) FIL *fd; FRESULT result = FR_OK; UINT byte_read; + FSIZE_t fsize; + int ret; if (file->vnode->type == FT_DIRECTORY) { @@ -573,13 +587,20 @@ ssize_t dfs_elm_read(struct dfs_file *file, void *buf, size_t len, off_t *pos) if (file->vnode->size > *pos) { + ret = dfs_elm_off_to_fsize(*pos, &fsize); + if (ret < 0) + return ret; + fd = (FIL *)(file->vnode->data); RT_ASSERT(fd != RT_NULL); rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER); - f_lseek(fd, *pos); - result = f_read(fd, buf, len, &byte_read); - /* update position */ - *pos = fd->fptr; + result = f_lseek(fd, fsize); + if (result == FR_OK) + { + result = f_read(fd, buf, len, &byte_read); + /* update position */ + *pos = fd->fptr; + } rt_mutex_release(&file->vnode->lock); if (result == FR_OK) return byte_read; @@ -593,6 +614,8 @@ ssize_t dfs_elm_write(struct dfs_file *file, const void *buf, size_t len, off_t FIL *fd; FRESULT result; UINT byte_write; + FSIZE_t fsize; + int ret; if (file->vnode->type == FT_DIRECTORY) { @@ -601,12 +624,19 @@ ssize_t dfs_elm_write(struct dfs_file *file, const void *buf, size_t len, off_t fd = (FIL *)(file->vnode->data); RT_ASSERT(fd != RT_NULL); + ret = dfs_elm_off_to_fsize(*pos, &fsize); + if (ret < 0) + return ret; + rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER); - f_lseek(fd, *pos); - result = f_write(fd, buf, len, &byte_write); - /* update position and file size */ - *pos = fd->fptr; - file->vnode->size = f_size(fd); + result = f_lseek(fd, fsize); + if (result == FR_OK) + { + result = f_write(fd, buf, len, &byte_write); + /* update position and file size */ + *pos = fd->fptr; + file->vnode->size = f_size(fd); + } rt_mutex_release(&file->vnode->lock); if (result == FR_OK) return byte_write; @@ -650,12 +680,18 @@ off_t dfs_elm_lseek(struct dfs_file *file, off_t offset, int wherece) if (file->vnode->type == FT_REGULAR) { FIL *fd; + FSIZE_t fsize; + int ret; /* regular file type */ fd = (FIL *)(file->vnode->data); RT_ASSERT(fd != RT_NULL); + ret = dfs_elm_off_to_fsize(offset, &fsize); + if (ret < 0) + return ret; + rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER); - result = f_lseek(fd, offset); + result = f_lseek(fd, fsize); pos = fd->fptr; rt_mutex_release(&file->vnode->lock); if (result == FR_OK) @@ -687,21 +723,26 @@ off_t dfs_elm_lseek(struct dfs_file *file, off_t offset, int wherece) static int dfs_elm_truncate(struct dfs_file *file, off_t offset) { FIL *fd; - FSIZE_t fptr; + FSIZE_t fptr, fsize; FRESULT result = FR_OK; + int ret; fd = (FIL *)(file->vnode->data); RT_ASSERT(fd != RT_NULL); + ret = dfs_elm_off_to_fsize(offset, &fsize); + if (ret < 0) + return ret; + /* save file read/write point */ fptr = fd->fptr; - if (offset <= fd->obj.objsize) + if (fsize <= fd->obj.objsize) { - fd->fptr = offset; + fd->fptr = fsize; result = f_truncate(fd); } else { - result = f_lseek(fd, offset); + result = f_lseek(fd, fsize); } /* restore file read/write point */ fd->fptr = fptr; @@ -1042,6 +1083,8 @@ ssize_t dfs_elm_page_write(struct dfs_page *page) FIL *fd; FRESULT result; UINT byte_write; + FSIZE_t fsize; + int ret; if (page->aspace->vnode->type == FT_DIRECTORY) { @@ -1050,9 +1093,16 @@ ssize_t dfs_elm_page_write(struct dfs_page *page) fd = (FIL *)(page->aspace->vnode->data); RT_ASSERT(fd != RT_NULL); + ret = dfs_elm_off_to_fsize(page->fpos, &fsize); + if (ret < 0) + return ret; + rt_mutex_take(&page->aspace->vnode->lock, RT_WAITING_FOREVER); - f_lseek(fd, page->fpos); - result = f_write(fd, page->page, page->len, &byte_write); + result = f_lseek(fd, fsize); + if (result == FR_OK) + { + result = f_write(fd, page->page, page->len, &byte_write); + } rt_mutex_release(&page->aspace->vnode->lock); if (result == FR_OK) { diff --git a/components/dfs/dfs_v2/filesystems/ramfs/dfs_ramfs.c b/components/dfs/dfs_v2/filesystems/ramfs/dfs_ramfs.c index fd7326bd018..f90b955baa9 100644 --- a/components/dfs/dfs_v2/filesystems/ramfs/dfs_ramfs.c +++ b/components/dfs/dfs_v2/filesystems/ramfs/dfs_ramfs.c @@ -151,7 +151,7 @@ int dfs_ramfs_write(struct dfs_file *fd, const void *buf, size_t count) return count; } -int dfs_ramfs_lseek(struct dfs_file *file, off_t offset) +off_t dfs_ramfs_lseek(struct dfs_file *file, off_t offset) { if (offset <= (off_t)file->vnode->size) { diff --git a/components/dfs/dfs_v2/filesystems/skeleton/skeleton.c b/components/dfs/dfs_v2/filesystems/skeleton/skeleton.c index af2c871dfc3..a048ae0caf1 100644 --- a/components/dfs/dfs_v2/filesystems/skeleton/skeleton.c +++ b/components/dfs/dfs_v2/filesystems/skeleton/skeleton.c @@ -34,7 +34,7 @@ int dfs_skt_read(struct dfs_file *file, void *buf, rt_size_t count) return count; } -int dfs_skt_lseek(struct dfs_file *file, rt_off_t offset) +off_t dfs_skt_lseek(struct dfs_file *file, off_t offset) { return -RT_EIO; } diff --git a/components/dfs/dfs_v2/include/dfs_file.h b/components/dfs/dfs_v2/include/dfs_file.h index 5010ed45346..5d41f1fa8e1 100644 --- a/components/dfs/dfs_v2/include/dfs_file.h +++ b/components/dfs/dfs_v2/include/dfs_file.h @@ -63,7 +63,11 @@ struct dfs_vnode struct dfs_mnt *mnt; /* which mounted file system does this vnode belong to */ +#ifdef RT_USING_DFS_LARGE_FILE + off_t size; +#else size_t size; +#endif uint32_t nlink; const struct dfs_file_ops *fops; diff --git a/components/dfs/dfs_v2/src/dfs_file.c b/components/dfs/dfs_v2/src/dfs_file.c index 9c6e383e1b4..09600f170c4 100644 --- a/components/dfs/dfs_v2/src/dfs_file.c +++ b/components/dfs/dfs_v2/src/dfs_file.c @@ -2521,6 +2521,48 @@ int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2) #define _COLOR_WHITE "\033[37m" #define _COLOR_NORMAL "\033[0m" +#ifdef RT_USING_DFS_LARGE_FILE +static void dfs_print_file_size(off_t size) +{ + char tmp[21]; + char buf[22]; + int index = 0; + int out = 0; + uint64_t value; + + if (size < 0) + { + value = (uint64_t)(-(size + 1)) + 1; + buf[out++] = '-'; + } + else + { + value = (uint64_t)size; + } + + if (value == 0) + { + tmp[index++] = '0'; + } + else + { + while ((value != 0) && (index < (int)sizeof(tmp))) + { + tmp[index++] = (char)('0' + (value % 10)); + value /= 10; + } + } + + while ((index > 0) && (out + 1 < (int)sizeof(buf))) + { + buf[out++] = tmp[--index]; + } + buf[out] = '\0'; + + rt_kprintf(" %-25s\n", buf); +} +#endif + /** * @brief List directory contents with colored output * @@ -2655,7 +2697,11 @@ void ls(const char *pathname) else if (stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { rt_kprintf(_COLOR_GREEN "%-20s" _COLOR_NORMAL, dirent.d_name); +#ifdef RT_USING_DFS_LARGE_FILE + dfs_print_file_size(stat.st_size); +#else rt_kprintf(" %-25lu\n", (unsigned long)stat.st_size); +#endif } else if (S_ISCHR(stat.st_mode)) { @@ -2665,7 +2711,11 @@ void ls(const char *pathname) else { rt_kprintf("%-20s", dirent.d_name); +#ifdef RT_USING_DFS_LARGE_FILE + dfs_print_file_size(stat.st_size); +#else rt_kprintf(" %-25lu\n", (unsigned long)stat.st_size); +#endif } } else @@ -3029,4 +3079,4 @@ void copy(const char *src, const char *dst) } FINSH_FUNCTION_EXPORT(copy, copy file or dir) -#endif \ No newline at end of file +#endif diff --git a/components/libc/compilers/common/extension/sys/stat.h b/components/libc/compilers/common/extension/sys/stat.h index e4b2da764c2..9d9ad2f0669 100644 --- a/components/libc/compilers/common/extension/sys/stat.h +++ b/components/libc/compilers/common/extension/sys/stat.h @@ -62,7 +62,11 @@ struct stat uint16_t st_uid; uint16_t st_gid; struct rt_device *st_rdev; +#ifdef RT_USING_DFS_LARGE_FILE + off_t st_size; +#else uint32_t st_size; +#endif time_t st_atime; long st_spare1; time_t st_mtime; @@ -70,7 +74,11 @@ struct stat time_t st_ctime; long st_spare3; uint32_t st_blksize; +#ifdef RT_USING_DFS_LARGE_FILE + uint64_t st_blocks; +#else uint32_t st_blocks; +#endif long st_spare4[2]; }; diff --git a/components/libc/compilers/common/extension/sys/types.h b/components/libc/compilers/common/extension/sys/types.h index cae4d4adcd6..457bb98e120 100644 --- a/components/libc/compilers/common/extension/sys/types.h +++ b/components/libc/compilers/common/extension/sys/types.h @@ -12,6 +12,7 @@ #ifndef __SYS_TYPES_H__ #define __SYS_TYPES_H__ +#include #include #include #include @@ -25,7 +26,11 @@ typedef int32_t key_t; /* Used for interprocess communication. typedef int pid_t; /* Used for process IDs and process group IDs. */ typedef unsigned short uid_t; typedef unsigned short gid_t; +#ifdef RT_USING_DFS_LARGE_FILE +typedef int64_t off_t; +#else typedef signed long off_t; +#endif typedef int mode_t; typedef signed long ssize_t; /* Used for a count of bytes or an error indication. */ typedef unsigned long __timer_t;