• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /****************************************************************************
37  * Included Files
38  ****************************************************************************/
39 
40 #include <vfs_config.h>
41 
42 #include "sys/types.h"
43 #include "unistd.h"
44 #include "sched.h"
45 #include "assert.h"
46 #include "errno.h"
47 #include "vnode.h"
48 
49 #if CONFIG_NFILE_DESCRIPTORS > 0
50 
51 /****************************************************************************
52  * Public Functions
53  ****************************************************************************/
54 
55 /****************************************************************************
56  * Name: file_seek64
57  *
58  * Description:
59  *   This is the internal implementation of lseek.  See the comments in
60  *   lseek() for further information.
61  *
62  * Input Parameters:
63  *   file     File structure instance
64  *   offset   Defines the offset to position to
65  *   whence   Defines how to use offset
66  *
67  * Returned Value:
68  *   The resulting offset on success.  A negated errno value is returned on
69  *   any failure (see lseek comments).
70  *
71  ****************************************************************************/
72 
file_seek64(struct file * filep,off64_t offset,int whence)73 off64_t file_seek64(struct file *filep, off64_t offset, int whence)
74 {
75   struct Vnode *vnode = NULL;
76   int err = OK;
77   off64_t pos;
78 
79   DEBUGASSERT(filep);
80   vnode =  filep->f_vnode;
81 
82   if (vnode == NULL)
83     {
84       err = -EBADF;
85       goto errout;
86     }
87 
88   /* Invoke the file seek method if available */
89 
90   if (filep->ops != NULL && filep->ops->seek != NULL)
91     {
92       pos = filep->ops->seek(filep, offset, whence);
93       if (pos < 0)
94         {
95           err = pos;
96           goto errout;
97         }
98       else
99         {
100           filep->f_pos = pos;
101         }
102     }
103   else
104     {       /* No... Just set the common file position value */
105       switch (whence)
106         {
107           case SEEK_CUR:
108             offset += filep->f_pos;
109 
110             /* FALLTHROUGH */
111 
112           case SEEK_SET:
113             if (offset >= 0)
114               {
115                 filep->f_pos = offset; /* Might be beyond the end-of-file */
116               }
117             else
118               {
119                 err = -EINVAL;
120                 goto errout;
121               }
122             break;
123 
124           case SEEK_END:
125             err = -ENOSYS;
126             goto errout;
127 
128           default:
129             err = -EINVAL;
130             goto errout;
131         }
132     }
133 
134   return filep->f_pos;
135 
136 errout:
137   set_errno(-err);
138   return (off64_t)VFS_ERROR;
139 }
140 
141 /****************************************************************************
142  * Name: lseek64
143  *
144  * Description:
145  *   The lseek64() function repositions the offset of the open file associated
146  *   with the file descriptor fd to the argument 'offset' according to the
147  *   directive 'whence' as follows:
148  *
149  *   SEEK_SET
150  *      The offset is set to offset bytes.
151  *   SEEK_CUR
152  *      The offset is set to its current location plus offset bytes.
153  *   SEEK_END
154  *      The offset is set to the size of the file plus offset bytes.
155  *
156  *  The lseek64() function allows the file offset to be set beyond the end of the
157  *  file (but this does not change the size of the file). If data is later written
158  *  at this point, subsequent reads of the data in the gap (a "hole") return null
159  *  bytes ('\0') until data is actually written into the gap.
160  *
161  * Input Parameters:
162  *   fd       File descriptor of device
163  *   offset   Defines the offset to position to
164  *   whence   Defines how to use offset
165  *
166  * Returned Value:
167  *   The resulting offset on success.  -1 on failure withi errno set properly:
168  *
169  *   EBADF      fd is not an open file descriptor.
170  *   EINVAL     whence  is  not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
171  *              resulting file offset would be negative, or beyond the end of a
172  *              seekable device.
173  *   EOVERFLOW  The resulting file offset cannot be represented in an off_t.
174  *   ESPIPE     fd is associated with a pipe, socket, or FIFO.
175  *
176  ****************************************************************************/
177 
lseek64(int fd,off64_t offset,int whence)178 off64_t lseek64(int fd, off64_t offset, int whence)
179 {
180   struct file *filep;
181 
182   /* Get the file structure corresponding to the file descriptor. */
183 
184   int ret = fs_getfilep(fd, &filep);
185   if (ret < 0)
186     {
187       /* The errno value has already been set */
188       return (off64_t)VFS_ERROR;
189     }
190 
191   /* Then let file_seek do the real work */
192 
193   return file_seek64(filep, offset, whence);
194 }
195 #endif
196