This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new ca0394bda43 fs/inode: Keep the rest of the path when a soft link in a
path is followed.
ca0394bda43 is described below
commit ca0394bda435296437314b9b2a1148810d877ef7
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Oct 11 11:43:40 2026 +0200
fs/inode: Keep the rest of the path when a soft link in a path is followed.
In inode_search(), name points to the rest of the path, inside
desc->buffer. When an intermediate node of the path is a soft link,
_inode_linktarget() releases desc->buffer and sets it up again for the
link target, usually with the same temporary buffer. name then pointed
into the link target: with "/bin" linked to "/mnt/bin", "/bin/sh" was
looked up as "/mnt/bin/bin" and failed with ENOENT, while "/usr/bin/sh"
with "/usr/bin" linked to "/mnt/bin" worked only because the rest of
that path lay beyond the end of the shorter link target.
Copy the rest of the path before the link is followed, and continue the
search with the copy, which becomes desc->buffer.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
fs/inode/fs_inodesearch.c | 107 +++++++++++++++++++++++++---------------------
1 file changed, 58 insertions(+), 49 deletions(-)
diff --git a/fs/inode/fs_inodesearch.c b/fs/inode/fs_inodesearch.c
index c6e214ffe75..add1fd532e1 100644
--- a/fs/inode/fs_inodesearch.c
+++ b/fs/inode/fs_inodesearch.c
@@ -666,8 +666,23 @@ int inode_search(FAR struct inode_search_s *desc, FAR
struct inode **inodep)
if (INODE_IS_SOFTLINK(inode))
{
FAR struct inode *newnode = inode;
+ FAR char *rest;
int status;
+ /* name points into desc->buffer, which
+ * _inode_linktarget() releases and reuses for the link
+ * target. Keep a copy of the rest of the path.
+ */
+
+ rest = lib_get_tempbuffer(PATH_MAX);
+ if (rest == NULL)
+ {
+ ret = -ENOMEM;
+ break;
+ }
+
+ strlcpy(rest, name, PATH_MAX);
+
/* If this intermediate inode in the is a soft link, then
* (1) recursively look-up the inode referenced by the
* soft link, and (2) continue searching with that inode
@@ -681,64 +696,58 @@ int inode_search(FAR struct inode_search_s *desc, FAR
struct inode **inodep)
* does not exist.
*/
+ lib_put_tempbuffer(rest);
ret = status;
break;
}
- else
+
+ /* The node was a valid symbolic link and we have jumped
+ * to a different spot in the pseudo file system tree.
+ * Check if this took us to a mountpoint.
+ */
+
+ if (INODE_IS_MOUNTPT(newnode))
{
- if (newnode != inode)
+ /* Return the mountpoint information. NOTE that the
+ * last path to the link target was already set by
+ * _inode_linktarget().
+ */
+
+ inode = newnode;
+ above = desc->parent;
+ left = desc->peer;
+ ret = OK;
+
+ if (*desc->relpath != '\0')
{
- /* The node was a valid symbolic link and we have
- * jumped to a different, spot in the pseudo file
- * system tree.
+ /* desc->relpath ends desc->buffer, which holds
+ * at least PATH_MAX bytes: append the rest of
+ * the path to it.
*/
- /* Check if this took us to a mountpoint. */
-
- if (INODE_IS_MOUNTPT(newnode))
- {
- /* Return the mountpoint information.
- * NOTE that the last path to the link target
- * was already set by _inode_linktarget().
- */
-
- inode = newnode;
- above = desc->parent;
- left = desc->peer;
- ret = OK;
-
- if (*desc->relpath != '\0')
- {
- FAR char *buffer = NULL;
-
- buffer = lib_get_tempbuffer(PATH_MAX);
- if (buffer == NULL)
- {
- ret = -ENOMEM;
- }
- else
- {
- snprintf(buffer, PATH_MAX, "%s/%s",
- desc->relpath, name);
- lib_put_tempbuffer(desc->buffer);
- desc->buffer = buffer;
- relpath = buffer;
- ret = OK;
- }
- }
- else
- {
- relpath = name;
- }
-
- break;
- }
-
- /* Continue from this new inode. */
-
- inode = newnode;
+ strlcat(desc->buffer, "/", PATH_MAX);
+ strlcat(desc->buffer, rest, PATH_MAX);
+ lib_put_tempbuffer(rest);
+ relpath = desc->relpath;
+ break;
}
}
+
+ /* desc->buffer holds the rest of the path from now on */
+
+ lib_put_tempbuffer(desc->buffer);
+ desc->buffer = rest;
+
+ if (INODE_IS_MOUNTPT(newnode))
+ {
+ relpath = rest;
+ break;
+ }
+
+ /* Continue from this new inode */
+
+ name = rest;
+ inode = newnode;
}
#endif