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