1 /* 2 * linux/fs/read_write.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 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/fsnotify.h> 14 #include <linux/security.h> 15 #include <linux/module.h> 16 #include <linux/syscalls.h> 17 #include <linux/pagemap.h> 18 #include <linux/splice.h> 19 #include "read_write.h" 20 21 #include <asm/uaccess.h> 22 #include <asm/unistd.h> 23 24 const struct file_operations generic_ro_fops = { 25 .llseek = generic_file_llseek, 26 .read = do_sync_read, 27 .aio_read = generic_file_aio_read, 28 .mmap = generic_file_readonly_mmap, 29 .splice_read = generic_file_splice_read, 30 }; 31 32 EXPORT_SYMBOL(generic_ro_fops); 33 34 loff_t 35 generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin) 36 { 37 loff_t retval; 38 struct inode *inode = file->f_mapping->host; 39 40 switch (origin) { 41 case SEEK_END: 42 offset += inode->i_size; 43 break; 44 case SEEK_CUR: 45 offset += file->f_pos; 46 } 47 retval = -EINVAL; 48 if (offset>=0 && offset<=inode->i_sb->s_maxbytes) { 49 /* Special lock needed here? */ 50 if (offset != file->f_pos) { 51 file->f_pos = offset; 52 file->f_version = 0; 53 } 54 retval = offset; 55 } 56 return retval; 57 } 58 EXPORT_SYMBOL(generic_file_llseek_unlocked); 59 60 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) 61 { 62 loff_t n; 63 mutex_lock(&file->f_dentry->d_inode->i_mutex); 64 n = generic_file_llseek_unlocked(file, offset, origin); 65 mutex_unlock(&file->f_dentry->d_inode->i_mutex); 66 return n; 67 } 68 EXPORT_SYMBOL(generic_file_llseek); 69 70 loff_t no_llseek(struct file *file, loff_t offset, int origin) 71 { 72 return -ESPIPE; 73 } 74 EXPORT_SYMBOL(no_llseek); 75 76 loff_t default_llseek(struct file *file, loff_t offset, int origin) 77 { 78 loff_t retval; 79 80 lock_kernel(); 81 switch (origin) { 82 case SEEK_END: 83 offset += i_size_read(file->f_path.dentry->d_inode); 84 break; 85 case SEEK_CUR: 86 offset += file->f_pos; 87 } 88 retval = -EINVAL; 89 if (offset >= 0) { 90 if (offset != file->f_pos) { 91 file->f_pos = offset; 92 file->f_version = 0; 93 } 94 retval = offset; 95 } 96 unlock_kernel(); 97 return retval; 98 } 99 EXPORT_SYMBOL(default_llseek); 100 101 loff_t vfs_llseek(struct file *file, loff_t offset, int origin) 102 { 103 loff_t (*fn)(struct file *, loff_t, int); 104 105 fn = no_llseek; 106 if (file->f_mode & FMODE_LSEEK) { 107 fn = default_llseek; 108 if (file->f_op && file->f_op->llseek) 109 fn = file->f_op->llseek; 110 } 111 return fn(file, offset, origin); 112 } 113 EXPORT_SYMBOL(vfs_llseek); 114 115 asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin) 116 { 117 off_t retval; 118 struct file * file; 119 int fput_needed; 120 121 retval = -EBADF; 122 file = fget_light(fd, &fput_needed); 123 if (!file) 124 goto bad; 125 126 retval = -EINVAL; 127 if (origin <= SEEK_MAX) { 128 loff_t res = vfs_llseek(file, offset, origin); 129 retval = res; 130 if (res != (loff_t)retval) 131 retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ 132 } 133 fput_light(file, fput_needed); 134 bad: 135 return retval; 136 } 137 138 #ifdef __ARCH_WANT_SYS_LLSEEK 139 asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, 140 unsigned long offset_low, loff_t __user * result, 141 unsigned int origin) 142 { 143 int retval; 144 struct file * file; 145 loff_t offset; 146 int fput_needed; 147 148 retval = -EBADF; 149 file = fget_light(fd, &fput_needed); 150 if (!file) 151 goto bad; 152 153 retval = -EINVAL; 154 if (origin > SEEK_MAX) 155 goto out_putf; 156 157 offset = vfs_llseek(file, ((loff_t) offset_high << 32) | offset_low, 158 origin); 159 160 retval = (int)offset; 161 if (offset >= 0) { 162 retval = -EFAULT; 163 if (!copy_to_user(result, &offset, sizeof(offset))) 164 retval = 0; 165 } 166 out_putf: 167 fput_light(file, fput_needed); 168 bad: 169 return retval; 170 } 171 #endif 172 173 /* 174 * rw_verify_area doesn't like huge counts. We limit 175 * them to something that fits in "int" so that others 176 * won't have to do range checks all the time. 177 */ 178 #define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK) 179 180 int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count) 181 { 182 struct inode *inode; 183 loff_t pos; 184 int retval = -EINVAL; 185 186 inode = file->f_path.dentry->d_inode; 187 if (unlikely((ssize_t) count < 0)) 188 return retval; 189 pos = *ppos; 190 if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) 191 return retval; 192 193 if (unlikely(inode->i_flock && mandatory_lock(inode))) { 194 retval = locks_mandatory_area( 195 read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, 196 inode, file, pos, count); 197 if (retval < 0) 198 return retval; 199 } 200 retval = security_file_permission(file, 201 read_write == READ ? MAY_READ : MAY_WRITE); 202 if (retval) 203 return retval; 204 return count > MAX_RW_COUNT ? MAX_RW_COUNT : count; 205 } 206 207 static void wait_on_retry_sync_kiocb(struct kiocb *iocb) 208 { 209 set_current_state(TASK_UNINTERRUPTIBLE); 210 if (!kiocbIsKicked(iocb)) 211 schedule(); 212 else 213 kiocbClearKicked(iocb); 214 __set_current_state(TASK_RUNNING); 215 } 216 217 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) 218 { 219 struct iovec iov = { .iov_base = buf, .iov_len = len }; 220 struct kiocb kiocb; 221 ssize_t ret; 222 223 init_sync_kiocb(&kiocb, filp); 224 kiocb.ki_pos = *ppos; 225 kiocb.ki_left = len; 226 227 for (;;) { 228 ret = filp->f_op->aio_read(&kiocb, &iov, 1, kiocb.ki_pos); 229 if (ret != -EIOCBRETRY) 230 break; 231 wait_on_retry_sync_kiocb(&kiocb); 232 } 233 234 if (-EIOCBQUEUED == ret) 235 ret = wait_on_sync_kiocb(&kiocb); 236 *ppos = kiocb.ki_pos; 237 return ret; 238 } 239 240 EXPORT_SYMBOL(do_sync_read); 241 242 ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) 243 { 244 ssize_t ret; 245 246 if (!(file->f_mode & FMODE_READ)) 247 return -EBADF; 248 if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)) 249 return -EINVAL; 250 if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) 251 return -EFAULT; 252 253 ret = rw_verify_area(READ, file, pos, count); 254 if (ret >= 0) { 255 count = ret; 256 if (file->f_op->read) 257 ret = file->f_op->read(file, buf, count, pos); 258 else 259 ret = do_sync_read(file, buf, count, pos); 260 if (ret > 0) { 261 fsnotify_access(file->f_path.dentry); 262 add_rchar(current, ret); 263 } 264 inc_syscr(current); 265 } 266 267 return ret; 268 } 269 270 EXPORT_SYMBOL(vfs_read); 271 272 ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) 273 { 274 struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; 275 struct kiocb kiocb; 276 ssize_t ret; 277 278 init_sync_kiocb(&kiocb, filp); 279 kiocb.ki_pos = *ppos; 280 kiocb.ki_left = len; 281 282 for (;;) { 283 ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); 284 if (ret != -EIOCBRETRY) 285 break; 286 wait_on_retry_sync_kiocb(&kiocb); 287 } 288 289 if (-EIOCBQUEUED == ret) 290 ret = wait_on_sync_kiocb(&kiocb); 291 *ppos = kiocb.ki_pos; 292 return ret; 293 } 294 295 EXPORT_SYMBOL(do_sync_write); 296 297 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) 298 { 299 ssize_t ret; 300 301 if (!(file->f_mode & FMODE_WRITE)) 302 return -EBADF; 303 if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write)) 304 return -EINVAL; 305 if (unlikely(!access_ok(VERIFY_READ, buf, count))) 306 return -EFAULT; 307 308 ret = rw_verify_area(WRITE, file, pos, count); 309 if (ret >= 0) { 310 count = ret; 311 if (file->f_op->write) 312 ret = file->f_op->write(file, buf, count, pos); 313 else 314 ret = do_sync_write(file, buf, count, pos); 315 if (ret > 0) { 316 fsnotify_modify(file->f_path.dentry); 317 add_wchar(current, ret); 318 } 319 inc_syscw(current); 320 } 321 322 return ret; 323 } 324 325 EXPORT_SYMBOL(vfs_write); 326 327 static inline loff_t file_pos_read(struct file *file) 328 { 329 return file->f_pos; 330 } 331 332 static inline void file_pos_write(struct file *file, loff_t pos) 333 { 334 file->f_pos = pos; 335 } 336 337 asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) 338 { 339 struct file *file; 340 ssize_t ret = -EBADF; 341 int fput_needed; 342 343 file = fget_light(fd, &fput_needed); 344 if (file) { 345 loff_t pos = file_pos_read(file); 346 ret = vfs_read(file, buf, count, &pos); 347 file_pos_write(file, pos); 348 fput_light(file, fput_needed); 349 } 350 351 return ret; 352 } 353 354 asmlinkage ssize_t sys_write(unsigned int fd, const char __user * buf, size_t count) 355 { 356 struct file *file; 357 ssize_t ret = -EBADF; 358 int fput_needed; 359 360 file = fget_light(fd, &fput_needed); 361 if (file) { 362 loff_t pos = file_pos_read(file); 363 ret = vfs_write(file, buf, count, &pos); 364 file_pos_write(file, pos); 365 fput_light(file, fput_needed); 366 } 367 368 return ret; 369 } 370 371 asmlinkage ssize_t sys_pread64(unsigned int fd, char __user *buf, 372 size_t count, loff_t pos) 373 { 374 struct file *file; 375 ssize_t ret = -EBADF; 376 int fput_needed; 377 378 if (pos < 0) 379 return -EINVAL; 380 381 file = fget_light(fd, &fput_needed); 382 if (file) { 383 ret = -ESPIPE; 384 if (file->f_mode & FMODE_PREAD) 385 ret = vfs_read(file, buf, count, &pos); 386 fput_light(file, fput_needed); 387 } 388 389 return ret; 390 } 391 392 asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char __user *buf, 393 size_t count, loff_t pos) 394 { 395 struct file *file; 396 ssize_t ret = -EBADF; 397 int fput_needed; 398 399 if (pos < 0) 400 return -EINVAL; 401 402 file = fget_light(fd, &fput_needed); 403 if (file) { 404 ret = -ESPIPE; 405 if (file->f_mode & FMODE_PWRITE) 406 ret = vfs_write(file, buf, count, &pos); 407 fput_light(file, fput_needed); 408 } 409 410 return ret; 411 } 412 413 /* 414 * Reduce an iovec's length in-place. Return the resulting number of segments 415 */ 416 unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) 417 { 418 unsigned long seg = 0; 419 size_t len = 0; 420 421 while (seg < nr_segs) { 422 seg++; 423 if (len + iov->iov_len >= to) { 424 iov->iov_len = to - len; 425 break; 426 } 427 len += iov->iov_len; 428 iov++; 429 } 430 return seg; 431 } 432 EXPORT_SYMBOL(iov_shorten); 433 434 ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, 435 unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) 436 { 437 struct kiocb kiocb; 438 ssize_t ret; 439 440 init_sync_kiocb(&kiocb, filp); 441 kiocb.ki_pos = *ppos; 442 kiocb.ki_left = len; 443 kiocb.ki_nbytes = len; 444 445 for (;;) { 446 ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos); 447 if (ret != -EIOCBRETRY) 448 break; 449 wait_on_retry_sync_kiocb(&kiocb); 450 } 451 452 if (ret == -EIOCBQUEUED) 453 ret = wait_on_sync_kiocb(&kiocb); 454 *ppos = kiocb.ki_pos; 455 return ret; 456 } 457 458 /* Do it by hand, with file-ops */ 459 ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, 460 unsigned long nr_segs, loff_t *ppos, io_fn_t fn) 461 { 462 struct iovec *vector = iov; 463 ssize_t ret = 0; 464 465 while (nr_segs > 0) { 466 void __user *base; 467 size_t len; 468 ssize_t nr; 469 470 base = vector->iov_base; 471 len = vector->iov_len; 472 vector++; 473 nr_segs--; 474 475 nr = fn(filp, base, len, ppos); 476 477 if (nr < 0) { 478 if (!ret) 479 ret = nr; 480 break; 481 } 482 ret += nr; 483 if (nr != len) 484 break; 485 } 486 487 return ret; 488 } 489 490 /* A write operation does a read from user space and vice versa */ 491 #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ) 492 493 ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, 494 unsigned long nr_segs, unsigned long fast_segs, 495 struct iovec *fast_pointer, 496 struct iovec **ret_pointer) 497 { 498 unsigned long seg; 499 ssize_t ret; 500 struct iovec *iov = fast_pointer; 501 502 /* 503 * SuS says "The readv() function *may* fail if the iovcnt argument 504 * was less than or equal to 0, or greater than {IOV_MAX}. Linux has 505 * traditionally returned zero for zero segments, so... 506 */ 507 if (nr_segs == 0) { 508 ret = 0; 509 goto out; 510 } 511 512 /* 513 * First get the "struct iovec" from user memory and 514 * verify all the pointers 515 */ 516 if (nr_segs > UIO_MAXIOV) { 517 ret = -EINVAL; 518 goto out; 519 } 520 if (nr_segs > fast_segs) { 521 iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); 522 if (iov == NULL) { 523 ret = -ENOMEM; 524 goto out; 525 } 526 } 527 if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) { 528 ret = -EFAULT; 529 goto out; 530 } 531 532 /* 533 * According to the Single Unix Specification we should return EINVAL 534 * if an element length is < 0 when cast to ssize_t or if the 535 * total length would overflow the ssize_t return value of the 536 * system call. 537 */ 538 ret = 0; 539 for (seg = 0; seg < nr_segs; seg++) { 540 void __user *buf = iov[seg].iov_base; 541 ssize_t len = (ssize_t)iov[seg].iov_len; 542 543 /* see if we we're about to use an invalid len or if 544 * it's about to overflow ssize_t */ 545 if (len < 0 || (ret + len < ret)) { 546 ret = -EINVAL; 547 goto out; 548 } 549 if (unlikely(!access_ok(vrfy_dir(type), buf, len))) { 550 ret = -EFAULT; 551 goto out; 552 } 553 554 ret += len; 555 } 556 out: 557 *ret_pointer = iov; 558 return ret; 559 } 560 561 static ssize_t do_readv_writev(int type, struct file *file, 562 const struct iovec __user * uvector, 563 unsigned long nr_segs, loff_t *pos) 564 { 565 size_t tot_len; 566 struct iovec iovstack[UIO_FASTIOV]; 567 struct iovec *iov = iovstack; 568 ssize_t ret; 569 io_fn_t fn; 570 iov_fn_t fnv; 571 572 if (!file->f_op) { 573 ret = -EINVAL; 574 goto out; 575 } 576 577 ret = rw_copy_check_uvector(type, uvector, nr_segs, 578 ARRAY_SIZE(iovstack), iovstack, &iov); 579 if (ret <= 0) 580 goto out; 581 582 tot_len = ret; 583 ret = rw_verify_area(type, file, pos, tot_len); 584 if (ret < 0) 585 goto out; 586 587 fnv = NULL; 588 if (type == READ) { 589 fn = file->f_op->read; 590 fnv = file->f_op->aio_read; 591 } else { 592 fn = (io_fn_t)file->f_op->write; 593 fnv = file->f_op->aio_write; 594 } 595 596 if (fnv) 597 ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, 598 pos, fnv); 599 else 600 ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); 601 602 out: 603 if (iov != iovstack) 604 kfree(iov); 605 if ((ret + (type == READ)) > 0) { 606 if (type == READ) 607 fsnotify_access(file->f_path.dentry); 608 else 609 fsnotify_modify(file->f_path.dentry); 610 } 611 return ret; 612 } 613 614 ssize_t vfs_readv(struct file *file, const struct iovec __user *vec, 615 unsigned long vlen, loff_t *pos) 616 { 617 if (!(file->f_mode & FMODE_READ)) 618 return -EBADF; 619 if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) 620 return -EINVAL; 621 622 return do_readv_writev(READ, file, vec, vlen, pos); 623 } 624 625 EXPORT_SYMBOL(vfs_readv); 626 627 ssize_t vfs_writev(struct file *file, const struct iovec __user *vec, 628 unsigned long vlen, loff_t *pos) 629 { 630 if (!(file->f_mode & FMODE_WRITE)) 631 return -EBADF; 632 if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) 633 return -EINVAL; 634 635 return do_readv_writev(WRITE, file, vec, vlen, pos); 636 } 637 638 EXPORT_SYMBOL(vfs_writev); 639 640 asmlinkage ssize_t 641 sys_readv(unsigned long fd, const struct iovec __user *vec, unsigned long vlen) 642 { 643 struct file *file; 644 ssize_t ret = -EBADF; 645 int fput_needed; 646 647 file = fget_light(fd, &fput_needed); 648 if (file) { 649 loff_t pos = file_pos_read(file); 650 ret = vfs_readv(file, vec, vlen, &pos); 651 file_pos_write(file, pos); 652 fput_light(file, fput_needed); 653 } 654 655 if (ret > 0) 656 add_rchar(current, ret); 657 inc_syscr(current); 658 return ret; 659 } 660 661 asmlinkage ssize_t 662 sys_writev(unsigned long fd, const struct iovec __user *vec, unsigned long vlen) 663 { 664 struct file *file; 665 ssize_t ret = -EBADF; 666 int fput_needed; 667 668 file = fget_light(fd, &fput_needed); 669 if (file) { 670 loff_t pos = file_pos_read(file); 671 ret = vfs_writev(file, vec, vlen, &pos); 672 file_pos_write(file, pos); 673 fput_light(file, fput_needed); 674 } 675 676 if (ret > 0) 677 add_wchar(current, ret); 678 inc_syscw(current); 679 return ret; 680 } 681 682 static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, 683 size_t count, loff_t max) 684 { 685 struct file * in_file, * out_file; 686 struct inode * in_inode, * out_inode; 687 loff_t pos; 688 ssize_t retval; 689 int fput_needed_in, fput_needed_out, fl; 690 691 /* 692 * Get input file, and verify that it is ok.. 693 */ 694 retval = -EBADF; 695 in_file = fget_light(in_fd, &fput_needed_in); 696 if (!in_file) 697 goto out; 698 if (!(in_file->f_mode & FMODE_READ)) 699 goto fput_in; 700 retval = -EINVAL; 701 in_inode = in_file->f_path.dentry->d_inode; 702 if (!in_inode) 703 goto fput_in; 704 if (!in_file->f_op || !in_file->f_op->splice_read) 705 goto fput_in; 706 retval = -ESPIPE; 707 if (!ppos) 708 ppos = &in_file->f_pos; 709 else 710 if (!(in_file->f_mode & FMODE_PREAD)) 711 goto fput_in; 712 retval = rw_verify_area(READ, in_file, ppos, count); 713 if (retval < 0) 714 goto fput_in; 715 count = retval; 716 717 /* 718 * Get output file, and verify that it is ok.. 719 */ 720 retval = -EBADF; 721 out_file = fget_light(out_fd, &fput_needed_out); 722 if (!out_file) 723 goto fput_in; 724 if (!(out_file->f_mode & FMODE_WRITE)) 725 goto fput_out; 726 retval = -EINVAL; 727 if (!out_file->f_op || !out_file->f_op->sendpage) 728 goto fput_out; 729 out_inode = out_file->f_path.dentry->d_inode; 730 retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count); 731 if (retval < 0) 732 goto fput_out; 733 count = retval; 734 735 if (!max) 736 max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); 737 738 pos = *ppos; 739 retval = -EINVAL; 740 if (unlikely(pos < 0)) 741 goto fput_out; 742 if (unlikely(pos + count > max)) { 743 retval = -EOVERFLOW; 744 if (pos >= max) 745 goto fput_out; 746 count = max - pos; 747 } 748 749 fl = 0; 750 #if 0 751 /* 752 * We need to debate whether we can enable this or not. The 753 * man page documents EAGAIN return for the output at least, 754 * and the application is arguably buggy if it doesn't expect 755 * EAGAIN on a non-blocking file descriptor. 756 */ 757 if (in_file->f_flags & O_NONBLOCK) 758 fl = SPLICE_F_NONBLOCK; 759 #endif 760 retval = do_splice_direct(in_file, ppos, out_file, count, fl); 761 762 if (retval > 0) { 763 add_rchar(current, retval); 764 add_wchar(current, retval); 765 } 766 767 inc_syscr(current); 768 inc_syscw(current); 769 if (*ppos > max) 770 retval = -EOVERFLOW; 771 772 fput_out: 773 fput_light(out_file, fput_needed_out); 774 fput_in: 775 fput_light(in_file, fput_needed_in); 776 out: 777 return retval; 778 } 779 780 asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t __user *offset, size_t count) 781 { 782 loff_t pos; 783 off_t off; 784 ssize_t ret; 785 786 if (offset) { 787 if (unlikely(get_user(off, offset))) 788 return -EFAULT; 789 pos = off; 790 ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS); 791 if (unlikely(put_user(pos, offset))) 792 return -EFAULT; 793 return ret; 794 } 795 796 return do_sendfile(out_fd, in_fd, NULL, count, 0); 797 } 798 799 asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t __user *offset, size_t count) 800 { 801 loff_t pos; 802 ssize_t ret; 803 804 if (offset) { 805 if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) 806 return -EFAULT; 807 ret = do_sendfile(out_fd, in_fd, &pos, count, 0); 808 if (unlikely(put_user(pos, offset))) 809 return -EFAULT; 810 return ret; 811 } 812 813 return do_sendfile(out_fd, in_fd, NULL, count, 0); 814 } 815