Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/sam/kbuild
[linux-2.6] / arch / um / kernel / syscall.c
1 /*
2  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3  * Licensed under the GPL
4  */
5
6 #include "linux/file.h"
7 #include "linux/fs.h"
8 #include "linux/mm.h"
9 #include "linux/sched.h"
10 #include "linux/utsname.h"
11 #include "asm/current.h"
12 #include "asm/mman.h"
13 #include "asm/uaccess.h"
14 #include "asm/unistd.h"
15
16 /*  Unlocked, I don't care if this is a bit off */
17 int nsyscalls = 0;
18
19 long sys_fork(void)
20 {
21         long ret;
22
23         current->thread.forking = 1;
24         ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
25                       &current->thread.regs, 0, NULL, NULL);
26         current->thread.forking = 0;
27         return ret;
28 }
29
30 long sys_vfork(void)
31 {
32         long ret;
33
34         current->thread.forking = 1;
35         ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
36                       UPT_SP(&current->thread.regs.regs),
37                       &current->thread.regs, 0, NULL, NULL);
38         current->thread.forking = 0;
39         return ret;
40 }
41
42 /* common code for old and new mmaps */
43 long sys_mmap2(unsigned long addr, unsigned long len,
44                unsigned long prot, unsigned long flags,
45                unsigned long fd, unsigned long pgoff)
46 {
47         long error = -EBADF;
48         struct file * file = NULL;
49
50         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
51         if (!(flags & MAP_ANONYMOUS)) {
52                 file = fget(fd);
53                 if (!file)
54                         goto out;
55         }
56
57         down_write(&current->mm->mmap_sem);
58         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
59         up_write(&current->mm->mmap_sem);
60
61         if (file)
62                 fput(file);
63  out:
64         return error;
65 }
66
67 long old_mmap(unsigned long addr, unsigned long len,
68               unsigned long prot, unsigned long flags,
69               unsigned long fd, unsigned long offset)
70 {
71         long err = -EINVAL;
72         if (offset & ~PAGE_MASK)
73                 goto out;
74
75         err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
76  out:
77         return err;
78 }
79 /*
80  * sys_pipe() is the normal C calling standard for creating
81  * a pipe. It's not the way unix traditionally does this, though.
82  */
83 long sys_pipe(unsigned long __user * fildes)
84 {
85         int fd[2];
86         long error;
87
88         error = do_pipe(fd);
89         if (!error) {
90                 if (copy_to_user(fildes, fd, sizeof(fd)))
91                         error = -EFAULT;
92         }
93         return error;
94 }
95
96
97 long sys_uname(struct old_utsname __user * name)
98 {
99         long err;
100         if (!name)
101                 return -EFAULT;
102         down_read(&uts_sem);
103         err = copy_to_user(name, utsname(), sizeof (*name));
104         up_read(&uts_sem);
105         return err?-EFAULT:0;
106 }
107
108 long sys_olduname(struct oldold_utsname __user * name)
109 {
110         long error;
111
112         if (!name)
113                 return -EFAULT;
114         if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
115                 return -EFAULT;
116
117         down_read(&uts_sem);
118
119         error = __copy_to_user(&name->sysname, &utsname()->sysname,
120                                __OLD_UTS_LEN);
121         error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
122         error |= __copy_to_user(&name->nodename, &utsname()->nodename,
123                                 __OLD_UTS_LEN);
124         error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
125         error |= __copy_to_user(&name->release, &utsname()->release,
126                                 __OLD_UTS_LEN);
127         error |= __put_user(0, name->release + __OLD_UTS_LEN);
128         error |= __copy_to_user(&name->version, &utsname()->version,
129                                 __OLD_UTS_LEN);
130         error |= __put_user(0, name->version + __OLD_UTS_LEN);
131         error |= __copy_to_user(&name->machine, &utsname()->machine,
132                                 __OLD_UTS_LEN);
133         error |= __put_user(0, name->machine + __OLD_UTS_LEN);
134
135         up_read(&uts_sem);
136
137         error = error ? -EFAULT : 0;
138
139         return error;
140 }
141
142 int kernel_execve(const char *filename, char *const argv[], char *const envp[])
143 {
144         mm_segment_t fs;
145         int ret;
146
147         fs = get_fs();
148         set_fs(KERNEL_DS);
149         ret = um_execve(filename, argv, envp);
150         set_fs(fs);
151
152         return ret;
153 }