summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/dfs/dfs_v1/src/dfs_posix.c47
-rw-r--r--components/dfs/dfs_v2/src/dfs_posix.c47
-rw-r--r--components/lwp/lwp_syscall.c42
3 files changed, 136 insertions, 0 deletions
diff --git a/components/dfs/dfs_v1/src/dfs_posix.c b/components/dfs/dfs_v1/src/dfs_posix.c
index fd6d56d0b5..b0b7e3dd16 100644
--- a/components/dfs/dfs_v1/src/dfs_posix.c
+++ b/components/dfs/dfs_v1/src/dfs_posix.c
@@ -62,6 +62,53 @@ int open(const char *file, int flags, ...)
}
RTM_EXPORT(open);
+#ifndef AT_FDCWD
+#define AT_FDCWD (-100)
+#endif
+int openat(int dirfd, const char *path, int flag, ...)
+{
+ struct dfs_file *d;
+ char *fullpath;
+ int fd;
+
+ if (!path)
+ {
+ rt_set_errno(-EBADF);
+ return -1;
+ }
+
+ fullpath = (char*)path;
+
+ if (path[0] != '/')
+ {
+ if (dirfd != AT_FDCWD)
+ {
+ d = fd_get(dirfd);
+ if (!d || !d->vnode)
+ {
+ rt_set_errno(-EBADF);
+ return -1;
+ }
+
+ fullpath = dfs_normalize_path(d->vnode->fullpath, path);
+ if (!fullpath)
+ {
+ rt_set_errno(-ENOMEM);
+ return -1;
+ }
+ }
+ }
+
+ fd = open(fullpath, flag, 0);
+
+ if (fullpath != path)
+ {
+ rt_free(fullpath);
+ }
+
+ return fd;
+}
+
/**
* this function is a POSIX compliant version,
* which will create a new file or rewrite an existing one
diff --git a/components/dfs/dfs_v2/src/dfs_posix.c b/components/dfs/dfs_v2/src/dfs_posix.c
index fd6d56d0b5..b0b7e3dd16 100644
--- a/components/dfs/dfs_v2/src/dfs_posix.c
+++ b/components/dfs/dfs_v2/src/dfs_posix.c
@@ -62,6 +62,53 @@ int open(const char *file, int flags, ...)
}
RTM_EXPORT(open);
+#ifndef AT_FDCWD
+#define AT_FDCWD (-100)
+#endif
+int openat(int dirfd, const char *path, int flag, ...)
+{
+ struct dfs_file *d;
+ char *fullpath;
+ int fd;
+
+ if (!path)
+ {
+ rt_set_errno(-EBADF);
+ return -1;
+ }
+
+ fullpath = (char*)path;
+
+ if (path[0] != '/')
+ {
+ if (dirfd != AT_FDCWD)
+ {
+ d = fd_get(dirfd);
+ if (!d || !d->vnode)
+ {
+ rt_set_errno(-EBADF);
+ return -1;
+ }
+
+ fullpath = dfs_normalize_path(d->vnode->fullpath, path);
+ if (!fullpath)
+ {
+ rt_set_errno(-ENOMEM);
+ return -1;
+ }
+ }
+ }
+
+ fd = open(fullpath, flag, 0);
+
+ if (fullpath != path)
+ {
+ rt_free(fullpath);
+ }
+
+ return fd;
+}
+
/**
* 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 f4295b4b55..c722ff6da1 100644
--- a/components/lwp/lwp_syscall.c
+++ b/components/lwp/lwp_syscall.c
@@ -518,6 +518,47 @@ sysret_t sys_open(const char *name, int flag, ...)
#endif
}
+/* syscall: "open" ret: "int" args: "const char *" "mode_t" "mode" */
+sysret_t sys_openat(int dirfd, const char *name, int flag, mode_t mode)
+{
+#ifdef ARCH_MM_MMU
+ int ret = -1;
+ int err = 0;
+ rt_size_t len = 0;
+ char *kname = RT_NULL;
+
+ len = lwp_user_strlen(name, &err);
+ if (!len || err != 0)
+ {
+ return -EINVAL;
+ }
+
+ kname = (char *)kmem_get(len + 1);
+ if (!kname)
+ {
+ return -ENOMEM;
+ }
+
+ lwp_get_from_user(kname, (void *)name, len + 1);
+ ret = openat(dirfd, kname, flag, mode);
+ if (ret < 0)
+ {
+ ret = GET_ERRNO();
+ }
+
+ kmem_put(kname);
+
+ return ret;
+#else
+ if (!lwp_user_accessable((void *)name, 1))
+ {
+ return -EFAULT;
+ }
+ int ret = openat(dirfd, name, flag, mode);
+ return (ret < 0 ? GET_ERRNO() : ret);
+#endif
+}
+
/* syscall: "close" ret: "int" args: "int" */
sysret_t sys_close(int fd)
{
@@ -4995,6 +5036,7 @@ const static struct rt_syscall_def func_table[] =
SYSCALL_SIGN(sys_statfs64),
SYSCALL_SIGN(sys_fstatfs),
SYSCALL_SIGN(sys_fstatfs64),
+ SYSCALL_SIGN(sys_openat), /* 175 */
};
const void *lwp_get_sys_api(rt_uint32_t number)