blob: 3f5d4df7dd105372b0cc3c10bba346b04ee22805 [file] [log] [blame]
#include "linux/types.h"
#include "linux/utsname.h"
#include "linux/utime.h"
#include "linux/mm.h"
#include "linux/unistd.h"
#include "linux/smp_lock.h"
#include "linux/file.h"
#include "linux/poll.h"
#include "linux/module.h"
#include "linux/msg.h"
#include "linux/shm.h"
#include "linux/spinlock.h"
#include "asm/segment.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
#include "asm/ipc.h"
#include "kern.h"
#include "user_util.h"
#include "kern_util.h"
extern int sys_getpid(void);
extern int sys_getppid(void);
extern long sys_open(const char * filename,int flags,int mode);
extern int sys_getuid(void);
extern int sys_geteuid(void);
extern int sys_getgid(void);
extern int sys_getegid(void);
extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
extern int sys_reboot(int magic, int magic_too, int flag);
extern int do_sigaction(int sig, const struct k_sigaction *act,
struct k_sigaction *oact);
extern unsigned long sys_brk(unsigned long brk);
extern int sys_time(int * tloc);
extern int sys_socketcall(int call, unsigned long *args);
extern long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
extern int sys_setsid(void);
extern int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset);
extern int sys_newlstat(char * filename, struct stat * statbuf);
extern int sys_newfstat(unsigned int fd, struct stat * statbuf);
extern int sys_unlink(const char * pathname);
extern int sys_write(unsigned int fd,char * buf,unsigned int count);
extern int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
extern int sys_read(unsigned int fd, char * buf, int count);
extern int sys_access(const char * filename, int mode);
extern int sys_munmap(unsigned long addr, size_t len);
extern int do_fork(unsigned long clone_flags, unsigned long usp,
struct pt_regs *regs);
extern int sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
struct rusage * ru);
extern int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
extern int sys_dup(unsigned int fildes);
extern int sys_exit(int error_code);
extern int sys_execve(char *file, char **argv, char **env);
extern long sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
extern int sys_dup2(unsigned int oldfd, unsigned int newfd);
extern int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
struct timeval *tvp);
extern int sys_mprotect(unsigned long start, size_t len, unsigned long prot);
extern int sys_newuname(struct new_utsname * name);
extern int sys_getppid(void);
extern int sys_newstat(char * filename, struct stat * statbuf);
extern int sys_getpgrp(void);
extern int sys_sethostname(char *name, int len);
extern int sys_getrusage(int who, struct rusage *ru);
extern int sys_setdomainname(char *name, int len);
extern int sys_sync(void);
extern int sys_llseek(unsigned int fd, unsigned long offset_high,
unsigned long offset_low, loff_t * result,
unsigned int origin);
extern int sys_readlink(const char * path, char * buf, int bufsiz);
extern int sys_mount(char * dev_name, char * dir_name, char * type,
unsigned long new_flags, void * data);
extern int sys_utime(char * filename, struct utimbuf * times);
extern int sys_getdents(unsigned int fd, void * dirent, unsigned int count);
extern int sys_ftruncate(unsigned int fd, unsigned long length);
extern int sys_syslog(int type, char * buf, int len);
extern int sys_chdir(const char * filename);
extern int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
extern int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
extern int sys_getpriority(int which, int who);
extern int sys_setpriority(int which, int who, int niceval);
extern int sys_getgroups(int gidsetsize, gid_t *grouplist);
extern int sys_setgroups(int gidsetsize, gid_t *grouplist);
extern int sys_umask(int mask);
extern int sys_chmod(const char * filename, mode_t mode);
extern int sys_chown(const char * filename, uid_t user, gid_t group);
extern unsigned int sys_alarm(unsigned int seconds);
extern int sys_flock(unsigned int fd, unsigned int cmd);
extern int sys_vhangup(void);
extern int sys_bdflush(int func, long data);
extern int sys_setpgid(pid_t pid, pid_t pgid);
extern int sys_setuid(uid_t uid);
extern int sys_setreuid(uid_t ruid, uid_t euid);
extern int sys_setregid(gid_t rgid, gid_t egid);
extern int sys_setgid(gid_t gid);
extern int sys_statfs(const char * path, struct statfs * buf);
extern int sys_lchown(const char * filename, uid_t user, gid_t group);
extern int sys_kill(int pid, int sig);
extern int sys_rt_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact, size_t sigsetsize);
extern int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
size_t sigsetsize);
extern int sys_getcwd(char *buf, unsigned long size);
extern int sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout);
extern int sys_link(const char * oldname, const char * newname);
extern ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
unsigned long count);
extern int sys_fsync(unsigned int fd);
extern int sys_get_kernel_syms(struct kernel_sym *table);
extern int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
extern int sys_fstatfs(unsigned int fd, struct statfs * buf);
extern int sys_delete_module(const char *name_user);
extern int sys_fchdir(unsigned int fd);
extern int sys_mkdir(const char * pathname, int mode);
extern int sys_rmdir(const char * pathname);
extern int sys_rename(const char * oldname, const char * newname);
extern int sys_mknod(const char * filename, int mode, dev_t dev);
extern int sys_umount(char * name, int flags);
extern int sys_fchmod(unsigned int fd, mode_t mode);
extern long sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
extern int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize);
extern long sys_setfsuid(uid_t uid);
extern long sys_setfsgid(gid_t gid);
extern long sys_swapon(const char * specialfile, int swap_flags);
extern long sys_swapoff(const char * specialfile);
extern long sys_symlink(const char *oldname, const char *newname);
extern long sys_oldumount(char * name);
extern long sys_fchown(unsigned int fd, uid_t user, gid_t group);
extern long sys_getpgid(pid_t pid);
extern unsigned long sys_mremap(unsigned long addr,
unsigned long old_len, unsigned long new_len,
unsigned long flags, unsigned long new_addr);
extern long sys_msync(unsigned long start, size_t len, int flags);
extern long sys_sysinfo(struct sysinfo *info);
extern long sys_stat64(char * filename, struct stat64 * statbuf, long flags);
extern long sys_lstat64(char * filename, struct stat64 * statbuf, long flags);
extern long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags);
extern long sys_times(struct tms * tbuf);
extern long sys_chroot(const char * filename);
extern long sys_creat(const char * pathname, int mode);
extern long sys_query_module(const char *name_user, int which, char *buf,
size_t bufsize, size_t *ret);
static int sys_fork(void)
{
return do_fork(SIGCHLD, 0, NULL);
}
int sys_vfork(void)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL);
}
struct mmap_arg_struct {
unsigned long addr;
unsigned long len;
unsigned long prot;
unsigned long flags;
unsigned long fd;
unsigned long offset;
};
static int old_mmap(struct mmap_arg_struct *arg)
{
int error = -EFAULT;
struct file * file = NULL;
struct mmap_arg_struct a;
if (copy_from_user(&a, arg, sizeof(a)))
return -EFAULT;
down(&current->mm->mmap_sem);
lock_kernel();
if (!(a.flags & MAP_ANONYMOUS)) {
error = -EBADF;
file = fget(a.fd);
if (!file)
goto out;
}
a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
if (file)
fput(file);
out:
unlock_kernel();
up(&current->mm->mmap_sem);
return error;
}
/*
* sys_pipe() is the normal C calling standard for creating
* a pipe. It's not the way unix traditionally does this, though.
*/
static int sys_pipe(unsigned long * fildes)
{
int fd[2];
int error;
lock_kernel();
error = do_pipe(fd);
unlock_kernel();
if (!error) {
if (copy_to_user(fildes, fd, 2*sizeof(int)))
error = -EFAULT;
}
return error;
}
static int sys_pause(void)
{
current->state = TASK_INTERRUPTIBLE;
schedule();
return -ERESTARTNOHAND;
}
static int sys_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
if (act) {
old_sigset_t mask;
if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret;
}
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
* This is really horribly ugly.
*/
int sys_ipc (uint call, int first, int second,
int third, void *ptr, long fifth)
{
int version, ret;
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
switch (call) {
case SEMOP:
return sys_semop (first, (struct sembuf *)ptr, second);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
union semun fourth;
if (!ptr)
return -EINVAL;
if (get_user(fourth.__pad, (void **) ptr))
return -EFAULT;
return sys_semctl (first, second, third, fourth);
}
case MSGSND:
return sys_msgsnd (first, (struct msgbuf *) ptr,
second, third);
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
if (!ptr)
return -EINVAL;
if (copy_from_user(&tmp,
(struct ipc_kludge *) ptr,
sizeof (tmp)))
return -EFAULT;
return sys_msgrcv (first, tmp.msgp, second,
tmp.msgtyp, third);
}
default:
panic("msgrcv with version != 0");
return sys_msgrcv (first,
(struct msgbuf *) ptr,
second, fifth, third);
}
case MSGGET:
return sys_msgget ((key_t) first, second);
case MSGCTL:
return sys_msgctl (first, second, (struct msqid_ds *) ptr);
case SHMAT:
switch (version) {
default: {
ulong raddr;
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
return ret;
return put_user (raddr, (ulong *) third);
}
case 1: /* iBCS2 emulator entry point */
if (!segment_eq(get_fs(), get_ds()))
return -EINVAL;
return sys_shmat (first, (char *) ptr, second, (ulong *) third);
}
case SHMDT:
return sys_shmdt ((char *)ptr);
case SHMGET:
return sys_shmget (first, second, third);
case SHMCTL:
return sys_shmctl (first, second,
(struct shmid_ds *) ptr);
default:
return -EINVAL;
}
}
int nsyscalls = 0;
int execute_syscall(int syscall, unsigned long *args)
{
unsigned long arg1, arg2, arg3, arg4, arg5;
int res;
current->thread.nsyscalls++;
nsyscalls++;
if(syscall == -1)
panic("syscall thread activated without a system call");
arg1 = args[0];
arg2 = args[1];
arg3 = args[2];
arg4 = args[3];
arg5 = args[4];
switch(syscall){
case __NR_exit: /* 1 */
res = sys_exit(arg1);
break;
case __NR_fork: /* 2 */
current->thread.forking = 1;
res = sys_fork();
current->thread.forking = 0;
break;
case __NR_read: /* 3 */
res = sys_read(arg1, (char *) arg2, arg3);
break;
case __NR_write: /* 4 */
res = sys_write(arg1, (char *) arg2, arg3);
break;
case __NR_open: /* 5 */
res = sys_open((char *) arg1, arg2, arg3);
break;
case __NR_close: /* 6 */
res = sys_close(arg1);
break;
case __NR_creat: /* 8 */
res = sys_creat((const char *) arg1, arg2);
break;
case __NR_link: /* 9 */
res = sys_link((const char *) arg1, (const char *) arg2);
break;
case __NR_unlink: /* 10 */
res = sys_unlink((char *)arg1);
break;
case __NR_execve: /* 11 */
res = sys_execve((char *) arg1, (char **) arg2, (char **) arg3);
printk("exec of \"%s\" returned %d\n", (char *) arg1, res);
break;
case __NR_chdir: /* 12 */
res = sys_chdir((char *) arg1);
break;
case __NR_time: /* 13 */
res = sys_time((int *) arg1);
break;
case __NR_mknod:
res = sys_mknod((const char *) arg1, arg2, arg3);
break;
case __NR_chmod: /* 15 */
res = sys_chmod((const char *) arg1, arg2);
break;
case __NR_lchown: /* 16 */
res = sys_lchown((const char *) arg1, arg2, arg3);
break;
case __NR_lseek: /* 19 */
res = sys_lseek(arg1, arg2, arg3);
break;
case __NR_getpid: /* 20 */
res = sys_getpid();
break;
case __NR_mount: /* 21 */
res = sys_mount((char *) arg1, (char *) arg2, (char *) arg3, arg4,
(void *) arg5);
break;
case __NR_umount: /* 22 */
res = sys_oldumount((char *) arg1);
break;
case __NR_setuid: /* 23 */
res = sys_setuid(arg1);
break;
case __NR_getuid: /* 24 */
res = sys_getuid();
break;
case __NR_alarm: /* 27 */
res = sys_alarm(arg1);
break;
case __NR_pause: /* 29 */
res = sys_pause();
break;
case __NR_utime: /* 30 */
res = sys_utime((char *) arg1, (struct utimbuf *) arg2);
break;
case __NR_access: /* 33 */
res = sys_access((char *) arg1, arg2);
break;
case __NR_sync: /* 36 */
res = sys_sync();
break;
case __NR_kill: /* 37 */
res = sys_kill(arg1, arg2);
break;
case __NR_rename: /* 38 */
res = sys_rename((const char *) arg1, (const char *) arg2);
break;
case __NR_mkdir: /* 39 */
res = sys_mkdir((const char *) arg1, arg2);
break;
case __NR_rmdir: /* 40 */
res = sys_rmdir((const char *) arg1);
break;
case __NR_dup: /* 41 */
res = sys_dup(arg1);
break;
case __NR_pipe: /* 42 */
res = sys_pipe((unsigned long *) arg1);
break;
case __NR_times: /* 43 */
res = sys_times((struct tms *) arg1);
break;
case __NR_brk: /* 45 */
res = sys_brk(arg1);
break;
case __NR_setgid: /* 46 */
res = sys_setgid(arg1);
break;
case __NR_getgid: /* 47 */
res = sys_getgid();
break;
case __NR_geteuid: /* 49 */
res = sys_geteuid();
break;
case __NR_getegid: /* 50 */
res = sys_getegid();
break;
case __NR_umount2: /* 52 */
res = sys_umount((char *) arg1, arg2);
break;
case __NR_ioctl: /* 54 */
res = sys_ioctl(arg1, arg2, arg3);
break;
case __NR_fcntl: /* 55 */
res = sys_fcntl(arg1, arg2, arg3);
break;
case __NR_setpgid: /* 57 */
res = sys_setpgid(arg1, arg2);
break;
case __NR_umask: /* 60 */
res = sys_umask(arg1);
break;
case __NR_chroot: /* 61 */
res = sys_chroot((const char *) arg1);
break;
case __NR_dup2: /* 63 */
res = sys_dup2(arg1, arg2);
break;
case __NR_getppid: /* 64 */
res = sys_getppid();
break;
case __NR_getpgrp: /* 65 */
res = sys_getpgrp();
break;
case __NR_setsid: /* 66 */
res = sys_setsid();
break;
case __NR_sigaction: /* 67 */
res = sys_sigaction(arg1, (struct old_sigaction *) arg2,
(struct old_sigaction *) arg3);
break;
case __NR_setreuid: /* 70 */
res = sys_setreuid(arg1, arg2);
break;
case __NR_setregid: /* 71 */
res = sys_setregid(arg1, arg2);
break;
case __NR_sethostname: /* 74 */
res = sys_sethostname((char *) arg1, arg2);
break;
case __NR_getrlimit: /* 75 */
res = sys_getrlimit(arg1, (struct rlimit *) arg2);
break;
case __NR_setrlimit: /* 76 */
res = sys_setrlimit(arg1, (struct rlimit *) arg2);
break;
case __NR_getrusage: /* 77 */
res = sys_getrusage(arg1, (struct rusage *) arg2);
break;
case __NR_gettimeofday: /* 78 */
res = sys_gettimeofday((struct timeval *) arg1, (struct timezone *) arg2);
break;
case __NR_getgroups: /* 80 */
res = sys_getgroups(arg1, (gid_t *) arg2);
break;
case __NR_setgroups: /* 81 */
res = sys_setgroups(arg1, (gid_t *) arg2);
break;
case __NR_symlink: /* 83 */
res = sys_symlink((const char *) arg1, (const char *) arg2);
break;
case __NR_readlink: /* 85 */
res = sys_readlink((const char *) arg1, (char *) arg2, arg3);
break;
case __NR_swapon: /* 87 */
res = sys_swapon((const char *) arg1, arg2);
break;
case __NR_reboot: /* 88 */
res = sys_reboot(arg1, arg2, arg3);
break;
case __NR_mmap: /* 90 */
res = old_mmap((struct mmap_arg_struct *) arg1);
break;
case __NR_munmap: /* 91 */
res = sys_munmap(arg1, arg2);
break;
case __NR_ftruncate: /* 93 */
res = sys_ftruncate(arg1, arg2);
break;
case __NR_fchmod: /* 94 */
res = sys_fchmod(arg1, arg2);
break;
case __NR_fchown:
res = sys_fchown(arg1, arg2, arg3);
break;
case __NR_getpriority: /* 96 */
res = sys_getpriority(arg1, arg2);
break;
case __NR_setpriority: /* 97 */
res = sys_setpriority(arg1, arg2, arg3);
break;
case __NR_statfs: /* 99 */
res = sys_statfs((const char *) arg1, (struct statfs *) arg2);
break;
case __NR_fstatfs: /* 100 */
res = sys_fstatfs(arg1, (struct statfs *) arg2);
break;
case __NR_ioperm: /* 101 */
/* User-mode has no io ports */
res = 0;
break;
case __NR_socketcall: /* 102 */
res = sys_socketcall(arg1, (unsigned long *) arg2);
break;
case __NR_syslog: /* 103 */
res = sys_syslog(arg1, (char *) arg2, arg3);
break;
case __NR_stat: /* 106 */
res = sys_newstat((char *) arg1, (struct stat *) arg2);
break;
case __NR_lstat: /* 107 */
res = sys_newlstat((char *) arg1, (struct stat *) arg2);
break;
case __NR_fstat: /* 108 */
res = sys_newfstat(arg1, (struct stat *) arg2);
break;
case __NR_iopl: /* 110 */
/* Fake this one */
res = 0;
break;
case __NR_vhangup: /* 111 */
res = sys_vhangup();
break;
case __NR_wait4: /* 114 */
res = sys_wait4(arg1, (unsigned int *) arg2, arg3, (struct rusage *) arg4);
break;
case __NR_swapoff: /* 115 */
res = sys_swapoff((char *) arg1);
break;
case __NR_sysinfo: /* 116 */
res = sys_sysinfo((struct sysinfo *) arg1);
break;
case __NR_ipc: /* 117 */
res = sys_ipc(arg1, arg2, arg3, arg4, (void *) arg5, 0);
break;
case __NR_fsync: /* 118 */
res = sys_fsync(arg1);
break;
case __NR_setdomainname: /* 121 */
res = sys_setdomainname((char *)arg1, arg2);
break;
case __NR_uname: /* 122 */
res = sys_newuname((struct new_utsname *) arg1);
break;
case __NR_mprotect: /* 125 */
res = sys_mprotect(arg1, arg2, arg3);
break;
case __NR_sigprocmask: /* 126 */
res = sys_sigprocmask(arg1, (sigset_t *) arg2, (sigset_t *) arg3);
break;
case __NR_delete_module: /* 129 */
res = sys_delete_module((const char *) arg1);
break;
case __NR_get_kernel_syms: /* 130 */
res = sys_get_kernel_syms((struct kernel_sym *) arg1);
break;
case __NR_quotactl: /* 131 */
res = sys_quotactl(arg1, (const char *) arg2, arg3, (caddr_t) arg4);
break;
case __NR_getpgid: /* 132 */
res = sys_getpgid(arg1);
break;
case __NR_fchdir: /* 133 */
res = sys_fchdir(arg1);
break;
case __NR_bdflush: /* 134 */
res = sys_bdflush(arg1, arg2);
break;
case __NR_personality: /* 136 */
res = sys_personality(arg1);
break;
case __NR_setfsuid: /* 138 */
res = sys_setfsuid(arg1);
break;
case __NR_setfsgid: /* 139 */
res = sys_setfsgid(arg1);
break;
case __NR__llseek: /* 140 */
res = sys_llseek(arg1, arg2, arg3, (loff_t *) arg4, arg5);
break;
case __NR_getdents: /* 141 */
res = sys_getdents(arg1, (void *) arg2, arg3);
break;
case __NR__newselect: /* 142 */
res = sys_select(arg1, (fd_set *) arg2, (fd_set *) arg3, (fd_set *) arg4,
(struct timeval *) arg5);
break;
case __NR_flock: /* 143 */
res = sys_flock(arg1, arg2);
break;
case __NR_msync: /* 144 */
res = sys_msync(arg1, arg2, arg3);
break;
case __NR_writev: /* 146 */
res = sys_writev(arg1, (const struct iovec *) arg2, arg3);
break;
case __NR_nanosleep: /* 162 */
res = sys_nanosleep((struct timespec *) arg1, (struct timespec *) arg2);
break;
case __NR_mremap: /* 163 */
res = sys_mremap(arg1, arg2, arg3, arg4, arg5);
break;
case __NR_setresuid: /* 164 */
res = sys_setresuid(arg1, arg2, arg3);
break;
case __NR_query_module:
res = sys_query_module((const char *) arg1, arg2, (char *) arg3,
arg4, (size_t *) arg5);
break;
case __NR_poll: /* 168 */
res = sys_poll((struct pollfd *) arg1, arg2, arg3);
break;
case __NR_rt_sigaction: /* 174 */
res = sys_rt_sigaction(arg1, (const struct sigaction *) arg2,
(struct sigaction *) arg3, arg4);
break;
case __NR_rt_sigprocmask: /* 175 */
res = sys_rt_sigprocmask(arg1, (sigset_t *) arg2, (sigset_t *) arg3,
arg4);
break;
case __NR_rt_sigsuspend: /* 179 */
res = sys_rt_sigsuspend((sigset_t *) arg1, arg2);
break;
case __NR_chown: /* 182 */
res = sys_chown((const char *) arg1, arg2, arg3);
break;
case __NR_getcwd: /* 183 */
res = sys_getcwd((char *) arg1, arg2);
break;
case __NR_vfork: /* 190 */
current->thread.forking = 1;
res = sys_vfork();
current->thread.forking = 0;
break;
case __NR_stat64: /* 195 */
res = sys_stat64((char *) arg1, (struct stat64 *) arg2, arg3);
break;
case __NR_lstat64: /* 196 */
res = sys_lstat64((char *) arg1, (struct stat64 *) arg2, arg3);
break;
case __NR_fstat64: /* 197 */
res = sys_fstat64(arg1, (struct stat64 *) arg2, arg3);
break;
default:
printk("Unimplemented syscall : %d\n", syscall);
res = -ENOSYS;
KERN_UNTESTED();
break;
}
return(res);
}
void store_syscall(void *t, int syscall, unsigned long arg1,
unsigned long arg2, unsigned long arg3, unsigned long arg4,
unsigned long arg5)
{
struct task_struct *task;
task = t;
task->thread.syscall.id = syscall;
task->thread.syscall.args[0] = arg1;
task->thread.syscall.args[1] = arg2;
task->thread.syscall.args[2] = arg3;
task->thread.syscall.args[3] = arg4;
task->thread.syscall.args[4] = arg5;
}
void set_syscall_result(void *t, int result, int again)
{
struct task_struct *task;
if(t == NULL) task = current;
else task = t;
if(task->thread.syscall.have_result)
panic("Already have result in set_syscall_result");
task->thread.syscall.result = result;
task->thread.syscall.again = again;
task->thread.syscall.have_result = 1;
}
int have_syscall_result(void *t, long *result_out, int *again_out)
{
struct task_struct *task;
task = t;
if(task->thread.syscall.have_result){
task->thread.syscall.have_result = 0;
*result_out = task->thread.syscall.result;
*again_out = task->thread.syscall.again;
return(1);
}
else return(0);
}
int current_syscall(void *t, unsigned long *args_out)
{
struct task_struct *task;
if(t == NULL) task = current;
else task = t;
args_out[0] = task->thread.syscall.args[0];
args_out[1] = task->thread.syscall.args[1];
args_out[2] = task->thread.syscall.args[2];
args_out[3] = task->thread.syscall.args[3];
args_out[4] = task->thread.syscall.args[4];
return(task->thread.syscall.id);
}
int redoing_syscall(void *t, unsigned long *args_out, long *result_out)
{
struct task_struct *task;
task = t;
if(task->thread.syscall.again == 0) return(-1);
*result_out = task->thread.syscall.result;
return(current_syscall(task, args_out));
}
spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED;
void lock_syscall(void)
{
spin_lock(&syscall_lock);
}
void unlock_syscall(void)
{
spin_unlock(&syscall_lock);
}