From 4939d285195d4d57df8239429d608c3f386a6960 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sat, 20 Jun 2026 21:36:03 +0800 Subject: [PATCH 1/3] sys/types: always use unsigned int for uid_t/gid_t Move uid_t/gid_t out of the CONFIG_SMALL_MEMORY #ifdef so they are always defined as unsigned int regardless of SMALL_MEMORY. Update include/nuttx/fs/hostfs.h to match: drop the int16_t variants of nuttx_gid_t/nuttx_uid_t and keep a single unsigned int definition so the hostfs RPC ABI stays in sync with sys/types.h. Signed-off-by: Xiang Xiao --- include/nuttx/fs/hostfs.h | 10 ++++++---- include/sys/types.h | 11 ++--------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/include/nuttx/fs/hostfs.h b/include/nuttx/fs/hostfs.h index 92c611e8b0385..65d0c1dd83acd 100644 --- a/include/nuttx/fs/hostfs.h +++ b/include/nuttx/fs/hostfs.h @@ -110,20 +110,21 @@ /* These must match the definitions in include/sys/types.h */ typedef int16_t nuttx_blksize_t; + # ifdef CONFIG_SMALL_MEMORY -typedef int16_t nuttx_gid_t; -typedef int16_t nuttx_uid_t; typedef uint16_t nuttx_size_t; typedef int16_t nuttx_ssize_t; # else /* CONFIG_SMALL_MEMORY */ -typedef unsigned int nuttx_gid_t; -typedef unsigned int nuttx_uid_t; typedef uintptr_t nuttx_size_t; typedef intptr_t nuttx_ssize_t; # endif /* CONFIG_SMALL_MEMORY */ + +typedef unsigned int nuttx_gid_t; +typedef unsigned int nuttx_uid_t; typedef uint32_t nuttx_dev_t; typedef uint16_t nuttx_ino_t; typedef uint16_t nuttx_nlink_t; + # ifdef CONFIG_FS_LARGEFILE typedef int64_t nuttx_off_t; typedef uint64_t nuttx_blkcnt_t; @@ -131,6 +132,7 @@ typedef uint64_t nuttx_blkcnt_t; typedef int32_t nuttx_off_t; typedef uint32_t nuttx_blkcnt_t; # endif + typedef unsigned int nuttx_mode_t; typedef int nuttx_fsid_t[2]; diff --git a/include/sys/types.h b/include/sys/types.h index 0836db8feb348..02ed42b08e676 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -123,19 +123,14 @@ typedef uint16_t size_t; typedef int16_t ssize_t; typedef uint16_t rsize_t; -/* uid_t is used for user IDs - * gid_t is used for group IDs. - */ - -typedef int16_t uid_t; -typedef int16_t gid_t; - #else /* CONFIG_SMALL_MEMORY */ typedef _size_t size_t; typedef _ssize_t ssize_t; typedef _size_t rsize_t; +#endif /* CONFIG_SMALL_MEMORY */ + /* uid_t is used for user IDs * gid_t is used for group IDs. */ @@ -143,8 +138,6 @@ typedef _size_t rsize_t; typedef unsigned int uid_t; typedef unsigned int gid_t; -#endif /* CONFIG_SMALL_MEMORY */ - /* dev_t is used for device IDs */ typedef uint32_t dev_t; From 106e240e4c351f49b01ebf0117b60788429436a4 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sat, 20 Jun 2026 21:39:20 +0800 Subject: [PATCH 2/3] fs: widen ino_t from uint16_t to uint32_t A 16-bit ino_t can only address 65536 distinct file serial numbers, which is not enough for filesystems with large directory trees and breaks portable software (e.g. dropbear's scp) that expects a wider inode number space. Widen ino_t (and nuttx_ino_t in the hostfs ABI) to uint32_t to match common POSIX practice. Update fs/rpmsgfs/rpmsgfs.h accordingly: promote the 'ino' field in struct rpmsgfs_stat_priv_s from uint16_t to uint32_t and move 'nlink' into the trailing 16-bit slot previously occupied by the reserved field, keeping the overall packed-struct layout/size unchanged. Signed-off-by: Xiang Xiao --- fs/rpmsgfs/rpmsgfs.h | 5 ++--- include/nuttx/fs/hostfs.h | 2 +- include/sys/types.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/rpmsgfs/rpmsgfs.h b/fs/rpmsgfs/rpmsgfs.h index ceb13db779d95..0d9f94c1c1a63 100644 --- a/fs/rpmsgfs/rpmsgfs.h +++ b/fs/rpmsgfs/rpmsgfs.h @@ -123,8 +123,7 @@ begin_packed_struct struct rpmsgfs_stat_priv_s uint32_t dev; /* Device ID of device containing file */ uint32_t mode; /* File type, attributes, and access mode bits */ uint32_t rdev; /* Device ID (if file is character or block special) */ - uint16_t ino; /* File serial number */ - uint16_t nlink; /* Number of hard links to the file */ + uint32_t ino; /* File serial number */ int64_t size; /* Size of file/directory, in bytes */ int64_t atim_sec; /* Time of last access, seconds */ int64_t atim_nsec; /* Time of last access, nanoseconds */ @@ -136,7 +135,7 @@ begin_packed_struct struct rpmsgfs_stat_priv_s int16_t uid; /* User ID of file */ int16_t gid; /* Group ID of file */ int16_t blksize; /* Block size used for filesystem I/O */ - uint16_t reserved; /* Reserved space */ + uint16_t nlink; /* Number of hard links to the file */ } end_packed_struct; begin_packed_struct struct rpmsgfs_fstat_s diff --git a/include/nuttx/fs/hostfs.h b/include/nuttx/fs/hostfs.h index 65d0c1dd83acd..2221591d256a9 100644 --- a/include/nuttx/fs/hostfs.h +++ b/include/nuttx/fs/hostfs.h @@ -122,7 +122,7 @@ typedef intptr_t nuttx_ssize_t; typedef unsigned int nuttx_gid_t; typedef unsigned int nuttx_uid_t; typedef uint32_t nuttx_dev_t; -typedef uint16_t nuttx_ino_t; +typedef uint32_t nuttx_ino_t; typedef uint16_t nuttx_nlink_t; # ifdef CONFIG_FS_LARGEFILE diff --git a/include/sys/types.h b/include/sys/types.h index 02ed42b08e676..e36aad87d4926 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -144,7 +144,7 @@ typedef uint32_t dev_t; /* ino_t is used for file serial numbers */ -typedef uint16_t ino_t; +typedef uint32_t ino_t; /* nlink_t is used for link counts */ From 06541824689c96291b3061e65ff05e35dbac91f5 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Tue, 9 Jun 2026 13:29:16 +0800 Subject: [PATCH 3/3] fs/dirent: add d_ino member to struct dirent Add the POSIX d_ino (file serial number) member to struct dirent and populate it on every readdir() path, so portable callers (e.g. scp in dropbear) that read dp->d_ino observe a meaningful, non-zero inode number: - include/dirent.h: declare d_ino in struct dirent and drop the outdated comment claiming the field is unimplemented. - include/nuttx/fs/hostfs.h: add d_ino to struct nuttx_dirent_s so the hostfs ABI can carry the inode number across the VFS boundary. - arch/sim/src/sim/posix/sim_hostfs.c: forward the host's ent->d_ino into entry->d_ino. - fs/vfs/fs_dir.c (read_pseudodir): copy the in-memory inode's i_ino into entry->d_ino for the pseudo filesystem. - fs/yaffs/yaffs_vfs.c: forward yaffs's dirent->d_ino into entry->d_ino. - fs/rpmsgfs: extend struct rpmsgfs_readdir_s with an 'ino' field and propagate it across the RPC in both rpmsgfs_server (fills it from the underlying entry) and rpmsgfs_client (writes it back to the caller's nuttx_dirent_s). Signed-off-by: Xiang Xiao --- arch/sim/src/sim/posix/sim_hostfs.c | 2 ++ fs/rpmsgfs/rpmsgfs.h | 1 + fs/rpmsgfs/rpmsgfs_client.c | 1 + fs/rpmsgfs/rpmsgfs_server.c | 1 + fs/vfs/fs_dir.c | 2 ++ include/dirent.h | 3 ++- include/nuttx/fs/hostfs.h | 1 + 7 files changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/sim/src/sim/posix/sim_hostfs.c b/arch/sim/src/sim/posix/sim_hostfs.c index 8597b036f1ca1..2cf414f98181e 100644 --- a/arch/sim/src/sim/posix/sim_hostfs.c +++ b/arch/sim/src/sim/posix/sim_hostfs.c @@ -443,6 +443,8 @@ int host_readdir(void *dirp, struct nuttx_dirent_s *entry) strncpy(entry->d_name, ent->d_name, sizeof(entry->d_name) - 1); entry->d_name[sizeof(entry->d_name) - 1] = 0; + entry->d_ino = ent->d_ino; + /* Map the type */ if (ent->d_type == DT_REG) diff --git a/fs/rpmsgfs/rpmsgfs.h b/fs/rpmsgfs/rpmsgfs.h index 0d9f94c1c1a63..aa6aa805d95ea 100644 --- a/fs/rpmsgfs/rpmsgfs.h +++ b/fs/rpmsgfs/rpmsgfs.h @@ -166,6 +166,7 @@ begin_packed_struct struct rpmsgfs_readdir_s { struct rpmsgfs_header_s header; int32_t fd; + uint32_t ino; uint32_t type; char name[0]; } end_packed_struct; diff --git a/fs/rpmsgfs/rpmsgfs_client.c b/fs/rpmsgfs/rpmsgfs_client.c index 1451ccd658ecd..dd1883a2ce28a 100644 --- a/fs/rpmsgfs/rpmsgfs_client.c +++ b/fs/rpmsgfs/rpmsgfs_client.c @@ -209,6 +209,7 @@ static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, { strlcpy(entry->d_name, rsp->name, sizeof(entry->d_name)); entry->d_type = rsp->type; + entry->d_ino = rsp->ino; } rpmsg_post(ept, &cookie->sem); diff --git a/fs/rpmsgfs/rpmsgfs_server.c b/fs/rpmsgfs/rpmsgfs_server.c index 1e87da502bb93..4377bf14f9994 100644 --- a/fs/rpmsgfs/rpmsgfs_server.c +++ b/fs/rpmsgfs/rpmsgfs_server.c @@ -622,6 +622,7 @@ static int rpmsgfs_readdir_handler(FAR struct rpmsg_endpoint *ept, size = MIN(size - len, strlen(entry->d_name) + 1); msg->type = entry->d_type; strlcpy(msg->name, entry->d_name, size); + msg->ino = entry->d_ino; len += size; ret = 0; } diff --git a/fs/vfs/fs_dir.c b/fs/vfs/fs_dir.c index 14c172bdc62a1..bf8b899bb9a90 100644 --- a/fs/vfs/fs_dir.c +++ b/fs/vfs/fs_dir.c @@ -376,6 +376,8 @@ static int read_pseudodir(FAR struct fs_dirent_s *dir, entry->d_type = DTYPE_DIRECTORY; } + entry->d_ino = pdir->next->i_ino; + /* Now get the inode to visit next time that readdir() is called */ inode_lock(); diff --git a/include/dirent.h b/include/dirent.h index 23da8e06bb994..3b8b95254c89e 100644 --- a/include/dirent.h +++ b/include/dirent.h @@ -107,11 +107,12 @@ * of char containing at least {NAME_MAX} plus one elements. * * POSIX also requires the field d_ino (type ino_t) that provides the file - * serial number. This functionality is not implemented in NuttX. + * serial number. */ struct dirent { + ino_t d_ino; /* File serial number */ uint8_t d_type; /* Type of file */ char d_name[NAME_MAX + 1]; /* File name */ }; diff --git a/include/nuttx/fs/hostfs.h b/include/nuttx/fs/hostfs.h index 2221591d256a9..94589ddc4f015 100644 --- a/include/nuttx/fs/hostfs.h +++ b/include/nuttx/fs/hostfs.h @@ -150,6 +150,7 @@ struct nuttx_timespec struct nuttx_dirent_s { + nuttx_ino_t d_ino; uint8_t d_type; /* type of file */ char d_name[CONFIG_NAME_MAX + 1]; /* filename */ };