• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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