distribution patches
[qemu] / linux-user / syscall.c
index dbe3de3..5f02fb7 100644 (file)
@@ -38,6 +38,7 @@
 #include <sched.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
+#include <sys/poll.h>
 //#include <sys/user.h>
 
 #define termios host_termios
@@ -55,7 +56,7 @@
 #include <linux/soundcard.h>
 #include <linux/dirent.h>
 
-#include "gemu.h"
+#include "qemu.h"
 
 //#define DEBUG
 
 #define        VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])
 #define        VFAT_IOCTL_READDIR_SHORT        _IOR('r', 2, struct dirent [2])
 
-#include "syscall_defs.h"
-
-#ifdef TARGET_I386
-#include "cpu-i386.h"
-#include "syscall-i386.h"
-#endif
-
-void host_to_target_siginfo(target_siginfo_t *tinfo, siginfo_t *info);
-void target_to_host_siginfo(siginfo_t *info, target_siginfo_t *tinfo);
+void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
+void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
 long do_sigreturn(CPUX86State *env);
 long do_rt_sigreturn(CPUX86State *env);
 
@@ -106,6 +100,13 @@ _syscall2(int,sys_fstatfs,int,fd,struct kernel_statfs *,buf)
 _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
 
 extern int personality(int);
+extern int flock(int, int);
+extern int setfsuid(int);
+extern int setfsgid(int);
+extern int setresuid(int,int,int);
+extern int getresuid(int *,int *,int *);
+extern int setresgid(int,int,int);
+extern int getresgid(int *,int *,int *);
 
 static inline long get_errno(long ret)
 {
@@ -437,7 +438,7 @@ static long do_ioctl(long fd, long cmd, long arg)
         ie++;
     }
     arg_type = ie->arg_type;
-#ifdef DEBUG
+#if defined(DEBUG)
     gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
 #endif
     switch(arg_type[0]) {
@@ -812,6 +813,10 @@ int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp)
 
 #endif
 
