# HG changeset patch # User Taylor R Campbell # Date 1725116374 0 # Sat Aug 31 14:59:34 2024 +0000 # Branch trunk # Node ID f39f4bb8989435150b682bb087c507f41adcaf8d # Parent 9aaaa3422f6c6a29e9679ebd97936a4038ca0060 # EXP-Topic riastradh-pr57145-readdirerrno readdir(3): Preserve errno on end-of-directory. PR pkg/57145: gmake: *** INTERNAL: readdir: Operation not supported. Stop. diff -r 9aaaa3422f6c -r f39f4bb89894 lib/libc/gen/readdir.c --- a/lib/libc/gen/readdir.c Thu Aug 29 13:39:42 2024 +0000 +++ b/lib/libc/gen/readdir.c Sat Aug 31 14:59:34 2024 +0000 @@ -56,35 +56,50 @@ static char sccsid[] = "@(#)readdir.c 8. struct dirent * _readdir_unlocked(DIR *dirp, int skipdeleted) { + const int saved_errno = errno; struct dirent *dp; for (;;) { if (dirp->dd_loc >= dirp->dd_size) { if (dirp->dd_flags & __DTF_READALL) - return (NULL); + break; dirp->dd_loc = 0; } if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) { dirp->dd_seek = lseek(dirp->dd_fd, (off_t)0, SEEK_CUR); dirp->dd_size = getdents(dirp->dd_fd, dirp->dd_buf, (size_t)dirp->dd_len); - if (dirp->dd_size <= 0) - return (NULL); + if (dirp->dd_size == 0) /* end of directory */ + break; + if (dirp->dd_size == -1) /* getdents sets errno */ + return NULL; + if (dirp->dd_size < 0) { /* paranoia */ + errno = EIO; + return NULL; + } } dp = (struct dirent *) (void *)(dirp->dd_buf + (size_t)dirp->dd_loc); - if ((intptr_t)dp & _DIRENT_ALIGN(dp))/* bogus pointer check */ - return (NULL); + /* bogus pointer check */ + if ((intptr_t)dp & _DIRENT_ALIGN(dp)) { + errno = EIO; + return NULL; + } /* d_reclen is unsigned; no need to compare it <= 0 */ - if (dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) - return (NULL); + if (dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc) { + errno = EIO; + return NULL; + } dirp->dd_loc += dp->d_reclen; if (dp->d_ino == 0 && skipdeleted) continue; if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW)) continue; - return (dp); + return dp; } + + errno = saved_errno; + return NULL; } struct dirent * # HG changeset patch # User Taylor R Campbell # Date 1725117699 0 # Sat Aug 31 15:21:39 2024 +0000 # Branch trunk # Node ID 9968b55e8b190dbb8f054fc6901e11a382264a72 # Parent f39f4bb8989435150b682bb087c507f41adcaf8d # EXP-Topic riastradh-pr57145-readdirerrno readdir_r(3): Fix criterion for returning error. _If_ the result is null, _then_ errno is set on error or preserved on end-of-directory. Otherwise, all bets are off: errno may be changed on success. PR pkg/57145: gmake: *** INTERNAL: readdir: Operation not supported. Stop. diff -r f39f4bb89894 -r 9968b55e8b19 lib/libc/gen/readdir.c --- a/lib/libc/gen/readdir.c Sat Aug 31 14:59:34 2024 +0000 +++ b/lib/libc/gen/readdir.c Sat Aug 31 15:21:39 2024 +0000 @@ -139,8 +139,8 @@ readdir_r(DIR *dirp, struct dirent *entr if ((dp = _readdir_unlocked(dirp, 1)) != NULL) memcpy(entry, dp, (size_t)_DIRENT_SIZE(dp)); - if (errno != 0) { - if (dp == NULL) + if (dp == NULL) { + if (errno != 0) return (errno); } else errno = saved_errno; # HG changeset patch # User Taylor R Campbell # Date 1725119342 0 # Sat Aug 31 15:49:02 2024 +0000 # Branch trunk # Node ID 38029f50cf37ce95668214c8d1a5a30aa712814a # Parent 9968b55e8b190dbb8f054fc6901e11a382264a72 # EXP-Topic riastradh-pr57145-readdirerrno lib/libc/gen/readdir.c: Sprinkle KNF. No functional change intended. Tidying after: PR pkg/57145: gmake: *** INTERNAL: readdir: Operation not supported. Stop. diff -r 9968b55e8b19 -r 38029f50cf37 lib/libc/gen/readdir.c --- a/lib/libc/gen/readdir.c Sat Aug 31 15:21:39 2024 +0000 +++ b/lib/libc/gen/readdir.c Sat Aug 31 15:49:02 2024 +0000 @@ -105,7 +105,7 @@ struct dirent * struct dirent * readdir(DIR *dirp) { - struct dirent *dp; + struct dirent *dp; #ifdef _REENTRANT if (__isthreaded) { @@ -116,7 +116,8 @@ readdir(DIR *dirp) else #endif dp = _readdir_unlocked(dirp, 1); - return (dp); + + return dp; } int @@ -134,14 +135,14 @@ readdir_r(DIR *dirp, struct dirent *entr memcpy(entry, dp, (size_t)_DIRENT_SIZE(dp)); mutex_unlock((mutex_t *)dirp->dd_lock); } - else + else #endif if ((dp = _readdir_unlocked(dirp, 1)) != NULL) memcpy(entry, dp, (size_t)_DIRENT_SIZE(dp)); if (dp == NULL) { if (errno != 0) - return (errno); + return errno; } else errno = saved_errno; @@ -150,5 +151,5 @@ readdir_r(DIR *dirp, struct dirent *entr else *result = NULL; - return (0); + return 0; }