FAR struct inode *inode_unlink(FAR const char *path) { const char *name = path; FAR struct inode *node; FAR struct inode *peer; FAR struct inode *parent; /* Verify parameters. Ignore null paths and relative paths */ if (!path || *path == '\0' || path[0] != '/') { return NULL; } /* Find the node to unlink */ node = inode_search(&name, &peer, &parent, (const char **)NULL); if (node) { /* If peer is non-null, then remove the node from the right of * of that peer node. */ if (peer) { peer->i_peer = node->i_peer; } /* If parent is non-null, then remove the node from head of * of the list of children. */ else if (parent) { parent->i_child = node->i_peer; } /* Otherwise, we must be removing the root inode. */ else { root_inode = node->i_peer; } node->i_peer = NULL; } return node; }
int inode_remove(FAR const char *path) { const char *name = path; FAR struct inode *node; FAR struct inode *left; FAR struct inode *parent; if (!*path || path[0] != '/') { return -EINVAL; } /* Find the node to delete */ node = inode_search(&name, &left, &parent, (const char **)NULL); if (node) { /* Found it, now remove it from the tree */ inode_unlink(node, left, parent); /* We cannot delete it if there reference to the inode */ if (node->i_crefs) { /* In that case, we will mark it deleted, when the FS * releases the inode, we will then, finally delete * the subtree. */ node->i_flags |= FSNODEFLAG_DELETED; return -EBUSY; } else { /* And delete it now -- recursively to delete all of its children */ inode_free(node->i_child); kfree(node); return OK; } } /* The node does not exist or it has references */ return -ENOENT; }
FAR struct inode *inode_find(FAR const char *path, FAR const char **relpath) { FAR struct inode *node; if (!*path || path[0] != '/') { return NULL; } /* Find the node matching the path. If found, * increment the count of references on the node. */ inode_semtake(); node = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL, relpath); if (node) { node->i_crefs++; } inode_semgive(); return node; }
FAR DIR *opendir(FAR const char *path) { FAR struct inode *inode = NULL; FAR struct fs_dirent_s *dir; FAR const char *relpath; bool isroot = false; int ret; /* If we are given 'nothing' then we will interpret this as * request for the root inode. */ inode_semtake(); if (!path || *path == 0 || strcmp(path, "/") == 0) { inode = root_inode; isroot = true; relpath = NULL; } else { /* We don't know what to do with relative pathes */ if (*path != '/') { ret = -ENOTDIR; goto errout_with_semaphore; } /* Find the node matching the path. */ inode = inode_search(&path, (FAR struct inode**)NULL, (FAR struct inode**)NULL, &relpath); } /* Did we get an inode? */ if (!inode) { /* 'path' is not a does not exist.*/ ret = ENOTDIR; goto errout_with_semaphore; } /* Allocate a type DIR -- which is little more than an inode * container. */ dir = (FAR struct fs_dirent_s *)kuzalloc(sizeof(struct fs_dirent_s)); if (!dir) { /* Insufficient memory to complete the operation.*/ ret = ENOMEM; goto errout_with_semaphore; } /* Populate the DIR structure and return it to the caller. The way that * we do this depends on whenever this is a "normal" pseudo-file-system * inode or a file system mountpoint. */ dir->fd_position = 0; /* This is the position in the read stream */ /* First, handle the special case of the root inode. This must be * special-cased here because the root inode might ALSO be a mountpoint. */ if (isroot) { /* Whatever payload the root inode carries, the root inode is always * a directory inode in the pseudo-file system */ open_pseudodir(inode, dir); } /* Is this a node in the pseudo filesystem? Or a mountpoint? If the node * is the root (isroot == TRUE), then this is a special case. */ #ifndef CONFIG_DISABLE_MOUNTPOINT else if (INODE_IS_MOUNTPT(inode)) { /* Yes, the node is a file system mountpoint */ dir->fd_root = inode; /* Save the inode where we start */ /* Open the directory at the relative path */ ret = open_mountpoint(inode, relpath, dir); if (ret != OK) { goto errout_with_direntry; } } #endif else { /* The node is part of the root pseudo file system. Does the inode * have a child? If so that the child would be the 'root' of a list * of nodes under the directory. */ FAR struct inode *child = inode->i_child; if (child) { /* It looks we have a valid pseudo-filesystem directory node. */ open_pseudodir(child, dir); } else if (!inode->u.i_ops) { /* This is a dangling node with no children and no operations. Set * up to enumerate an empty directory. */ open_emptydir(dir); } else { ret = ENOTDIR; goto errout_with_direntry; } } inode_semgive(); return ((DIR*)dir); /* Nasty goto's make error handling simpler */ errout_with_direntry: kufree(dir); errout_with_semaphore: inode_semgive(); set_errno(ret); return NULL; }
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; } }