public inbox for cygwin-cvs@sourceware.org help / color / mirror / Atom feed
From: Corinna Vinschen <corinna@sourceware.org> To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin/main] Cygwin: lseek: implement SEEK_DATA and SEEK_HOLE for files Date: Wed, 9 Aug 2023 15:25:21 +0000 (GMT) [thread overview] Message-ID: <20230809152522.01E9D385773C@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=edfa581d3c5a783ace9f837be1cbaccb97330c34 commit edfa581d3c5a783ace9f837be1cbaccb97330c34 Author: Corinna Vinschen <corinna@vinschen.de> AuthorDate: Wed Aug 9 17:18:14 2023 +0200 Commit: Corinna Vinschen <corinna@vinschen.de> CommitDate: Wed Aug 9 17:18:14 2023 +0200 Cygwin: lseek: implement SEEK_DATA and SEEK_HOLE for files Signed-off-by: Corinna Vinschen <corinna@vinschen.de> Diff: --- winsup/cygwin/fhandler/base.cc | 85 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/fhandler/base.cc b/winsup/cygwin/fhandler/base.cc index 9b49ec7b9ede..d8351d7a642e 100644 --- a/winsup/cygwin/fhandler/base.cc +++ b/winsup/cygwin/fhandler/base.cc @@ -1109,7 +1109,7 @@ fhandler_base::lseek (off_t offset, int whence) } fpi.CurrentByteOffset.QuadPart += offset; break; - default: /* SEEK_END */ + case SEEK_END: status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi, FileStandardInformation); if (!NT_SUCCESS (status)) @@ -1119,6 +1119,89 @@ fhandler_base::lseek (off_t offset, int whence) } fpi.CurrentByteOffset.QuadPart = fsi.EndOfFile.QuadPart + offset; break; + case SEEK_DATA: + case SEEK_HOLE: + { + FILE_ALLOCATED_RANGE_BUFFER inp, out; + + status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi, + FileStandardInformation); + if (!NT_SUCCESS (status)) + { + __seterrno_from_nt_status (status); + return -1; + } + /* Per Linux man page, ENXIO if offset is beyond EOF */ + if (offset > fsi.EndOfFile.QuadPart) + { + set_errno (ENXIO); + return -1; + } + if (!pc.support_sparse ()) + { + /* Default behaviour if sparse files are not supported: + SEEK_DATA: seek to offset + SEEK_HOLE: seek to EOF */ + fpi.CurrentByteOffset.QuadPart = (whence == SEEK_DATA) + ? offset + : fsi.EndOfFile.QuadPart; + break; + } + inp.FileOffset.QuadPart = offset; + inp.Length.QuadPart = fsi.EndOfFile.QuadPart - offset; + /* Note that we only fetch a single region, so we expect the + function to fail with STATUS_BUFFER_OVERFLOW. It still + returns the data region containing offset, or the next + region after offset, if offset is within a hole. */ + status = NtFsControlFile (get_output_handle (), NULL, NULL, NULL, + &io, FSCTL_QUERY_ALLOCATED_RANGES, + &inp, sizeof inp, + &out, sizeof out); + if (!NT_SUCCESS (status) && status != STATUS_BUFFER_OVERFLOW) + { + /* On error, fall back to default behaviour, see above. */ + fpi.CurrentByteOffset.QuadPart = (whence == SEEK_DATA) + ? offset + : fsi.EndOfFile.QuadPart; + break; + } + if (io.Information == 0) + { + /* No valid region, so offset is within a hole at EOF. + SEEK_DATA: ENXIO + SEEK_HOLE: seek to offset */ + if (whence == SEEK_DATA) + { + set_errno (ENXIO); + return -1; + } + fpi.CurrentByteOffset.QuadPart = offset; + } + else if (out.FileOffset.QuadPart == offset) + { + /* offset within valid data range? In that case, that region + supposedly starts at offset, and the region length is corrected + accordingly. That's quite helpful. + SEEK_DATA: seek to offset + SEEK_HOLE: seek to end of range */ + fpi.CurrentByteOffset.QuadPart = offset; + if (whence == SEEK_HOLE) + fpi.CurrentByteOffset.QuadPart += out.Length.QuadPart; + } + else + { + /* Is range beyond offset? + SEEK_DATA: seek to start of range + SEEK_HOLE: seek to offset */ + fpi.CurrentByteOffset.QuadPart = (whence == SEEK_DATA) + ? out.FileOffset.QuadPart + : offset; + } + } + break; + default: /* Should never be reached */ + set_errno (EINVAL); + return -1; } debug_printf ("setting file pointer to %U", fpi.CurrentByteOffset.QuadPart);
reply other threads:[~2023-08-09 15:25 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20230809152522.01E9D385773C@sourceware.org \ --to=corinna@sourceware.org \ --cc=cygwin-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).