qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 10/19] bsd-user: add support for file system rela


From: Stacey Son
Subject: [Qemu-devel] [PATCH v2 10/19] bsd-user: add support for file system related system calls
Date: Fri, 8 Nov 2013 10:33:28 -0600

This change adds support or stubs for file system (except stat) related system
calls including read(2), pread(2), readv(2), write(2), pwrite(2), writev(2),
pwritev(2),  open(2), openat(2), close(2), closefrom(2), revoke(2), access(2),
eaccess(2), faccessat(2), chdir(2), fchdir(2), rename(2), renameat(2), link(2),
linkat(2), unlink(2), unlinkat(2), mkdir(2), mkdirat(2), rmdir(2), __getcwd(),
dup(2), dup2(2), truncate(2), ftruncate(2), acct(2), sync(2), mount(2), 
nmount(2),
symlink(2), symlinkat(2), readlink(2), readlinkat(2), chmod(2), fchmod(2),
lchmod(2), fchmodat(2), mknod(2), mknodat(2), chown(2), fchown(2), lchown(2),
fchownat(2), chflags(2), lchflags(2), fchflags(2), chroot(2), flock(2), 
mkfifo(2),
mkfifoat(2), pathconf(2), lpathconf(2), fpathconf(2), undelete(2), poll(2),
lseek(2), pipe(2), swapon(2), swapoff(2), and the undocumented openbsd_poll()
and freebsd6_*() system calls.

Signed-off-by: Stacey Son <address@hidden>
---
 bsd-user/bsd-file.h | 1111 +++++++++++++++++++++++++++++++++++++++++++++++++++
 bsd-user/qemu.h     |   36 ++
 bsd-user/syscall.c  |  391 ++++++++++++++----
 3 files changed, 1454 insertions(+), 84 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..fc279a8
--- /dev/null
+++ b/bsd-user/bsd-file.h
@@ -0,0 +1,1111 @@
+/*
+ *  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(void *cpu_env, abi_long arg1,
+    abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    if (regpairs_aligned(cpu_env) != 0) {
+        arg4 = arg5;
+        arg5 = arg6;
+    }
+    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(void *cpu_env, abi_long arg1,
+    abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
+{
+    abi_long ret;
+    void *p;
+
+    p = lock_user(VERIFY_READ, arg2, arg3, 1);
+    if (p == NULL) {
+        return -TARGET_EFAULT;
+    }
+    if (regpairs_aligned(cpu_env) != 0) {
+        arg4 = arg5;
+        arg5 = arg6;
+    }
+    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(void *cpu_env, abi_long arg1,
+    abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
+{
+    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;
+    }
+    if (regpairs_aligned(cpu_env) != 0) {
+        arg4 = arg5;
+        arg5 = arg6;
+    }
+    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) != 0) {
+        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 arg5)
+{
+    abi_long ret;
+#if TARGET_ABI_BITS == 32
+    int64_t res;
+
+    /* 32-bit arch's use two 32 registers for 64 bit return value */
+    if (regpairs_aligned(cpu_env) != 0) {
+       res = lseek(arg1, target_offset64(arg3, arg4), arg5);
+    } else {
+        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/qemu.h b/bsd-user/qemu.h
index a9f5666..e668a67 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -446,6 +446,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/syscall.c b/bsd-user/syscall.c
index f8a40f0..15780af 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -41,6 +41,7 @@
 static int host_to_target_errno(int err);
 
 /* BSD independent syscall shims */
+#include "bsd-file.h"
 #include "bsd-proc.h"
 #include "bsd-signal.h"
 
@@ -176,7 +177,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);
@@ -433,38 +433,305 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, 
abi_long arg1,
         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);
+        /*
+         * File system calls.
+         */
+    case TARGET_FREEBSD_NR_read: /* read(2) */
+        ret = do_bsd_read(arg1, arg2, arg3);
         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);
+
+    case TARGET_FREEBSD_NR_pread: /* pread(2) */
+        ret = do_bsd_pread(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
         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);
-        }
+    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(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
+        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(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
+        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_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_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, arg5);
+        break;
+
+    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;
+
+
+
     case TARGET_FREEBSD_NR_mmap:
         ret = get_errno(target_mmap(arg1, arg2, arg3,
                                     target_to_host_bitmask(arg4, 
mmap_flags_tbl),
@@ -654,16 +921,12 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, 
abi_long arg1,
                     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,
@@ -671,7 +934,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);
@@ -681,34 +943,19 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, 
abi_long arg1,
 
     switch(num) {
     case TARGET_NETBSD_NR_exit:
-#ifdef TARGET_GPROF
-        _mcleanup();
-#endif
-        gdb_exit(cpu_env, arg1);
-        /* XXX: should free thread stack and CPU env */
-        _exit(arg1);
-        ret = 0; /* avoid warning */
+        ret = do_bsd_exit(cpu_env, arg1);
         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:
         ret = get_errno(target_mmap(arg1, arg2, arg3,
                                     target_to_host_bitmask(arg4, 
mmap_flags_tbl),
@@ -727,16 +974,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,
@@ -744,7 +987,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);
@@ -754,34 +996,19 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, 
abi_long arg1,
 
     switch(num) {
     case TARGET_OPENBSD_NR_exit:
-#ifdef TARGET_GPROF
-        _mcleanup();
-#endif
-        gdb_exit(cpu_env, arg1);
-        /* XXX: should free thread stack and CPU env */
-        _exit(arg1);
-        ret = 0; /* avoid warning */
+        ret = do_bsd_exit(cpu_env, arg1);
         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:
         ret = get_errno(target_mmap(arg1, arg2, arg3,
                                     target_to_host_bitmask(arg4, 
mmap_flags_tbl),
@@ -800,16 +1027,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)
-- 
1.7.8




reply via email to

[Prev in Thread] Current Thread [Next in Thread]