Browse Source

add sys_utimensat (#8124)

xiao-mang 1 year ago
parent
commit
5d16042765

+ 20 - 0
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

+ 3 - 0
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;

+ 107 - 0
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

+ 40 - 0
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)