# 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 *