From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id EDE823858C53; Fri, 1 Mar 2024 14:44:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EDE823858C53 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1709304246; bh=O7PpFbhp5XEGAP0sWxIdLIwO9KbJtV1vs1LMlVKsDLU=; h=From:To:Subject:Date:From; b=qOtSFzp/Gm1ZFzYrDvcBYa3rj3YTy50eb4gCMhi2wODavSCbiT2znXtSrZ7jV/Bly joiQaF906pCxvm4iyXM+PTmdmM72HCBHCYK8T2s1RlfBPEMC65kiQ2D4R6qdxmHg+5 Gqx30U3bedMNB2n1j1A84lWNpgp6gduSddsEkNtM= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin/main] Cygwin: lseek: improve seeking posix_getdents descriptors X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/main X-Git-Oldrev: c77a5689f7bd4520f6d87481fd08591747b5da0f X-Git-Newrev: 6d936915477ca8f64ecba31c9876103d69827fb2 Message-Id: <20240301144406.EDE823858C53@sourceware.org> Date: Fri, 1 Mar 2024 14:44:06 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D6d936915477= ca8f64ecba31c9876103d69827fb2 commit 6d936915477ca8f64ecba31c9876103d69827fb2 Author: Corinna Vinschen AuthorDate: Fri Mar 1 15:16:44 2024 +0100 Commit: Corinna Vinschen CommitDate: Fri Mar 1 15:32:39 2024 +0100 Cygwin: lseek: improve seeking posix_getdents descriptors =20 Transfer code lseeking on posix_getdents() directory descriptor into its own static function and rework it so SEEK_END, SEEK_DATA and SEEK_HOLE work here as expected, too. =20 Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/syscalls.cc | 83 ++++++++++++++++++++++++++++++++++---------= ---- 1 file changed, 61 insertions(+), 22 deletions(-) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 600c6c54e343..2c5bf7cbe08b 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1596,6 +1596,66 @@ open (const char *unix_path, int flags, ...) =20 EXPORT_ALIAS (open, _open ) =20 +static int +posix_getdents_lseek (cygheap_fdget &cfd, off_t pos, int dir) +{ + long cur =3D cfd->telldir (cfd->getdents_dir ()); + long abs_pos; + + switch (dir) + { + case SEEK_CUR: + abs_pos =3D cur + pos; + break; + case SEEK_SET: + case SEEK_DATA: + abs_pos =3D pos; + break; + case SEEK_END: + case SEEK_HOLE: + /* First read full dir to learn end-of-dir position. */ + while (::readdir (cfd->getdents_dir ())) + ; + long eod =3D cfd->telldir (cfd->getdents_dir ()); + /* Seek back so it looks like nothing happend in error case */ + cfd->seekdir (cfd->getdents_dir (), cur); + if (dir =3D=3D SEEK_HOLE) + { + if (pos > eod) + { + set_errno (ENXIO); + return -1; + } + abs_pos =3D eod; + } + else + abs_pos =3D eod + pos; + break; + } + if (abs_pos < 0) + { + set_errno (EINVAL); + return -1; + } + if (abs_pos !=3D cur) + { + cfd->seekdir (cfd->getdents_dir (), abs_pos); + /* In SEEK_DATA case, check that we didn't seek beyond EOF */ + if (dir =3D=3D SEEK_DATA || dir =3D=3D SEEK_HOLE) + { + pos =3D cfd->telldir (cfd->getdents_dir ()); + if (pos < abs_pos) + { + /* Seek back so it looks like nothing happend */ + cfd->seekdir (cfd->getdents_dir (), cur); + set_errno (ENXIO); + return -1; + } + } + } + return abs_pos; +} + extern "C" off_t lseek (int fd, off_t pos, int dir) { @@ -1612,28 +1672,7 @@ lseek (int fd, off_t pos, int dir) if (cfd < 0) res =3D -1; else if (cfd->getdents_dir ()) - { - if (dir !=3D SEEK_SET && dir !=3D SEEK_CUR) /* No SEEK_END */ - { - set_errno (EINVAL); - res =3D -1; - } - else - { - long cur; - - cur =3D cfd->telldir (cfd->getdents_dir ()); - if (dir =3D=3D SEEK_CUR && cur =3D=3D 0) - res =3D cur; - else - { - if (dir =3D=3D SEEK_CUR) - pos =3D cur + pos; - cfd->seekdir (cfd->getdents_dir (), pos); - res =3D pos; - } - } - } + res =3D posix_getdents_lseek (cfd, pos, dir); else res =3D cfd->lseek (pos, dir); }