1beacf11bSopenharmony_ci/**************************************************************************** 2beacf11bSopenharmony_ci * fs/vfs/fs_open.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 "errno.h" 28beacf11bSopenharmony_ci#include "sys/types.h" 29beacf11bSopenharmony_ci#include "fcntl.h" 30beacf11bSopenharmony_ci#include "sched.h" 31beacf11bSopenharmony_ci#include "assert.h" 32beacf11bSopenharmony_ci#ifdef LOSCFG_FILE_MODE 33beacf11bSopenharmony_ci#include "stdarg.h" 34beacf11bSopenharmony_ci#endif 35beacf11bSopenharmony_ci#include "stdlib.h" 36beacf11bSopenharmony_ci#include "vnode.h" 37beacf11bSopenharmony_ci#include "blockproxy.h" 38beacf11bSopenharmony_ci#include "path_cache.h" 39beacf11bSopenharmony_ci#include "unistd.h" 40beacf11bSopenharmony_ci#ifdef LOSCFG_KERNEL_DEV_PLIMIT 41beacf11bSopenharmony_ci#include "los_plimits.h" 42beacf11bSopenharmony_ci#endif 43beacf11bSopenharmony_ci 44beacf11bSopenharmony_ci/**************************************************************************** 45beacf11bSopenharmony_ci * Public Functions 46beacf11bSopenharmony_ci ****************************************************************************/ 47beacf11bSopenharmony_ci 48beacf11bSopenharmony_cistatic int oflag_convert_mode(int oflags) 49beacf11bSopenharmony_ci{ 50beacf11bSopenharmony_ci /* regular file operations */ 51beacf11bSopenharmony_ci 52beacf11bSopenharmony_ci int acc_mode = 0; 53beacf11bSopenharmony_ci if ((oflags & O_ACCMODE) == O_RDONLY) 54beacf11bSopenharmony_ci acc_mode |= READ_OP; 55beacf11bSopenharmony_ci if (oflags & O_WRONLY) 56beacf11bSopenharmony_ci acc_mode |= WRITE_OP; 57beacf11bSopenharmony_ci if (oflags & O_RDWR) 58beacf11bSopenharmony_ci acc_mode |= READ_OP | WRITE_OP; 59beacf11bSopenharmony_ci 60beacf11bSopenharmony_ci /* Opens the file, if it is existing. If not, a new file is created. */ 61beacf11bSopenharmony_ci 62beacf11bSopenharmony_ci if (oflags & O_CREAT) 63beacf11bSopenharmony_ci acc_mode |= WRITE_OP; 64beacf11bSopenharmony_ci 65beacf11bSopenharmony_ci /* Creates a new file. If the file is existing, it is truncated and overwritten. */ 66beacf11bSopenharmony_ci 67beacf11bSopenharmony_ci if (oflags & O_TRUNC) 68beacf11bSopenharmony_ci acc_mode |= WRITE_OP; 69beacf11bSopenharmony_ci 70beacf11bSopenharmony_ci /* Creates a new file. The function fails if the file is already existing. */ 71beacf11bSopenharmony_ci 72beacf11bSopenharmony_ci if (oflags & O_EXCL) 73beacf11bSopenharmony_ci acc_mode |= WRITE_OP; 74beacf11bSopenharmony_ci if (oflags & O_APPEND) 75beacf11bSopenharmony_ci acc_mode |= WRITE_OP; 76beacf11bSopenharmony_ci 77beacf11bSopenharmony_ci /* mark for executing operation */ 78beacf11bSopenharmony_ci 79beacf11bSopenharmony_ci if (oflags & O_EXECVE) 80beacf11bSopenharmony_ci acc_mode |= EXEC_OP; 81beacf11bSopenharmony_ci return acc_mode; 82beacf11bSopenharmony_ci} 83beacf11bSopenharmony_ci 84beacf11bSopenharmony_ciint get_path_from_fd(int fd, char **path) 85beacf11bSopenharmony_ci{ 86beacf11bSopenharmony_ci struct file *file = NULL; 87beacf11bSopenharmony_ci char *copypath = NULL; 88beacf11bSopenharmony_ci 89beacf11bSopenharmony_ci if (fd == AT_FDCWD) 90beacf11bSopenharmony_ci { 91beacf11bSopenharmony_ci return OK; 92beacf11bSopenharmony_ci } 93beacf11bSopenharmony_ci 94beacf11bSopenharmony_ci int ret = fs_getfilep(fd, &file); 95beacf11bSopenharmony_ci if (ret < 0) 96beacf11bSopenharmony_ci { 97beacf11bSopenharmony_ci return -ENOENT; 98beacf11bSopenharmony_ci } 99beacf11bSopenharmony_ci 100beacf11bSopenharmony_ci if ((file == NULL) || (file->f_vnode == NULL) || (file->f_path == NULL)) 101beacf11bSopenharmony_ci { 102beacf11bSopenharmony_ci return -EBADF; 103beacf11bSopenharmony_ci } 104beacf11bSopenharmony_ci 105beacf11bSopenharmony_ci copypath = strdup((const char*)file->f_path); 106beacf11bSopenharmony_ci if (copypath == NULL) 107beacf11bSopenharmony_ci { 108beacf11bSopenharmony_ci return VFS_ERROR; 109beacf11bSopenharmony_ci } 110beacf11bSopenharmony_ci 111beacf11bSopenharmony_ci *path = copypath; 112beacf11bSopenharmony_ci return OK; 113beacf11bSopenharmony_ci} 114beacf11bSopenharmony_ci 115beacf11bSopenharmony_cistatic int do_creat(struct Vnode *parentNode, char *fullpath, mode_t mode, struct Vnode **node) 116beacf11bSopenharmony_ci{ 117beacf11bSopenharmony_ci int ret; 118beacf11bSopenharmony_ci char *name = strrchr(fullpath, '/') + 1; 119beacf11bSopenharmony_ci parentNode->useCount++; 120beacf11bSopenharmony_ci 121beacf11bSopenharmony_ci if (parentNode->vop != NULL && parentNode->vop->Create != NULL) 122beacf11bSopenharmony_ci { 123beacf11bSopenharmony_ci ret = parentNode->vop->Create(parentNode, name, mode, node); 124beacf11bSopenharmony_ci } 125beacf11bSopenharmony_ci else 126beacf11bSopenharmony_ci { 127beacf11bSopenharmony_ci ret = -ENOSYS; 128beacf11bSopenharmony_ci } 129beacf11bSopenharmony_ci 130beacf11bSopenharmony_ci parentNode->useCount--; 131beacf11bSopenharmony_ci if (ret < 0) 132beacf11bSopenharmony_ci { 133beacf11bSopenharmony_ci return ret; 134beacf11bSopenharmony_ci } 135beacf11bSopenharmony_ci 136beacf11bSopenharmony_ci struct PathCache *dt = PathCacheAlloc(parentNode, *node, name, strlen(name)); 137beacf11bSopenharmony_ci if (dt == NULL) 138beacf11bSopenharmony_ci { 139beacf11bSopenharmony_ci // alloc name cache failed is not a critical problem, let it go. 140beacf11bSopenharmony_ci PRINT_ERR("alloc path cache %s failed\n", name); 141beacf11bSopenharmony_ci } 142beacf11bSopenharmony_ci return OK; 143beacf11bSopenharmony_ci} 144beacf11bSopenharmony_ci 145beacf11bSopenharmony_ciint fp_open(int dirfd, const char *path, int oflags, mode_t mode) 146beacf11bSopenharmony_ci{ 147beacf11bSopenharmony_ci int ret; 148beacf11bSopenharmony_ci int accmode; 149beacf11bSopenharmony_ci struct file *filep = NULL; 150beacf11bSopenharmony_ci struct Vnode *vnode = NULL; 151beacf11bSopenharmony_ci struct Vnode *parentVnode = NULL; 152beacf11bSopenharmony_ci char *fullpath = NULL; 153beacf11bSopenharmony_ci 154beacf11bSopenharmony_ci VnodeHold(); 155beacf11bSopenharmony_ci ret = follow_symlink(dirfd, path, &vnode, &fullpath); 156beacf11bSopenharmony_ci if (ret == OK) 157beacf11bSopenharmony_ci { 158beacf11bSopenharmony_ci /* if file exist */ 159beacf11bSopenharmony_ci if (vnode->type == VNODE_TYPE_BCHR) 160beacf11bSopenharmony_ci { 161beacf11bSopenharmony_ci ret = -EINVAL; 162beacf11bSopenharmony_ci VnodeDrop(); 163beacf11bSopenharmony_ci goto errout; 164beacf11bSopenharmony_ci } 165beacf11bSopenharmony_ci#ifdef LOSCFG_KERNEL_DEV_PLIMIT 166beacf11bSopenharmony_ci if (vnode->type == VNODE_TYPE_CHR) 167beacf11bSopenharmony_ci { 168beacf11bSopenharmony_ci if (OsDevLimitCheckPermission(vnode->type, fullpath, oflags) != LOS_OK) 169beacf11bSopenharmony_ci { 170beacf11bSopenharmony_ci ret = -EPERM; 171beacf11bSopenharmony_ci VnodeDrop(); 172beacf11bSopenharmony_ci goto errout; 173beacf11bSopenharmony_ci } 174beacf11bSopenharmony_ci } 175beacf11bSopenharmony_ci#endif 176beacf11bSopenharmony_ci#ifdef LOSCFG_FS_VFS_BLOCK_DEVICE 177beacf11bSopenharmony_ci if (vnode->type == VNODE_TYPE_BLK) 178beacf11bSopenharmony_ci { 179beacf11bSopenharmony_ci VnodeDrop(); 180beacf11bSopenharmony_ci int fd = block_proxy(fullpath, oflags); 181beacf11bSopenharmony_ci if (fd < 0) 182beacf11bSopenharmony_ci { 183beacf11bSopenharmony_ci ret = fd; 184beacf11bSopenharmony_ci goto errout; 185beacf11bSopenharmony_ci } 186beacf11bSopenharmony_ci#ifdef LOSCFG_KERNEL_DEV_PLIMIT 187beacf11bSopenharmony_ci if (OsDevLimitCheckPermission(vnode->type, fullpath, oflags) != LOS_OK) 188beacf11bSopenharmony_ci { 189beacf11bSopenharmony_ci ret = -EPERM; 190beacf11bSopenharmony_ci goto errout; 191beacf11bSopenharmony_ci } 192beacf11bSopenharmony_ci#endif 193beacf11bSopenharmony_ci return fd; 194beacf11bSopenharmony_ci } 195beacf11bSopenharmony_ci#endif 196beacf11bSopenharmony_ci if ((vnode->originMount) && (vnode->originMount->mountFlags & MS_RDONLY) && 197beacf11bSopenharmony_ci (((oflags & O_ACCMODE) != O_RDONLY) || (oflags & O_TRUNC))) 198beacf11bSopenharmony_ci { 199beacf11bSopenharmony_ci ret = -EROFS; 200beacf11bSopenharmony_ci VnodeDrop(); 201beacf11bSopenharmony_ci goto errout; 202beacf11bSopenharmony_ci } 203beacf11bSopenharmony_ci if ((oflags & O_CREAT) && (oflags & O_EXCL)) 204beacf11bSopenharmony_ci { 205beacf11bSopenharmony_ci ret = -EEXIST; 206beacf11bSopenharmony_ci VnodeDrop(); 207beacf11bSopenharmony_ci goto errout; 208beacf11bSopenharmony_ci } 209beacf11bSopenharmony_ci if (vnode->type == VNODE_TYPE_DIR) 210beacf11bSopenharmony_ci { 211beacf11bSopenharmony_ci ret = -EISDIR; 212beacf11bSopenharmony_ci VnodeDrop(); 213beacf11bSopenharmony_ci goto errout; 214beacf11bSopenharmony_ci } 215beacf11bSopenharmony_ci accmode = oflag_convert_mode(oflags); 216beacf11bSopenharmony_ci if (VfsVnodePermissionCheck(vnode, accmode)) 217beacf11bSopenharmony_ci { 218beacf11bSopenharmony_ci ret = -EACCES; 219beacf11bSopenharmony_ci VnodeDrop(); 220beacf11bSopenharmony_ci goto errout; 221beacf11bSopenharmony_ci } 222beacf11bSopenharmony_ci } 223beacf11bSopenharmony_ci 224beacf11bSopenharmony_ci if ((ret != OK) && (oflags & O_CREAT) && vnode) 225beacf11bSopenharmony_ci { 226beacf11bSopenharmony_ci /* if file not exist, but parent dir of the file is exist */ 227beacf11bSopenharmony_ci if ((vnode->originMount) && (vnode->originMount->mountFlags & MS_RDONLY)) 228beacf11bSopenharmony_ci { 229beacf11bSopenharmony_ci ret = -EROFS; 230beacf11bSopenharmony_ci VnodeDrop(); 231beacf11bSopenharmony_ci goto errout; 232beacf11bSopenharmony_ci } 233beacf11bSopenharmony_ci if (VfsVnodePermissionCheck(vnode, (WRITE_OP | EXEC_OP))) 234beacf11bSopenharmony_ci { 235beacf11bSopenharmony_ci ret = -EACCES; 236beacf11bSopenharmony_ci VnodeDrop(); 237beacf11bSopenharmony_ci goto errout; 238beacf11bSopenharmony_ci } 239beacf11bSopenharmony_ci parentVnode = vnode; 240beacf11bSopenharmony_ci ret = do_creat(parentVnode, fullpath, mode, &vnode); 241beacf11bSopenharmony_ci if (ret != OK) 242beacf11bSopenharmony_ci { 243beacf11bSopenharmony_ci VnodeDrop(); 244beacf11bSopenharmony_ci goto errout; 245beacf11bSopenharmony_ci } 246beacf11bSopenharmony_ci vnode->filePath = strdup(fullpath); 247beacf11bSopenharmony_ci } 248beacf11bSopenharmony_ci 249beacf11bSopenharmony_ci if (ret != OK) 250beacf11bSopenharmony_ci { 251beacf11bSopenharmony_ci /* found nothing */ 252beacf11bSopenharmony_ci VnodeDrop(); 253beacf11bSopenharmony_ci goto errout; 254beacf11bSopenharmony_ci } 255beacf11bSopenharmony_ci vnode->useCount++; 256beacf11bSopenharmony_ci VnodeDrop(); 257beacf11bSopenharmony_ci 258beacf11bSopenharmony_ci if (oflags & O_TRUNC) 259beacf11bSopenharmony_ci { 260beacf11bSopenharmony_ci if (vnode->useCount > 1) 261beacf11bSopenharmony_ci { 262beacf11bSopenharmony_ci ret = -EBUSY; 263beacf11bSopenharmony_ci goto errout_with_count; 264beacf11bSopenharmony_ci } 265beacf11bSopenharmony_ci 266beacf11bSopenharmony_ci if (vnode->vop->Truncate) 267beacf11bSopenharmony_ci { 268beacf11bSopenharmony_ci ret = vnode->vop->Truncate(vnode, 0); 269beacf11bSopenharmony_ci if (ret != OK) 270beacf11bSopenharmony_ci { 271beacf11bSopenharmony_ci goto errout_with_count; 272beacf11bSopenharmony_ci } 273beacf11bSopenharmony_ci } 274beacf11bSopenharmony_ci else 275beacf11bSopenharmony_ci { 276beacf11bSopenharmony_ci ret = -ENOSYS; 277beacf11bSopenharmony_ci goto errout_with_count; 278beacf11bSopenharmony_ci } 279beacf11bSopenharmony_ci } 280beacf11bSopenharmony_ci 281beacf11bSopenharmony_ci filep = files_allocate(vnode, oflags, 0, NULL, FILE_START_FD); 282beacf11bSopenharmony_ci if (filep == NULL) 283beacf11bSopenharmony_ci { 284beacf11bSopenharmony_ci ret = -EMFILE; 285beacf11bSopenharmony_ci goto errout_with_count; 286beacf11bSopenharmony_ci } 287beacf11bSopenharmony_ci 288beacf11bSopenharmony_ci if (filep->ops && filep->ops->open) 289beacf11bSopenharmony_ci { 290beacf11bSopenharmony_ci ret = filep->ops->open(filep); 291beacf11bSopenharmony_ci } 292beacf11bSopenharmony_ci 293beacf11bSopenharmony_ci if (ret < 0) 294beacf11bSopenharmony_ci { 295beacf11bSopenharmony_ci files_release(filep->fd); 296beacf11bSopenharmony_ci goto errout_with_count; 297beacf11bSopenharmony_ci } 298beacf11bSopenharmony_ci 299beacf11bSopenharmony_ci if (fullpath) 300beacf11bSopenharmony_ci { 301beacf11bSopenharmony_ci free(fullpath); 302beacf11bSopenharmony_ci } 303beacf11bSopenharmony_ci return filep->fd; 304beacf11bSopenharmony_ci 305beacf11bSopenharmony_cierrout_with_count: 306beacf11bSopenharmony_ci VnodeHold(); 307beacf11bSopenharmony_ci vnode->useCount--; 308beacf11bSopenharmony_ci VnodeDrop(); 309beacf11bSopenharmony_cierrout: 310beacf11bSopenharmony_ci if (fullpath) 311beacf11bSopenharmony_ci { 312beacf11bSopenharmony_ci free(fullpath); 313beacf11bSopenharmony_ci } 314beacf11bSopenharmony_ci set_errno(-ret); 315beacf11bSopenharmony_ci return VFS_ERROR; 316beacf11bSopenharmony_ci} 317beacf11bSopenharmony_ci 318beacf11bSopenharmony_ciint do_open(int dirfd, const char *path, int oflags, mode_t mode) 319beacf11bSopenharmony_ci{ 320beacf11bSopenharmony_ci int ret; 321beacf11bSopenharmony_ci int fd; 322beacf11bSopenharmony_ci 323beacf11bSopenharmony_ci if ((oflags & (O_WRONLY | O_CREAT)) != 0) 324beacf11bSopenharmony_ci { 325beacf11bSopenharmony_ci mode &= ~GetUmask(); 326beacf11bSopenharmony_ci mode &= (S_IRWXU | S_IRWXG | S_IRWXO); 327beacf11bSopenharmony_ci } 328beacf11bSopenharmony_ci 329beacf11bSopenharmony_ci fd = fp_open(dirfd, path, oflags, mode); 330beacf11bSopenharmony_ci if (fd < 0) 331beacf11bSopenharmony_ci { 332beacf11bSopenharmony_ci ret = -get_errno(); 333beacf11bSopenharmony_ci goto errout; 334beacf11bSopenharmony_ci } 335beacf11bSopenharmony_ci 336beacf11bSopenharmony_ci return fd; 337beacf11bSopenharmony_ci 338beacf11bSopenharmony_cierrout: 339beacf11bSopenharmony_ci set_errno(-ret); 340beacf11bSopenharmony_ci return VFS_ERROR; 341beacf11bSopenharmony_ci} 342beacf11bSopenharmony_ci 343beacf11bSopenharmony_ci/**************************************************************************** 344beacf11bSopenharmony_ci * Name: open 345beacf11bSopenharmony_ci * 346beacf11bSopenharmony_ci * Description: Standard 'open' interface 347beacf11bSopenharmony_ci * 348beacf11bSopenharmony_ci ****************************************************************************/ 349beacf11bSopenharmony_ci 350beacf11bSopenharmony_ciint open(const char *path, int oflags, ...) 351beacf11bSopenharmony_ci{ 352beacf11bSopenharmony_ci mode_t mode = DEFAULT_FILE_MODE; /* File read-write properties. */ 353beacf11bSopenharmony_ci#ifdef LOSCFG_FILE_MODE 354beacf11bSopenharmony_ci va_list ap; 355beacf11bSopenharmony_ci va_start(ap, oflags); 356beacf11bSopenharmony_ci mode = va_arg(ap, int); 357beacf11bSopenharmony_ci va_end(ap); 358beacf11bSopenharmony_ci#endif 359beacf11bSopenharmony_ci 360beacf11bSopenharmony_ci return do_open(AT_FDCWD, path, oflags, mode); 361beacf11bSopenharmony_ci} 362beacf11bSopenharmony_ci 363beacf11bSopenharmony_ciint open64 (const char *__path, int __oflag, ...) 364beacf11bSopenharmony_ci{ 365beacf11bSopenharmony_ci mode_t mode = DEFAULT_FILE_MODE; /* File read-write properties. */ 366beacf11bSopenharmony_ci#ifdef LOSCFG_FILE_MODE 367beacf11bSopenharmony_ci va_list ap; 368beacf11bSopenharmony_ci va_start(ap, __oflag); 369beacf11bSopenharmony_ci mode = va_arg(ap, int); 370beacf11bSopenharmony_ci va_end(ap); 371beacf11bSopenharmony_ci if ((__oflag & (O_WRONLY | O_CREAT)) != 0) 372beacf11bSopenharmony_ci { 373beacf11bSopenharmony_ci mode &= ~GetUmask(); 374beacf11bSopenharmony_ci mode &= (S_IRWXU|S_IRWXG|S_IRWXO); 375beacf11bSopenharmony_ci } 376beacf11bSopenharmony_ci#endif 377beacf11bSopenharmony_ci return open (__path, ((unsigned int)__oflag) | O_LARGEFILE, mode); 378beacf11bSopenharmony_ci} 379