This source file includes following definitions.
- sys_lseek
- sys_llseek
- sys_read
- sys_write
- sock_readv_writev
- do_readv_writev
- 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/fcntl.h>
13 #include <linux/mm.h>
14 #include <linux/uio.h>
15
16 #include <asm/segment.h>
17
18 asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
19 {
20 struct file * file;
21 long tmp = -1;
22
23 if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
24 return -EBADF;
25 if (origin > 2)
26 return -EINVAL;
27 if (file->f_op && file->f_op->lseek)
28 return file->f_op->lseek(file->f_inode,file,offset,origin);
29
30
31 switch (origin) {
32 case 0:
33 tmp = offset;
34 break;
35 case 1:
36 tmp = file->f_pos + offset;
37 break;
38 case 2:
39 if (!file->f_inode)
40 return -EINVAL;
41 tmp = file->f_inode->i_size + offset;
42 break;
43 }
44 if (tmp < 0)
45 return -EINVAL;
46 if (tmp != file->f_pos) {
47 file->f_pos = tmp;
48 file->f_reada = 0;
49 file->f_version = ++event;
50 }
51 return file->f_pos;
52 }
53
54 asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
55 unsigned long offset_low, loff_t * result,
56 unsigned int origin)
57 {
58 struct file * file;
59 loff_t tmp = -1;
60 loff_t offset;
61 int err;
62
63 if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
64 return -EBADF;
65 if (origin > 2)
66 return -EINVAL;
67 if ((err = verify_area(VERIFY_WRITE, result, sizeof(loff_t))))
68 return err;
69 offset = (loff_t) (((unsigned long long) offset_high << 32) | offset_low);
70
71
72
73 if (file->f_op && file->f_op->lseek) {
74 if (offset != (long) offset)
75 return -EINVAL;
76 return file->f_op->lseek(file->f_inode,file,offset,origin);
77 }
78
79 switch (origin) {
80 case 0:
81 tmp = offset;
82 break;
83 case 1:
84 tmp = file->f_pos + offset;
85 break;
86 case 2:
87 if (!file->f_inode)
88 return -EINVAL;
89 tmp = file->f_inode->i_size + offset;
90 break;
91 }
92 if (tmp < 0)
93 return -EINVAL;
94 if (tmp != file->f_pos) {
95 file->f_pos = tmp;
96 file->f_reada = 0;
97 file->f_version = ++event;
98 }
99 memcpy_tofs(result, &file->f_pos, sizeof(loff_t));
100 return 0;
101 }
102
103 asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
104 {
105 int error;
106 struct file * file;
107 struct inode * inode;
108
109 if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
110 return -EBADF;
111 if (!(file->f_mode & 1))
112 return -EBADF;
113 if (!file->f_op || !file->f_op->read)
114 return -EINVAL;
115 if (!count)
116 return 0;
117 error = locks_verify_area(FLOCK_VERIFY_READ,inode,file,file->f_pos,count);
118 if (error)
119 return error;
120 error = verify_area(VERIFY_WRITE,buf,count);
121 if (error)
122 return error;
123 return file->f_op->read(inode,file,buf,count);
124 }
125
126 asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
127 {
128 int error;
129 struct file * file;
130 struct inode * inode;
131 int written;
132
133 if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
134 return -EBADF;
135 if (!(file->f_mode & 2))
136 return -EBADF;
137 if (!file->f_op || !file->f_op->write)
138 return -EINVAL;
139 if (!count)
140 return 0;
141 error = locks_verify_area(FLOCK_VERIFY_WRITE,inode,file,file->f_pos,count);
142 if (error)
143 return error;
144 error = verify_area(VERIFY_READ,buf,count);
145 if (error)
146 return error;
147
148
149
150
151
152
153
154 if (!suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
155 struct iattr newattrs;
156
157
158
159
160 newattrs.ia_mode = inode->i_mode &
161 ~(S_ISUID | ((inode->i_mode & S_IXGRP) ? S_ISGID : 0));
162 newattrs.ia_valid = ATTR_CTIME | ATTR_MODE | ATTR_FORCE;
163 notify_change(inode, &newattrs);
164 }
165
166 down(&inode->i_sem);
167 written = file->f_op->write(inode,file,buf,count);
168 up(&inode->i_sem);
169 return written;
170 }
171
172 static int sock_readv_writev(int type, struct inode * inode, struct file * file,
173 const struct iovec * iov, long count, long size)
174 {
175 struct msghdr msg;
176 struct socket *sock;
177
178 sock = &inode->u.socket_i;
179 if (!sock->ops)
180 return -EOPNOTSUPP;
181 msg.msg_name = NULL;
182 msg.msg_namelen = 0;
183 msg.msg_accrights = NULL;
184 msg.msg_iov = (struct iovec *) iov;
185 msg.msg_iovlen = count;
186
187
188 if (type == VERIFY_WRITE) {
189 if (!sock->ops->recvmsg)
190 return -EOPNOTSUPP;
191 return sock->ops->recvmsg(sock, &msg, size,
192 (file->f_flags & O_NONBLOCK), 0, NULL);
193 }
194 if (!sock->ops->sendmsg)
195 return -EOPNOTSUPP;
196 return sock->ops->sendmsg(sock, &msg, size,
197 (file->f_flags & O_NONBLOCK), 0);
198 }
199
200 typedef int (*IO_fn_t)(struct inode *, struct file *, char *, int);
201
202 static int do_readv_writev(int type, struct inode * inode, struct file * file,
203 const struct iovec * vector, unsigned long count)
204 {
205 size_t tot_len;
206 struct iovec iov[MAX_IOVEC];
207 int retval, i;
208 IO_fn_t fn;
209
210
211
212
213
214 if (!count)
215 return 0;
216 if (count > MAX_IOVEC)
217 return -EINVAL;
218 retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
219 if (retval)
220 return retval;
221 memcpy_fromfs(iov, vector, count*sizeof(*vector));
222 tot_len = 0;
223 for (i = 0 ; i < count ; i++) {
224 tot_len += iov[i].iov_len;
225 retval = verify_area(type, iov[i].iov_base, iov[i].iov_len);
226 if (retval)
227 return retval;
228 }
229
230 retval = locks_verify_area(type == VERIFY_READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
231 inode, file, file->f_pos, tot_len);
232 if (retval)
233 return retval;
234
235
236
237
238
239
240 if (inode->i_sock)
241 return sock_readv_writev(type, inode, file, iov, count, tot_len);
242
243 if (!file->f_op)
244 return -EINVAL;
245
246 fn = file->f_op->read;
247 if (type == VERIFY_READ)
248 fn = (IO_fn_t) file->f_op->write;
249 vector = iov;
250 while (count > 0) {
251 void * base;
252 int len, nr;
253
254 base = vector->iov_base;
255 len = vector->iov_len;
256 vector++;
257 count--;
258 nr = fn(inode, file, base, len);
259 if (nr < 0) {
260 if (retval)
261 break;
262 retval = nr;
263 break;
264 }
265 retval += nr;
266 if (nr != len)
267 break;
268 }
269 return retval;
270 }
271
272 asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long count)
273 {
274 struct file * file;
275 struct inode * inode;
276
277 if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
278 return -EBADF;
279 if (!(file->f_mode & 1))
280 return -EBADF;
281 return do_readv_writev(VERIFY_WRITE, inode, file, vector, count);
282 }
283
284 asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count)
285 {
286 int error;
287 struct file * file;
288 struct inode * inode;
289
290 if (fd >= NR_OPEN || !(file = current->files->fd[fd]) || !(inode = file->f_inode))
291 return -EBADF;
292 if (!(file->f_mode & 2))
293 return -EBADF;
294 down(&inode->i_sem);
295 error = do_readv_writev(VERIFY_READ, inode, file, vector, count);
296 up(&inode->i_sem);
297 return error;
298 }