fs_lseek.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /****************************************************************************
  2. * fs/vfs/fs_lseek.c
  3. *
  4. * Copyright (C) 2008, 2017 Gregory Nutt. All rights reserved.
  5. * Author: Gregory Nutt <gnutt@nuttx.org>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <unistd.h>
  41. #include <sched.h>
  42. #include <errno.h>
  43. #include <assert.h>
  44. #include "inode/inode.h"
  45. /****************************************************************************
  46. * Public Functions
  47. ****************************************************************************/
  48. /****************************************************************************
  49. * Name: file_seek
  50. *
  51. * Description:
  52. * This is the internal implementation of lseek. See the comments in
  53. * lseek() for further information.
  54. *
  55. * Input Parameters:
  56. * file File structure instance
  57. * offset Defines the offset to position to
  58. * whence Defines how to use offset
  59. *
  60. * Returned Value:
  61. * The resulting offset on success. A negated errno value is returned on
  62. * any failure (see lseek comments).
  63. *
  64. ****************************************************************************/
  65. off_t file_seek(FAR struct file *filep, off_t offset, int whence)
  66. {
  67. FAR struct inode *inode;
  68. int ret;
  69. DEBUGASSERT(filep);
  70. inode = filep->f_inode;
  71. /* Invoke the file seek method if available */
  72. if (inode && inode->u.i_ops && inode->u.i_ops->seek)
  73. {
  74. ret = (int)inode->u.i_ops->seek(filep, offset, whence);
  75. if (ret < 0)
  76. {
  77. return ret;
  78. }
  79. }
  80. else
  81. {
  82. /* No... Just set the common file position value */
  83. switch (whence)
  84. {
  85. case SEEK_CUR:
  86. offset += filep->f_pos;
  87. /* FALLTHROUGH */
  88. case SEEK_SET:
  89. if (offset >= 0)
  90. {
  91. filep->f_pos = offset; /* Might be beyond the end-of-file */
  92. break;
  93. }
  94. else
  95. {
  96. return -EINVAL;
  97. }
  98. break;
  99. case SEEK_END:
  100. return -ENOSYS;
  101. default:
  102. return -EINVAL;
  103. }
  104. }
  105. return filep->f_pos;
  106. }
  107. /****************************************************************************
  108. * Name: nx_seek
  109. *
  110. * Description:
  111. * nx_seek() function repositions the offset of the open file associated
  112. * with the file descriptor fd to the argument 'offset' according to the
  113. * directive 'whence'. nx_seek() is an internal OS function. It is
  114. * functionally equivalent to lseek() except that:
  115. *
  116. * - It does not modify the errno variable, and
  117. * - It is not a cancellation point.
  118. *
  119. ****************************************************************************/
  120. off_t nx_seek(int fd, off_t offset, int whence)
  121. {
  122. FAR struct file *filep;
  123. int ret;
  124. /* Get the file structure corresponding to the file descriptor. */
  125. ret = fs_getfilep(fd, &filep);
  126. if (ret < 0)
  127. {
  128. return ret;
  129. }
  130. DEBUGASSERT(filep != NULL);
  131. /* Then let file_seek do the real work */
  132. return file_seek(filep, offset, whence);
  133. }
  134. /****************************************************************************
  135. * Name: lseek
  136. *
  137. * Description:
  138. * The lseek() function repositions the offset of the open file associated
  139. * with the file descriptor fd to the argument 'offset' according to the
  140. * directive 'whence' as follows:
  141. *
  142. * SEEK_SET
  143. * The offset is set to offset bytes.
  144. * SEEK_CUR
  145. * The offset is set to its current location plus offset bytes.
  146. * SEEK_END
  147. * The offset is set to the size of the file plus offset bytes.
  148. *
  149. * The lseek() function allows the file offset to be set beyond the end of
  150. * the file (but this does not change the size of the file). If data is
  151. * later written at this point, subsequent reads of the data in the gap (a
  152. * "hole") return null bytes ('\0') until data is actually written into the
  153. * gap.
  154. *
  155. * Input Parameters:
  156. * fd File descriptor of device
  157. * offset Defines the offset to position to
  158. * whence Defines how to use offset
  159. *
  160. * Returned Value:
  161. * The resulting offset on success. -1 on failure withi errno set properly:
  162. *
  163. * EBADF fd is not an open file descriptor.
  164. * EINVAL whence is not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
  165. * resulting file offset would be negative, or beyond the end of
  166. * a seekable device.
  167. * EOVERFLOW The resulting file offset cannot be represented in an off_t.
  168. * ESPIPE fd is associated with a pipe, socket, or FIFO.
  169. *
  170. ****************************************************************************/
  171. off_t lseek(int fd, off_t offset, int whence)
  172. {
  173. off_t newpos;
  174. /* Let nx_seek do the real work */
  175. newpos = nx_seek(fd, offset, whence);
  176. if (newpos < 0)
  177. {
  178. set_errno(-newpos);
  179. return ERROR;
  180. }
  181. return newpos;
  182. }