Soft Links: Fix several issues in initial testing

This commit is contained in:
Gregory Nutt 2017-02-02 19:37:58 -06:00
parent b39d962021
commit d833144869
2 changed files with 87 additions and 10 deletions

View File

@ -186,6 +186,7 @@ static inline FAR struct inode *
_inode_dereference(FAR struct inode *node, FAR struct inode **peer,
FAR struct inode **parent, FAR const char **relpath)
{
FAR const char *copy;
unsigned int count = 0;
/* An infinite loop is avoided only by the loop count.
@ -196,9 +197,14 @@ _inode_dereference(FAR struct inode *node, FAR struct inode **peer,
while (node != NULL && INODE_IS_SOFTLINK(node))
{
node = inode_search_nofollow((FAR const char **)&node->u.i_link,
peer, parent, relpath);
if (++count > SYMLOOP_MAX)
/* Careful: inode_search_nofollow overwrites the input string pointer */
copy = (FAR const char *)node->u.i_link;
/* Now, look-up the inode associated with the target path */
node = inode_search_nofollow(&copy, peer, parent, relpath);
if (node == NULL && ++count > SYMLOOP_MAX)
{
return NULL;
}
@ -348,6 +354,20 @@ FAR struct inode *inode_search(FAR const char **path,
FAR struct inode *node = g_root_inode;
FAR struct inode *left = NULL;
FAR struct inode *above = NULL;
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
FAR struct inode *newnode;
#endif
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
/* Handle the case were the root node is a symbolic link */
#warning Missing logic
#endif
/* Traverse the pseudo file system node tree until either (1) all nodes
* have been examined without finding the matching node, or (2) the
* matching node is found.
*/
while (node != NULL)
{
@ -383,13 +403,32 @@ FAR struct inode *inode_search(FAR const char **path,
FAR const char *nextname = inode_nextname(name);
if (*nextname != '\0')
{
node = _inode_dereference(node, NULL, &above, relpath);
if (node == NULL)
newnode = _inode_dereference(node, NULL, &above, relpath);
if (newnode == NULL)
{
/* Probably means that the node is a symbolic link, but
* that the target of the symbolic link does not exist.
*/
break;
}
else if (newnode != node)
{
/* The node was a valid symbolic link and we have jumped to a
* different, spot in the the pseudo file system tree. Reset
* everything and continue looking at the next level "down"
* from that new spot in the tree.
*/
above = newnode;
left = NULL;
node = newnode->i_child;
continue;
}
}
#endif
/* Continue looking to the left */
left = node;
node = node->i_peer;
}
@ -429,7 +468,7 @@ FAR struct inode *inode_search(FAR const char **path,
}
else
{
/* More to go.. */
/* More nodes to be examined in the path... */
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
/* If this intermediate inode in the is a soft link, then (1)
@ -438,13 +477,46 @@ FAR struct inode *inode_search(FAR const char **path,
* continue searching with that inode instead.
*/
node = _inode_dereference(node, NULL, NULL, relpath);
if (node == NULL)
newnode = _inode_dereference(node, NULL, NULL, relpath);
if (newnode == NULL)
{
/* Probably means that the node is a symbolic link, but
* that the target of the symbolic link does not exist.
*/
break;
}
#endif
else if (newnode != node)
{
/* The node was a valid symbolic link and we have jumped to a
* different, spot in the the pseudo file system tree. Reset
* everything and continue looking to the right (if possible)
* otherwise at the next level "down" from that new spot in
* the tree.
*/
if (newnode->i_peer != NULL)
{
above = NULL; /* REVISIT: This can't be right */
left = newnode;
node = newnode->i_peer;
/* Did the symbolic link take us to a mountpoint? */
if (INODE_IS_MOUNTPT(newnode))
{
/* Yes.. return the mountpoint information */
if (relpath)
{
*relpath = name;
}
break;
}
}
}
#endif
/* Keep looking at the next level "down" */
above = node;

View File

@ -58,6 +58,11 @@
* path refers to. This is normally done in preparation to removing or
* moving an inode.
*
* In symbolic links in the pseduo file system are enabled, then this
* logic will follow the symbolic links up until the terminal node. Then
* that link in removed. So if this the terminal node is a symbolic link,
* the symbolic link node will be removed, not the target of the link.
*
* Assumptions/Limitations:
* The caller must hold the inode semaphore
*
@ -79,7 +84,7 @@ FAR struct inode *inode_unlink(FAR const char *path)
/* Find the node to unlink */
node = inode_search(&name, &peer, &parent, (const char **)NULL);
node = inode_search_nofollow(&name, &peer, &parent, (const char **)NULL);
if (node)
{
/* If peer is non-null, then remove the node from the right of