summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxiao-mang <[email protected]>2023-10-13 19:21:49 +0800
committerGitHub <[email protected]>2023-10-13 19:21:49 +0800
commit5d16042765ac989cab9bb4e9b112f1a98e17f4d5 (patch)
tree248b5ad9152677e729ece17c9552458912b80f4a
parenta289ae1b186b8a0d64f77b0a2387c1693ab473e8 (diff)
add sys_utimensat (#8124)
-rw-r--r--components/dfs/dfs_v2/include/dfs.h20
-rw-r--r--components/dfs/dfs_v2/include/dfs_fs.h3
-rw-r--r--components/dfs/dfs_v2/src/dfs_posix.c107
-rw-r--r--components/lwp/lwp_syscall.c40
4 files changed, 170 insertions, 0 deletions
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 <rtatomic.h>
#include <rtdevice.h>
+#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(&current_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)