diff --git a/components/dfs/src/dfs_posix.c b/components/dfs/src/dfs_posix.c index aa9c48e329..ce1a3329d3 100644 --- a/components/dfs/src/dfs_posix.c +++ b/components/dfs/src/dfs_posix.c @@ -520,6 +520,32 @@ int statfs(const char *path, struct statfs *buf) } RTM_EXPORT(statfs); +/** + * this function is a POSIX compliant version, which will return the + * information about a mounted file system. + * + * @param fildes the file description. + * @param buf the buffer to save the returned information. + * + * @return 0 on successful, others on failed. + */ +int fstatfs(int fildes, struct statfs *buf) +{ + struct dfs_fd *d; + + /* get the fd */ + d = fd_get(fildes); + if (d == NULL) + { + rt_set_errno(-EBADF); + + return -1; + } + + return statfs(d->vnode->fullpath, buf); +} +RTM_EXPORT(fstatfs); + /** * this function is a POSIX compliant version, which will make a directory * diff --git a/components/libc/compilers/common/include/sys/statfs.h b/components/libc/compilers/common/include/sys/statfs.h index 818ec9eb77..8765e1d820 100644 --- a/components/libc/compilers/common/include/sys/statfs.h +++ b/components/libc/compilers/common/include/sys/statfs.h @@ -5,6 +5,7 @@ * * Change Logs: * Date Author Notes + * 2023-03-27 xqyjlj adapt musl */ #ifndef __SYS_STATFS_H__ @@ -16,16 +17,31 @@ extern "C" { #endif +#ifdef RT_USING_MUSLLIBC +/* this is required for musl */ +#ifndef _POSIX_SOURCE +#define _POSIX_SOURCE +#include_next +/* limiting influence of _POSIX_SOURCE */ +#undef _POSIX_SOURCE + +#else /* def _POSIX_SOURCE */ +#include_next +#endif +#else struct statfs { size_t f_bsize; /* block size */ size_t f_blocks; /* total data blocks in file system */ size_t f_bfree; /* free blocks in file system */ + size_t f_bavail; /* free blocks available to unprivileged user*/ }; int statfs(const char *path, struct statfs *buf); int fstatfs(int fd, struct statfs *buf); +#endif + #ifdef __cplusplus } #endif diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index db5434264c..e7851c29cd 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -4611,6 +4611,144 @@ sysret_t sys_uname(struct utsname *uts) return 0; } +sysret_t sys_statfs(const char *path, struct statfs *buf) +{ + int ret = 0; + int err; + size_t len; + size_t copy_len; + char *copy_path; + struct statfs statfsbuff = {0}; + + if (!lwp_user_accessable((void *)buf, sizeof(struct statfs))) + { + return -EFAULT; + } + + len = lwp_user_strlen(path, &err); + if (err) + { + return -EFAULT; + } + + copy_path = (char*)rt_malloc(len + 1); + if (!copy_path) + { + return -ENOMEM; + } + + copy_len = lwp_get_from_user(copy_path, (void*)path, len); + if (copy_len == 0) + { + rt_free(copy_path); + return -EFAULT; + } + copy_path[copy_len] = '\0'; + + ret = _SYS_WRAP(statfs(copy_path, &statfsbuff)); + rt_free(copy_path); + + if (ret == 0) + { + lwp_put_to_user(buf, &statfsbuff, sizeof statfsbuff); + } + + return ret; +} + +sysret_t sys_statfs64(const char *path, size_t sz, struct statfs *buf) +{ + int ret = 0; + int err; + size_t len; + size_t copy_len; + char *copy_path; + struct statfs statfsbuff = {0}; + + if (!lwp_user_accessable((void *)buf, sizeof(struct statfs))) + { + return -EFAULT; + } + + if (sz != sizeof(struct statfs)) { + return -EINVAL; + } + + len = lwp_user_strlen(path, &err); + if (err) + { + return -EFAULT; + } + + copy_path = (char*)rt_malloc(len + 1); + if (!copy_path) + { + return -ENOMEM; + } + + copy_len = lwp_get_from_user(copy_path, (void*)path, len); + if (copy_len == 0) + { + rt_free(copy_path); + return -EFAULT; + } + copy_path[copy_len] = '\0'; + + ret = _SYS_WRAP(statfs(copy_path, &statfsbuff)); + rt_free(copy_path); + + if (ret == 0) + { + lwp_put_to_user(buf, &statfsbuff, sizeof statfsbuff); + } + + return ret; +} + +sysret_t sys_fstatfs(int fd, struct statfs *buf) +{ + int ret = 0; + struct statfs statfsbuff = {0}; + + if (!lwp_user_accessable((void *)buf, sizeof(struct statfs))) + { + return -EFAULT; + } + + ret = _SYS_WRAP(fstatfs(fd, &statfsbuff)); + + if (ret == 0) + { + lwp_put_to_user(buf, &statfsbuff, sizeof statfsbuff); + } + + return ret; +} + +sysret_t sys_fstatfs64(int fd, size_t sz, struct statfs *buf) +{ + int ret = 0; + struct statfs statfsbuff = {0}; + + if (!lwp_user_accessable((void *)buf, sizeof(struct statfs))) + { + return -EFAULT; + } + + if (sz != sizeof(struct statfs)) { + return -EINVAL; + } + + ret = _SYS_WRAP(fstatfs(fd, &statfsbuff)); + + if (ret == 0) + { + lwp_put_to_user(buf, &statfsbuff, sizeof statfsbuff); + } + + return ret; +} + const static struct rt_syscall_def func_table[] = { SYSCALL_SIGN(sys_exit), /* 01 */ @@ -4822,6 +4960,10 @@ const static struct rt_syscall_def func_table[] = SYSCALL_SIGN(sys_mq_close), SYSCALL_SIGN(sys_stat), //TODO should be replaced by sys_lstat if symbolic link are implemented SYSCALL_SIGN(sys_uname), /* 170 */ + SYSCALL_SIGN(sys_statfs), + SYSCALL_SIGN(sys_statfs64), + SYSCALL_SIGN(sys_fstatfs), + SYSCALL_SIGN(sys_fstatfs64), }; const void *lwp_get_sys_api(rt_uint32_t number)