diff -urNp linux-860/arch/i386/kernel/entry.S linux-880/arch/i386/kernel/entry.S --- linux-860/arch/i386/kernel/entry.S +++ linux-880/arch/i386/kernel/entry.S @@ -651,7 +651,7 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_lremovexattr) .long SYMBOL_NAME(sys_fremovexattr) .long SYMBOL_NAME(sys_tkill) - .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sendfile64 */ + .long SYMBOL_NAME(sys_sendfile64) /* reserved for sendfile64 */ .long SYMBOL_NAME(sys_ni_syscall) /* 240 reserved for futex */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_setaffinity */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_getaffinity */ diff -urNp linux-860/mm/filemap.c linux-880/mm/filemap.c --- linux-860/mm/filemap.c +++ linux-880/mm/filemap.c @@ -1755,7 +1755,7 @@ int file_send_actor(read_descriptor_t * return written; } -asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) +static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t count) { ssize_t retval; struct file * in_file, * out_file; @@ -1800,27 +1800,19 @@ asmlinkage ssize_t sys_sendfile(int out_ retval = 0; if (count) { read_descriptor_t desc; - loff_t pos = 0, *ppos; - - retval = -EFAULT; - ppos = &in_file->f_pos; - if (offset) { - if (get_user(pos, offset)) - goto fput_out; - ppos = &pos; - } + + if (!offset) + offset = &in_file->f_pos; desc.written = 0; desc.count = count; desc.buf = (char *) out_file; desc.error = 0; - do_generic_file_read(in_file, ppos, &desc, file_send_actor); + do_generic_file_read(in_file, offset, &desc, file_send_actor); retval = desc.written; if (!retval) retval = desc.error; - if (offset) - put_user(pos, offset); } fput_out: @@ -1831,6 +1823,38 @@ out: return retval; } +asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count) +{ + loff_t pos, *ppos = NULL; + ssize_t ret; + if (offset) { + off_t off; + if (unlikely(get_user(off, offset))) + return -EFAULT; + pos = off; + ppos = &pos; + } + ret = common_sendfile(out_fd, in_fd, ppos, count); + if (offset) + put_user((off_t)pos, offset); + return ret; +} + +asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count) +{ + loff_t pos, *ppos = NULL; + ssize_t ret; + if (offset) { + if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t)))) + return -EFAULT; + ppos = &pos; + } + ret = common_sendfile(out_fd, in_fd, ppos, count); + if (offset) + put_user(pos, offset); + return ret; +} + static ssize_t do_readahead(struct file *file, unsigned long index, unsigned long nr) { struct address_space *mapping = file->f_dentry->d_inode->i_mapping;