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