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