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