Replace extern inline with static inline.
[linux-2.6/linux-mips.git] / fs / read_write.c
blob12dea3752b7a692fbe0fef4b880d57ee7a11541b
1 /*
2 * linux/fs/read_write.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/slab.h>
8 #include <linux/stat.h>
9 #include <linux/fcntl.h>
10 #include <linux/file.h>
11 #include <linux/uio.h>
12 #include <linux/smp_lock.h>
13 #include <linux/dnotify.h>
14 #include <linux/security.h>
15 #include <linux/module.h>
17 #include <asm/uaccess.h>
19 struct file_operations generic_ro_fops = {
20 .llseek = generic_file_llseek,
21 .read = generic_file_read,
22 .mmap = generic_file_readonly_mmap,
23 .sendfile = generic_file_sendfile,
26 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
28 long long retval;
29 struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
31 down(&inode->i_sem);
32 switch (origin) {
33 case 2:
34 offset += inode->i_size;
35 break;
36 case 1:
37 offset += file->f_pos;
39 retval = -EINVAL;
40 if (offset>=0 && offset<=inode->i_sb->s_maxbytes) {
41 if (offset != file->f_pos) {
42 file->f_pos = offset;
43 file->f_version = 0;
45 retval = offset;
47 up(&inode->i_sem);
48 return retval;
51 loff_t remote_llseek(struct file *file, loff_t offset, int origin)
53 long long retval;
55 lock_kernel();
56 switch (origin) {
57 case 2:
58 offset += i_size_read(file->f_dentry->d_inode);
59 break;
60 case 1:
61 offset += file->f_pos;
63 retval = -EINVAL;
64 if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) {
65 if (offset != file->f_pos) {
66 file->f_pos = offset;
67 file->f_version = 0;
69 retval = offset;
71 unlock_kernel();
72 return retval;
75 loff_t no_llseek(struct file *file, loff_t offset, int origin)
77 return -ESPIPE;
80 loff_t default_llseek(struct file *file, loff_t offset, int origin)
82 long long retval;
84 lock_kernel();
85 switch (origin) {
86 case 2:
87 offset += i_size_read(file->f_dentry->d_inode);
88 break;
89 case 1:
90 offset += file->f_pos;
92 retval = -EINVAL;
93 if (offset >= 0) {
94 if (offset != file->f_pos) {
95 file->f_pos = offset;
96 file->f_version = 0;
98 retval = offset;
100 unlock_kernel();
101 return retval;
104 static inline loff_t llseek(struct file *file, loff_t offset, int origin)
106 loff_t (*fn)(struct file *, loff_t, int);
108 fn = default_llseek;
109 if (file->f_op && file->f_op->llseek)
110 fn = file->f_op->llseek;
111 return fn(file, offset, origin);
114 asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
116 off_t retval;
117 struct file * file;
118 int fput_needed;
120 retval = -EBADF;
121 file = fget_light(fd, &fput_needed);
122 if (!file)
123 goto bad;
125 retval = -EINVAL;
126 if (origin <= 2) {
127 loff_t res = llseek(file, offset, origin);
128 retval = res;
129 if (res != (loff_t)retval)
130 retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */
132 fput_light(file, fput_needed);
133 bad:
134 return retval;
137 #if !defined(__alpha__)
138 asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
139 unsigned long offset_low, loff_t __user * result,
140 unsigned int origin)
142 int retval;
143 struct file * file;
144 loff_t offset;
145 int fput_needed;
147 retval = -EBADF;
148 file = fget_light(fd, &fput_needed);
149 if (!file)
150 goto bad;
152 retval = -EINVAL;
153 if (origin > 2)
154 goto out_putf;
156 offset = llseek(file, ((loff_t) offset_high << 32) | offset_low,
157 origin);
159 retval = (int)offset;
160 if (offset >= 0) {
161 retval = -EFAULT;
162 if (!copy_to_user(result, &offset, sizeof(offset)))
163 retval = 0;
165 out_putf:
166 fput_light(file, fput_needed);
167 bad:
168 return retval;
170 #endif
172 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
174 struct kiocb kiocb;
175 ssize_t ret;
177 init_sync_kiocb(&kiocb, filp);
178 kiocb.ki_pos = *ppos;
179 ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos);
180 if (-EIOCBQUEUED == ret)
181 ret = wait_on_sync_kiocb(&kiocb);
182 *ppos = kiocb.ki_pos;
183 return ret;
186 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
188 struct inode *inode = file->f_dentry->d_inode;
189 ssize_t ret;
191 if (!(file->f_mode & FMODE_READ))
192 return -EBADF;
193 if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
194 return -EINVAL;
196 ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
197 if (!ret) {
198 ret = security_file_permission (file, MAY_READ);
199 if (!ret) {
200 if (file->f_op->read)
201 ret = file->f_op->read(file, buf, count, pos);
202 else
203 ret = do_sync_read(file, buf, count, pos);
204 if (ret > 0)
205 dnotify_parent(file->f_dentry, DN_ACCESS);
209 return ret;
212 ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
214 struct kiocb kiocb;
215 ssize_t ret;
217 init_sync_kiocb(&kiocb, filp);
218 kiocb.ki_pos = *ppos;
219 ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos);
220 if (-EIOCBQUEUED == ret)
221 ret = wait_on_sync_kiocb(&kiocb);
222 *ppos = kiocb.ki_pos;
223 return ret;
226 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
228 struct inode *inode = file->f_dentry->d_inode;
229 ssize_t ret;
231 if (!(file->f_mode & FMODE_WRITE))
232 return -EBADF;
233 if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
234 return -EINVAL;
236 ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
237 if (!ret) {
238 ret = security_file_permission (file, MAY_WRITE);
239 if (!ret) {
240 if (file->f_op->write)
241 ret = file->f_op->write(file, buf, count, pos);
242 else
243 ret = do_sync_write(file, buf, count, pos);
244 if (ret > 0)
245 dnotify_parent(file->f_dentry, DN_MODIFY);
249 return ret;
252 asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
254 struct file *file;
255 ssize_t ret = -EBADF;
256 int fput_needed;
258 file = fget_light(fd, &fput_needed);
259 if (file) {
260 ret = vfs_read(file, buf, count, &file->f_pos);
261 fput_light(file, fput_needed);
264 return ret;
267 asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count)
269 struct file *file;
270 ssize_t ret = -EBADF;
271 int fput_needed;
273 file = fget_light(fd, &fput_needed);
274 if (file) {
275 ret = vfs_write(file, buf, count, &file->f_pos);
276 fput_light(file, fput_needed);
279 return ret;
282 asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf,
283 size_t count, loff_t pos)
285 struct file *file;
286 ssize_t ret = -EBADF;
287 int fput_needed;
289 if (pos < 0)
290 return -EINVAL;
292 file = fget_light(fd, &fput_needed);
293 if (file) {
294 ret = vfs_read(file, buf, count, &pos);
295 fput_light(file, fput_needed);
298 return ret;
301 asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf,
302 size_t count, loff_t pos)
304 struct file *file;
305 ssize_t ret = -EBADF;
306 int fput_needed;
308 if (pos < 0)
309 return -EINVAL;
311 file = fget_light(fd, &fput_needed);
312 if (file) {
313 ret = vfs_write(file, buf, count, &pos);
314 fput_light(file, fput_needed);
317 return ret;
321 * Reduce an iovec's length in-place. Return the resulting number of segments
323 unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
325 unsigned long seg = 0;
326 size_t len = 0;
328 while (seg < nr_segs) {
329 seg++;
330 if (len + iov->iov_len >= to) {
331 iov->iov_len = to - len;
332 break;
334 len += iov->iov_len;
335 iov++;
337 return seg;
340 static ssize_t do_readv_writev(int type, struct file *file,
341 const struct iovec __user * uvector,
342 unsigned long nr_segs, loff_t *pos)
344 typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *);
345 typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
347 size_t tot_len;
348 struct iovec iovstack[UIO_FASTIOV];
349 struct iovec *iov=iovstack, *vector;
350 ssize_t ret;
351 int seg;
352 io_fn_t fn;
353 iov_fn_t fnv;
354 struct inode *inode;
357 * SuS says "The readv() function *may* fail if the iovcnt argument
358 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has
359 * traditionally returned zero for zero segments, so...
361 ret = 0;
362 if (nr_segs == 0)
363 goto out;
366 * First get the "struct iovec" from user memory and
367 * verify all the pointers
369 ret = -EINVAL;
370 if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
371 goto out;
372 if (!file->f_op)
373 goto out;
374 if (nr_segs > UIO_FASTIOV) {
375 ret = -ENOMEM;
376 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
377 if (!iov)
378 goto out;
380 ret = -EFAULT;
381 if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector)))
382 goto out;
385 * Single unix specification:
386 * We should -EINVAL if an element length is not >= 0 and fitting an
387 * ssize_t. The total length is fitting an ssize_t
389 * Be careful here because iov_len is a size_t not an ssize_t
391 tot_len = 0;
392 ret = -EINVAL;
393 for (seg = 0 ; seg < nr_segs; seg++) {
394 ssize_t tmp = tot_len;
395 ssize_t len = (ssize_t)iov[seg].iov_len;
396 if (len < 0) /* size_t not fitting an ssize_t .. */
397 goto out;
398 tot_len += len;
399 if (tot_len < tmp) /* maths overflow on the ssize_t */
400 goto out;
402 if (tot_len == 0) {
403 ret = 0;
404 goto out;
407 inode = file->f_dentry->d_inode;
408 /* VERIFY_WRITE actually means a read, as we write to user space */
409 ret = locks_verify_area((type == READ
410 ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
411 inode, file, *pos, tot_len);
412 if (ret)
413 goto out;
415 fnv = NULL;
416 if (type == READ) {
417 fn = file->f_op->read;
418 fnv = file->f_op->readv;
419 } else {
420 fn = (io_fn_t)file->f_op->write;
421 fnv = file->f_op->writev;
423 if (fnv) {
424 ret = fnv(file, iov, nr_segs, pos);
425 goto out;
428 /* Do it by hand, with file-ops */
429 ret = 0;
430 vector = iov;
431 while (nr_segs > 0) {
432 void __user * base;
433 size_t len;
434 ssize_t nr;
436 base = vector->iov_base;
437 len = vector->iov_len;
438 vector++;
439 nr_segs--;
441 nr = fn(file, base, len, pos);
443 if (nr < 0) {
444 if (!ret) ret = nr;
445 break;
447 ret += nr;
448 if (nr != len)
449 break;
451 out:
452 if (iov != iovstack)
453 kfree(iov);
454 if ((ret + (type == READ)) > 0)
455 dnotify_parent(file->f_dentry,
456 (type == READ) ? DN_ACCESS : DN_MODIFY);
457 return ret;
460 ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
461 unsigned long vlen, loff_t *pos)
463 if (!(file->f_mode & FMODE_READ))
464 return -EBADF;
465 if (!file->f_op || (!file->f_op->readv && !file->f_op->read))
466 return -EINVAL;
468 return do_readv_writev(READ, file, vec, vlen, pos);
471 ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
472 unsigned long vlen, loff_t *pos)
474 if (!(file->f_mode & FMODE_WRITE))
475 return -EBADF;
476 if (!file->f_op || (!file->f_op->writev && !file->f_op->write))
477 return -EINVAL;
479 return do_readv_writev(WRITE, file, vec, vlen, pos);
483 asmlinkage ssize_t
484 sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
486 struct file *file;
487 ssize_t ret = -EBADF;
488 int fput_needed;
490 file = fget_light(fd, &fput_needed);
491 if (file) {
492 ret = vfs_readv(file, vec, vlen, &file->f_pos);
493 fput_light(file, fput_needed);
496 return ret;
499 asmlinkage ssize_t
500 sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen)
502 struct file *file;
503 ssize_t ret = -EBADF;
504 int fput_needed;
506 file = fget_light(fd, &fput_needed);
507 if (file) {
508 ret = vfs_writev(file, vec, vlen, &file->f_pos);
509 fput_light(file, fput_needed);
512 return ret;
515 static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
516 size_t count, loff_t max)
518 struct file * in_file, * out_file;
519 struct inode * in_inode, * out_inode;
520 loff_t pos;
521 ssize_t retval;
522 int fput_needed_in, fput_needed_out;
525 * Get input file, and verify that it is ok..
527 retval = -EBADF;
528 in_file = fget_light(in_fd, &fput_needed_in);
529 if (!in_file)
530 goto out;
531 if (!(in_file->f_mode & FMODE_READ))
532 goto fput_in;
533 retval = -EINVAL;
534 in_inode = in_file->f_dentry->d_inode;
535 if (!in_inode)
536 goto fput_in;
537 if (!in_file->f_op || !in_file->f_op->sendfile)
538 goto fput_in;
539 retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count);
540 if (retval)
541 goto fput_in;
543 retval = security_file_permission (in_file, MAY_READ);
544 if (retval)
545 goto fput_in;
548 * Get output file, and verify that it is ok..
550 retval = -EBADF;
551 out_file = fget_light(out_fd, &fput_needed_out);
552 if (!out_file)
553 goto fput_in;
554 if (!(out_file->f_mode & FMODE_WRITE))
555 goto fput_out;
556 retval = -EINVAL;
557 if (!out_file->f_op || !out_file->f_op->sendpage)
558 goto fput_out;
559 out_inode = out_file->f_dentry->d_inode;
560 retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count);
561 if (retval)
562 goto fput_out;
564 retval = security_file_permission (out_file, MAY_WRITE);
565 if (retval)
566 goto fput_out;
568 if (!ppos)
569 ppos = &in_file->f_pos;
571 if (!max)
572 max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
574 pos = *ppos;
575 retval = -EINVAL;
576 if (unlikely(pos < 0))
577 goto fput_out;
578 if (unlikely(pos + count > max)) {
579 retval = -EOVERFLOW;
580 if (pos >= max)
581 goto fput_out;
582 count = max - pos;
585 retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
587 if (*ppos > max)
588 retval = -EOVERFLOW;
590 fput_out:
591 fput_light(out_file, fput_needed_out);
592 fput_in:
593 fput_light(in_file, fput_needed_in);
594 out:
595 return retval;
598 asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t __user *offset, size_t count)
600 loff_t pos;
601 off_t off;
602 ssize_t ret;
604 if (offset) {
605 if (unlikely(get_user(off, offset)))
606 return -EFAULT;
607 pos = off;
608 ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
609 if (unlikely(put_user(pos, offset)))
610 return -EFAULT;
611 return ret;
614 return do_sendfile(out_fd, in_fd, NULL, count, MAX_NON_LFS);
617 asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t __user *offset, size_t count)
619 loff_t pos;
620 ssize_t ret;
622 if (offset) {
623 if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
624 return -EFAULT;
625 ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
626 if (unlikely(put_user(pos, offset)))
627 return -EFAULT;
628 return ret;
631 return do_sendfile(out_fd, in_fd, NULL, count, 0);
634 EXPORT_SYMBOL(do_sync_read);
635 EXPORT_SYMBOL(do_sync_write);