mirror of
https://github.com/apache/nuttx.git
synced 2026-08-17 01:23:01 +08:00
fs: resolve a trailing lone '.' path component
inode_nextname() already skipped a '.' segment mid-path (e.g. "./foo"), but only checked for a '/' right after it -- a path ending in a bare '.' (e.g. "/foo/.", or "." itself once AT_FDCWD resolution prepends $PWD) fell through and was looked up as a literal child named ".", which no real node is ever named, failing with ENOENT. This broke every "operate on the current directory" idiom relative paths rely on: bare `ls`, `stat .`, `cd .`, etc., all failed outright even though the equivalent absolute path worked fine. Found while testing the Toybox port's interactive REPL, but this is generic VFS path resolution, not Toybox-specific. Signed-off-by: Alan C. Assis <acassis@gmail.com> Assisted-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Xiang Xiao
parent
3cbf6f2168
commit
c1891e07c9
@@ -558,15 +558,32 @@ FAR const char *inode_nextname(FAR const char *name)
|
||||
name++;
|
||||
}
|
||||
|
||||
/* Skip single '.' path segment, but not '..' */
|
||||
/* Skip single '.' path segment, but not '..'. This includes a lone
|
||||
* trailing '.' as the final path component (e.g. "/foo/."), which
|
||||
* refers to "foo" itself the same way "/foo/./" would -- without this,
|
||||
* a trailing '.' is instead treated as a literal child name to look up
|
||||
* under "foo" and fails to resolve, since no real node is ever named
|
||||
* ".", rather than resolving to the node the search already reached.
|
||||
*/
|
||||
|
||||
if (*name == '.' && *(name + 1) == '/')
|
||||
if (*name == '.' && (*(name + 1) == '/' || *(name + 1) == '\0'))
|
||||
{
|
||||
/* If there is a '/' after '.',
|
||||
* continue searching from the next character
|
||||
*/
|
||||
if (*(name + 1) == '/')
|
||||
{
|
||||
/* If there is a '/' after '.',
|
||||
* continue searching from the next character
|
||||
*/
|
||||
|
||||
name = inode_nextname(name);
|
||||
name = inode_nextname(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Lone trailing '.': point past it, at the terminating NUL,
|
||||
* the same as if the path had ended one character earlier.
|
||||
*/
|
||||
|
||||
name++;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
|
||||
Reference in New Issue
Block a user