1 /****************************************************************************
2 * fs/vfs/fs_unlink.c
3 *
4 * Copyright (C) 2007-2009, 2017 Gregory Nutt. All rights reserved.
5 * Author: Gregory Nutt <gnutt@nuttx.org>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name NuttX nor the names of its contributors may be
18 * used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 ****************************************************************************/
35
36 /****************************************************************************
37 * Included Files
38 ****************************************************************************/
39
40 #include "vfs_config.h"
41
42 #include "unistd.h"
43 #include "errno.h"
44 #include "fcntl.h"
45
46 #include "vnode.h"
47 #include "stdlib.h"
48 #include "fs/mount.h"
49
50 /****************************************************************************
51 * Private Functions
52 ****************************************************************************/
check_target(struct Vnode * vnode)53 static int check_target(struct Vnode *vnode)
54 {
55 if (vnode->type == VNODE_TYPE_DIR)
56 {
57 return -EISDIR;
58 }
59
60 if ((vnode->originMount) && (vnode->originMount->mountFlags & MS_RDONLY))
61 {
62 return -EROFS;
63 }
64
65 if (vnode->useCount > 0)
66 {
67 return -EBUSY;
68 }
69
70 if (VfsVnodePermissionCheck(vnode->parent, (WRITE_OP | EXEC_OP)))
71 {
72 return -EACCES;
73 }
74 return OK;
75 }
76 /****************************************************************************
77 * Public Functions
78 ****************************************************************************/
79
80 /****************************************************************************
81 * Name: do_unlink
82 *
83 * Description: Remove a file managed a mountpoint
84 *
85 ****************************************************************************/
86
do_unlink(int dirfd,const char * pathname)87 int do_unlink(int dirfd, const char *pathname)
88 {
89 struct Vnode *vnode = NULL;
90 int ret;
91 char *name = NULL;
92 char *fullpath = NULL;
93 char *relativepath = NULL;
94
95 /* Get relative path by dirfd*/
96 ret = get_path_from_fd(dirfd, &relativepath);
97 if (ret < 0)
98 {
99 goto errout;
100 }
101
102 ret = vfs_normalize_path((const char *)relativepath, pathname, &fullpath);
103 if (relativepath)
104 {
105 free(relativepath);
106 }
107
108 if (ret < 0)
109 {
110 goto errout;
111 }
112
113 VnodeHold();
114 ret = VnodeLookup(fullpath, &vnode, 0);
115 if (ret < 0)
116 {
117 goto errout_with_lock;
118 }
119
120 ret = check_target(vnode);
121 if (ret < 0)
122 {
123 goto errout_with_lock;
124 }
125 name = strrchr(fullpath, '/') + 1;
126
127 if (vnode && vnode->vop && vnode->vop->Unlink)
128 {
129 ret = vnode->vop->Unlink(vnode->parent, vnode, name);
130 }
131 else if (vnode && vnode->fop && vnode->fop->unlink)
132 {
133 ret = vnode->fop->unlink(vnode);
134 if (ret == OK) {
135 goto done;
136 }
137 }
138 else
139 {
140 ret = -ENOSYS;
141 }
142
143 if (ret != OK)
144 {
145 goto errout_with_lock;
146 }
147
148 VnodeFree(vnode);
149
150 done:
151 VnodeDrop();
152
153 /* Successfully unlinked */
154
155 free(fullpath);
156 return OK;
157
158 errout_with_lock:
159 VnodeDrop();
160
161 errout:
162 if (fullpath)
163 {
164 free(fullpath);
165 }
166 set_errno(-ret);
167
168 return VFS_ERROR;
169 }
170
171 /****************************************************************************
172 * Name: unlink
173 *
174 * Description: Remove a file managed a mountpoint
175 *
176 ****************************************************************************/
177
unlink(const char * pathname)178 int unlink(const char *pathname)
179 {
180 return do_unlink(AT_FDCWD, pathname);
181 }
182
183 /****************************************************************************
184 * Name: unlinkat
185 *
186 * Description: Remove a file managed a mountpoint by dirfd
187 *
188 ****************************************************************************/
189 extern int do_rmdir(int dirfd, const char *pathname);
190
unlinkat(int dirfd,const char * pathname,int flag)191 int unlinkat(int dirfd, const char *pathname, int flag)
192 {
193 int ret;
194
195 if (pathname == NULL)
196 {
197 ret = -EINVAL;
198 goto errout;
199 }
200
201 /* Now flag only support 0 && AT_REMOVEDIR */
202 if ((flag & ~AT_REMOVEDIR) != 0)
203 {
204 ret = -EINVAL;
205 goto errout;
206 }
207
208 if (flag & AT_REMOVEDIR)
209 return do_rmdir(dirfd, pathname);
210
211 return do_unlink(dirfd, pathname);
212
213 errout:
214 set_errno(-ret);
215 return VFS_ERROR;
216 }
217