FAR const char *inode_basename(FAR const char *name) { FAR const char *basename = NULL; for (;;) { /* Get the name for the next path segment */ name = inode_nextname(name); /* When the final segment is terminated by the NUL character, then * previous name that we saved is the basename. */ if (*name == '\0') { return basename; } } /* We won't get here */ return NULL; }
FAR struct inode *inode_search(const char **path, FAR struct inode **peer, FAR struct inode **parent, const char **relpath) { const char *name = *path + 1; /* Skip over leading '/' */ FAR struct inode *node = root_inode; FAR struct inode *left = NULL; FAR struct inode *above = NULL; while (node) { int result = _inode_compare(name, node); /* Case 1: The name is less than the name of the node. * Since the names are ordered, these means that there * is no peer node with this name and that there can be * no match in the fileystem. */ if (result < 0) { node = NULL; break; } /* Case 2: the name is greater than the name of the node. * In this case, the name may still be in the list to the * "right" */ else if (result > 0) { left = node; node = node->i_peer; } /* The names match */ else { /* Now there are three more possibilities: * (1) This is the node that we are looking for or, * (2) The node we are looking for is "below" this one. * (3) This node is a mountpoint and will absorb all request * below this one */ name = inode_nextname(name); if (!*name || INODE_IS_MOUNTPT(node)) { /* Either (1) we are at the end of the path, so this must be the * node we are looking for or else (2) this node is a mountpoint * and will handle the remaining part of the pathname */ if (relpath) { *relpath = name; } break; } else { /* More to go, keep looking at the next level "down" */ above = node; left = NULL; node = node->i_child; } } } /* node is null. This can happen in one of four cases: * With node = NULL * (1) We went left past the final peer: The new node * name is larger than any existing node name at * that level. * (2) We broke out in the middle of the list of peers * because the name was not found in the ordered * list. * (3) We went down past the final parent: The new node * name is "deeper" than anything that we currently * have in the tree. * with node != NULL * (4) When the node matching the full path is found */ if (peer) { *peer = left; } if (parent) { *parent = above; } *path = name; return node; }
int inode_reserve(FAR const char *path, FAR struct inode **inode) { const char *name = path; FAR struct inode *left; FAR struct inode *parent; /* Assume failure */ DEBUGASSERT(path && inode); *inode = NULL; /* Handle paths that are interpreted as the root directory */ if (!*path || path[0] != '/') { return -EINVAL; } /* Find the location to insert the new subtree */ if (inode_search(&name, &left, &parent, (FAR const char **)NULL) != NULL) { /* It is an error if the node already exists in the tree */ return -EEXIST; } /* Now we now where to insert the subtree */ for (;;) { FAR struct inode *node; /* Create a new node -- we need to know if this is the * the leaf node or some intermediary. We can find this * by looking at the next name. */ FAR const char *next_name = inode_nextname(name); if (*next_name) { /* Insert an operationless node */ node = inode_alloc(name); if (node) { inode_insert(node, left, parent); /* Set up for the next time through the loop */ name = next_name; left = NULL; parent = node; continue; } } else { node = inode_alloc(name); if (node) { inode_insert(node, left, parent); *inode = node; return OK; } } /* We get here on failures to allocate node memory */ return -ENOMEM; } }