+#define high2lowuid(x) (x)
+#define high2lowgid(x) (x)
+#define low2highuid(x) (x)
+#define low2highgid(x) (x)
 
 void syscall_init(void)
 {
@@ -916,7 +921,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         ret = get_errno(umount((const char *)arg1));
         break;
     case TARGET_NR_setuid:
-        ret = get_errno(setuid(arg1));
+        ret = get_errno(setuid(low2highuid(arg1)));
         break;
     case TARGET_NR_getuid:
         ret = get_errno(getuid());
@@ -987,7 +992,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_prof:
         goto unimplemented;
     case TARGET_NR_setgid:
-        ret = get_errno(setgid(arg1));
+        ret = get_errno(setgid(low2highgid(arg1)));
         break;
     case TARGET_NR_getgid:
         ret = get_errno(getgid());
@@ -1244,9 +1249,30 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         ret = get_errno(sethostname((const char *)arg1, arg2));
         break;
     case TARGET_NR_setrlimit:
-        goto unimplemented;
+        {
+            /* XXX: convert resource ? */
+            int resource = arg1;
+            struct target_rlimit *target_rlim = (void *)arg2;
+            struct rlimit rlim;
+            rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
+            rlim.rlim_max = tswapl(target_rlim->rlim_max);
+            ret = get_errno(setrlimit(resource, &rlim));
+        }
+        break;
     case TARGET_NR_getrlimit:
-        goto unimplemented;
+        {
+            /* XXX: convert resource ? */
+            int resource = arg1;
+            struct target_rlimit *target_rlim = (void *)arg2;
+            struct rlimit rlim;
+            
+            ret = get_errno(getrlimit(resource, &rlim));
+            if (!is_error(ret)) {
+                target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
+                target_rlim->rlim_max = tswapl(rlim.rlim_max);
+            }
+        }
+        break;
     case TARGET_NR_getrusage:
         goto unimplemented;
     case TARGET_NR_gettimeofday:
@@ -1317,6 +1343,27 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_munmap:
         ret = get_errno(munmap((void *)arg1, arg2));
         break;
+    case TARGET_NR_mprotect:
+        ret = get_errno(mprotect((void *)arg1, arg2, arg3));
+        break;
+    case TARGET_NR_mremap:
+        ret = get_errno((long)mremap((void *)arg1, arg2, arg3, arg4));
+        break;
+    case TARGET_NR_msync:
+        ret = get_errno(msync((void *)arg1, arg2, arg3));
+        break;
+    case TARGET_NR_mlock:
+        ret = get_errno(mlock((void *)arg1, arg2));
+        break;
+    case TARGET_NR_munlock:
+        ret = get_errno(munlock((void *)arg1, arg2));
+        break;
+    case TARGET_NR_mlockall:
+        ret = get_errno(mlockall(arg1));
+        break;
+    case TARGET_NR_munlockall:
+        ret = get_errno(munlockall());
+        break;
     case TARGET_NR_truncate:
         ret = get_errno(truncate((const char *)arg1, arg2));
         break;
@@ -1506,9 +1553,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
 #endif
     case TARGET_NR_adjtimex:
         goto unimplemented;
-    case TARGET_NR_mprotect:
-        ret = get_errno(mprotect((void *)arg1, arg2, arg3));
-        break;
     case TARGET_NR_create_module:
     case TARGET_NR_init_module:
     case TARGET_NR_delete_module:
@@ -1532,9 +1576,11 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
     case TARGET_NR_afs_syscall:
         goto unimplemented;
     case TARGET_NR_setfsuid:
-        goto unimplemented;
+        ret = get_errno(setfsuid(arg1));
+        break;
     case TARGET_NR_setfsgid:
-        goto unimplemented;
+        ret = get_errno(setfsgid(arg1));
+        break;
     case TARGET_NR__llseek:
         {
             int64_t res;
@@ -1596,10 +1642,31 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, 
                         (void *)arg5);
         break;
+    case TARGET_NR_poll:
+        {
+            struct target_pollfd *target_pfd = (void *)arg1;
+            unsigned int nfds = arg2;
+            int timeout = arg3;
+            struct pollfd *pfd;
+            int i;
+
+            pfd = alloca(sizeof(struct pollfd) * nfds);
+            for(i = 0; i < nfds; i++) {
+                pfd->fd = tswap32(target_pfd->fd);
+                pfd->events = tswap16(target_pfd->events);
+            }
+            ret = get_errno(poll(pfd, nfds, timeout));
+            if (!is_error(ret)) {
+                for(i = 0; i < nfds; i++) {
+                    target_pfd->revents = tswap16(pfd->revents);
+                }
+            }
+        }
+        break;
     case TARGET_NR_flock:
-        goto unimplemented;
-    case TARGET_NR_msync:
-        ret = get_errno(msync((void *)arg1, arg2, arg3));
+        /* NOTE: the flock constant seems to be the same for every
+           Linux platform */
+        ret = get_errno(flock(arg1, arg2));
         break;
     case TARGET_NR_readv:
         {
@@ -1638,18 +1705,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         goto unimplemented;
     case TARGET_NR__sysctl:
         goto unimplemented;
-    case TARGET_NR_mlock:
-        ret = get_errno(mlock((void *)arg1, arg2));
-        break;
-    case TARGET_NR_munlock:
-        ret = get_errno(munlock((void *)arg1, arg2));
-        break;
-    case TARGET_NR_mlockall:
-        ret = get_errno(mlockall(arg1));
-        break;
-    case TARGET_NR_munlockall:
-        ret = get_errno(munlockall());
-        break;
     case TARGET_NR_sched_setparam:
         goto unimplemented;
     case TARGET_NR_sched_getparam:
@@ -1680,16 +1735,41 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
             }
         }
         break;
-
-    case TARGET_NR_mremap:
     case TARGET_NR_setresuid:
+        ret = get_errno(setresuid(low2highuid(arg1), 
+                                  low2highuid(arg2), 
+                                  low2highuid(arg3)));
+        break;
     case TARGET_NR_getresuid:
