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