fs_lseek.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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: lseek
  109. *
  110. * Description:
  111. * The lseek() 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' as follows:
  114. *
  115. * SEEK_SET
  116. * The offset is set to offset bytes.
  117. * SEEK_CUR
  118. * The offset is set to its current location plus offset bytes.
  119. * SEEK_END
  120. * The offset is set to the size of the file plus offset bytes.
  121. *
  122. * The lseek() function allows the file offset to be set beyond the end of the
  123. * file (but this does not change the size of the file). If data is later written
  124. * at this point, subsequent reads of the data in the gap (a "hole") return null
  125. * bytes ('\0') until data is actually written into the gap.
  126. *
  127. * Input Parameters:
  128. * fd File descriptor of device
  129. * offset Defines the offset to position to
  130. * whence Defines how to use offset
  131. *
  132. * Returned Value:
  133. * The resulting offset on success. -1 on failure withi errno set properly:
  134. *
  135. * EBADF fd is not an open file descriptor.
  136. * EINVAL whence is not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
  137. * resulting file offset would be negative, or beyond the end of a
  138. * seekable device.
  139. * EOVERFLOW The resulting file offset cannot be represented in an off_t.
  140. * ESPIPE fd is associated with a pipe, socket, or FIFO.
  141. *
  142. ****************************************************************************/
  143. off_t lseek(int fd, off_t offset, int whence)
  144. {
  145. FAR struct file *filep;
  146. off_t newpos;
  147. int errcode;
  148. int ret;
  149. /* Get the file structure corresponding to the file descriptor. */
  150. ret = fs_getfilep(fd, &filep);
  151. if (ret < 0)
  152. {
  153. errcode = -ret;
  154. goto errout;
  155. }
  156. DEBUGASSERT(filep != NULL);
  157. /* Then let file_seek do the real work */
  158. newpos = file_seek(filep, offset, whence);
  159. if (newpos < 0)
  160. {
  161. errcode = (int)-newpos;
  162. goto errout;
  163. }
  164. return newpos;
  165. errout:
  166. set_errno(errcode);
  167. return (off_t)ERROR;
  168. }