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 a0777a774b1124b0584970ecd79e6e528a47936e Author: Marco Casaroli <[email protected]> AuthorDate: Fri Oct 9 08:41:45 2026 +0200 libs/libc/grp: Add getgrent(), setgrent() and endgrent(). POSIX specifies getgrent(), setgrent() and endgrent() to walk the group database. NuttX had the passwd equivalents (getpwent() and the others) but not these. With CONFIG_LIBC_GROUP_FILE the entries come from the group file, found by index with a new grp_findby_index(). Without it the only group is root, as for getgrgid(). Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli <[email protected]> --- include/grp.h | 3 + libs/libc/grp/CMakeLists.txt | 10 ++- libs/libc/grp/Make.defs | 2 +- libs/libc/grp/lib_find_grpfile.c | 63 +++++++++++++++++ libs/libc/grp/{lib_grp.h => lib_getgrent.c} | 106 ++++++++++++++++------------ libs/libc/grp/lib_grp.h | 2 + 6 files changed, 137 insertions(+), 49 deletions(-) diff --git a/include/grp.h b/include/grp.h index 1c4f215e54f..7a066539945 100644 --- a/include/grp.h +++ b/include/grp.h @@ -63,6 +63,9 @@ extern "C" FAR struct group *getgrnam(FAR const char *name); FAR struct group *getgrgid(gid_t gid); +FAR struct group *getgrent(void); +void setgrent(void); +void endgrent(void); int getgrnam_r(FAR const char *name, FAR struct group *grp, FAR char *buf, diff --git a/libs/libc/grp/CMakeLists.txt b/libs/libc/grp/CMakeLists.txt index 62d98a9056a..111d4048e16 100644 --- a/libs/libc/grp/CMakeLists.txt +++ b/libs/libc/grp/CMakeLists.txt @@ -19,8 +19,14 @@ # the License. # # ############################################################################## -set(SRCS lib_getgrgid.c lib_getgrgidr.c lib_getgrnam.c lib_getgrnamr.c - lib_initgroups.c lib_getgrouplist.c) +set(SRCS + lib_getgrgid.c + lib_getgrgidr.c + lib_getgrnam.c + lib_getgrnamr.c + lib_initgroups.c + lib_getgrouplist.c + lib_getgrent.c) if(CONFIG_LIBC_GROUP_FILE) list(APPEND SRCS lib_find_grpfile.c lib_grp_globals.c) diff --git a/libs/libc/grp/Make.defs b/libs/libc/grp/Make.defs index 2fe4e37fc05..3654a811d0d 100644 --- a/libs/libc/grp/Make.defs +++ b/libs/libc/grp/Make.defs @@ -23,7 +23,7 @@ # Add the grp C files to the build CSRCS += lib_getgrgid.c lib_getgrgidr.c lib_getgrnam.c lib_getgrnamr.c -CSRCS += lib_initgroups.c lib_getgrouplist.c +CSRCS += lib_initgroups.c lib_getgrouplist.c lib_getgrent.c ifeq ($(CONFIG_LIBC_GROUP_FILE),y) CSRCS += lib_find_grpfile.c lib_grp_globals.c diff --git a/libs/libc/grp/lib_find_grpfile.c b/libs/libc/grp/lib_find_grpfile.c index a7f63db4c3f..f74842ef501 100644 --- a/libs/libc/grp/lib_find_grpfile.c +++ b/libs/libc/grp/lib_find_grpfile.c @@ -56,6 +56,14 @@ struct grp_user_s int count; /* Number of group IDs found so far */ }; +/* Context used by grp_match_index() to find the record with a given index */ + +struct grp_index_s +{ + int index; /* Index of the record to find */ + int current; /* Index of the record being visited */ +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -110,6 +118,31 @@ static int grp_match_gid(FAR const struct group *entry, uintptr_t arg) return match_gid == entry->gr_gid ? 1 : 0; } +/**************************************************************************** + * Name: grp_match_index + * + * Description: + * Called for each record in the group file. Returns "1" for the record + * with the index in the context (passed as arg). + * + * Input Parameters: + * entry - The parsed group file record + * arg - A pointer to the struct grp_index_s context + * + * Returned Value: + * = 0 : This is not the record with the index. + * = 1 : This is the record with the index. + * + ****************************************************************************/ + +static int grp_match_index(FAR const struct group *entry, uintptr_t arg) +{ + FAR struct grp_index_s *ctx = (FAR struct grp_index_s *)arg; + + UNUSED(entry); + return ctx->current++ == ctx->index ? 1 : 0; +} + /**************************************************************************** * Name: grp_match_user * @@ -401,6 +434,36 @@ int grp_findby_gid(gid_t gid, FAR struct group *entry, FAR char *buffer, return grp_foreach(grp_match_gid, (uintptr_t)gid, entry, buffer, buflen); } +/**************************************************************************** + * Name: grp_findby_index + * + * Description: + * Find the group file entry with the given index (0 is the first). + * + * Input Parameters: + * index - The index of the entry + * entry - Location to return the parsed group file entry + * buffer - I/O buffer used to access the group file + * buflen - The size of the I/O buffer in bytes + * + * Returned Value: + * < 0 : An error has occurred. + * = 0 : There is no entry with this index. + * = 1 : The entry with this index was found. + * + ****************************************************************************/ + +int grp_findby_index(int index, FAR struct group *entry, FAR char *buffer, + size_t buflen) +{ + struct grp_index_s ctx; + + ctx.index = index; + ctx.current = 0; + return grp_foreach(grp_match_index, (uintptr_t)&ctx, entry, buffer, + buflen); +} + /**************************************************************************** * Name: grp_findby_user * diff --git a/libs/libc/grp/lib_grp.h b/libs/libc/grp/lib_getgrent.c similarity index 53% copy from libs/libc/grp/lib_grp.h copy to libs/libc/grp/lib_getgrent.c index 0d84dd39652..761e904a13a 100644 --- a/libs/libc/grp/lib_grp.h +++ b/libs/libc/grp/lib_getgrent.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/grp/lib_grp.h + * libs/libc/grp/lib_getgrent.c * * SPDX-License-Identifier: Apache-2.0 * @@ -20,9 +20,6 @@ * ****************************************************************************/ -#ifndef __LIBS_LIBC_GRP_LIB_GRP_H -#define __LIBS_LIBC_GRP_LIB_GRP_H - /**************************************************************************** * Included Files ****************************************************************************/ @@ -31,65 +28,82 @@ #include <grp.h> +#include "grp/lib_grp.h" + /**************************************************************************** - * Pre-processor Definitions + * Private Data ****************************************************************************/ -#define ROOT_GID 0 -#define ROOT_NAME "root" -#define ROOT_PASSWD "x" +/* Index of the next entry that getgrent() returns */ -/* Reserver space for a NULL terminated list for group member names */ +static int g_group_index; -#define MEMBER_SIZE ((CONFIG_LIBC_GROUP_NUSERS + 1) * sizeof(FAR char *)) +/**************************************************************************** + * Public Functions + ****************************************************************************/ -/* Reserve space for the maximum line in the group file PLUS space for an - * array of Member names. - */ +/**************************************************************************** + * Name: setgrent + * + * Description: + * Rewind the group database, so that the next getgrent() returns the + * first entry. + * + ****************************************************************************/ -#define GRPBUF_RESERVE_SIZE (CONFIG_LIBC_GROUP_LINESIZE + MEMBER_SIZE) +void setgrent(void) +{ + g_group_index = 0; +} /**************************************************************************** - * Public Data + * Name: endgrent + * + * Description: + * Close the group database. The next getgrent() returns the first entry. + * ****************************************************************************/ -#ifdef __cplusplus -#define EXTERN extern "C" -extern "C" +void endgrent(void) { -#else -#define EXTERN extern -#endif + g_group_index = 0; +} +/**************************************************************************** + * Name: getgrent + * + * Description: + * Return the next entry of the group database. + * + * Returned Value: + * A pointer to a statically allocated group structure, or NULL if there + * are no more entries or an error occurs. + * + ****************************************************************************/ + +FAR struct group *getgrent(void) +{ #ifdef CONFIG_LIBC_GROUP_FILE -/* Data for non-reentrant group functions */ + int ret; -EXTERN struct group g_group; -EXTERN char g_group_buffer[GRPBUF_RESERVE_SIZE]; -#endif + ret = grp_findby_index(g_group_index, &g_group, g_group_buffer, + GRPBUF_RESERVE_SIZE); + if (ret != 1) + { + return NULL; + } -/**************************************************************************** - * Public Function Prototypes - ****************************************************************************/ + g_group_index++; + return &g_group; +#else + /* The only group is root */ -FAR struct group *getgrbuf(gid_t gid, FAR const char *name, - FAR const char *passwd); -int getgrbuf_r(gid_t gid, FAR const char *name, FAR const char *passwd, - FAR struct group *grp, FAR char *buf, size_t buflen, - FAR struct group **result); + if (g_group_index != 0) + { + return NULL; + } -#ifdef CONFIG_LIBC_GROUP_FILE -int grp_findby_name(FAR const char *gname, FAR struct group *entry, - FAR char *buffer, size_t buflen); -int grp_findby_gid(gid_t gid, FAR struct group *entry, FAR char *buffer, - size_t buflen); -int grp_findby_user(FAR const char *user, gid_t group, - FAR gid_t *grouplist, int maxgroups, FAR int *count); + g_group_index++; + return getgrbuf(ROOT_GID, ROOT_NAME, ROOT_PASSWD); #endif - -#undef EXTERN -#ifdef __cplusplus } -#endif - -#endif /* __LIBS_LIBC_GRP_LIB_GRP_H */ diff --git a/libs/libc/grp/lib_grp.h b/libs/libc/grp/lib_grp.h index 0d84dd39652..b70831d2a2b 100644 --- a/libs/libc/grp/lib_grp.h +++ b/libs/libc/grp/lib_grp.h @@ -83,6 +83,8 @@ int grp_findby_name(FAR const char *gname, FAR struct group *entry, FAR char *buffer, size_t buflen); int grp_findby_gid(gid_t gid, FAR struct group *entry, FAR char *buffer, size_t buflen); +int grp_findby_index(int index, FAR struct group *entry, FAR char *buffer, + size_t buflen); int grp_findby_user(FAR const char *user, gid_t group, FAR gid_t *grouplist, int maxgroups, FAR int *count); #endif
