1/**************************************************************************** 2 * fs/vfs/fs_mkdir.c 3 * 4 * Copyright (c) 2023 Huawei Device Co., Ltd. All rights reserved. 5 * Based on NuttX originally from nuttx source (nuttx/fs/ and nuttx/drivers/) 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * 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, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 ****************************************************************************/ 20 21/**************************************************************************** 22 * Included Files 23 ****************************************************************************/ 24 25#include "vfs_config.h" 26#include "errno.h" 27#include "sys/types.h" 28#include "sys/stat.h" 29#include "stdlib.h" 30#include "vnode.h" 31#include "string.h" 32#include "capability_api.h" 33#include "path_cache.h" 34 35/**************************************************************************** 36 * Private Functions 37 ****************************************************************************/ 38int do_mkdir(int dirfd, const char *pathname, mode_t mode) 39{ 40 struct Vnode *parentVnode = NULL; 41 struct Vnode *vnode = NULL; 42 struct Mount *mount = NULL; 43 int ret; 44 char *fullpath = NULL; 45 char *relativepath = NULL; 46 char *dirname = NULL; 47 48 mode &= ~GetUmask(); 49 mode &= (S_IRWXU|S_IRWXG|S_IRWXO); 50 51 /* Get absolute path by dirfd*/ 52 ret = get_path_from_fd(dirfd, &relativepath); 53 if (ret < 0) 54 { 55 goto errout; 56 } 57 58 ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath); 59 if (relativepath) 60 { 61 free(relativepath); 62 } 63 64 if (ret < 0) 65 { 66 goto errout; 67 } 68#ifdef LOSCFG_KERNEL_PLIMITS 69 if (!strncmp(fullpath, "/dev", 4) || !strcmp(fullpath, "/proc")) 70#else 71 if (!strncmp(fullpath, "/dev", 4) || !strncmp(fullpath, "/proc", 5)) 72#endif 73 { 74 // virtual root create virtual dir 75 VnodeHold(); 76 ret = VnodeLookup(fullpath, &vnode, V_DUMMY|V_CREATE); 77 if (ret != OK) 78 { 79 goto errout_with_lock; 80 } 81 vnode->mode = mode | S_IFDIR; 82 vnode->type = VNODE_TYPE_DIR; 83 VnodeDrop(); 84 goto out; 85 } 86 87 dirname = strrchr(fullpath, '/') + 1; 88 89 VnodeHold(); 90 ret = VnodeLookup(fullpath, &parentVnode, 0); 91 if (ret == OK) 92 { 93 ret = -EEXIST; 94 goto errout_with_lock; 95 } 96 97 if (parentVnode == NULL) 98 { 99 ret = -ENOENT; 100 goto errout_with_lock; 101 } 102 mount = parentVnode->originMount; 103 if ((mount != NULL) && (mount->mountFlags & MS_RDONLY)) 104 { 105 ret = -EROFS; 106 goto errout_with_lock; 107 } 108 109 parentVnode->useCount++; 110 111 if (VfsVnodePermissionCheck(parentVnode, (WRITE_OP | EXEC_OP))) 112 { 113 ret = -EACCES; 114 goto errout_with_count; 115 } 116 117 if ((parentVnode->vop != NULL) && (parentVnode->vop->Mkdir != NULL)) 118 { 119 ret = parentVnode->vop->Mkdir(parentVnode, dirname, mode, &vnode); 120 } 121 else 122 { 123 ret = -ENOSYS; 124 } 125 126 if (ret < 0) 127 { 128 goto errout_with_count; 129 } 130 131 struct PathCache *dt = PathCacheAlloc(parentVnode, vnode, dirname, strlen(dirname)); 132 if (dt == NULL) { 133 // alloc name cache failed is not a critical problem, let it go. 134 PRINT_ERR("alloc path cache %s failed\n", dirname); 135 } 136 vnode->filePath = strdup(fullpath); 137 parentVnode->useCount--; 138 VnodeDrop(); 139out: 140 /* Directory successfully created */ 141 free(fullpath); 142 143 return OK; 144errout_with_count: 145 parentVnode->useCount--; 146errout_with_lock: 147 VnodeDrop(); 148errout: 149 set_errno(-ret); 150 if (fullpath) 151 { 152 free(fullpath); 153 } 154 return VFS_ERROR; 155} 156 157/**************************************************************************** 158 * Public Functions 159 ****************************************************************************/ 160 161/**************************************************************************** 162 * Name: mkdir 163 * 164 * Description: Create a directory 165 * 166 ****************************************************************************/ 167 168int mkdir(const char *pathname, mode_t mode) 169{ 170 return do_mkdir(AT_FDCWD, pathname, mode); 171} 172 173/**************************************************************************** 174 * Name: mkdirat 175 * 176 * Description: Create a directory by dirfd 177 * 178 ****************************************************************************/ 179 180int mkdirat(int dirfd, const char *pathname, mode_t mode) 181{ 182 return do_mkdir(dirfd, pathname, mode); 183} 184