1beacf11bSopenharmony_ci/**************************************************************************** 2beacf11bSopenharmony_ci * fs/vfs/fs_pwrite.c 3beacf11bSopenharmony_ci * 4beacf11bSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved. 5beacf11bSopenharmony_ci * Based on NuttX originally from nuttx source (nuttx/fs/ and nuttx/drivers/) 6beacf11bSopenharmony_ci * 7beacf11bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8beacf11bSopenharmony_ci * you may not use this file except in compliance with the License. 9beacf11bSopenharmony_ci * You may obtain a copy of the License at 10beacf11bSopenharmony_ci * 11beacf11bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12beacf11bSopenharmony_ci * 13beacf11bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14beacf11bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15beacf11bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16beacf11bSopenharmony_ci * See the License for the specific language governing permissions and 17beacf11bSopenharmony_ci * limitations under the License. 18beacf11bSopenharmony_ci * 19beacf11bSopenharmony_ci ****************************************************************************/ 20beacf11bSopenharmony_ci 21beacf11bSopenharmony_ci/**************************************************************************** 22beacf11bSopenharmony_ci * Included Files 23beacf11bSopenharmony_ci ****************************************************************************/ 24beacf11bSopenharmony_ci 25beacf11bSopenharmony_ci#include "vfs_config.h" 26beacf11bSopenharmony_ci 27beacf11bSopenharmony_ci#include "sys/types.h" 28beacf11bSopenharmony_ci#include "unistd.h" 29beacf11bSopenharmony_ci#include "errno.h" 30beacf11bSopenharmony_ci 31beacf11bSopenharmony_ci#include "fs/file.h" 32beacf11bSopenharmony_ci 33beacf11bSopenharmony_ci/**************************************************************************** 34beacf11bSopenharmony_ci * Public Functions 35beacf11bSopenharmony_ci ****************************************************************************/ 36beacf11bSopenharmony_ci 37beacf11bSopenharmony_ci/**************************************************************************** 38beacf11bSopenharmony_ci * Name: file_pwrite 39beacf11bSopenharmony_ci * 40beacf11bSopenharmony_ci * Description: 41beacf11bSopenharmony_ci * Equivalent to the standard pwrite function except that is accepts a 42beacf11bSopenharmony_ci * struct file instance instead of a file descriptor. Currently used 43beacf11bSopenharmony_ci * only by aio_write(); 44beacf11bSopenharmony_ci * 45beacf11bSopenharmony_ci ****************************************************************************/ 46beacf11bSopenharmony_ci 47beacf11bSopenharmony_cissize_t file_pwrite(struct file *filep, const void *buf, 48beacf11bSopenharmony_ci size_t nbytes, off_t offset) 49beacf11bSopenharmony_ci{ 50beacf11bSopenharmony_ci off_t savepos; 51beacf11bSopenharmony_ci off_t pos; 52beacf11bSopenharmony_ci ssize_t ret; 53beacf11bSopenharmony_ci int errcode; 54beacf11bSopenharmony_ci 55beacf11bSopenharmony_ci /* Perform the seek to the current position. This will not move the 56beacf11bSopenharmony_ci * file pointer, but will return its current setting 57beacf11bSopenharmony_ci */ 58beacf11bSopenharmony_ci 59beacf11bSopenharmony_ci savepos = file_seek(filep, 0, SEEK_CUR); 60beacf11bSopenharmony_ci if (savepos == (off_t)-1) 61beacf11bSopenharmony_ci { 62beacf11bSopenharmony_ci /* file_seek might fail if this if the media is not seekable */ 63beacf11bSopenharmony_ci 64beacf11bSopenharmony_ci return VFS_ERROR; 65beacf11bSopenharmony_ci } 66beacf11bSopenharmony_ci 67beacf11bSopenharmony_ci /* Then seek to the correct position in the file */ 68beacf11bSopenharmony_ci 69beacf11bSopenharmony_ci pos = file_seek(filep, offset, SEEK_SET); 70beacf11bSopenharmony_ci if (pos == (off_t)-1) 71beacf11bSopenharmony_ci { 72beacf11bSopenharmony_ci /* This might fail is the offset is beyond the end of file */ 73beacf11bSopenharmony_ci 74beacf11bSopenharmony_ci return VFS_ERROR; 75beacf11bSopenharmony_ci } 76beacf11bSopenharmony_ci 77beacf11bSopenharmony_ci /* Then perform the write operation */ 78beacf11bSopenharmony_ci 79beacf11bSopenharmony_ci ret = file_write(filep, buf, nbytes); 80beacf11bSopenharmony_ci errcode = get_errno(); 81beacf11bSopenharmony_ci 82beacf11bSopenharmony_ci /* Restore the file position */ 83beacf11bSopenharmony_ci 84beacf11bSopenharmony_ci pos = file_seek(filep, savepos, SEEK_SET); 85beacf11bSopenharmony_ci if (pos == (off_t)-1 && ret >= 0) 86beacf11bSopenharmony_ci { 87beacf11bSopenharmony_ci /* This really should not fail */ 88beacf11bSopenharmony_ci 89beacf11bSopenharmony_ci return VFS_ERROR; 90beacf11bSopenharmony_ci } 91beacf11bSopenharmony_ci 92beacf11bSopenharmony_ci if (errcode != 0) 93beacf11bSopenharmony_ci { 94beacf11bSopenharmony_ci set_errno(errcode); 95beacf11bSopenharmony_ci } 96beacf11bSopenharmony_ci return ret; 97beacf11bSopenharmony_ci} 98beacf11bSopenharmony_ci 99beacf11bSopenharmony_ci/**************************************************************************** 100beacf11bSopenharmony_ci * Name: pwrite 101beacf11bSopenharmony_ci * 102beacf11bSopenharmony_ci * Description: 103beacf11bSopenharmony_ci * The pwrite() function performs the same action as write(), except that 104beacf11bSopenharmony_ci * it writes into a given position without changing the file pointer. The 105beacf11bSopenharmony_ci * first three arguments to pwrite() are the same as write() with the 106beacf11bSopenharmony_ci * addition of a fourth argument offset for the desired position inside 107beacf11bSopenharmony_ci * the file. 108beacf11bSopenharmony_ci * 109beacf11bSopenharmony_ci * NOTE: This function could have been wholly implemented within libc but 110beacf11bSopenharmony_ci * it is not. Why? Because if pwrite were implemented in libc, it would 111beacf11bSopenharmony_ci * require four system calls. If it is implemented within the kernel, 112beacf11bSopenharmony_ci * only three. 113beacf11bSopenharmony_ci * 114beacf11bSopenharmony_ci * Input Parameters: 115beacf11bSopenharmony_ci * fd file descriptor (or socket descriptor) to write to 116beacf11bSopenharmony_ci * buf Data to write 117beacf11bSopenharmony_ci * nbytes Length of data to write 118beacf11bSopenharmony_ci * 119beacf11bSopenharmony_ci * Returned Value: 120beacf11bSopenharmony_ci * The positive non-zero number of bytes read on success, 0 on if an 121beacf11bSopenharmony_ci * end-of-file condition, or -1 on failure with errno set appropriately. 122beacf11bSopenharmony_ci * See write() return values 123beacf11bSopenharmony_ci * 124beacf11bSopenharmony_ci * Assumptions/Limitations: 125beacf11bSopenharmony_ci * POSIX requires that opening a file with the O_APPEND flag should have no 126beacf11bSopenharmony_ci * effect on the location at which pwrite() writes data. However, on NuttX 127beacf11bSopenharmony_ci * like on Linux, if a file is opened with O_APPEND, pwrite() appends data 128beacf11bSopenharmony_ci * to the end of the file, regardless of the value of offset. 129beacf11bSopenharmony_ci * 130beacf11bSopenharmony_ci ****************************************************************************/ 131beacf11bSopenharmony_ci 132beacf11bSopenharmony_cissize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset) 133beacf11bSopenharmony_ci{ 134beacf11bSopenharmony_ci struct file *filep; 135beacf11bSopenharmony_ci 136beacf11bSopenharmony_ci /* Get the file structure corresponding to the file descriptor. */ 137beacf11bSopenharmony_ci 138beacf11bSopenharmony_ci int ret = fs_getfilep(fd, &filep); 139beacf11bSopenharmony_ci if (ret < 0) 140beacf11bSopenharmony_ci { 141beacf11bSopenharmony_ci /* The errno value has already been set */ 142beacf11bSopenharmony_ci set_errno(-ret); 143beacf11bSopenharmony_ci return (ssize_t)VFS_ERROR; 144beacf11bSopenharmony_ci } 145beacf11bSopenharmony_ci 146beacf11bSopenharmony_ci if (filep->f_oflags & O_DIRECTORY) 147beacf11bSopenharmony_ci { 148beacf11bSopenharmony_ci set_errno(EBADF); 149beacf11bSopenharmony_ci return (ssize_t)VFS_ERROR; 150beacf11bSopenharmony_ci } 151beacf11bSopenharmony_ci 152beacf11bSopenharmony_ci /* Let file_pread do the real work */ 153beacf11bSopenharmony_ci 154beacf11bSopenharmony_ci return file_pwrite(filep, buf, nbytes, offset); 155beacf11bSopenharmony_ci} 156