1 /****************************************************************************
2 * fs/vfs/fs_unlink.c
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership. The
7 * ASF licenses this file to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance with the
9 * License. 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, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 * License for the specific language governing permissions and limitations
17 * 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 ****************************************************************************/
check_target(struct Vnode * vnode)38 static 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
do_unlink(int dirfd,const char * pathname)72 int 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
135 done:
136 VnodeDrop();
137
138 /* Successfully unlinked */
139
140 free(fullpath);
141 return OK;
142
143 errout_with_lock:
144 VnodeDrop();
145
146 errout:
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
unlink(const char * pathname)163 int 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 ****************************************************************************/
174 extern int do_rmdir(int dirfd, const char *pathname);
175
unlinkat(int dirfd,const char * pathname,int flag)176 int 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
198 errout:
199 set_errno(-ret);
200 return VFS_ERROR;
201 }
202