[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 11/23] bsd-user: add shims for file related system c
From: |
Stacey Son |
Subject: |
[Qemu-devel] [PATCH 11/23] bsd-user: add shims for file related system calls |
Date: |
Sun, 23 Jun 2013 21:03:43 -0500 |
This changes adds support for file and file system related system calls that
are largely BSD OS independent. Also includes some more clean up of syscall.c.
Signed-off-by: Stacey Son <address@hidden>
---
bsd-user/bsd-file.h | 1095 ++++++++++++++++++++++++++++++++
bsd-user/i386/target_arch_vmparam.h | 5 +
bsd-user/mips/target_arch_vmparam.h | 5 +
bsd-user/mips64/target_arch_vmparam.h | 5 +
bsd-user/qemu.h | 36 +
bsd-user/sparc/target_arch_vmparam.h | 5 +
bsd-user/sparc64/target_arch_vmparam.h | 5 +
bsd-user/syscall.c | 384 +++++++++---
bsd-user/x86_64/target_arch_vmparam.h | 5 +
9 files changed, 1467 insertions(+), 78 deletions(-)
create mode 100644 bsd-user/bsd-file.h
diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
new file mode 100644
index 0000000..f2c0fc7
--- /dev/null
+++ b/bsd-user/bsd-file.h
@@ -0,0 +1,1095 @@
+/*
+ * file related system call shims and definitions
+ *
+ * Copyright (c) 2013 Stacey D. Son
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BSD_FILE_H_
+#define __BSD_FILE_H_
+
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define target_to_host_bitmask(x, tbl) (x)
+
+#define LOCK_PATH(p, arg) do { \
+ (p) = lock_user_string(arg); \
+ if ((p) == NULL) { \
+ return -TARGET_EFAULT; \
+ } \
+} while (0)
+
+#define UNLOCK_PATH(p, arg) unlock_user((p), (arg), 0)
+
+struct target_pollfd {
+ int32_t fd; /* file descriptor */
+ int16_t events; /* requested events */
+ int16_t revents; /* returned events */
+};
+
+static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
+ int count, int copy);
+static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+ int count, int copy);
+extern int __getcwd(char *path, size_t len);
+
+/* read(2) */
+static inline abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(read(arg1, p, arg3));
+ unlock_user(p, arg2, ret);
+
+ return ret;
+}
+
+/* pread(2) */
+static inline abi_long do_bsd_pread(abi_long arg1, abi_long arg2, abi_long
arg3,
+ abi_long arg4, abi_long arg5)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5)));
+ unlock_user(p, arg2, ret);
+
+ return ret;
+}
+
+/* readv(2) */
+static inline abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long
arg3)
+{
+ abi_long ret;
+ int count = arg3;
+ struct iovec *vec;
+
+ vec = alloca(count * sizeof(struct iovec));
+ if (vec == NULL) {
+ return -TARGET_ENOMEM;
+ }
+ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(readv(arg1, vec, count));
+ unlock_iovec(vec, arg2, count, 1);
+
+ return ret;
+}
+
+/* write(2) */
+static inline abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long
arg3)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_READ, arg2, arg3, 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(write(arg1, p, arg3));
+ unlock_user(p, arg2, 0);
+
+ return ret;
+}
+
+/* pwrite(2) */
+static inline abi_long do_bsd_pwrite(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_READ, arg2, arg3, 1);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5)));
+ unlock_user(p, arg2, 0);
+
+ return ret;
+}
+
+/* writev(2) */
+static inline abi_long do_bsd_writev(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ int count = arg3;
+ struct iovec *vec;
+
+ vec = alloca(count * sizeof(struct iovec));
+ if (vec == NULL) {
+ return -TARGET_ENOMEM;
+ }
+ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(writev(arg1, vec, count));
+ unlock_iovec(vec, arg2, count, 0);
+
+ return ret;
+}
+
+/* pwritev(2) */
+static inline abi_long do_bsd_pwritev(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ abi_long ret;
+ int count = arg3;
+ struct iovec *vec;
+
+ vec = alloca(count * sizeof(struct iovec));
+ if (vec == NULL) {
+ return -TARGET_ENOMEM;
+ }
+ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(pwritev(arg1, vec, count, target_offset64(arg4, arg5)));
+ unlock_iovec(vec, arg2, count, 0);
+
+ return ret;
+}
+
+/* open(2) */
+static inline abi_long do_bsd_open(abi_long arg1, abi_long arg2, abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(open(path(p), target_to_host_bitmask(arg2,
fcntl_flags_tbl),
+ arg3));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* openat(2) */
+static inline abi_long do_bsd_openat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(openat(arg1, path(p),
+ target_to_host_bitmask(arg3, fcntl_flags_tbl), arg4));
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* close(2) */
+static inline abi_long do_bsd_close(abi_long arg1)
+{
+
+ return get_errno(close(arg1));
+}
+
+/* closefrom(2) */
+static inline abi_long do_bsd_closefrom(abi_long arg1)
+{
+
+ closefrom(arg1); /* returns void */
+ return get_errno(0);
+}
+
+/* revoke(2) */
+static inline abi_long do_bsd_revoke(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(revoke(p)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* creat(2) (obsolete) */
+static inline abi_long do_bsd_creat(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(open(path(p), O_CREAT | O_TRUNC | O_WRONLY, arg2));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+
+/* access(2) */
+static inline abi_long do_bsd_access(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(access(path(p), arg2));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* eaccess(2) */
+static inline abi_long do_bsd_eaccess(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(eaccess(path(p), arg2));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* faccessat(2) */
+static inline abi_long do_bsd_faccessat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(faccessat(arg1, p, arg3, arg4)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* chdir(2) */
+static inline abi_long do_bsd_chdir(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(chdir(p)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fchdir(2) */
+static inline abi_long do_bsd_fchdir(abi_long arg1)
+{
+
+ return get_errno(fchdir(arg1));
+}
+
+/* rename(2) */
+static inline abi_long do_bsd_rename(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ LOCK_PATH(p2, arg2);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(rename(p1, p2)); /* XXX path(p1), path(p2) */
+ }
+ UNLOCK_PATH(p2, arg2);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* renameat(2) */
+static inline abi_long do_bsd_renameat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ LOCK_PATH(p2, arg2);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(renameat(arg1, p1, arg3, p2));
+ }
+ UNLOCK_PATH(p2, arg2);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* link(2) */
+static inline abi_long do_bsd_link(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ LOCK_PATH(p2, arg2);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(link(p1, p2)); /* XXX path(p1), path(p2) */
+ }
+ UNLOCK_PATH(p2, arg2);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* linkat(2) */
+static inline abi_long do_bsd_linkat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg2);
+ LOCK_PATH(p2, arg4);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(linkat(arg1, p1, arg3, p2, arg5));
+ }
+ UNLOCK_PATH(p2, arg4);
+ UNLOCK_PATH(p1, arg2);
+
+ return ret;
+}
+
+/* unlink(2) */
+static inline abi_long do_bsd_unlink(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(unlink(p)); /* XXX path(p) */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* unlinkat(2) */
+static inline abi_long do_bsd_unlinkat(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(unlinkat(arg1, p, arg3)); /* XXX path(p) */
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* mkdir(2) */
+static inline abi_long do_bsd_mkdir(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(mkdir(p, arg2)); /* XXX path(p) */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+
+/* mkdirat(2) */
+static inline abi_long do_bsd_mkdirat(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(mkdirat(arg1, p, arg3));
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+
+/* rmdir(2) */
+static inline abi_long do_bsd_rmdir(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(rmdir(p)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* undocumented __getcwd(char *buf, size_t len) system call */
+static inline abi_long do_bsd___getcwd(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
+ if (p == NULL) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(__getcwd(p, arg2));
+ unlock_user(p, arg1, ret);
+
+ return ret;
+}
+
+/* dup(2) */
+static inline abi_long do_bsd_dup(abi_long arg1)
+{
+
+ return get_errno(dup(arg1));
+}
+
+/* dup2(2) */
+static inline abi_long do_bsd_dup2(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(dup2(arg1, arg2));
+}
+
+/* truncate(2) */
+static inline abi_long do_bsd_truncate(void *cpu_env, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ if (regpairs_aligned(cpu_env) != 0) {
+ arg2 = arg3;
+ arg3 = arg4;
+ }
+ ret = get_errno(truncate(p, target_offset64(arg2, arg3)));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* ftruncate(2) */
+static inline abi_long do_bsd_ftruncate(void *cpu_env, abi_long arg1,
+ abi_long arg2, abi_long arg3, abi_long arg4)
+{
+
+ if (regpairs_aligned(cpu_env)) {
+ arg2 = arg3;
+ arg3 = arg4;
+ }
+ return get_errno(ftruncate(arg1, target_offset64(arg2, arg3)));
+}
+
+/* acct(2) */
+static inline abi_long do_bsd_acct(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ if (arg1 == 0) {
+ ret = get_errno(acct(NULL));
+ } else {
+ LOCK_PATH(p, arg1);
+ ret = get_errno(acct(path(p)));
+ UNLOCK_PATH(p, arg1);
+ }
+ return ret;
+}
+
+/* sync(2) */
+static inline abi_long do_bsd_sync(void)
+{
+
+ sync();
+ return 0;
+}
+
+/* mount(2) */
+static inline abi_long do_bsd_mount(abi_long arg1, abi_long arg2, abi_long
arg3,
+ abi_long arg4)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ LOCK_PATH(p2, arg2);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ /*
+ * XXX arg4 should be locked, but it isn't clear how to do that
+ * since it's it may be not be a NULL-terminated string.
+ */
+ if (arg4 == 0) {
+ ret = get_errno(mount(p1, p2, arg3, NULL)); /* XXX path(p2)? */
+ } else {
+ ret = get_errno(mount(p1, p2, arg3, g2h(arg4))); /* XXX path(p2)?
*/
+ }
+ }
+ UNLOCK_PATH(p2, arg2);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* unmount(2) */
+static inline abi_long do_bsd_unmount(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(unmount(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* nmount(2) */
+static inline abi_long do_bsd_nmount(abi_long arg1, abi_long count,
+ abi_long flags)
+{
+ abi_long ret;
+ struct iovec *vec;
+
+ vec = alloca(count * sizeof(struct iovec));
+ if (lock_iovec(VERIFY_READ, vec, arg1, count, 1) < 0) {
+ return -TARGET_EFAULT;
+ }
+ ret = get_errno(nmount(vec, count, flags));
+ unlock_iovec(vec, arg1, count, 0);
+
+ return ret;
+}
+
+/* symlink(2) */
+static inline abi_long do_bsd_symlink(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ LOCK_PATH(p2, arg2);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(symlink(p1, p2)); /* XXX path(p1), path(p2) */
+ }
+ UNLOCK_PATH(p2, arg2);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* symlinkat(2) */
+static inline abi_long do_bsd_symlinkat(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ LOCK_PATH(p2, arg3);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(symlinkat(p1, arg2, p2)); /* XXX path(p1), path(p2) */
+ }
+ UNLOCK_PATH(p2, arg3);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* readlink(2) */
+static inline abi_long do_bsd_readlink(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg1);
+ p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(readlink(path(p1), p2, arg3));
+ }
+ unlock_user(p2, arg2, ret);
+ UNLOCK_PATH(p1, arg1);
+
+ return ret;
+}
+
+/* readlinkat(2) */
+static inline abi_long do_bsd_readlinkat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p1, *p2;
+
+ LOCK_PATH(p1, arg2);
+ p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
+ if (!p1 || !p2) {
+ ret = -TARGET_EFAULT;
+ } else {
+ ret = get_errno(readlinkat(arg1, p1, p2, arg4));
+ }
+ unlock_user(p2, arg3, ret);
+ UNLOCK_PATH(p1, arg2);
+
+ return ret;
+}
+
+/* chmod(2) */
+static inline abi_long do_bsd_chmod(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(chmod(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fchmod(2) */
+static inline abi_long do_bsd_fchmod(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(fchmod(arg1, arg2));
+}
+
+/* lchmod(2) */
+static inline abi_long do_bsd_lchmod(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(lchmod(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fchmodat(2) */
+static inline abi_long do_bsd_fchmodat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(fchmodat(arg1, p, arg3, arg4));
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* mknod(2) */
+static inline abi_long do_bsd_mknod(abi_long arg1, abi_long arg2, abi_long
arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(mknod(p, arg2, arg3)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* mknodat(2) */
+static inline abi_long do_bsd_mknodat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(mknodat(arg1, p, arg3, arg4));
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* chown(2) */
+static inline abi_long do_bsd_chown(abi_long arg1, abi_long arg2, abi_long
arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(chown(p, arg2, arg3)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fchown(2) */
+static inline abi_long do_bsd_fchown(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+
+ return get_errno(fchown(arg1, arg2, arg3));
+}
+
+/* lchown(2) */
+static inline abi_long do_bsd_lchown(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(lchown(p, arg2, arg3)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fchownat(2) */
+static inline abi_long do_bsd_fchownat(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(fchownat(arg1, p, arg3, arg4, arg5)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* chflags(2) */
+static inline abi_long do_bsd_chflags(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(chflags(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* lchflags(2) */
+static inline abi_long do_bsd_lchflags(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(lchflags(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fchflags(2) */
+static inline abi_long do_bsd_fchflags(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(fchflags(arg1, arg2));
+}
+
+/* chroot(2) */
+static inline abi_long do_bsd_chroot(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(chroot(p)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* flock(2) */
+static abi_long do_bsd_flock(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(flock(arg1, arg2));
+}
+
+/* mkfifo(2) */
+static inline abi_long do_bsd_mkfifo(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(mkfifo(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* mkfifoat(2) */
+static inline abi_long do_bsd_mkfifoat(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg2);
+ ret = get_errno(mkfifoat(arg1, p, arg3));
+ UNLOCK_PATH(p, arg2);
+
+ return ret;
+}
+
+/* pathconf(2) */
+static inline abi_long do_bsd_pathconf(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(pathconf(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* lpathconf(2) */
+static inline abi_long do_bsd_lpathconf(abi_long arg1, abi_long arg2)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(lpathconf(p, arg2)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* fpathconf(2) */
+static inline abi_long do_bsd_fpathconf(abi_long arg1, abi_long arg2)
+{
+
+ return get_errno(fpathconf(arg1, arg2));
+}
+
+/* undelete(2) */
+static inline abi_long do_bsd_undelete(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(undelete(p)); /* XXX path(p)? */
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* poll(2) */
+static abi_long do_bsd_poll(abi_long arg1, abi_long arg2, abi_long arg3)
+{
+ abi_long ret;
+ nfds_t i, nfds = arg2;
+ int timeout = arg3;
+ struct pollfd *pfd;
+ struct target_pollfd *target_pfd;
+
+ target_pfd = lock_user(VERIFY_WRITE, arg1,
+ sizeof(struct target_pollfd) * nfds, 1);
+ if (!target_pfd) {
+ return -TARGET_EFAULT;
+ }
+ pfd = alloca(sizeof(struct pollfd) * nfds);
+ for (i = 0; i < nfds; i++) {
+ pfd[i].fd = tswap32(target_pfd[i].fd);
+ pfd[i].events = tswap16(target_pfd[i].events);
+ } ret = get_errno(poll(pfd, nfds, timeout));
+ if (!is_error(ret)) {
+ for (i = 0; i < nfds; i++) {
+ target_pfd[i].revents = tswap16(pfd[i].revents);
+ }
+ }
+ unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
+
+ return ret;
+}
+
+/*
+ * undocumented openbsd_poll(struct pollfd *fds, u_int nfds, int
+ * timeout) system call.
+ */
+static abi_long do_bsd_openbsd_poll(abi_long arg1, abi_long arg2, abi_long
arg3)
+{
+
+ qemu_log("qemu: Unsupported syscall openbsd_poll()\n");
+ return -TARGET_ENOSYS;
+}
+
+/* lseek(2) */
+static abi_long do_bsd_lseek(void *cpu_env, abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+ abi_long ret;
+
+#if TARGET_ABI_BITS == 32
+ /* 32-bit arch's use two 32 registers for 64 bit return value */
+ int64_t res = lseek(arg1, target_offset64(arg2, arg3), arg4);
+
+ if (res == -1) {
+ ret = get_errno(res);
+ } else {
+ ret = res & 0xFFFFFFFF;
+ set_second_rval(cpu_env, (res >> 32) & 0xFFFFFFFF);
+ }
+#else
+ ret = get_errno(lseek(arg1, arg2, arg3));
+#endif
+ return ret;
+}
+
+/* pipe(2) */
+static abi_long do_bsd_pipe(void *cpu_env, abi_long arg1)
+{
+ abi_long ret;
+ int host_pipe[2];
+ int host_ret = pipe(host_pipe);
+
+ if (host_ret != -1) {
+ set_second_rval(cpu_env, host_pipe[1]);
+ ret = host_pipe[0];
+ } else {
+ ret = get_errno(host_ret);
+ }
+ return ret;
+}
+
+/* swapon(2) */
+static abi_long do_bsd_swapon(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(swapon(path(p)));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/* swapoff(2) */
+static abi_long do_bsd_swapoff(abi_long arg1)
+{
+ abi_long ret;
+ void *p;
+
+ LOCK_PATH(p, arg1);
+ ret = get_errno(swapoff(path(p)));
+ UNLOCK_PATH(p, arg1);
+
+ return ret;
+}
+
+/*
+ * undocumented freebsd6_pread(int fd, void *buf, size_t nbyte, int pad,
+ * off_t offset) system call.
+ */
+static abi_long do_bsd_freebsd6_pread(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+
+ qemu_log("qemu: Unsupported syscall freebsd6_pread()\n");
+ return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented freebsd6_pwrite(int fd, void *buf, size_t nbyte, int pad,
+ * off_t offset) system call.
+ */
+static abi_long do_bsd_freebsd6_pwrite(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4, abi_long arg5)
+{
+
+ qemu_log("qemu: Unsupported syscall freebsd6_pwrite()\n");
+ return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented freebsd6_lseek(int fd, int pad, off_t offset, int whence)
+ * system call.
+ */
+static abi_long do_bsd_freebsd6_lseek(abi_long arg1, abi_long arg2,
+ abi_long arg3, abi_long arg4)
+{
+
+ qemu_log("qemu: Unsupported syscall freebsd6_lseek()\n");
+ return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented freebsd6_truncate(char *path, int pad, off_t offset) system
+ * call.
+ */
+static abi_long do_bsd_freebsd6_truncate(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+
+ qemu_log("qemu: Unsupported syscall freebsd6_truncate()\n");
+ return -TARGET_ENOSYS;
+}
+
+/*
+ * undocumented freebsd6_ftruncate(int fd, int pad, off_t offset) system
+ * call.
+ */
+static abi_long do_bsd_freebsd6_ftruncate(abi_long arg1, abi_long arg2,
+ abi_long arg3)
+{
+
+ qemu_log("qemu: Unsupported syscall freebsd6_ftruncate()\n");
+ return -TARGET_ENOSYS;
+}
+
+#endif /* !__BSD_FILE_H_ */
diff --git a/bsd-user/i386/target_arch_vmparam.h
b/bsd-user/i386/target_arch_vmparam.h
index 6d3cf4f..654400a 100644
--- a/bsd-user/i386/target_arch_vmparam.h
+++ b/bsd-user/i386/target_arch_vmparam.h
@@ -18,4 +18,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State
*state)
return state->regs[R_ESP];
}
+static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
+{
+ state->regs[R_EDX] = retval2;
+}
+
#endif /* !_TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/mips/target_arch_vmparam.h
b/bsd-user/mips/target_arch_vmparam.h
index 8f8bc9e..f9e54ce 100644
--- a/bsd-user/mips/target_arch_vmparam.h
+++ b/bsd-user/mips/target_arch_vmparam.h
@@ -39,4 +39,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUMIPSState
*state)
return state->active_tc.gpr[29];
}
+static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2)
+{
+ state->active_tc.gpr[3] = retval2;
+}
+
#endif /* ! _TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/mips64/target_arch_vmparam.h
b/bsd-user/mips64/target_arch_vmparam.h
index 0480035..1ba09e0 100644
--- a/bsd-user/mips64/target_arch_vmparam.h
+++ b/bsd-user/mips64/target_arch_vmparam.h
@@ -39,4 +39,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUMIPSState
*state)
return state->active_tc.gpr[29];
}
+static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2)
+{
+ state->active_tc.gpr[3] = retval2;
+}
+
#endif /* ! _TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index 02a05bb..da69073 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -422,6 +422,42 @@ static inline void *lock_user_string(abi_ulong guest_addr)
#define unlock_user_struct(host_ptr, guest_addr, copy) \
unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
+#if TARGET_ABI_BITS == 32
+static inline uint64_t
+target_offset64(uint32_t word0, uint32_t word1)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ return ((uint64_t)word0 << 32) | word1;
+#else
+ return ((uint64_t)word1 << 32) | word0;
+#endif
+}
+#else /* TARGET_ABI_BITS != 32 */
+static inline uint64_t
+target_offset64(uint64_t word0, uint64_t word1)
+{
+ return word0;
+}
+#endif /* TARGET_ABI_BITS != 32 */
+
+/* ARM EABI and MIPS expect 64bit types aligned even on pairs of registers */
+#ifdef TARGET_ARM
+static inline int
+regpairs_aligned(void *cpu_env) {
+ return ((((CPUARMState *)cpu_env)->eabi) == 1);
+}
+#elif defined(TARGET_MIPS) && TARGET_ABI_BITS == 32
+static inline int regpairs_aligned(void *cpu_env)
+{
+ return 1;
+}
+#else
+static inline int regpairs_aligned(void *cpu_env)
+{
+ return 0;
+}
+#endif
+
#if defined(CONFIG_USE_NPTL)
#include <pthread.h>
#endif
diff --git a/bsd-user/sparc/target_arch_vmparam.h
b/bsd-user/sparc/target_arch_vmparam.h
index 4bda417..75bbeeb 100644
--- a/bsd-user/sparc/target_arch_vmparam.h
+++ b/bsd-user/sparc/target_arch_vmparam.h
@@ -26,5 +26,10 @@ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState
*state)
return state->regwptr[UREG_FP];
}
+static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2)
+{
+ state->regwptr[1] = retval2;
+}
+
#endif /* !_TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/sparc64/target_arch_vmparam.h
b/bsd-user/sparc64/target_arch_vmparam.h
index 87548da..2c2323b 100644
--- a/bsd-user/sparc64/target_arch_vmparam.h
+++ b/bsd-user/sparc64/target_arch_vmparam.h
@@ -28,5 +28,10 @@ static inline abi_ulong get_sp_from_cpustate(CPUSPARCState
*state)
return state->regwptr[UREG_FP];
}
+static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2)
+{
+ state->regwptr[1] = retval2;
+}
+
#endif /* !_TARGET_ARCH_VMPARAM_H_ */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index b64c0b0..2efa772 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -16,21 +16,16 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <time.h>
-#include <limits.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/param.h>
#include <sys/sysctl.h>
-#include <utime.h>
#include "qemu.h"
#include "qemu-common.h"
@@ -38,6 +33,7 @@
#define target_to_host_bitmask(x, tbl) (x)
#include "bsd-errno.h"
+#include "bsd-file.h"
#include "bsd-mem.h"
/* #define DEBUG */
@@ -282,7 +278,6 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
abi_long arg8)
{
abi_long ret;
- void *p;
#ifdef DEBUG
gemu_log("freebsd syscall %d\n", num);
@@ -300,39 +295,305 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
_exit(arg1);
ret = 0; /* avoid warning */
break;
- case TARGET_FREEBSD_NR_read:
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(read(arg1, p, arg3));
- unlock_user(p, arg2, ret);
- break;
- case TARGET_FREEBSD_NR_write:
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(write(arg1, p, arg3));
- unlock_user(p, arg2, 0);
- break;
- case TARGET_FREEBSD_NR_writev:
- {
- int count = arg3;
- struct iovec *vec;
-
- vec = alloca(count * sizeof(struct iovec));
- if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
- goto efault;
- ret = get_errno(writev(arg1, vec, count));
- unlock_iovec(vec, arg2, count, 0);
- }
+
+ /*
+ * File system calls.
+ */
+ case TARGET_FREEBSD_NR_read: /* read(2) */
+ ret = do_bsd_read(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_pread: /* pread(2) */
+ ret = do_bsd_pread(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_readv: /* readv(2) */
+ ret = do_bsd_read(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_write: /* write(2) */
+ ret = do_bsd_write(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_pwrite: /* pwrite(2) */
+ ret = do_bsd_pwrite(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_writev: /* writev(2) */
+ ret = do_bsd_writev(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_pwritev: /* pwritev(2) */
+ ret = do_bsd_pwritev(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_open: /* open(2) */
+ ret = do_bsd_open(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_openat: /* openat(2) */
+ ret = do_bsd_openat(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_close: /* close(2) */
+ ret = do_bsd_close(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_closefrom: /* closefrom(2) */
+ ret = do_bsd_closefrom(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_revoke: /* revoke(2) */
+ ret = do_bsd_revoke(arg1);
+ break;
+
+#ifdef TARGET_FREEBSD_NR_creat
+ case TARGET_FREEBSD_NR_creat: /* creat(2) (obsolete) */
+ ret = do_bsd_creat(arg1);
+ break;
+#endif
+
+ case TARGET_FREEBSD_NR_access: /* access(2) */
+ ret = do_bsd_access(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_eaccess: /* eaccess(2) */
+ ret = do_bsd_eaccess(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_faccessat: /* faccessat(2) */
+ ret = do_bsd_faccessat(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_chdir: /* chdir(2) */
+ ret = do_bsd_chdir(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_fchdir: /* fchdir(2) */
+ ret = do_bsd_fchdir(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_rename: /* rename(2) */
+ ret = do_bsd_rename(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_renameat: /* renameat(2) */
+ ret = do_bsd_renameat(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_link: /* link(2) */
+ ret = do_bsd_link(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_linkat: /* linkat(2) */
+ ret = do_bsd_linkat(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_unlink: /* unlink(2) */
+ ret = do_bsd_unlink(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_unlinkat: /* unlinkat(2) */
+ ret = do_bsd_unlinkat(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_mkdir: /* mkdir(2) */
+ ret = do_bsd_mkdir(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_mkdirat: /* mkdirat(2) */
+ ret = do_bsd_mkdirat(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_rmdir: /* rmdir(2) (XXX no rmdirat()?) */
+ ret = do_bsd_rmdir(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR___getcwd: /* undocumented __getcwd() */
+ ret = do_bsd___getcwd(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_dup: /* dup(2) */
+ ret = do_bsd_dup(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_dup2: /* dup2(2) */
+ ret = do_bsd_dup2(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_truncate: /* truncate(2) */
+ ret = do_bsd_truncate(cpu_env, arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_ftruncate: /* ftruncate(2) */
+ ret = do_bsd_ftruncate(cpu_env, arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_acct: /* acct(2) */
+ ret = do_bsd_acct(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_sync: /* sync(2) */
+ ret = do_bsd_sync();
+ break;
+
+ case TARGET_FREEBSD_NR_mount: /* mount(2) */
+ ret = do_bsd_mount(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_unmount: /* unmount(2) */
+ ret = do_bsd_unmount(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_nmount: /* nmount(2) */
+ ret = do_bsd_nmount(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_symlink: /* symlink(2) */
+ ret = do_bsd_symlink(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_symlinkat: /* symlinkat(2) */
+ ret = do_bsd_symlinkat(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_readlink: /* readlink(2) */
+ ret = do_bsd_readlink(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_readlinkat: /* readlinkat(2) */
+ ret = do_bsd_readlinkat(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_chmod: /* chmod(2) */
+ ret = do_bsd_chmod(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_fchmod: /* fchmod(2) */
+ ret = do_bsd_fchmod(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_lchmod: /* lchmod(2) */
+ ret = do_bsd_lchmod(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_fchmodat: /* fchmodat(2) */
+ ret = do_bsd_fchmodat(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_mknod: /* mknod(2) */
+ ret = do_bsd_mknod(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_mknodat: /* mknodat(2) */
+ ret = do_bsd_mknodat(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_chown: /* chown(2) */
+ ret = do_bsd_chown(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_fchown: /* fchown(2) */
+ ret = do_bsd_fchown(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_lchown: /* lchown(2) */
+ ret = do_bsd_lchown(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_fchownat: /* fchownat(2) */
+ ret = do_bsd_fchownat(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_chflags: /* chflags(2) */
+ ret = do_bsd_chflags(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_lchflags: /* lchflags(2) */
+ ret = do_bsd_lchflags(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_fchflags: /* fchflags(2) */
+ ret = do_bsd_fchflags(arg2, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_chroot: /* chroot(2) */
+ ret = do_bsd_chroot(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_flock: /* flock(2) */
+ ret = do_bsd_flock(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_mkfifo: /* mkfifo(2) */
+ ret = do_bsd_mkfifo(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_mkfifoat: /* mkfifoat(2) */
+ ret = do_bsd_mkfifoat(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_pathconf: /* pathconf(2) */
+ ret = do_bsd_pathconf(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_lpathconf: /* lpathconf(2) */
+ ret = do_bsd_lpathconf(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_fpathconf: /* fpathconf(2) */
+ ret = do_bsd_fpathconf(arg1, arg2);
+ break;
+
+ case TARGET_FREEBSD_NR_undelete: /* undelete(2) */
+ ret = do_bsd_undelete(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_poll: /* poll(2) */
+ ret = do_bsd_poll(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_openbsd_poll: /* undocumented openbsd_poll() */
+ ret = do_bsd_openbsd_poll(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_lseek: /* lseek(2) */
+ ret = do_bsd_lseek(cpu_env, arg1, arg2, arg3, arg4);
break;
- case TARGET_FREEBSD_NR_open:
- if (!(p = lock_user_string(arg1)))
- goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
- unlock_user(p, arg1, 0);
+
+ case TARGET_FREEBSD_NR_pipe: /* pipe(2) */
+ ret = do_bsd_pipe(cpu_env, arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_swapon: /* swapon(2) */
+ ret = do_bsd_swapon(arg1);
+ break;
+
+ case TARGET_FREEBSD_NR_swapoff: /* swapoff(2) */
+ ret = do_bsd_swapoff(arg1);
break;
+ case TARGET_FREEBSD_NR_freebsd6_pread: /* undocumented freebsd6_pread() */
+ ret = do_bsd_freebsd6_pread(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_freebsd6_pwrite: /* undocumented freebsd6_pwrite()
*/
+ ret = do_bsd_freebsd6_pwrite(arg1, arg2, arg3, arg4, arg5);
+ break;
+
+ case TARGET_FREEBSD_NR_freebsd6_lseek: /* undocumented freebsd6_lseek() */
+ ret = do_bsd_freebsd6_lseek(arg1, arg2, arg3, arg4);
+ break;
+
+ case TARGET_FREEBSD_NR_freebsd6_truncate: /* undocumented */
+ ret = do_bsd_freebsd6_truncate(arg1, arg2, arg3);
+ break;
+
+ case TARGET_FREEBSD_NR_freebsd6_ftruncate: /* undocumented */
+ ret = do_bsd_freebsd6_ftruncate(arg1, arg2, arg3);
+ break;
+
+
/*
* Memory management system calls.
*/
@@ -440,16 +701,13 @@ abi_long do_freebsd_syscall(void *cpu_env, int num,
abi_long arg1,
ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
arg8));
break;
}
- fail:
+
#ifdef DEBUG
gemu_log(" = %ld\n", ret);
#endif
if (do_strace)
print_freebsd_syscall_ret(num, ret);
return ret;
- efault:
- ret = -TARGET_EFAULT;
- goto fail;
}
abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
@@ -457,7 +715,6 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long
arg1,
abi_long arg5, abi_long arg6)
{
abi_long ret;
- void *p;
#ifdef DEBUG
gemu_log("netbsd syscall %d\n", num);
@@ -475,25 +732,15 @@ abi_long do_netbsd_syscall(void *cpu_env, int num,
abi_long arg1,
_exit(arg1);
ret = 0; /* avoid warning */
break;
+
case TARGET_NETBSD_NR_read:
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(read(arg1, p, arg3));
- unlock_user(p, arg2, ret);
+ ret = do_bsd_read(arg1, arg2, arg3);
break;
case TARGET_NETBSD_NR_write:
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(write(arg1, p, arg3));
- unlock_user(p, arg2, 0);
+ ret = do_bsd_write(arg1, arg2, arg3);
break;
case TARGET_NETBSD_NR_open:
- if (!(p = lock_user_string(arg1)))
- goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
- unlock_user(p, arg1, 0);
+ ret = do_bsd_open(arg1, arg2, arg3);
break;
case TARGET_NETBSD_NR_mmap:
@@ -511,16 +758,12 @@ abi_long do_netbsd_syscall(void *cpu_env, int num,
abi_long arg1,
ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
break;
}
- fail:
#ifdef DEBUG
gemu_log(" = %ld\n", ret);
#endif
if (do_strace)
print_netbsd_syscall_ret(num, ret);
return ret;
- efault:
- ret = -TARGET_EFAULT;
- goto fail;
}
abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
@@ -528,7 +771,6 @@ abi_long do_openbsd_syscall(void *cpu_env, int num,
abi_long arg1,
abi_long arg5, abi_long arg6)
{
abi_long ret;
- void *p;
#ifdef DEBUG
gemu_log("openbsd syscall %d\n", num);
@@ -546,25 +788,15 @@ abi_long do_openbsd_syscall(void *cpu_env, int num,
abi_long arg1,
_exit(arg1);
ret = 0; /* avoid warning */
break;
+
case TARGET_OPENBSD_NR_read:
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(read(arg1, p, arg3));
- unlock_user(p, arg2, ret);
+ ret = do_bsd_read(arg1, arg2, arg3);
break;
case TARGET_OPENBSD_NR_write:
- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
- goto efault;
- ret = get_errno(write(arg1, p, arg3));
- unlock_user(p, arg2, 0);
+ ret = do_bsd_write(arg1, arg2, arg3);
break;
case TARGET_OPENBSD_NR_open:
- if (!(p = lock_user_string(arg1)))
- goto efault;
- ret = get_errno(open(path(p),
- target_to_host_bitmask(arg2, fcntl_flags_tbl),
- arg3));
- unlock_user(p, arg1, 0);
+ ret = do_bsd_open(arg1, arg2, arg3);
break;
case TARGET_OPENBSD_NR_mmap:
@@ -582,16 +814,12 @@ abi_long do_openbsd_syscall(void *cpu_env, int num,
abi_long arg1,
ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
break;
}
- fail:
#ifdef DEBUG
gemu_log(" = %ld\n", ret);
#endif
if (do_strace)
print_openbsd_syscall_ret(num, ret);
return ret;
- efault:
- ret = -TARGET_EFAULT;
- goto fail;
}
void syscall_init(void)
diff --git a/bsd-user/x86_64/target_arch_vmparam.h
b/bsd-user/x86_64/target_arch_vmparam.h
index 8acf7a5..5e13076 100644
--- a/bsd-user/x86_64/target_arch_vmparam.h
+++ b/bsd-user/x86_64/target_arch_vmparam.h
@@ -20,4 +20,9 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State
*state)
return state->regs[R_ESP];
}
+static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
+{
+ state->regs[R_EDX] = retval2;
+}
+
#endif /* !_TARGET_ARCH_VMPARAM_H_ */
--
1.7.8
- [Qemu-devel] [PATCH 00/23] bsd-user: FreeBSD support for mips/mips64 and arm, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 07/23] bsd-user: find target executable in path when absolute path not given, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 05/23] bsd-user: add bsd_binprm to TaskState for core dumping emulation, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 06/23] bsd-user: fix thread initialization and ELF addresses for mips/mips64, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 13/23] bsd-user: add shims for signal related system calls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 08/23] bsd-user: initialize stack with signal trampolin code and canary, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 02/23] bsd-user: add initial support for mips/mips64, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 01/23] bsd-user: initial code clean up, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 11/23] bsd-user: add shims for file related system calls,
Stacey Son <=
- [Qemu-devel] [PATCH 10/23] bsd-user: add shims for memory management related syscalls, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 09/23] bsd-user: refresh FreeBSD's system call numbers, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 12/23] bsd-user: add shims for time related system calls., Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 03/23] bsd-user: additional seperation of OS and architecture dependent code, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 04/23] bsd-user: add bsd signal emulation, Stacey Son, 2013/06/24
- [Qemu-devel] [PATCH 22/23] bsd-user: add more strace formating, Stacey Son, 2013/06/24