This source file includes following definitions.
- sys_lseek
- sys_llseek
- sys_read
- sys_write
- sys_readv
- sys_writev
1
2
3
4
5
6
7 #include <linux/types.h>
8 #include <linux/errno.h>
9 #include <linux/stat.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/mm.h>
13 #include <linux/uio.h>
14
15 #include <asm/segment.h>
16
17 asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
18 {
19 struct file * file;
20 int tmp = -1;
21
22 if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
23 return -EBADF;
24 if (origin > 2)
25 return -EINVAL;
26 if (file->f_op && file->f_op->lseek)
27 return file->f_op->lseek(file->f_inode,file,offset,origin);
28
29
30 switch (origin) {
31 case 0:
32 tmp = offset;
33 break;
34 case 1:
35 tmp = file->f_pos + offset;
36 break;
37 case 2:
38 if (!file->f_inode)
39 return -EINVAL;
40 tmp = file->f_inode->i_size + offset;
41 break;
42 }
43 if (tmp < 0)
44 return -EINVAL;
45 if (tmp != file->f_pos) {
46 file->f_pos = tmp;
47 file->f_reada = 0;
48 file->f_version = ++event;
49 }
50 return file->f_pos;
51 }
52
53 asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
54 unsigned long offset_low, loff_t * result,
55 unsigned int origin)
56 {
57 struct file * file;
58 loff_t tmp = -1;
59 loff_t offset;
60 int err;
61
62 if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
63 return -EBADF;
64 if (origin > 2)
65 return -EINVAL;
66 if ((err = verify_area(VERIFY_WRITE, result, sizeof(loff_t))))
67 return err;
68 offset = (loff_t) (((unsigned long long) offset_high << 32) | offset_low);
69
70
71
72 if (file->f_op && file->f_op->lseek) {
73 if (offset != (long) offset)
74 return -EINVAL;
75 return file->f_op->lseek(file->f_inode,file,offset,origin);
76 }
77
78 switch (origin) {
79 case 0:
80 tmp = offset;
81 break;
82 case 1:
83 tmp = file->f_pos + offset;
84 break;
85 case 2:
86 if (!file->f_inode)
87 return -EINVAL;
88 tmp = file->f_inode->i_size + offset;
89 break;
90 }
91 if (tmp < 0)
92 return -EINVAL;
93 if (tmp != file->f_pos) {
94 file->f_pos = tmp;
95 file->f_reada = 0;
96 file->f_version = ++event;
97 }
98 memcpy_tofs(result, &file->f_pos, sizeof(loff_t));
99 return 0;
100 }
101
102 asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
103 {
104 int error;
105 struct file * file;
106 struct inode * inode;
107
108 if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
109 return -EBADF;
110 if (!(file->f_mode & 1))
111 return -EBADF;
112 if (!file->f_op || !file->f_op->read)
113 return -EINVAL;
114 if (!count)
115 return 0;
116 error = verify_area(VERIFY_WRITE,buf,count);
117 if (error)
118 return error;
119 return file->f_op->read(inode,file,buf,count);
120 }
121
122 asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
123 {
124 int error;
125 struct file * file;
126 struct inode * inode;
127 int written;
128
129 if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
130 return -EBADF;
131 if (!(file->f_mode & 2))
132 return -EBADF;
133 if (!file->f_op || !file->f_op->write)
134 return -EINVAL;
135 if (!count)
136 return 0;
137 error = verify_area(VERIFY_READ,buf,count);
138 if (error)
139 return error;
140 written = file->f_op->write(inode,file,buf,count);
141
142
143
144
145 if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
146 struct iattr newattrs;
147 newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
148 newattrs.ia_valid = ATTR_MODE;
149 notify_change(inode, &newattrs);
150 }
151 return written;
152 }
153
154
155
156
157
158
159
160
161 asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long count)
162 {
163 int retval;
164 struct file * file;
165 struct inode * inode;
166
167 if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
168 return -EBADF;
169 if (!(file->f_mode & 1))
170 return -EBADF;
171 if (!file->f_op || !file->f_op->read)
172 return -EINVAL;
173 if (!count)
174 return 0;
175 retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
176 if (retval)
177 return retval;
178
179 while (count > 0) {
180 void * base;
181 int len, nr;
182
183 base = get_user(&vector->iov_base);
184 len = get_user(&vector->iov_len);
185 vector++;
186 count--;
187 nr = verify_area(VERIFY_WRITE, base, len);
188 if (!nr)
189 nr = file->f_op->read(inode, file, base, len);
190 if (nr < 0) {
191 if (retval)
192 return retval;
193 return nr;
194 }
195 retval += nr;
196 if (nr != len)
197 break;
198 }
199 return retval;
200 }
201
202 asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count)
203 {
204 int retval;
205 struct file * file;
206 struct inode * inode;
207
208 if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
209 return -EBADF;
210 if (!(file->f_mode & 2))
211 return -EBADF;
212 if (!file->f_op || !file->f_op->write)
213 return -EINVAL;
214 if (!count)
215 return 0;
216 retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
217 if (retval)
218 return retval;
219
220 while (count > 0) {
221 void * base;
222 int len, nr;
223
224 base = get_user(&vector->iov_base);
225 len = get_user(&vector->iov_len);
226 vector++;
227 count--;
228 nr = verify_area(VERIFY_READ, base, len);
229 if (!nr)
230 nr = file->f_op->write(inode, file, base, len);
231 if (nr < 0) {
232 if (retval)
233 return retval;
234 return nr;
235 }
236 retval += nr;
237 if (nr != len)
238 break;
239 }
240 return retval;
241 }