+        {
+            int ruid, euid, suid;
+            ret = get_errno(getresuid(&ruid, &euid, &suid));
+            if (!is_error(ret)) {
+                *(uint16_t *)arg1 = tswap16(high2lowuid(ruid));
+                *(uint16_t *)arg2 = tswap16(high2lowuid(euid));
+                *(uint16_t *)arg3 = tswap16(high2lowuid(suid));
+            }
+        }
+        break;
+    case TARGET_NR_setresgid:
+        ret = get_errno(setresgid(low2highgid(arg1), 
+                                  low2highgid(arg2), 
+                                  low2highgid(arg3)));
+        break;
+    case TARGET_NR_getresgid:
+        {
+            int rgid, egid, sgid;
+            ret = get_errno(getresgid(&rgid, &egid, &sgid));
+            if (!is_error(ret)) {
+                *(uint16_t *)arg1 = high2lowgid(tswap16(rgid));
+                *(uint16_t *)arg2 = high2lowgid(tswap16(egid));
+                *(uint16_t *)arg3 = high2lowgid(tswap16(sgid));
+            }
+        }
+        break;
     case TARGET_NR_vm86:
     case TARGET_NR_query_module:
-    case TARGET_NR_poll:
     case TARGET_NR_nfsservctl:
-    case TARGET_NR_setresgid:
-    case TARGET_NR_getresgid:
     case TARGET_NR_prctl:
     case TARGET_NR_pread:
     case TARGET_NR_pwrite:
@@ -1744,26 +1824,80 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         break;
 
     case TARGET_NR_lchown32:
+        ret = get_errno(lchown((const char *)arg1, arg2, arg3));
+        break;
     case TARGET_NR_getuid32:
+        ret = get_errno(getuid());
+        break;
     case TARGET_NR_getgid32:
+        ret = get_errno(getgid());
+        break;
     case TARGET_NR_geteuid32:
+        ret = get_errno(geteuid());
+        break;
     case TARGET_NR_getegid32:
+        ret = get_errno(getegid());
+        break;
     case TARGET_NR_setreuid32:
+        ret = get_errno(setreuid(arg1, arg2));
+        break;
     case TARGET_NR_setregid32:
+        ret = get_errno(setregid(arg1, arg2));
+        break;
     case TARGET_NR_getgroups32:
+        goto unimplemented;
     case TARGET_NR_setgroups32:
+        goto unimplemented;
     case TARGET_NR_fchown32:
+        ret = get_errno(fchown(arg1, arg2, arg3));
+        break;
     case TARGET_NR_setresuid32:
+        ret = get_errno(setresuid(arg1, arg2, arg3));
+        break;
     case TARGET_NR_getresuid32:
+        {
+            int ruid, euid, suid;
+            ret = get_errno(getresuid(&ruid, &euid, &suid));
+            if (!is_error(ret)) {
+                *(uint32_t *)arg1 = tswap32(ruid);
+                *(uint32_t *)arg2 = tswap32(euid);
+                *(uint32_t *)arg3 = tswap32(suid);
+            }
+        }
+        break;
     case TARGET_NR_setresgid32:
+        ret = get_errno(setresgid(arg1, arg2, arg3));
+        break;
     case TARGET_NR_getresgid32:
+        {
+            int rgid, egid, sgid;
+            ret = get_errno(getresgid(&rgid, &egid, &sgid));
+            if (!is_error(ret)) {
+                *(uint32_t *)arg1 = tswap32(rgid);
+                *(uint32_t *)arg2 = tswap32(egid);
+                *(uint32_t *)arg3 = tswap32(sgid);
+            }
+        }
+        break;
     case TARGET_NR_chown32:
+        ret = get_errno(chown((const char *)arg1, arg2, arg3));
+        break;
     case TARGET_NR_setuid32:
+        ret = get_errno(setuid(arg1));
+        break;
     case TARGET_NR_setgid32:
+        ret = get_errno(setgid(arg1));
+        break;
     case TARGET_NR_setfsuid32:
+        ret = get_errno(setfsuid(arg1));
+        break;
     case TARGET_NR_setfsgid32:
+        ret = get_errno(setfsgid(arg1));
+        break;
     case TARGET_NR_pivot_root:
+        goto unimplemented;
     case TARGET_NR_mincore:
+        goto unimplemented;
     case TARGET_NR_madvise:
         goto unimplemented;
 #if TARGET_LONG_BITS == 32
@@ -1800,7 +1934,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
         goto unimplemented;
     default:
     unimplemented:
-        gemu_log("Unsupported syscall: %d\n", num);
+        gemu_log("gemu: Unsupported syscall: %d\n", num);
         ret = -ENOSYS;
         break;
     }