aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xconfigure66
-rw-r--r--fesvr/fesvr.ac5
-rw-r--r--fesvr/syscall.cc94
-rw-r--r--fesvr/syscall.h1
4 files changed, 166 insertions, 0 deletions
diff --git a/configure b/configure
index 82feebb..e51a251 100755
--- a/configure
+++ b/configure
@@ -1748,6 +1748,63 @@ fi
as_fn_set_status $ac_retval
} # ac_fn_cxx_try_link
+
+# ac_fn_cxx_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ------------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_cxx_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_member
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@@ -4699,6 +4756,15 @@ else
fi
+ac_fn_cxx_check_member "$LINENO" "struct statx" "stx_mnt_id" "ac_cv_member_struct_statx_stx_mnt_id" "$ac_includes_default"
+if test "x$ac_cv_member_struct_statx_stx_mnt_id" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STATX_MNT_ID 1
+_ACEOF
+
+fi
+
diff --git a/fesvr/fesvr.ac b/fesvr/fesvr.ac
index 60e6c57..9a211b1 100644
--- a/fesvr/fesvr.ac
+++ b/fesvr/fesvr.ac
@@ -1 +1,6 @@
AC_CHECK_LIB(pthread, pthread_create, [], [AC_MSG_ERROR([libpthread is required])])
+
+AC_CHECK_MEMBER(struct statx.stx_mnt_id,
+ AC_DEFINE_UNQUOTED(HAVE_STATX_MNT_ID, 1, [Define to 1 if struct statx has stx_mnt_id.]),
+ ,
+)
diff --git a/fesvr/syscall.cc b/fesvr/syscall.cc
index fb2c3f8..8a9b29b 100644
--- a/fesvr/syscall.cc
+++ b/fesvr/syscall.cc
@@ -57,6 +57,84 @@ struct riscv_stat
__unused4(), __unused5() {}
};
+
+struct riscv_statx_timestamp {
+ target_endian<int64_t> tv_sec;
+ target_endian<uint32_t> tv_nsec;
+ target_endian<int32_t> __reserved;
+};
+
+struct riscv_statx
+{
+ target_endian<uint32_t> mask;
+ target_endian<uint32_t> blksize;
+ target_endian<uint64_t> attributes;
+ target_endian<uint32_t> nlink;
+ target_endian<uint32_t> uid;
+ target_endian<uint32_t> gid;
+ target_endian<uint16_t> mode;
+ target_endian<uint16_t> __spare0[1];
+ target_endian<uint64_t> ino;
+ target_endian<uint64_t> size;
+ target_endian<uint64_t> blocks;
+ target_endian<uint64_t> attributes_mask;
+ struct riscv_statx_timestamp atime;
+ struct riscv_statx_timestamp btime;
+ struct riscv_statx_timestamp ctime;
+ struct riscv_statx_timestamp mtime;
+ target_endian<uint32_t> rdev_major;
+ target_endian<uint32_t> rdev_minor;
+ target_endian<uint32_t> dev_major;
+ target_endian<uint32_t> dev_minor;
+#ifdef HAVE_STATX_MNT_ID
+ target_endian<uint64_t> mnt_id;
+ target_endian<uint64_t> __spare2;
+ target_endian<uint64_t> __spare3[12];
+#else
+ target_endian<uint64_t> __spare2[14];
+#endif
+
+ riscv_statx(const struct statx& s, htif_t* htif)
+ : mask(htif->to_target<uint32_t>(s.stx_mask)),
+ blksize(htif->to_target<uint32_t>(s.stx_blksize)),
+ attributes(htif->to_target<uint64_t>(s.stx_attributes)),
+ nlink(htif->to_target<uint32_t>(s.stx_nlink)),
+ uid(htif->to_target<uint32_t>(s.stx_uid)),
+ gid(htif->to_target<uint32_t>(s.stx_gid)),
+ mode(htif->to_target<uint16_t>(s.stx_mode)), __spare0(),
+ ino(htif->to_target<uint64_t>(s.stx_ino)),
+ size(htif->to_target<uint64_t>(s.stx_size)),
+ blocks(htif->to_target<uint64_t>(s.stx_blocks)),
+ attributes_mask(htif->to_target<uint64_t>(s.stx_attributes_mask)),
+ atime {
+ htif->to_target<int64_t>(s.stx_atime.tv_sec),
+ htif->to_target<uint32_t>(s.stx_atime.tv_nsec)
+ },
+ btime {
+ htif->to_target<int64_t>(s.stx_btime.tv_sec),
+ htif->to_target<uint32_t>(s.stx_btime.tv_nsec)
+ },
+ ctime {
+ htif->to_target<int64_t>(s.stx_ctime.tv_sec),
+ htif->to_target<uint32_t>(s.stx_ctime.tv_nsec)
+ },
+ mtime {
+ htif->to_target<int64_t>(s.stx_mtime.tv_sec),
+ htif->to_target<uint32_t>(s.stx_mtime.tv_nsec)
+ },
+ rdev_major(htif->to_target<uint32_t>(s.stx_rdev_major)),
+ rdev_minor(htif->to_target<uint32_t>(s.stx_rdev_minor)),
+ dev_major(htif->to_target<uint32_t>(s.stx_dev_major)),
+ dev_minor(htif->to_target<uint32_t>(s.stx_dev_minor)),
+#ifdef HAVE_STATX_MNT_ID
+ mnt_id(htif->to_target<uint64_t>(s.stx_mnt_id)),
+ __spare2(), __spare3()
+#else
+ __spare2()
+#endif
+ {}
+};
+
syscall_t::syscall_t(htif_t* htif)
: htif(htif), memif(&htif->memif()), table(2048)
{
@@ -79,6 +157,7 @@ syscall_t::syscall_t(htif_t* htif)
table[79] = &syscall_t::sys_fstatat;
table[80] = &syscall_t::sys_fstat;
table[93] = &syscall_t::sys_exit;
+ table[291] = &syscall_t::sys_statx;
table[1039] = &syscall_t::sys_lstat;
table[2011] = &syscall_t::sys_getmainvars;
@@ -222,6 +301,21 @@ reg_t syscall_t::sys_lstat(reg_t pname, reg_t len, reg_t pbuf, reg_t a3, reg_t a
return ret;
}
+reg_t syscall_t::sys_statx(reg_t fd, reg_t pname, reg_t len, reg_t flags, reg_t mask, reg_t pbuf, reg_t a6)
+{
+ std::vector<char> name(len);
+ memif->read(pname, len, &name[0]);
+
+ struct statx buf;
+ reg_t ret = sysret_errno(statx(fds.lookup(fd), do_chroot(&name[0]).c_str(), flags, mask, &buf));
+ if (ret != (reg_t)-1)
+ {
+ riscv_statx rbuf(buf, htif);
+ memif->write(pbuf, sizeof(rbuf), &rbuf);
+ }
+ return ret;
+}
+
#define AT_SYSCALL(syscall, fd, name, ...) \
(syscall(fds.lookup(fd), int(fd) == RISCV_AT_FDCWD ? do_chroot(name).c_str() : (name), __VA_ARGS__))
diff --git a/fesvr/syscall.h b/fesvr/syscall.h
index 8294696..4915efd 100644
--- a/fesvr/syscall.h
+++ b/fesvr/syscall.h
@@ -56,6 +56,7 @@ class syscall_t : public device_t
reg_t sys_lseek(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);
reg_t sys_fstat(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);
reg_t sys_lstat(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);
+ reg_t sys_statx(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);
reg_t sys_fstatat(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);
reg_t sys_faccessat(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);
reg_t sys_fcntl(reg_t, reg_t, reg_t, reg_t, reg_t, reg_t, reg_t);