This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit f5cff1cbd66f39d76310098117829062caa0f413 Author: Marco Casaroli <[email protected]> AuthorDate: Mon Oct 19 17:38:52 2026 +0200 fs: Let lchown(), lchmod() and lutimens() change the link on a mount point. On a mount point, chstat_recursive() calls the chstat() method of the file system with the same flags for chown() and for lchown(). The file system cannot know that it must not follow the symbolic link. So lchown(), lchmod() and lutimens() (and fchownat(), fchmodat() and utimensat() with AT_SYMLINK_NOFOLLOW) changed the file that the link points to, and left the link as it was. Add the flag CH_STAT_NOFOLLOW. chstat_recursive() sets it when the caller does not resolve the link. V9FS walks to the link without following it when the flag is set, as its lstat() does. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- fs/v9fs/v9fs.c | 3 ++- fs/vfs/fs_chstat.c | 7 +++++++ include/nuttx/fs/fs.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/v9fs/v9fs.c b/fs/v9fs/v9fs.c index 52514c40b06..e0b881e322a 100644 --- a/fs/v9fs/v9fs.c +++ b/fs/v9fs/v9fs.c @@ -961,7 +961,8 @@ static int v9fs_vfs_chstat(FAR struct inode *mountpt, client = mountpt->i_private; - ret = v9fs_client_walk(client, relpath, NULL, false); + ret = v9fs_client_walk(client, relpath, NULL, + (flags & CH_STAT_NOFOLLOW) != 0); if (ret < 0) { ferr("ERROR: Can't find the fid of the relpath %d\n", ret); diff --git a/fs/vfs/fs_chstat.c b/fs/vfs/fs_chstat.c index e06ce347288..44b85dfbcf2 100644 --- a/fs/vfs/fs_chstat.c +++ b/fs/vfs/fs_chstat.c @@ -94,6 +94,13 @@ static int chstat_recursive(FAR const char *path, if (inode->u.i_mops && inode->u.i_mops->chstat) { + /* lchown(), lchmod() and lutimens() change the link itself */ + + if (resolve == 0) + { + flags |= CH_STAT_NOFOLLOW; + } + /* Perform the chstat() operation */ ret = inode->u.i_mops->chstat(inode, desc.relpath, buf, flags); diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 7a33f4dea2a..89022cebf24 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -175,6 +175,7 @@ #define CH_STAT_ATIME (1 << 3) #define CH_STAT_MTIME (1 << 4) #define CH_STAT_SIZE (1 << 7) +#define CH_STAT_NOFOLLOW (1 << 8) /* Do not follow a final symbolic link */ /**************************************************************************** * Public Type Definitions
