diff --git a/components/dfs/dfs_v2/include/dfs.h b/components/dfs/dfs_v2/include/dfs.h index 1ebd8b608f..61c78b62a5 100644 --- a/components/dfs/dfs_v2/include/dfs.h +++ b/components/dfs/dfs_v2/include/dfs.h @@ -25,6 +25,26 @@ #include #include +#ifndef ATTR_ATIME_SET +#define ATTR_ATIME_SET (1 << 7) +#endif + +#ifndef ATTR_MTIME_SET +#define ATTR_MTIME_SET (1 << 8) +#endif + +#ifndef AT_SYMLINK_NOFOLLOW +#define AT_SYMLINK_NOFOLLOW 0x100 +#endif + +#ifndef UTIME_NOW +#define UTIME_NOW 0x3fffffff +#endif + +#ifndef UTIME_OMIT +#define UTIME_OMIT 0x3ffffffe +#endif + #ifndef DFS_FD_MAX #define DFS_FD_MAX 16 #endif diff --git a/components/dfs/dfs_v2/include/dfs_fs.h b/components/dfs/dfs_v2/include/dfs_fs.h index 4a56119d51..9dc99ee367 100644 --- a/components/dfs/dfs_v2/include/dfs_fs.h +++ b/components/dfs/dfs_v2/include/dfs_fs.h @@ -31,7 +31,10 @@ struct dfs_partition struct dfs_attr { + unsigned int ia_valid; mode_t st_mode; + struct timespec ia_atime; + struct timespec ia_mtime; }; struct dfs_mnt; diff --git a/components/dfs/dfs_v2/src/dfs_posix.c b/components/dfs/dfs_v2/src/dfs_posix.c index ba67fe54b8..3319efe2bf 100644 --- a/components/dfs/dfs_v2/src/dfs_posix.c +++ b/components/dfs/dfs_v2/src/dfs_posix.c @@ -125,6 +125,113 @@ int openat(int dirfd, const char *path, int flag, ...) return fd; } +int utimensat(int __fd, const char *__path, const struct timespec __times[2], int __flags) +{ + int ret; + struct stat buffer; + struct dfs_file *d; + char *fullpath; + struct dfs_attr attr; + time_t current_time; + char *link_fn = (char *)rt_malloc(DFS_PATH_MAX); + int err; + + if (__path == NULL) + { + return -EFAULT; + } + + if (__path[0] == '/' || __fd == AT_FDCWD) + { + if (stat(__path, &buffer) < 0) + { + return -ENOENT; + } + else + { + fullpath = (char*)__path; + } + } + else + { + if (__fd != AT_FDCWD) + { + d = fd_get(__fd); + if (!d || !d->vnode) + { + return -EBADF; + } + + fullpath = dfs_dentry_full_path(d->dentry); + if (!fullpath) + { + rt_set_errno(-ENOMEM); + return -1; + } + } + } + + //update time + attr.ia_valid = ATTR_ATIME_SET | ATTR_MTIME_SET; + time(¤t_time); + if (UTIME_NOW == __times[0].tv_nsec) + { + attr.ia_atime.tv_sec = current_time; + } + else if (UTIME_OMIT != __times[0].tv_nsec) + { + attr.ia_atime.tv_sec = __times[0].tv_sec; + } + else + { + attr.ia_valid &= ~ATTR_ATIME_SET; + } + + if (UTIME_NOW == __times[1].tv_nsec) + { + attr.ia_mtime.tv_sec = current_time; + } + else if (UTIME_OMIT == __times[1].tv_nsec) + { + attr.ia_mtime.tv_sec = __times[1].tv_sec; + } + else + { + attr.ia_valid &= ~ATTR_MTIME_SET; + } + + if (dfs_file_lstat(fullpath, &buffer) == 0) + { + if (S_ISLNK(buffer.st_mode) && (__flags != AT_SYMLINK_NOFOLLOW)) + { + if (link_fn) + { + err = dfs_file_readlink(fullpath, link_fn, DFS_PATH_MAX); + if (err < 0) + { + rt_free(link_fn); + return -ENOENT; + } + else + { + fullpath = link_fn; + if (dfs_file_stat(fullpath, &buffer) != 0) + { + rt_free(link_fn); + return -ENOENT; + } + } + } + + } + } + attr.st_mode = buffer.st_mode; + ret = dfs_file_setattr(fullpath, &attr); + rt_free(link_fn); + + return ret; +} + /** * this function is a POSIX compliant version, * which will create a new file or rewrite an existing one diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 043af53f3c..e4f429afdb 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -6135,6 +6135,45 @@ sysret_t sys_ftruncate(int fd, off_t length) return (ret < 0 ? GET_ERRNO() : ret); } +sysret_t sys_utimensat(int __fd, const char *__path, const struct timespec __times[2], int __flags) +{ +#ifdef RT_USING_DFS_V2 +#ifdef ARCH_MM_MMU + int ret = -1; + rt_size_t len = 0; + char *kpath = RT_NULL; + + len = lwp_user_strlen(__path); + if (len <= 0) + { + return -EINVAL; + } + + kpath = (char *)kmem_get(len + 1); + if (!kpath) + { + return -ENOMEM; + } + + lwp_get_from_user(kpath, (void *)__path, len + 1); + ret = utimensat(__fd, kpath, __times, __flags); + + kmem_put(kpath); + + return ret; +#else + if (!lwp_user_accessable((void *)__path, 1)) + { + return -EFAULT; + } + int ret = utimensat(__fd, __path, __times, __flags); + return ret; +#endif +#else + return -1; +#endif +} + sysret_t sys_chmod(const char *fileName, mode_t mode) { char *copy_fileName; @@ -6661,6 +6700,7 @@ const static struct rt_syscall_def func_table[] = SYSCALL_SIGN(sys_memfd_create), /* 200 */ SYSCALL_SIGN(sys_ftruncate), SYSCALL_SIGN(sys_setitimer), + SYSCALL_SIGN(sys_utimensat), }; const void *lwp_get_sys_api(rt_uint32_t number)