• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  * fs/inode/fs_registerreserve.c
3  *
4  *   Copyright (C) 2007-2009, 2011-2012, 2015, 2017 Gregory Nutt. All
5  *     rights reserved.
6  *   Author: Gregory Nutt <gnutt@nuttx.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name NuttX nor the names of its contributors may be
19  *    used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  ****************************************************************************/
36 
37 /****************************************************************************
38  * Included Files
39  ****************************************************************************/
40 
41 #include "vfs_config.h"
42 
43 #include "assert.h"
44 #include "errno.h"
45 
46 #include "stdlib.h"
47 #include "fs/fs.h"
48 #include "fs/dirent_fs.h"
49 #include "string.h"
50 #include "inode/inode.h"
51 #include "capability_api.h"
52 
53 /****************************************************************************
54  * Private Functions
55  ****************************************************************************/
56 
57 /****************************************************************************
58  * Name: check_name
59  ****************************************************************************/
60 
check_name(FAR const char * name)61 static bool check_name(FAR const char *name)
62 {
63   while (*name != '\0')
64     {
65       if ((*name == '/') && *(name+1) != '\0')
66         {
67           return false;
68         }
69       name ++;
70     }
71   return true;
72 }
73 
74 /****************************************************************************
75  * Name: inode_namelen
76  ****************************************************************************/
77 
inode_namelen(FAR const char * name)78 static int inode_namelen(FAR const char *name)
79 {
80   const char *tmp = name;
81   while (*tmp && *tmp != '/')
82     {
83       tmp++;
84     }
85 
86   return tmp - name;
87 }
88 
89 /****************************************************************************
90  * Name: inode_namecpy
91  ****************************************************************************/
92 
inode_namecpy(char * dest,const char * src)93 static void inode_namecpy(char *dest, const char *src)
94 {
95   while (*src && *src != '/')
96     {
97       *dest++ = *src++;
98     }
99 
100   *dest = '\0';
101 }
102 
103 /****************************************************************************
104  * Name: inode_alloc
105  ****************************************************************************/
106 
inode_alloc(FAR const char * name)107 static FAR struct inode *inode_alloc(FAR const char *name)
108 {
109   FAR struct inode *node;
110   int namelen;
111 
112   namelen = inode_namelen(name);
113   node = (FAR struct inode*)LOS_MemAlloc(m_aucSysMem0, FSNODE_SIZE(namelen));
114   if (node)
115     {
116       (void)memset_s(node, FSNODE_SIZE(namelen), 0, FSNODE_SIZE(namelen));
117       inode_namecpy(node->i_name, name);
118     }
119 
120   return node;
121 }
122 
123 /****************************************************************************
124  * Name: IsInRootfs
125  ****************************************************************************/
126 
IsInRootfs(const char * relpath)127 bool IsInRootfs(const char *relpath)
128 {
129     bool ret = true;
130     char *name = NULL;
131     char *path = NULL;
132     struct stat statInfo;
133 
134     if ((!g_root_inode->u.i_mops) || (!g_root_inode->u.i_mops->stat)) {
135         return false;
136     }
137 
138     name = strdup(relpath);
139     if (name) {
140         path = strsep(&name, "/");
141         if (g_root_inode->u.i_mops->stat(g_root_inode, path, &statInfo) == -ENOENT) {
142             ret = false;
143         }
144         free(path);
145     }
146 
147     return ret;
148 }
149 
150 /****************************************************************************
151  * Name: inode_insert
152  ****************************************************************************/
153 
inode_insert(FAR struct inode * node,FAR struct inode * peer,FAR struct inode * parent)154 static void inode_insert(FAR struct inode *node,
155                          FAR struct inode *peer,
156                          FAR struct inode *parent)
157 {
158   /* If peer is non-null, then new node simply goes to the right
159    * of that peer node.
160    */
161 
162   if (peer)
163     {
164       node->i_peer = peer->i_peer;
165       peer->i_peer = node;
166     }
167 
168   /* If parent is non-null, then it must go at the head of its
169    * list of children.
170    */
171 
172   else if (parent)
173     {
174       node->i_peer    = parent->i_child;
175       parent->i_child = node;
176     }
177 
178   /* Otherwise, this must be the new root_inode */
179 
180   else
181     {
182       node->i_peer = g_root_inode;
183       g_root_inode = node;
184     }
185 }
186 
187 /****************************************************************************
188  * Public Functions
189  ****************************************************************************/
190 
191 /****************************************************************************
192  * Name: inode_reserve_rootdir
193  *
194  * Description:
195  *   Reserve an (initialized) inode the pseudo file system.  The initial
196  *   reference count on the new inode is zero.
197  *
198  * Input Parameters:
199  *   path - The path to the inode to create
200  *   inode - The location to return the inode pointer
201  *   force - force to reserve the inode if the value is true
202  *
203  * Returned Value:
204  *   Zero on success (with the inode point in 'inode'); A negated errno
205  *   value is returned on failure:
206  *
207  *   EINVAL - 'path' is invalid for this operation
208  *   EEXIST - An inode already exists at 'path'
209  *   ENOMEM - Failed to allocate in-memory resources for the operation
210  *
211  * Assumptions:
212  *   Caller must hold the inode semaphore
213  *
214  ****************************************************************************/
215 
216 #ifndef LOSCFG_FS_ZPFS
217 static inline
218 #endif
inode_reserve_rootdir(FAR const char * path,FAR struct inode ** inode_ptr,bool force)219 int inode_reserve_rootdir(FAR const char *path, FAR struct inode **inode_ptr, bool force)
220 {
221   FAR const char   *name = path;
222   FAR const char   *relpath;
223   FAR struct inode *pathnode;
224   FAR struct inode *left;
225   FAR struct inode *parent;
226 
227   /* Assume failure */
228 
229   DEBUGASSERT(path && inode_ptr);
230   *inode_ptr = NULL;
231 
232   /* Handle paths that are interpreted as the root directory */
233 
234   if (!*path || path[0] != '/')
235     {
236       return -EINVAL;
237     }
238 
239   /* Find the location to insert the new subtree */
240 
241   pathnode = inode_search(&name, &left, &parent, &relpath);
242   if (pathnode)
243     {
244       if (!*(relpath))
245         {
246           /* It is an error if the node already exists in the tree */
247 
248           return -EEXIST;
249         }
250 #ifndef CONFIG_DISABLE_MOUNTPOINT
251       else if (INODE_IS_MOUNTPT(pathnode))
252         {
253           if ((pathnode != g_root_inode) ||
254             (force ? false : IsInRootfs(relpath)))
255             {
256               /* The node cannot be a child of a mounted point, except the root node. */
257 
258               return -EINVAL;
259             }
260         }
261 #endif
262     }
263   else
264     {
265       /* not find pathnode and the node is not g_root_inode express you have no access authority */
266 
267       if (g_root_inode != NULL)
268         {
269            return -EACCES;
270         }
271     }
272 
273   if ((force == false) && (check_name(name) == false))
274     {
275       /* check the path has no '/' symbol, prevent to create multilevel directory */
276       return -EINVAL;
277     }
278 
279   /* Now we now where to insert the subtree */
280 
281   for (; ; )
282     {
283       FAR struct inode *node;
284 
285       /* Create a new node -- we need to know if this is the
286        * the leaf node or some intermediary.  We can find this
287        * by looking at the next name.
288        */
289 
290       FAR const char *next_name = inode_nextname(name);
291       if (*next_name)
292         {
293           /* Insert an operationless node */
294 
295           node = inode_alloc(name);
296           if (node)
297             {
298               inode_insert(node, left, parent);
299 
300               /* Set up for the next time through the loop */
301 
302               name   = next_name;
303               left   = NULL;
304               parent = node;
305               continue;
306             }
307         }
308       else
309         {
310           node = inode_alloc(name);
311           if (node)
312             {
313               inode_insert(node, left, parent);
314               *inode_ptr = node;
315               return OK;
316             }
317         }
318 
319       /* We get here on failures to allocate node memory */
320 
321       return -ENOMEM;
322     }
323 }
324 
325 /****************************************************************************
326  * Name: inode_reserve
327  *
328  * Description:
329  *   Reserve an (initialized) inode the pseudo file system.  The initial
330  *   reference count on the new inode is zero.
331  *
332  * Input Parameters:
333  *   path - The path to the inode to create
334  *   inode - The location to return the inode pointer
335  *
336  * Returned Value:
337  *   Zero on success (with the inode point in 'inode'); A negated errno
338  *   value is returned on failure:
339  *
340  *   EINVAL - 'path' is invalid for this operation
341  *   EEXIST - An inode already exists at 'path'
342  *   ENOMEM - Failed to allocate in-memory resources for the operation
343  *
344  * Assumptions:
345  *   Caller must hold the inode semaphore
346  *
347  ****************************************************************************/
348 
inode_reserve(FAR const char * path,FAR struct inode ** inode_ptr)349 int inode_reserve(FAR const char *path, FAR struct inode **inode_ptr)
350 {
351     return inode_reserve_rootdir(path, inode_ptr, false);
352 }
353 
354