• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_lseek.c
3  *
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.  The
7  * ASF licenses this file to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance with the
9  * License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
16  * License for the specific language governing permissions and limitations
17  * under the License.
18  *
19  ****************************************************************************/
20 
21 /****************************************************************************
22  * Included Files
23  ****************************************************************************/
24 
25 #include <vfs_config.h>
26 
27 #include "sys/types.h"
28 #include "unistd.h"
29 #include "sched.h"
30 #include "assert.h"
31 #include "errno.h"
32 #include "vnode.h"
33 
34 #if CONFIG_NFILE_DESCRIPTORS > 0
35 
36 /****************************************************************************
37  * Public Functions
38  ****************************************************************************/
39 
40 /****************************************************************************
41  * Name: file_seek
42  *
43  * Description:
44  *   This is the internal implementation of lseek.  See the comments in
45  *   lseek() for further information.
46  *
47  * Input Parameters:
48  *   file     File structure instance
49  *   offset   Defines the offset to position to
50  *   whence   Defines how to use offset
51  *
52  * Returned Value:
53  *   The resulting offset on success.  A negated errno value is returned on
54  *   any failure (see lseek comments).
55  *
56  ****************************************************************************/
57 
file_seek(struct file * filep,off_t offset,int whence)58 off_t file_seek(struct file *filep, off_t offset, int whence)
59 {
60   struct Vnode *vnode;
61   int err = OK;
62   off_t pos;
63 
64   vnode = filep->f_vnode;
65 
66   if (!vnode)
67     {
68       err = -EBADF;
69       goto errout;
70     }
71 
72   /* Invoke the file seek method if available */
73 
74   if (filep->ops != NULL && filep->ops->seek != NULL)
75     {
76       pos = filep->ops->seek(filep, offset, whence);
77       if (pos < 0)
78         {
79           err = pos;
80           goto errout;
81         }
82       else
83         {
84           filep->f_pos = pos;
85         }
86     }
87   else
88     {       /* No... Just set the common file position value */
89       switch (whence)
90         {
91           case SEEK_CUR:
92             offset += (off_t)filep->f_pos;
93 
94             /* FALLTHROUGH */
95 
96           case SEEK_SET:
97             if (offset >= 0)
98               {
99                 filep->f_pos = (loff_t)offset; /* Might be beyond the end-of-file */
100               }
101             else
102               {
103                 err = -EINVAL;
104                 goto errout;
105               }
106             break;
107           case SEEK_END:
108             err = -ENOSYS;
109             goto errout;
110 
111           default:
112             err = -EINVAL;
113             goto errout;
114         }
115   }
116 
117   return (off_t)filep->f_pos;
118 
119 errout:
120   set_errno(-err);
121   return (off_t)VFS_ERROR;
122 }
123 
124 /****************************************************************************
125  * Name: lseek
126  *
127  * Description:
128  *   The lseek() function repositions the offset of the open file associated
129  *   with the file descriptor fd to the argument 'offset' according to the
130  *   directive 'whence' as follows:
131  *
132  *   SEEK_SET
133  *      The offset is set to offset bytes.
134  *   SEEK_CUR
135  *      The offset is set to its current location plus offset bytes.
136  *   SEEK_END
137  *      The offset is set to the size of the file plus offset bytes.
138  *
139  *  The lseek() function allows the file offset to be set beyond the end of the
140  *  file (but this does not change the size of the file). If data is later written
141  *  at this point, subsequent reads of the data in the gap (a "hole") return null
142  *  bytes ('\0') until data is actually written into the gap.
143  *
144  * Input Parameters:
145  *   fd       File descriptor of device
146  *   offset   Defines the offset to position to
147  *   whence   Defines how to use offset
148  *
149  * Returned Value:
150  *   The resulting offset on success.  -1 on failure withi errno set properly:
151  *
152  *   EBADF      fd is not an open file descriptor.
153  *   EINVAL     whence  is  not one of SEEK_SET, SEEK_CUR, SEEK_END; or the
154  *              resulting file offset would be negative, or beyond the end of a
155  *              seekable device.
156  *   EOVERFLOW  The resulting file offset cannot be represented in an off_t.
157  *   ESPIPE     fd is associated with a pipe, socket, or FIFO.
158  *
159  ****************************************************************************/
160 
lseek(int fd,off_t offset,int whence)161 off_t lseek(int fd, off_t offset, int whence)
162 {
163   struct file *filep;
164 
165   /* Get the file structure corresponding to the file descriptor. */
166 
167   int ret = fs_getfilep(fd, &filep);
168   if (ret < 0)
169     {
170       /* The errno value has already been set */
171       return (off_t)VFS_ERROR;
172     }
173 
174   /* Then let file_seek do the real work */
175 
176   return file_seek(filep, offset, whence);
177 }
178 #endif
179