read_write.c 17 KB

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