• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_pread.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) 2014, 2016-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 "errno.h"
48 
49 #include "fs/file.h"
50 
51 /****************************************************************************
52  * Public Functions
53  ****************************************************************************/
54 
55 /****************************************************************************
56  * Name: file_pread64
57  *
58  * Description:
59  *   Equivalent to the standard pread function except that is accepts a
60  *   struct file instance instead of a file descriptor.  Currently used
61  *   only by aio_read();
62  *
63  ****************************************************************************/
64 
file_pread64(struct file * filep,void * buf,size_t nbytes,off64_t offset)65 ssize_t file_pread64(struct file *filep, void *buf, size_t nbytes,
66                      off64_t offset)
67 {
68   off64_t savepos;
69   off64_t pos;
70   ssize_t ret;
71   int errcode;
72 
73   /* Perform the seek to the current position.  This will not move the
74    * file pointer, but will return its current setting
75    */
76 
77   savepos = file_seek64(filep, 0, SEEK_CUR);
78   if (savepos == (off64_t)-1)
79     {
80       /* file_seek64 might fail if this if the media is not seekable */
81 
82       return VFS_ERROR;
83     }
84 
85   /* Then seek to the correct position in the file */
86 
87   pos = file_seek64(filep, offset, SEEK_SET);
88   if (pos == (off64_t)-1)
89     {
90       /* This might fail is the offset is beyond the end of file */
91 
92       return VFS_ERROR;
93     }
94 
95   /* Then perform the read operation */
96 
97   ret = file_read(filep, buf, nbytes);
98   errcode = get_errno();
99 
100   /* Restore the file position */
101 
102   pos = file_seek64(filep, savepos, SEEK_SET);
103   if (pos == (off64_t)-1 && ret >= 0)
104     {
105       /* This really should not fail */
106 
107       return VFS_ERROR;
108     }
109 
110   if (errcode != 0)
111     {
112       set_errno(errcode);
113     }
114   return ret;
115 }
116 
117 /****************************************************************************
118  * Name: pread64
119  *
120  * Description:
121  *   The pread() function performs the same action as read(), except that it
122  *   reads from a given position in the file without changing the file
123  *   pointer. The first three arguments to pread() are the same as read()
124  *   with the addition of a fourth argument offset for the desired position
125  *   inside the file. An attempt to perform a pread() on a file that is
126  *   incapable of seeking results in an error.
127  *
128  *   NOTE: This function could have been wholly implemented within libc but
129  *   it is not.  Why?  Because if pread were implemented in libc, it would
130  *   require four system calls.  If it is implemented within the kernel,
131  *   only three.
132  *
133  * Input Parameters:
134  *   file     File structure instance
135  *   buf      User-provided to save the data
136  *   nbytes   The maximum size of the user-provided buffer
137  *   offset   The file offset
138  *
139  * Returned Value:
140  *   The positive non-zero number of bytes read on success, 0 on if an
141  *   end-of-file condition, or -1 on failure with errno set appropriately.
142  *   See read() return values
143  *
144  ****************************************************************************/
145 
pread64(int fd,void * buf,size_t nbytes,off64_t offset)146 ssize_t pread64(int fd, void *buf, size_t nbytes, off64_t offset)
147 {
148   struct file *filep;
149 
150   /* Get the file structure corresponding to the file descriptor. */
151 
152   int ret = fs_getfilep(fd, &filep);
153   if (ret < 0)
154     {
155       /* The errno value has already been set */
156       return (ssize_t)VFS_ERROR;
157     }
158 
159   if (filep->f_oflags & O_DIRECTORY)
160     {
161       set_errno(EBADF);
162       return VFS_ERROR;
163     }
164 
165   /* Let file_pread do the real work */
166 
167   return file_pread64(filep, buf, nbytes, offset);
168 }
169