xref: /third_party/NuttX/fs/vfs/fs_unlink.c (revision beacf11b)
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