fs_inodereserve.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /****************************************************************************
  2. * fs/inode/fs_registerreserve.c
  3. *
  4. * Copyright (C) 2007-2009, 2011-2012, 2015, 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. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <assert.h>
  40. #include <errno.h>
  41. #include <nuttx/kmalloc.h>
  42. #include <nuttx/fs/fs.h>
  43. #include "inode/inode.h"
  44. /****************************************************************************
  45. * Private Functions
  46. ****************************************************************************/
  47. /****************************************************************************
  48. * Name: inode_namelen
  49. ****************************************************************************/
  50. static int inode_namelen(FAR const char *name)
  51. {
  52. const char *tmp = name;
  53. while (*tmp && *tmp != '/')
  54. {
  55. tmp++;
  56. }
  57. return tmp - name;
  58. }
  59. /****************************************************************************
  60. * Name: inode_namecpy
  61. ****************************************************************************/
  62. static void inode_namecpy(char *dest, const char *src)
  63. {
  64. while (*src && *src != '/')
  65. {
  66. *dest++ = *src++;
  67. }
  68. *dest = '\0';
  69. }
  70. /****************************************************************************
  71. * Name: inode_alloc
  72. ****************************************************************************/
  73. static FAR struct inode *inode_alloc(FAR const char *name)
  74. {
  75. int namelen = inode_namelen(name);
  76. FAR struct inode *node = (FAR struct inode *)kmm_zalloc(FSNODE_SIZE(namelen));
  77. if (node)
  78. {
  79. inode_namecpy(node->i_name, name);
  80. }
  81. return node;
  82. }
  83. /****************************************************************************
  84. * Name: inode_insert
  85. ****************************************************************************/
  86. static void inode_insert(FAR struct inode *node,
  87. FAR struct inode *peer,
  88. FAR struct inode *parent)
  89. {
  90. /* If peer is non-null, then new node simply goes to the right
  91. * of that peer node.
  92. */
  93. if (peer)
  94. {
  95. node->i_peer = peer->i_peer;
  96. peer->i_peer = node;
  97. }
  98. /* If parent is non-null, then it must go at the head of its
  99. * list of children.
  100. */
  101. else if (parent)
  102. {
  103. node->i_peer = parent->i_child;
  104. parent->i_child = node;
  105. }
  106. /* Otherwise, this must be the new root_inode */
  107. else
  108. {
  109. node->i_peer = g_root_inode;
  110. g_root_inode = node;
  111. }
  112. }
  113. /****************************************************************************
  114. * Public Functions
  115. ****************************************************************************/
  116. /****************************************************************************
  117. * Name: inode_reserve
  118. *
  119. * Description:
  120. * Reserve an (initialized) inode the pseudo file system. The initial
  121. * reference count on the new inode is zero.
  122. *
  123. * Input parameters:
  124. * path - The path to the inode to create
  125. * inode - The location to return the inode pointer
  126. *
  127. * Returned Value:
  128. * Zero on success (with the inode point in 'inode'); A negated errno
  129. * value is returned on failure:
  130. *
  131. * EINVAL - 'path' is invalid for this operation
  132. * EEXIST - An inode already exists at 'path'
  133. * ENOMEM - Failed to allocate in-memory resources for the operation
  134. *
  135. * Assumptions:
  136. * Caller must hold the inode semaphore
  137. *
  138. ****************************************************************************/
  139. int inode_reserve(FAR const char *path, FAR struct inode **inode)
  140. {
  141. struct inode_search_s desc;
  142. FAR struct inode *left;
  143. FAR struct inode *parent;
  144. FAR const char *name;
  145. int ret;
  146. /* Assume failure */
  147. DEBUGASSERT(path != NULL && inode != NULL);
  148. *inode = NULL;
  149. /* Handle paths that are interpreted as the root directory */
  150. if (path[0] == '\0' || path[0] != '/')
  151. {
  152. return -EINVAL;
  153. }
  154. /* Find the location to insert the new subtree */
  155. SETUP_SEARCH(&desc, path, false);
  156. ret = inode_search(&desc);
  157. if (ret >= 0)
  158. {
  159. /* It is an error if the node already exists in the tree (or if it
  160. * lies within a mountpoint, we don't distinguish here).
  161. */
  162. ret = -EEXIST;
  163. goto errout_with_search;
  164. }
  165. /* Now we now where to insert the subtree */
  166. name = desc.path;
  167. left = desc.peer;
  168. parent = desc.parent;
  169. for (; ; )
  170. {
  171. FAR struct inode *node;
  172. /* Create a new node -- we need to know if this is the
  173. * the leaf node or some intermediary. We can find this
  174. * by looking at the next name.
  175. */
  176. FAR const char *nextname = inode_nextname(name);
  177. if (*nextname != '\0')
  178. {
  179. /* Insert an operationless node */
  180. node = inode_alloc(name);
  181. if (node != NULL)
  182. {
  183. inode_insert(node, left, parent);
  184. /* Set up for the next time through the loop */
  185. name = nextname;
  186. left = NULL;
  187. parent = node;
  188. continue;
  189. }
  190. }
  191. else
  192. {
  193. node = inode_alloc(name);
  194. if (node != NULL)
  195. {
  196. inode_insert(node, left, parent);
  197. *inode = node;
  198. ret = OK;
  199. break;
  200. }
  201. }
  202. /* We get here on failures to allocate node memory */
  203. ret = -ENOMEM;
  204. break;
  205. }
  206. errout_with_search:
  207. RELEASE_SEARCH(&desc);
  208. return ret;
  209. }