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