pkgsrc-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: pkg/57145: gmake: *** INTERNAL: readdir: Operation not supported. Stop.
The following reply was made to PR pkg/57145; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: matthew green <mrg%NetBSD.org@localhost>
Cc: Andrew Cagney <andrew.cagney%gmail.com@localhost>,
gnats-bugs%NetBSD.org@localhost, netbsd-bugs%NetBSD.org@localhost
Subject: Re: pkg/57145: gmake: *** INTERNAL: readdir: Operation not supported. Stop.
Date: Sun, 1 Sep 2024 15:36:05 +0000
This is a multi-part message in MIME format.
--=_UO/DuVWULAgwAF6z8mwyycn6j85jhood
Content-Transfer-Encoding: quoted-printable
> Date: Tue, 20 Aug 2024 07:03:34 +0000
> From: mrg%NetBSD.org@localhost
>=20
> this is a gmake bug. it checks errno after readdir() but readdir() is
> not expected to set/clear errno for 'end of dir' condition, and thus
> converts some prior random error into a readdir error.
Not a gmake bug. readdir is required to preserve errno in the
end-of-directory case:
DESCRIPTION
[...]
Applications wishing to check for error situations should set errno
to 0 before calling readdir(). If errno is set to non-zero on
return, an error occurred.
RETURN VALUE
[...] When the end of the directory is encountered, a null pointer
shall be returned and errno is not changed.
POSIX 2024: https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/fu=
nctions/readdir.html
SUSv2 1997: https://pubs.opengroup.org/onlinepubs/7908799/xsh/readdir.html
It's been this way for decades and we just screwed it up in the event
that lseek fails.
The attached patch arranges to preserve errno in the end-of-directory
case (and in the success case), and to set errno in error cases.
However, I would like to add an automatic test for this.
> Date: Fri, 30 Aug 2024 21:52:34 +0000
> From: mrg%NetBSD.org@localhost
>=20
> we store lseek() into dirp->dd_seek for later usage, and in the case
> that it returns -1 and sets errno (this PR shows EOPNOTSUPP but most
> instances i've and others have seen is EINVAL - mine happens on pure
> FFS obj, not in a chroot.)
Can you share your reproducer for this? Maybe we can adapt it to an
atf test.
--=_UO/DuVWULAgwAF6z8mwyycn6j85jhood
Content-Type: text/plain; charset="ISO-8859-1"; name="pr57145-readdirerrno-v6"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="pr57145-readdirerrno-v6.patch"
# HG changeset patch
# User Taylor R Campbell <riastradh%NetBSD.org@localhost>
# 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[] =3D "@(#)readdir.c 8.
struct dirent *
_readdir_unlocked(DIR *dirp, int skipdeleted)
{
+ const int saved_errno =3D errno;
struct dirent *dp;
=20
for (;;) {
if (dirp->dd_loc >=3D dirp->dd_size) {
if (dirp->dd_flags & __DTF_READALL)
- return (NULL);
+ break;
dirp->dd_loc =3D 0;
}
if (dirp->dd_loc =3D=3D 0 && !(dirp->dd_flags & __DTF_READALL)) {
dirp->dd_seek =3D lseek(dirp->dd_fd, (off_t)0, SEEK_CUR);
dirp->dd_size =3D getdents(dirp->dd_fd,
dirp->dd_buf, (size_t)dirp->dd_len);
- if (dirp->dd_size <=3D 0)
- return (NULL);
+ if (dirp->dd_size =3D=3D 0) /* end of directory */
+ break;
+ if (dirp->dd_size =3D=3D -1) /* getdents sets errno */
+ return NULL;
+ if (dirp->dd_size < 0) { /* paranoia */
+ errno =3D EIO;
+ return NULL;
+ }
}
dp =3D (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 =3D EIO;
+ return NULL;
+ }
/* d_reclen is unsigned; no need to compare it <=3D 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 =3D EIO;
+ return NULL;
+ }
dirp->dd_loc +=3D dp->d_reclen;
if (dp->d_ino =3D=3D 0 && skipdeleted)
continue;
if (dp->d_type =3D=3D DT_WHT && (dirp->dd_flags & DTF_HIDEW))
continue;
- return (dp);
+ return dp;
}
+
+ errno =3D saved_errno;
+ return NULL;
}
=20
struct dirent *
--=_UO/DuVWULAgwAF6z8mwyycn6j85jhood--
Home |
Main Index |
Thread Index |
Old Index