• 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_seek
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_seek(struct file * filep,off_t offset,int whence)73 off_t file_seek(struct file *filep, off_t offset, int whence)
74 {
75   struct Vnode *vnode;
76   int err = OK;
77   off_t pos;
78 
79   vnode = filep->f_vnode;
80 
81   if (!vnode)
82     {
83       err = -EBADF;
84       goto errout;
85     }
86 
87   /* Invoke the file seek method if available */
88 
89   if (filep->ops != NULL && filep->ops->seek != NULL)
90     {
91       pos = filep->ops->seek(filep, offset, whence);
92       if (pos < 0)
93         {
94           err = pos;
95           goto errout;
96         }
97       else
98         {
99           filep->f_pos = pos;
100         }
101     }
102   else
103     {       /* No... Just set the common file position value */
104       switch (whence)
105         {
106           case SEEK_CUR:
107             offset += (off_t)filep->f_pos;
108 
109             /* FALLTHROUGH */
110 
111           case SEEK_SET:
112             if (offset >= 0)
113               {
114                 filep->f_pos = (loff_t)offset; /* Might be beyond the end-of-file */
115               }
116             else
117               {
118                 err = -EINVAL;
119                 goto errout;
120               }
121             break;
122           case SEEK_END:
123             err = -ENOSYS;
124             goto errout;
125 
126           default:
127             err = -EINVAL;
128             goto errout;
129         }
130   }
131 
132   return (off_t)filep->f_pos;
133 
134 errout:
135   set_errno(-err);
136   return (off_t)VFS_ERROR;
137 }
138 
139 /****************************************************************************
140  * Name: lseek
141  *
142  * Description:
143  *   The lseek() function repositions the offset of the open file associated
144  *   with the file descriptor fd to the argument 'offset' according to the
145  *   directive 'whence' as follows:
146  *
147  *   SEEK_SET
148  *      The offset is set to offset bytes.
149  *   SEEK_CUR
150  *      The offset is set to its current location plus offset bytes.
151  *   SEEK_END
152  *      The offset is set to the size of the file plus offset bytes.
153  *
154  *  The lseek() function allows the file offset to be set beyond the end of the
155  *  file (but this does not change the size of the file). If data is later written
156  *  at this point, subsequent reads of the data in the gap (a "hole") return null
157  *  bytes ('\0') until data is actually written into the gap.
158  *
159  * Input Parameters:
160  *   fd       File descriptor of device
161  *   offset   Defines the offset to position to
162  *   whence   Defines how to use offset
163  *
164  * Returned Value:
165  *   The resulting offset on success.  -1 on failure withi errno set properly:
166  *
167  *   EBADF      fd is not an open file descriptor.
168  *   EINVAL     whence  is  not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
169  *              resulting file offset would be negative, or beyond the end of a
170  *              seekable device.
171  *   EOVERFLOW  The resulting file offset cannot be represented in an off_t.
172  *   ESPIPE     fd is associated with a pipe, socket, or FIFO.
173  *
174  ****************************************************************************/
175 
lseek(int fd,off_t offset,int whence)176 off_t lseek(int fd, off_t offset, int whence)
177 {
178   struct file *filep;
179 
180   /* Get the file structure corresponding to the file descriptor. */
181 
182   int ret = fs_getfilep(fd, &filep);
183   if (ret < 0)
184     {
185       /* The errno value has already been set */
186       return (off_t)VFS_ERROR;
187     }
188 
189   /* Then let file_seek do the real work */
190 
191   return file_seek(filep, offset, whence);
192 }
193 #endif
194