1/**************************************************************************** 2 * fs/vfs/fs_rmdir.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 27#include "unistd.h" 28#include "errno.h" 29#include "stdlib.h" 30#include "vnode.h" 31#include "sys/stat.h" 32#include "string.h" 33#include "limits.h" 34#include "fs/mount.h" 35 36/**************************************************************************** 37 * Private Functions 38 ****************************************************************************/ 39static int check_target(struct Vnode *vnode, char *name) 40{ 41 if (vnode == NULL) 42 { 43 return -ENOENT; 44 } 45 46 if ((vnode->originMount) && (vnode->originMount->mountFlags & MS_RDONLY)) 47 { 48 return -EROFS; 49 } 50 51 if (vnode->type != VNODE_TYPE_DIR) 52 { 53 return -ENOTDIR; 54 } 55 56 if (vnode->useCount > 0) 57 { 58 return -EBUSY; 59 } 60 61 if ((vnode->flag & VNODE_FLAG_MOUNT_ORIGIN) 62 || (vnode->flag & VNODE_FLAG_MOUNT_NEW)) 63 { 64 return -EBUSY; 65 } 66 67 char cwd[PATH_MAX]; 68 char *pret = getcwd(cwd, PATH_MAX); 69 if (pret != NULL) 70 { 71 struct Vnode *cwdnode = NULL; 72 int ret = VnodeLookup(cwd, &cwdnode, 0); 73 if (ret == OK && (cwdnode == vnode)) 74 { 75 return -EBUSY; 76 } 77 } 78 return OK; 79} 80/**************************************************************************** 81 * Public Functions 82 ****************************************************************************/ 83 84/**************************************************************************** 85 * Name: do_rmdir 86 * 87 * Description: Remove a file managed a mountpoint 88 * 89 ****************************************************************************/ 90 91int do_rmdir(int dirfd, const char *pathname) 92{ 93 struct Vnode *vnode = NULL; 94 char *fullpath = NULL; 95 char *relativepath = NULL; 96 char *name = NULL; 97 int ret; 98 99 if (pathname == NULL) 100 { 101 ret = -EINVAL; 102 goto errout; 103 } 104 105 /* Get relative path by dirfd*/ 106 ret = get_path_from_fd(dirfd, &relativepath); 107 if (ret < 0) 108 { 109 goto errout; 110 } 111 112 if (relativepath) 113 { 114 ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath); 115 free(relativepath); 116 if (ret < 0) 117 { 118 goto errout; 119 } 120 121 name = strrchr(fullpath, '/'); 122 VnodeHold(); 123 ret = VnodeLookup(fullpath, &vnode, 0); 124 } 125 else 126 { 127 name = strrchr(pathname, '/'); 128 VnodeHold(); 129 if (name == NULL) 130 { 131 name = (char *)pathname; 132 } 133 else 134 { 135 name++; 136 } 137 ret = VnodeLookup(pathname, &vnode, 0); 138 } 139 140 if (ret != OK) 141 { 142 goto errout_with_lock; 143 } 144 145 ret = check_target(vnode, name); 146 if (ret != OK) { 147 PRINT_ERR("rmdir failed err = %d\n", ret); 148 goto errout_with_lock; 149 } 150 151 if (VfsVnodePermissionCheck(vnode->parent, (WRITE_OP | EXEC_OP))) { 152 ret = -EACCES; 153 goto errout_with_lock; 154 } 155 156 if (vnode && vnode->vop && vnode->vop->Rmdir) { 157 ret = vnode->vop->Rmdir(vnode->parent, vnode, name); 158 } else { 159 ret = -ENOSYS; 160 } 161 if (ret < 0) { 162 goto errout_with_lock; 163 } 164 VnodeFree(vnode); 165 VnodeDrop(); 166 167 /* Successfully unlinked */ 168 if (fullpath) 169 { 170 free(fullpath); 171 } 172 173 return OK; 174 175errout_with_lock: 176 VnodeDrop(); 177 178errout: 179 if (fullpath) 180 { 181 free(fullpath); 182 } 183 184 set_errno(-ret); 185 return VFS_ERROR; 186} 187 188/**************************************************************************** 189 * Name: rmdir 190 * 191 * Description: Remove a file managed a mountpoint 192 * 193 ****************************************************************************/ 194 195int rmdir(const char *pathname) 196{ 197 return do_rmdir(AT_FDCWD, pathname); 198} 199