• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/vfs/fs_pwrite.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_pwrite
39  *
40  * Description:
41  *   Equivalent to the standard pwrite function except that is accepts a
42  *   struct file instance instead of a file descriptor.  Currently used
43  *   only by aio_write();
44  *
45  ****************************************************************************/
46 
file_pwrite(struct file * filep,const void * buf,size_t nbytes,off_t offset)47 ssize_t file_pwrite(struct file *filep, const void *buf,
48                     size_t nbytes, 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 write operation */
78 
79   ret = file_write(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: pwrite
101  *
102  * Description:
103  *   The pwrite() function performs the same action as write(), except that
104  *   it writes into a given position without changing the file pointer. The
105  *   first three arguments to pwrite() are the same as write() with the
106  *   addition of a fourth argument offset for the desired position inside
107  *   the file.
108  *
109  *   NOTE: This function could have been wholly implemented within libc but
110  *   it is not.  Why?  Because if pwrite were implemented in libc, it would
111  *   require four system calls.  If it is implemented within the kernel,
112  *   only three.
113  *
114  * Input Parameters:
115  *   fd       file descriptor (or socket descriptor) to write to
116  *   buf      Data to write
117  *   nbytes   Length of data to write
118  *
119  * Returned Value:
120  *   The positive non-zero number of bytes read on success, 0 on if an
121  *   end-of-file condition, or -1 on failure with errno set appropriately.
122  *   See write() return values
123  *
124  * Assumptions/Limitations:
125  *   POSIX requires that opening a file with the O_APPEND flag should have no
126  *   effect on the location at which pwrite() writes data.  However, on NuttX
127  *   like on Linux, if a file is opened with O_APPEND, pwrite() appends data
128  *   to the end of the file, regardless of the value of offset.
129  *
130  ****************************************************************************/
131 
pwrite(int fd,const void * buf,size_t nbytes,off_t offset)132 ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
133 {
134   struct file *filep;
135 
136   /* Get the file structure corresponding to the file descriptor. */
137 
138   int ret = fs_getfilep(fd, &filep);
139   if (ret < 0)
140     {
141       /* The errno value has already been set */
142       set_errno(-ret);
143       return (ssize_t)VFS_ERROR;
144     }
145 
146   if (filep->f_oflags & O_DIRECTORY)
147     {
148       set_errno(EBADF);
149       return (ssize_t)VFS_ERROR;
150     }
151 
152   /* Let file_pread do the real work */
153 
154   return file_pwrite(filep, buf, nbytes, offset);
155 }
156