fs_inodereserve.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /****************************************************************************
  2. * fs/inode/fs_inodereserve.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <assert.h>
  25. #include <errno.h>
  26. #include <nuttx/kmalloc.h>
  27. #include <nuttx/fs/fs.h>
  28. #include "inode/inode.h"
  29. /****************************************************************************
  30. * Private Functions
  31. ****************************************************************************/
  32. /****************************************************************************
  33. * Name: inode_namelen
  34. ****************************************************************************/
  35. static int inode_namelen(FAR const char *name)
  36. {
  37. const char *tmp = name;
  38. while (*tmp && *tmp != '/')
  39. {
  40. tmp++;
  41. }
  42. return tmp - name;
  43. }
  44. /****************************************************************************
  45. * Name: inode_namecpy
  46. ****************************************************************************/
  47. static void inode_namecpy(char *dest, const char *src)
  48. {
  49. while (*src && *src != '/')
  50. {
  51. *dest++ = *src++;
  52. }
  53. *dest = '\0';
  54. }
  55. /****************************************************************************
  56. * Name: inode_alloc
  57. ****************************************************************************/
  58. static FAR struct inode *inode_alloc(FAR const char *name)
  59. {
  60. FAR struct inode *node;
  61. int namelen;
  62. namelen = inode_namelen(name);
  63. node = (FAR struct inode *)kmm_zalloc(FSNODE_SIZE(namelen));
  64. if (node)
  65. {
  66. inode_namecpy(node->i_name, name);
  67. }
  68. return node;
  69. }
  70. /****************************************************************************
  71. * Name: inode_insert
  72. ****************************************************************************/
  73. static void inode_insert(FAR struct inode *node,
  74. FAR struct inode *peer,
  75. FAR struct inode *parent)
  76. {
  77. /* If peer is non-null, then new node simply goes to the right
  78. * of that peer node.
  79. */
  80. if (peer)
  81. {
  82. node->i_peer = peer->i_peer;
  83. peer->i_peer = node;
  84. }
  85. /* Then it must go at the head of parent's list of children. */
  86. else
  87. {
  88. DEBUGASSERT(parent != NULL);
  89. node->i_peer = parent->i_child;
  90. parent->i_child = node;
  91. }
  92. }
  93. /****************************************************************************
  94. * Public Functions
  95. ****************************************************************************/
  96. /****************************************************************************
  97. * Name: inode_root_reserve
  98. *
  99. * Description:
  100. * Reserve the root inode for the pseudo file system.
  101. *
  102. ****************************************************************************/
  103. void inode_root_reserve(void)
  104. {
  105. g_root_inode = inode_alloc("");
  106. }
  107. /****************************************************************************
  108. * Name: inode_reserve
  109. *
  110. * Description:
  111. * Reserve an (initialized) inode the pseudo file system. The initial
  112. * reference count on the new inode is zero.
  113. *
  114. * Input Parameters:
  115. * path - The path to the inode to create
  116. * inode - The location to return the inode pointer
  117. *
  118. * Returned Value:
  119. * Zero on success (with the inode point in 'inode'); A negated errno
  120. * value is returned on failure:
  121. *
  122. * EINVAL - 'path' is invalid for this operation
  123. * EEXIST - An inode already exists at 'path'
  124. * ENOMEM - Failed to allocate in-memory resources for the operation
  125. *
  126. * Assumptions:
  127. * Caller must hold the inode semaphore
  128. *
  129. ****************************************************************************/
  130. int inode_reserve(FAR const char *path, FAR struct inode **inode)
  131. {
  132. struct inode_search_s desc;
  133. FAR struct inode *left;
  134. FAR struct inode *parent;
  135. FAR const char *name;
  136. int ret;
  137. /* Assume failure */
  138. DEBUGASSERT(path != NULL && inode != NULL);
  139. *inode = NULL;
  140. if (path[0] == '\0')
  141. {
  142. return -EINVAL;
  143. }
  144. /* Find the location to insert the new subtree */
  145. SETUP_SEARCH(&desc, path, false);
  146. ret = inode_search(&desc);
  147. if (ret >= 0)
  148. {
  149. /* It is an error if the node already exists in the tree (or if it
  150. * lies within a mountpoint, we don't distinguish here).
  151. */
  152. ret = -EEXIST;
  153. goto errout_with_search;
  154. }
  155. /* Now we now where to insert the subtree */
  156. name = desc.path;
  157. left = desc.peer;
  158. parent = desc.parent;
  159. for (; ; )
  160. {
  161. FAR struct inode *node;
  162. /* Create a new node -- we need to know if this is the
  163. * the leaf node or some intermediary. We can find this
  164. * by looking at the next name.
  165. */
  166. FAR const char *nextname = inode_nextname(name);
  167. if (*nextname != '\0')
  168. {
  169. /* Insert an operationless node */
  170. node = inode_alloc(name);
  171. if (node != NULL)
  172. {
  173. inode_insert(node, left, parent);
  174. /* Set up for the next time through the loop */
  175. name = nextname;
  176. left = NULL;
  177. parent = node;
  178. continue;
  179. }
  180. }
  181. else
  182. {
  183. node = inode_alloc(name);
  184. if (node != NULL)
  185. {
  186. inode_insert(node, left, parent);
  187. *inode = node;
  188. ret = OK;
  189. break;
  190. }
  191. }
  192. /* We get here on failures to allocate node memory */
  193. ret = -ENOMEM;
  194. break;
  195. }
  196. errout_with_search:
  197. RELEASE_SEARCH(&desc);
  198. return ret;
  199. }