• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ****************************************************************************/
check_target(struct Vnode * vnode,char * name)39 static 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 
do_rmdir(int dirfd,const char * pathname)91 int 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 
175 errout_with_lock:
176   VnodeDrop();
177 
178 errout:
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 
rmdir(const char * pathname)195 int rmdir(const char *pathname)
196 {
197   return do_rmdir(AT_FDCWD, pathname);
198 }
199