You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/10/09 18:32:29 UTC
(nuttx) 05/06: libs/libc/grp: Add getgrent(), setgrent() and endgrent().
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 <ma...@gmail.com>
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 <ma...@gmail.com>
---
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