git: 98b041239c25 - stable/14 - opendir, readdir, telldir: Use the correct types.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 05 Feb 2026 15:27:31 UTC
The branch stable/14 has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=98b041239c252d0c2433e5d412d74f90a235d0f2
commit 98b041239c252d0c2433e5d412d74f90a235d0f2
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2025-07-09 20:34:22 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-02-05 14:48:34 +0000
opendir, readdir, telldir: Use the correct types.
Use either size_t or off_t (as appropriate) instead of long.
Sponsored by: Klara, Inc.
Reviewed by: kevans
Differential Revision: https://reviews.freebsd.org/D51210
(cherry picked from commit 42e613018da50ee6877d24815c7626d79629e707)
readdir: Fix error check.
Now that dd_size is unsigned, we need to check if the return value from
getdirentries() was negative before assigning it to dd_size.
While here, simplify the scandir_error test case slightly, and verify
that calling readdir() again after EOF still returns NULL.
Fixes: 42e613018da5
Sponsored by: Klara, Inc.
Reviewed by: kevans
Differential Revision: https://reviews.freebsd.org/D51266
(cherry picked from commit 920b2183919e430cf85c4aa1fa337bfded12aee5)
---
lib/libc/gen/gen-private.h | 4 ++--
lib/libc/gen/opendir2.c | 6 ++++--
lib/libc/gen/readdir.c | 11 +++++++----
lib/libc/gen/telldir.c | 4 ++--
lib/libc/gen/telldir.h | 6 +++---
lib/libc/tests/gen/opendir_test.c | 1 +
lib/libc/tests/gen/scandir_test.c | 12 +++++-------
7 files changed, 24 insertions(+), 20 deletions(-)
diff --git a/lib/libc/gen/gen-private.h b/lib/libc/gen/gen-private.h
index 3792a61ff942..b6749b3435cd 100644
--- a/lib/libc/gen/gen-private.h
+++ b/lib/libc/gen/gen-private.h
@@ -43,8 +43,8 @@ struct pthread_mutex;
*/
struct _dirdesc {
int dd_fd; /* file descriptor associated with directory */
- long dd_loc; /* offset in current buffer */
- long dd_size; /* amount of data returned by getdirentries */
+ size_t dd_loc; /* offset in current buffer */
+ size_t dd_size; /* amount of data returned by getdirentries */
char *dd_buf; /* data buffer */
int dd_len; /* size of data buffer */
off_t dd_seek; /* magic cookie returned by getdirentries */
diff --git a/lib/libc/gen/opendir2.c b/lib/libc/gen/opendir2.c
index 928145b468c1..f85cdb9f6c75 100644
--- a/lib/libc/gen/opendir2.c
+++ b/lib/libc/gen/opendir2.c
@@ -264,6 +264,7 @@ DIR *
__opendir_common(int fd, int flags, bool use_current_pos)
{
DIR *dirp;
+ ssize_t ret;
int incr;
int saved_errno;
bool unionstack;
@@ -313,13 +314,14 @@ __opendir_common(int fd, int flags, bool use_current_pos)
* to prime dd_seek. This also checks if the
* fd passed to fdopendir() is a directory.
*/
- dirp->dd_size = _getdirentries(dirp->dd_fd,
+ ret = _getdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
- if (dirp->dd_size < 0) {
+ if (ret < 0) {
if (errno == EINVAL)
errno = ENOTDIR;
goto fail;
}
+ dirp->dd_size = (size_t)ret;
dirp->dd_flags |= __DTF_SKIPREAD;
} else {
dirp->dd_size = 0;
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
index d2c8636651ff..823ffc49b476 100644
--- a/lib/libc/gen/readdir.c
+++ b/lib/libc/gen/readdir.c
@@ -50,8 +50,9 @@ struct dirent *
_readdir_unlocked(DIR *dirp, int flags)
{
struct dirent *dp;
- long initial_seek;
- long initial_loc = 0;
+ off_t initial_seek;
+ size_t initial_loc = 0;
+ ssize_t ret;
for (;;) {
if (dirp->dd_loc >= dirp->dd_size) {
@@ -63,11 +64,13 @@ _readdir_unlocked(DIR *dirp, int flags)
}
if (dirp->dd_loc == 0 &&
!(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) {
+ dirp->dd_size = 0;
initial_seek = dirp->dd_seek;
- dirp->dd_size = _getdirentries(dirp->dd_fd,
+ ret = _getdirentries(dirp->dd_fd,
dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
- if (dirp->dd_size <= 0)
+ if (ret <= 0)
return (NULL);
+ dirp->dd_size = (size_t)ret;
_fixtelldir(dirp, initial_seek, initial_loc);
}
dirp->dd_flags &= ~__DTF_SKIPREAD;
diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c
index 9b60093ac472..ac0e2e50f9b3 100644
--- a/lib/libc/gen/telldir.c
+++ b/lib/libc/gen/telldir.c
@@ -120,7 +120,7 @@ _seekdir(DIR *dirp, long loc)
struct dirent *dp;
union ddloc_packed ddloc;
off_t loc_seek;
- long loc_loc;
+ size_t loc_loc;
ddloc.l = loc;
@@ -173,7 +173,7 @@ _seekdir(DIR *dirp, long loc)
* fetching a new block to fix any such telldir locations.
*/
void
-_fixtelldir(DIR *dirp, long oldseek, long oldloc)
+_fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc)
{
struct ddloc_mem *lp;
diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h
index 6d113491e819..02fd52af9060 100644
--- a/lib/libc/gen/telldir.h
+++ b/lib/libc/gen/telldir.h
@@ -46,9 +46,9 @@
*/
struct ddloc_mem {
LIST_ENTRY(ddloc_mem) loc_lqe; /* entry in list */
- long loc_index; /* key associated with structure */
+ size_t loc_index; /* key associated with structure */
off_t loc_seek; /* magic cookie returned by getdirentries */
- long loc_loc; /* offset of entry in buffer */
+ size_t loc_loc; /* offset of entry in buffer */
};
#ifdef __LP64__
@@ -102,7 +102,7 @@ bool _filldir(DIR *, bool);
struct dirent *_readdir_unlocked(DIR *, int);
void _reclaim_telldir(DIR *);
void _seekdir(DIR *, long);
-void _fixtelldir(DIR *dirp, long oldseek, long oldloc);
+void _fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc);
DIR *__opendir_common(int, int, bool);
#define RDU_SKIP 0x0001
diff --git a/lib/libc/tests/gen/opendir_test.c b/lib/libc/tests/gen/opendir_test.c
index 89be2becc607..b7481255654f 100644
--- a/lib/libc/tests/gen/opendir_test.c
+++ b/lib/libc/tests/gen/opendir_test.c
@@ -46,6 +46,7 @@ opendir_check(const struct atf_tc *tc, DIR *dirp)
ATF_CHECK_STREQ("subdir", ent->d_name);
ATF_CHECK_EQ(DT_DIR, ent->d_type);
ATF_CHECK(readdir(dirp) == NULL);
+ ATF_CHECK(readdir(dirp) == NULL);
}
ATF_TC(opendir_ok);
diff --git a/lib/libc/tests/gen/scandir_test.c b/lib/libc/tests/gen/scandir_test.c
index f7b52b5e3616..afd25bf7c0b2 100644
--- a/lib/libc/tests/gen/scandir_test.c
+++ b/lib/libc/tests/gen/scandir_test.c
@@ -157,7 +157,7 @@ ATF_TC_BODY(scandir_error, tc)
{
char path[16];
struct dirent **namelist = NULL;
- int fd, i, ret;
+ int fd, i;
ATF_REQUIRE_EQ(0, mkdir("dir", 0755));
for (i = 0; i < 1024; i++) {
@@ -170,9 +170,8 @@ ATF_TC_BODY(scandir_error, tc)
scandir_error_count = 0;
scandir_error_fd = fd;
scandir_error_select_return = 0;
- ret = fdscandir(fd, &namelist, scandir_error_select, NULL);
- ATF_CHECK_EQ(-1, ret);
- ATF_CHECK_ERRNO(EBADF, ret < 0);
+ ATF_CHECK_ERRNO(EBADF,
+ fdscandir(fd, &namelist, scandir_error_select, NULL) < 0);
ATF_CHECK_EQ(NULL, namelist);
/* second pass, select everything */
@@ -180,9 +179,8 @@ ATF_TC_BODY(scandir_error, tc)
scandir_error_count = 0;
scandir_error_fd = fd;
scandir_error_select_return = 1;
- ret = fdscandir(fd, &namelist, scandir_error_select, NULL);
- ATF_CHECK_EQ(-1, ret);
- ATF_CHECK_ERRNO(EBADF, ret < 0);
+ ATF_CHECK_ERRNO(EBADF,
+ fdscandir(fd, &namelist, scandir_error_select, NULL) < 0);
ATF_CHECK_EQ(NULL, namelist);
}