Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[pandora-kernel.git] / 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 long sys_fork(void)
17 {
18         long ret;
19
20         current->thread.forking = 1;
21         ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
22                       &current->thread.regs, 0, NULL, NULL);
23         current->thread.forking = 0;
24         return ret;
25 }
26
27 long sys_vfork(void)
28 {
29         long ret;
30
31         current->thread.forking = 1;
32         ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
33                       UPT_SP(&current->thread.regs.regs),
34                       &current->thread.regs, 0, NULL, NULL);
35         current->thread.forking = 0;
36         return ret;
37 }
38
39 /* common code for old and new mmaps */
40 long sys_mmap2(unsigned long addr, unsigned long len,
41                unsigned long prot, unsigned long flags,
42                unsigned long fd, unsigned long pgoff)
43 {
44         long error = -EBADF;
45         struct file * file = NULL;
46
47         flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
48         if (!(flags & MAP_ANONYMOUS)) {
49                 file = fget(fd);
50                 if (!file)
51                         goto out;
52         }
53
54         down_write(&current->mm->mmap_sem);
55         error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
56         up_write(&current->mm->mmap_sem);
57
58         if (file)
59                 fput(file);
60  out:
61         return error;
62 }
63
64 long old_mmap(unsigned long addr, unsigned long len,
65               unsigned long prot, unsigned long flags,
66               unsigned long fd, unsigned long offset)
67 {
68         long err = -EINVAL;
69         if (offset & ~PAGE_MASK)
70                 goto out;
71
72         err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
73  out:
74         return err;
75 }
76 /*
77  * sys_pipe() is the normal C calling standard for creating
78  * a pipe. It's not the way unix traditionally does this, though.
79  */
80 long sys_pipe(unsigned long __user * fildes)
81 {
82         int fd[2];
83         long error;
84
85         error = do_pipe(fd);
86         if (!error) {
87                 if (copy_to_user(fildes, fd, sizeof(fd)))
88                         error = -EFAULT;
89         }
90         return error;
91 }
92
93
94 long sys_uname(struct old_utsname __user * name)
95 {
96         long err;
97         if (!name)
98                 return -EFAULT;
99         down_read(&uts_sem);
100         err = copy_to_user(name, utsname(), sizeof (*name));
101         up_read(&uts_sem);
102         return err?-EFAULT:0;
103 }
104
105 long sys_olduname(struct oldold_utsname __user * name)
106 {
107         long error;
108
109         if (!name)
110                 return -EFAULT;
111         if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
112                 return -EFAULT;
113
114         down_read(&uts_sem);
115
116         error = __copy_to_user(&name->sysname, &utsname()->sysname,
117                                __OLD_UTS_LEN);
118         error |= __put_user(0, name->sysname + __OLD_UTS_LEN);
119         error |= __copy_to_user(&name->nodename, &utsname()->nodename,
120                                 __OLD_UTS_LEN);
121         error |= __put_user(0, name->nodename + __OLD_UTS_LEN);
122         error |= __copy_to_user(&name->release, &utsname()->release,
123                                 __OLD_UTS_LEN);
124         error |= __put_user(0, name->release + __OLD_UTS_LEN);
125         error |= __copy_to_user(&name->version, &utsname()->version,
126                                 __OLD_UTS_LEN);
127         error |= __put_user(0, name->version + __OLD_UTS_LEN);
128         error |= __copy_to_user(&name->machine, &utsname()->machine,
129                                 __OLD_UTS_LEN);
130         error |= __put_user(0, name->machine + __OLD_UTS_LEN);
131
132         up_read(&uts_sem);
133
134         error = error ? -EFAULT : 0;
135
136         return error;
137 }
138
139 int kernel_execve(const char *filename, char *const argv[], char *const envp[])
140 {
141         mm_segment_t fs;
142         int ret;
143
144         fs = get_fs();
145         set_fs(KERNEL_DS);
146         ret = um_execve(filename, argv, envp);
147         set_fs(fs);
148
149         return ret;
150 }