From 663b17b24be8477806b1583393c48527732f72b3 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Thu, 16 Jul 2026 15:14:59 +0800 Subject: [PATCH 1/5] arch/sim: Add AF_LOCAL support to host usrsock The sim host usrsock backend only accepted INET/NETLINK domains and translated socket addresses through plain struct sockaddr. That prevents simulated applications from using POSIX AF_LOCAL sockets through the standard socket API when CONFIG_NET_USRSOCK is used. Add AF_LOCAL address conversion for struct sockaddr_un, allow PF_LOCAL sockets through usrsock, handle NuttX socket type flags, and poll host descriptors from the sim usrsock work item so nonblocking connect/read/write readiness is reported back to NuttX. Use sockaddr_storage for native address translation so larger address structures are not truncated. Testing: - Host: Ubuntu 22.04 x86_64. - Board/config: sim:nsh with CONFIG_NET_USRSOCK=y and CONFIG_EXAMPLES_HELLO=y. - make clean && make -j16. - Ran a temporary hello example that connected to host AF_UNIX SOCK_STREAM and SOCK_SEQPACKET sockets through NuttX socket(), connect(), write(), and read(). Both received pong and printed "AF_LOCAL usrsock test passed". Assisted-by: Claude:Claude-Fable-5 Signed-off-by: Lingao Meng --- arch/sim/src/sim/posix/sim_hostusrsock.c | 248 +++++++++++++++++------ arch/sim/src/sim/sim_hostusrsock.h | 8 + arch/sim/src/sim/sim_usrsock.c | 1 + net/usrsock/usrsock_sockif.c | 10 +- 4 files changed, 202 insertions(+), 65 deletions(-) diff --git a/arch/sim/src/sim/posix/sim_hostusrsock.c b/arch/sim/src/sim/posix/sim_hostusrsock.c index 4ba0fb0dafa54..52cd495ecadbf 100644 --- a/arch/sim/src/sim/posix/sim_hostusrsock.c +++ b/arch/sim/src/sim/posix/sim_hostusrsock.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include +#include #include "sim_internal.h" #include "sim_hostusrsock.h" @@ -92,26 +94,93 @@ static void host_usrsock_set_fd(int fd, fd_set *fds) } } -static void sockaddr_to_native(const struct nuttx_sockaddr *addr, - const nuttx_socklen_t addrlen, - struct sockaddr *naddr, - socklen_t *naddrlen) +static int sockaddr_to_native(const struct nuttx_sockaddr *addr, + nuttx_socklen_t addrlen, + struct sockaddr_storage *naddr, + socklen_t *naddrlen) { - naddr->sa_family = addr->sa_family; - memcpy(naddr->sa_data, addr->sa_data, sizeof(naddr->sa_data)); + if (addr == NULL || naddr == NULL || naddrlen == NULL) + { + return -EINVAL; + } + + memset(naddr, 0, sizeof(*naddr)); + + if (addr->sa_family == NUTTX_AF_LOCAL) + { + const struct nuttx_sockaddr_un *un = + (const struct nuttx_sockaddr_un *)addr; + struct sockaddr_un *native = (struct sockaddr_un *)naddr; + size_t pathlen; + + if (addrlen < offsetof(struct nuttx_sockaddr_un, sun_path) + 1) + { + return -EINVAL; + } + + pathlen = strnlen(un->sun_path, sizeof(un->sun_path)); + if (pathlen >= sizeof(native->sun_path)) + { + return -ENAMETOOLONG; + } + native->sun_family = AF_UNIX; + memcpy(native->sun_path, un->sun_path, pathlen + 1); + *naddrlen = offsetof(struct sockaddr_un, sun_path) + pathlen + 1; + + return 0; + } + + if (addrlen > sizeof(*naddr)) + { + return -ENOSPC; + } + + memcpy(naddr, addr, addrlen); *naddrlen = addrlen; + + return 0; } -static void sockaddr_to_nuttx(const struct sockaddr *naddr, - const socklen_t naddrlen, - struct nuttx_sockaddr *addr, - nuttx_socklen_t *addrlen) +static int sockaddr_to_nuttx(const struct sockaddr_storage *naddr, + socklen_t naddrlen, + struct nuttx_sockaddr *addr, + nuttx_socklen_t *addrlen) { - addr->sa_family = naddr->sa_family; - memcpy(addr->sa_data, naddr->sa_data, sizeof(addr->sa_data)); + if (naddr == NULL || addr == NULL || addrlen == NULL) + { + return -EINVAL; + } + + if (naddr->ss_family == AF_UNIX) + { + const struct sockaddr_un *native = (const struct sockaddr_un *)naddr; + struct nuttx_sockaddr_un *un = (struct nuttx_sockaddr_un *)addr; + size_t pathlen; + + if (*addrlen < sizeof(*un)) + { + return -ENOSPC; + } + + memset(un, 0, sizeof(*un)); + pathlen = strnlen(native->sun_path, sizeof(native->sun_path)); + un->sun_family = NUTTX_AF_LOCAL; + memcpy(un->sun_path, native->sun_path, pathlen); + *addrlen = offsetof(struct nuttx_sockaddr_un, sun_path) + pathlen + 1; + + return 0; + } + if (*addrlen < naddrlen) + { + return -ENOSPC; + } + + memcpy(addr, naddr, naddrlen); *addrlen = naddrlen; + + return 0; } static void sock_nonblock(int socket, int enable) @@ -248,33 +317,68 @@ static int host_usrsock_sockopt(int sockfd, int level, int optname, int host_usrsock_socket(int domain, int type, int protocol) { int opt = 1; + int sockflags = 0; int ret; - if (domain == NUTTX_PF_INET) + switch (domain) { - domain = PF_INET; - } - else - { - return -EINVAL; - } + case NUTTX_PF_INET: + domain = PF_INET; + break; - if (type == NUTTX_SOCK_STREAM) - { - type = SOCK_STREAM; +#ifdef CONFIG_NET_IPv6 + case NUTTX_PF_INET6: + domain = PF_INET6; + break; +#endif + + case NUTTX_PF_LOCAL: + domain = PF_UNIX; + break; + + default: + return -EINVAL; } - else if (type == NUTTX_SOCK_DGRAM) + + switch (type & NUTTX_SOCK_TYPE_MASK) { - type = SOCK_DGRAM; + case NUTTX_SOCK_STREAM: + sockflags = SOCK_STREAM; + break; + + case NUTTX_SOCK_DGRAM: + sockflags = SOCK_DGRAM; + break; + + case NUTTX_SOCK_RAW: + sockflags = SOCK_RAW; + break; + + case NUTTX_SOCK_SEQPACKET: +#ifdef SOCK_SEQPACKET + sockflags = SOCK_SEQPACKET; + break; +#else + return -EPROTONOSUPPORT; +#endif + + default: + return -EINVAL; } - else if (type == NUTTX_SOCK_RAW) + +#ifdef SOCK_CLOEXEC + if ((type & NUTTX_SOCK_CLOEXEC) != 0) { - type = SOCK_RAW; + sockflags |= SOCK_CLOEXEC; } - else +#endif + +#ifdef SOCK_NONBLOCK + if ((type & NUTTX_SOCK_NONBLOCK) != 0) { - return -EINVAL; + sockflags |= SOCK_NONBLOCK; } +#endif if (protocol == NUTTX_IPPROTO_IP) { @@ -297,7 +401,7 @@ int host_usrsock_socket(int domain, int type, int protocol) return -EINVAL; } - ret = socket(domain, type, protocol); + ret = socket(domain, sockflags, protocol); if (ret < 0) { return -errno; @@ -327,17 +431,26 @@ int host_usrsock_connect(int sockfd, const struct nuttx_sockaddr *addr, nuttx_socklen_t addrlen) { - struct sockaddr naddr; + struct sockaddr_storage naddr; socklen_t naddrlen; int ret; - sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); + ret = sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); + if (ret < 0) + { + return ret; + } - sock_nonblock(sockfd, false); - ret = connect(sockfd, &naddr, naddrlen); - sock_nonblock(sockfd, true); + ret = connect(sockfd, (struct sockaddr *)&naddr, naddrlen); if (ret < 0) { + if (errno == EINPROGRESS || errno == EALREADY || errno == EWOULDBLOCK) + { + host_usrsock_set_fd(sockfd, &g_active_write_fds); + host_usrsock_set_fd(sockfd, &g_active_read_fds); + return -EINPROGRESS; + } + return -errno; } @@ -351,14 +464,20 @@ ssize_t host_usrsock_sendto(int sockfd, const void *buf, const struct nuttx_sockaddr *dest_addr, nuttx_socklen_t addrlen) { - struct sockaddr naddr; + struct sockaddr_storage naddr; socklen_t naddrlen; int ret; if (dest_addr && addrlen >= sizeof(*dest_addr)) { - sockaddr_to_native(dest_addr, addrlen, &naddr, &naddrlen); - ret = sendto(sockfd, buf, len, flags, &naddr, naddrlen); + ret = sockaddr_to_native(dest_addr, addrlen, &naddr, &naddrlen); + if (ret < 0) + { + return ret; + } + + ret = sendto(sockfd, buf, len, flags, + (struct sockaddr *)&naddr, naddrlen); } else { @@ -384,14 +503,14 @@ ssize_t host_usrsock_recvfrom(int sockfd, void *buf, size_t len, int flags, struct nuttx_sockaddr *src_addr, nuttx_socklen_t *addrlen) { - struct sockaddr naddr; - socklen_t naddrlen; + struct sockaddr_storage naddr; + socklen_t naddrlen = sizeof(naddr); int ret; - if (src_addr && addrlen && *addrlen >= sizeof(*src_addr)) + if (src_addr && addrlen) { - sockaddr_to_native(src_addr, *addrlen, &naddr, &naddrlen); - ret = recvfrom(sockfd, buf, len, flags, &naddr, &naddrlen); + ret = recvfrom(sockfd, buf, len, flags, + (struct sockaddr *)&naddr, &naddrlen); } else { @@ -408,7 +527,7 @@ ssize_t host_usrsock_recvfrom(int sockfd, void *buf, size_t len, int flags, return -errno; } - if (src_addr && addrlen && *addrlen >= sizeof(*src_addr)) + if (src_addr && addrlen) { sockaddr_to_nuttx(&naddr, naddrlen, src_addr, addrlen); } @@ -436,19 +555,19 @@ int host_usrsock_getsockname(int sockfd, struct nuttx_sockaddr *addr, nuttx_socklen_t *addrlen) { - socklen_t naddrlen = sizeof(struct sockaddr); - struct sockaddr naddr; + socklen_t naddrlen = sizeof(struct sockaddr_storage); + struct sockaddr_storage naddr; int ret; - ret = getsockname(sockfd, &naddr, &naddrlen); + ret = getsockname(sockfd, (struct sockaddr *)&naddr, &naddrlen); if (ret < 0) { return -errno; } - if (addr && addrlen && *addrlen >= sizeof(*addr)) + if (addr && addrlen) { - sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); + ret = sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); } return ret; @@ -458,19 +577,19 @@ int host_usrsock_getpeername(int sockfd, struct nuttx_sockaddr *addr, nuttx_socklen_t *addrlen) { - socklen_t naddrlen = sizeof(struct sockaddr); - struct sockaddr naddr; + socklen_t naddrlen = sizeof(struct sockaddr_storage); + struct sockaddr_storage naddr; int ret; - ret = getpeername(sockfd, &naddr, &naddrlen); + ret = getpeername(sockfd, (struct sockaddr *)&naddr, &naddrlen); if (ret < 0) { return -errno; } - if (addr && addrlen && *addrlen >= sizeof(*addr)) + if (addr && addrlen) { - sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); + ret = sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); } return ret; @@ -480,12 +599,17 @@ int host_usrsock_bind(int sockfd, const struct nuttx_sockaddr *addr, nuttx_socklen_t addrlen) { - struct sockaddr naddr; + struct sockaddr_storage naddr; socklen_t naddrlen; + int ret; - sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); + ret = sockaddr_to_native(addr, addrlen, &naddr, &naddrlen); + if (ret < 0) + { + return ret; + } - return bind(sockfd, &naddr, naddrlen) < 0 ? -errno : 0; + return bind(sockfd, (struct sockaddr *)&naddr, naddrlen) < 0 ? -errno : 0; } int host_usrsock_listen(int sockfd, int backlog) @@ -506,17 +630,17 @@ int host_usrsock_listen(int sockfd, int backlog) int host_usrsock_accept(int sockfd, struct nuttx_sockaddr *addr, nuttx_socklen_t *addrlen) { - socklen_t naddrlen = sizeof(socklen_t); - struct sockaddr naddr; + socklen_t naddrlen = sizeof(struct sockaddr_storage); + struct sockaddr_storage naddr; int ret; - ret = accept(sockfd, &naddr, &naddrlen); - if (ret <= 0) + ret = accept(sockfd, (struct sockaddr *)&naddr, &naddrlen); + if (ret < 0) { return -errno; } - if (addr && addrlen && *addrlen >= sizeof(*addr)) + if (addr && addrlen) { sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen); } @@ -562,7 +686,7 @@ void host_usrsock_loop(void) int ret; int i; - if (g_active_maxfd <= 0) + if (g_active_maxfd < 0) { return; } diff --git a/arch/sim/src/sim/sim_hostusrsock.h b/arch/sim/src/sim/sim_hostusrsock.h index e5fb2f10d3d31..34a2ce243b563 100644 --- a/arch/sim/src/sim/sim_hostusrsock.h +++ b/arch/sim/src/sim/sim_hostusrsock.h @@ -83,6 +83,8 @@ #define NUTTX_PF_PKTRADIO 64 #define NUTTX_PF_RPMSG 65 +#define NUTTX_UNIX_PATH_MAX 108 + #define NUTTX_AF_UNSPEC NUTTX_PF_UNSPEC #define NUTTX_AF_UNIX NUTTX_PF_UNIX #define NUTTX_AF_LOCAL NUTTX_PF_LOCAL @@ -219,6 +221,12 @@ struct nuttx_sockaddr char sa_data[14]; /* 14-bytes data (actually variable length) */ }; +struct nuttx_sockaddr_un +{ + sa_family_t sun_family; /* Address family: AF_LOCAL */ + char sun_path[NUTTX_UNIX_PATH_MAX]; +}; + struct nuttx_linger { int l_onoff; /* Indicates whether linger option is enabled. */ diff --git a/arch/sim/src/sim/sim_usrsock.c b/arch/sim/src/sim/sim_usrsock.c index c8210d0336149..ae41fc663b089 100644 --- a/arch/sim/src/sim/sim_usrsock.c +++ b/arch/sim/src/sim/sim_usrsock.c @@ -415,6 +415,7 @@ static const usrsock_handler_t g_usrsock_handler[] = static void sim_usrsock_work(void *arg) { + host_usrsock_loop(); work_queue_next_wq(g_work_queue, &g_usrsock.work, sim_usrsock_work, NULL, SIM_USRSOCK_PERIOD); } diff --git a/net/usrsock/usrsock_sockif.c b/net/usrsock/usrsock_sockif.c index 28079dfd38cf0..2e796a2b7dba9 100644 --- a/net/usrsock/usrsock_sockif.c +++ b/net/usrsock/usrsock_sockif.c @@ -103,10 +103,14 @@ static int usrsock_sockif_setup(FAR struct socket *psock) int ret; if (psock->s_domain != PF_INET && psock->s_domain != PF_INET6 && - psock->s_domain != PF_NETLINK) + psock->s_domain != PF_NETLINK +#ifndef CONFIG_NET_LOCAL + && psock->s_domain != PF_LOCAL +#endif + ) { - return -ENOTSUP; /* Only ipv4, ipv6 and netlink support the offload */ - }; + return -ENOTSUP; /* Only supported families can use usrsock offload */ + } /* Let the user socket logic handle the setup... * From 5b9707cb5c7d8378f5e6b2c2a71b1b91dd0a266a Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Thu, 16 Jul 2026 15:26:05 +0800 Subject: [PATCH 2/5] fs/hostfs: Handle POSIX byte-range locks fcntl(F_GETLK/F_SETLK/F_SETLKW) is handled by VFS and reaches file systems as private FIOC_* ioctl commands. hostfs previously forwarded those private ioctl command numbers to the host ioctl backend, which is not the POSIX file-locking interface and cannot be interpreted by the host OS. Keep hostfs on the generic host_ioctl() path and define the FIOC_* lock command values in the hostfs host ABI. The POSIX sim backend recognizes those commands in host_ioctl() and translates struct flock fields to the host ABI before calling host fcntl(). Other hostfs backends keep their existing unsupported-host-ioctl behavior. F_SETLKW is implemented in the POSIX sim backend by retrying non-blocking host F_SETLK with a short sleep. This preserves the blocking NuttX API without forwarding host F_SETLKW directly. Testing: - Host: Ubuntu 22.04 x86_64. - Board/config: sim:nsh with CONFIG_FS_HOSTFS=y, CONFIG_SIM_HOSTFS=y and CONFIG_EXAMPLES_SIM_POSIX=y. - make -j16. - Ran examples/sim_posix from nuttx-apps. The test mounted a long /tmp hostfs path, opened a host-backed file, and verified fcntl(F_SETLK), fcntl(F_GETLK), fcntl(F_SETLKW), and unlocking with F_UNLCK. The app printed "sim_posix: hostfs locks ok" and "sim_posix: PASS". Assisted-by: Claude:Claude-Fable-5 Signed-off-by: Lingao Meng --- arch/sim/src/sim/posix/sim_hostfs.c | 262 +++++++++++++++++++++------- fs/hostfs/hostfs.c | 6 - include/nuttx/fs/hostfs.h | 21 +++ 3 files changed, 217 insertions(+), 72 deletions(-) diff --git a/arch/sim/src/sim/posix/sim_hostfs.c b/arch/sim/src/sim/posix/sim_hostfs.c index 8716e9fe5123f..67380d14038f8 100644 --- a/arch/sim/src/sim/posix/sim_hostfs.c +++ b/arch/sim/src/sim/posix/sim_hostfs.c @@ -39,10 +39,191 @@ #include "hostfs.h" #include "sim_internal.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define HOSTFS_RETRY_DELAY_US 10000 + /**************************************************************************** * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: host_oflags_convert + ****************************************************************************/ + +static int host_oflags_convert(int flags) +{ + int mapflags = 0; + + switch (flags & NUTTX_O_ACCMODE) + { + case NUTTX_O_RDONLY: + mapflags = O_RDONLY; + break; + + case NUTTX_O_WRONLY: + mapflags = O_WRONLY; + break; + + case NUTTX_O_RDWR: + mapflags = O_RDWR; + break; + } + + if (flags & NUTTX_O_APPEND) + { + mapflags |= O_APPEND; + } + + if (flags & NUTTX_O_CREAT) + { + mapflags |= O_CREAT; + } + + if (flags & NUTTX_O_EXCL) + { + mapflags |= O_EXCL; + } + + if (flags & NUTTX_O_TRUNC) + { + mapflags |= O_TRUNC; + } + + if (flags & NUTTX_O_NONBLOCK) + { + mapflags |= O_NONBLOCK; + } + + if (flags & NUTTX_O_SYNC) + { + mapflags |= O_SYNC; + } + +#ifdef O_DIRECT + if (flags & NUTTX_O_DIRECT) + { + mapflags |= O_DIRECT; + } +#endif + + if (flags & NUTTX_O_CLOEXEC) + { + mapflags |= O_CLOEXEC; + } + + if (flags & NUTTX_O_DIRECTORY) + { + mapflags |= O_DIRECTORY; + } + + return mapflags; +} + +/**************************************************************************** + * Name: host_flock_type_convert + ****************************************************************************/ + +static int host_flock_type_convert(int type) +{ + switch (type) + { + case NUTTX_F_RDLCK: + return F_RDLCK; + + case NUTTX_F_WRLCK: + return F_WRLCK; + + case NUTTX_F_UNLCK: + return F_UNLCK; + + default: + return -EINVAL; + } +} + +/**************************************************************************** + * Name: host_flock_type_revert + ****************************************************************************/ + +static int host_flock_type_revert(int type) +{ + switch (type) + { + case F_RDLCK: + return NUTTX_F_RDLCK; + + case F_WRLCK: + return NUTTX_F_WRLCK; + + case F_UNLCK: + return NUTTX_F_UNLCK; + + default: + return -EINVAL; + } +} + +/**************************************************************************** + * Name: host_ioctl_fcntl + ****************************************************************************/ + +static int host_ioctl_fcntl(int fd, int request, unsigned long arg) +{ + struct nuttx_flock_s *lock = (struct nuttx_flock_s *)(uintptr_t)arg; + struct flock hostlock; + int ret; + + if (lock == NULL) + { + return -EINVAL; + } + + hostlock.l_type = host_flock_type_convert(lock->l_type); + if (hostlock.l_type < 0) + { + return hostlock.l_type; + } + + hostlock.l_whence = lock->l_whence; + hostlock.l_start = lock->l_start; + hostlock.l_len = lock->l_len; + hostlock.l_pid = lock->l_pid; + + for (; ; ) + { + ret = fcntl(fd, request == NUTTX_FIOC_GETLK ? F_GETLK : F_SETLK, + &hostlock); + if (ret >= 0 || request != NUTTX_FIOC_SETLKW || + (errno != EAGAIN && errno != EACCES)) + { + break; + } + + usleep(HOSTFS_RETRY_DELAY_US); + } + + if (ret < 0) + { + return host_errno_convert(-errno); + } + + lock->l_type = host_flock_type_revert(hostlock.l_type); + if (lock->l_type < 0) + { + return lock->l_type; + } + + lock->l_whence = hostlock.l_whence; + lock->l_start = hostlock.l_start; + lock->l_len = hostlock.l_len; + lock->l_pid = hostlock.l_pid; + + return ret; +} + /**************************************************************************** * Name: host_stat_convert ****************************************************************************/ @@ -130,71 +311,7 @@ static void host_stat_convert(struct stat *hostbuf, struct nuttx_stat_s *buf) int host_open(const char *pathname, int flags, int mode) { - int mapflags = 0; - - /* Perform flag mapping */ - - switch (flags & NUTTX_O_ACCMODE) - { - case NUTTX_O_RDONLY: - mapflags = O_RDONLY; - break; - - case NUTTX_O_WRONLY: - mapflags = O_WRONLY; - break; - - case NUTTX_O_RDWR: - mapflags = O_RDWR; - break; - } - - if (flags & NUTTX_O_APPEND) - { - mapflags |= O_APPEND; - } - - if (flags & NUTTX_O_CREAT) - { - mapflags |= O_CREAT; - } - - if (flags & NUTTX_O_EXCL) - { - mapflags |= O_EXCL; - } - - if (flags & NUTTX_O_TRUNC) - { - mapflags |= O_TRUNC; - } - - if (flags & NUTTX_O_NONBLOCK) - { - mapflags |= O_NONBLOCK; - } - - if (flags & NUTTX_O_SYNC) - { - mapflags |= O_SYNC; - } - -#ifdef O_DIRECT - if (flags & NUTTX_O_DIRECT) - { - mapflags |= O_DIRECT; - } -#endif - - if (flags & NUTTX_O_CLOEXEC) - { - mapflags |= O_CLOEXEC; - } - - if (flags & NUTTX_O_DIRECTORY) - { - mapflags |= O_DIRECTORY; - } + int mapflags = host_oflags_convert(flags); int ret = open(pathname, mapflags, mode); if (ret == -1) @@ -280,9 +397,22 @@ nuttx_off_t host_lseek(int fd, nuttx_off_t pos, nuttx_off_t offset, int host_ioctl(int fd, int request, unsigned long arg) { + int ret; + + switch (request) + { + case NUTTX_FIOC_GETLK: + case NUTTX_FIOC_SETLK: + case NUTTX_FIOC_SETLKW: + return host_ioctl_fcntl(fd, request, arg); + + default: + break; + } + /* Just call the ioctl routine */ - int ret = ioctl(fd, request, arg); + ret = ioctl(fd, request, arg); if (ret < 0) { ret = host_errno_convert(-errno); diff --git a/fs/hostfs/hostfs.c b/fs/hostfs/hostfs.c index 092655ef609ae..53143a6d30989 100644 --- a/fs/hostfs/hostfs.c +++ b/fs/hostfs/hostfs.c @@ -49,12 +49,6 @@ #include "hostfs.h" #include "fs_heap.h" -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define HOSTFS_RETRY_DELAY_MS 10 - /**************************************************************************** * Private Types ****************************************************************************/ diff --git a/include/nuttx/fs/hostfs.h b/include/nuttx/fs/hostfs.h index 694efe10c45fe..601b210db5aa5 100644 --- a/include/nuttx/fs/hostfs.h +++ b/include/nuttx/fs/hostfs.h @@ -113,6 +113,18 @@ #define NUTTX_CH_STAT_ATIME (1 << 3) #define NUTTX_CH_STAT_MTIME (1 << 4) +/* These must exactly match the definitions from include/nuttx/fs/ioctl.h: */ + +#define NUTTX_FIOC_SETLK 0x0312 +#define NUTTX_FIOC_GETLK 0x0313 +#define NUTTX_FIOC_SETLKW 0x0314 + +/* These must exactly match the definitions from include/fcntl.h: */ + +#define NUTTX_F_RDLCK 0 +#define NUTTX_F_WRLCK 1 +#define NUTTX_F_UNLCK 2 + #endif /* __SIM__ */ /**************************************************************************** @@ -203,6 +215,15 @@ struct nuttx_stat_s nuttx_blkcnt_t st_blocks; /* Number of blocks allocated */ }; +struct nuttx_flock_s +{ + int16_t l_type; + int16_t l_whence; + nuttx_off_t l_start; + nuttx_off_t l_len; + int32_t l_pid; +}; + #endif /* __SIM__ */ /**************************************************************************** From 2a934fbfba8df4bee5f137055d2a6713ff53c71a Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Thu, 16 Jul 2026 15:34:02 +0800 Subject: [PATCH 3/5] netdb: Add http and https service entries getaddrinfo() and getservbyname() use the built-in service table when resolving service names. The table only contained ntp, so common service names such as http and https could not be resolved without a numeric port. Add http and https entries for both TCP and UDP to match the existing service table style. Testing: - Host: Ubuntu 22.04 x86_64. - Board/config: sim:nsh with CONFIG_LIBC_NETDB=y and CONFIG_EXAMPLES_HELLO=y. - make clean && make -j16. - Ran a temporary hello example that called getservbyname("http", "tcp") and getservbyname("https", "tcp"). The app verified ports 80 and 443 and printed "getservbyname http/https test passed". Assisted-by: Claude:Claude-Fable-5 Signed-off-by: Lingao Meng --- libs/libc/netdb/lib_getservbynamer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/libc/netdb/lib_getservbynamer.c b/libs/libc/netdb/lib_getservbynamer.c index a1fe9fee71ce2..eaf3a26e7db45 100644 --- a/libs/libc/netdb/lib_getservbynamer.c +++ b/libs/libc/netdb/lib_getservbynamer.c @@ -46,6 +46,10 @@ const struct services_db_s g_services_db[] = { + { "http", 80, IP_PROTO_TCP }, + { "http", 80, IP_PROTO_UDP }, + { "https", 443, IP_PROTO_TCP }, + { "https", 443, IP_PROTO_UDP }, { "ntp", 123, IP_PROTO_TCP }, { "ntp", 123, IP_PROTO_UDP }, { NULL, 0, 0 } From abc545ee95671d450e50cbf005225e1fdb8d2535 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Fri, 17 Jul 2026 16:00:00 +0800 Subject: [PATCH 4/5] fs/hostfs: Fix long root path construction hostfs_mkpath() appends a relative path to the configured host root with strlcat(). The third argument to strlcat() is the total destination buffer size, not the remaining free space. Passing pathlen - strlen(path) makes the effective limit shrink after a long host root has already been copied. With a sufficiently long root, a valid relative path can be dropped or truncated, so operations under the mount point may resolve to the host root instead of the requested child path. Pass the full destination buffer size and let strlcat() account for the current string length internally. The companion examples/hostfs_longpath app validates this regression by mounting hostfs with a long host root, writing a probe file below the mount point, and reading it back. The old size argument drops the relative component in that scenario; this fix preserves it. Assisted-by: Claude:Claude-Fable-5 Signed-off-by: Lingao Meng --- fs/hostfs/hostfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/hostfs/hostfs.c b/fs/hostfs/hostfs.c index 53143a6d30989..697a121548611 100644 --- a/fs/hostfs/hostfs.c +++ b/fs/hostfs/hostfs.c @@ -230,7 +230,7 @@ static void hostfs_mkpath(FAR struct hostfs_mountpt_s *fs, if (depth >= 0) { - strlcat(path, &relpath[first], pathlen - strlen(path)); + strlcat(path, &relpath[first], pathlen); } } From 8942c08ea6548079a7016901888102d24b3702b8 Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Fri, 17 Jul 2026 16:01:25 +0800 Subject: [PATCH 5/5] fs/hostfs: Use configured path length hostfs keeps its own HOSTFS_MAX_PATH wrapper for internal buffers, but it should not hard-code a path length separate from the system path configuration. Define HOSTFS_MAX_PATH from PATH_MAX instead. PATH_MAX is backed by CONFIG_PATH_MAX, whose default remains 256, so the default hostfs behavior does not change while configurations that choose a larger path limit are honored consistently. Assisted-by: Claude:Claude-Fable-5 Signed-off-by: Lingao Meng --- fs/hostfs/hostfs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 096be6ae75ae6..05486aed7cf32 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -29,6 +29,7 @@ #include +#include #include #include #include @@ -37,7 +38,7 @@ * Pre-processor Definitions ****************************************************************************/ -#define HOSTFS_MAX_PATH 256 +#define HOSTFS_MAX_PATH PATH_MAX /**************************************************************************** * Public Types