diff --git a/lib_eio_posix/flow.ml b/lib_eio_posix/flow.ml index b1cff7d09..dd1f3eb25 100644 --- a/lib_eio_posix/flow.ml +++ b/lib_eio_posix/flow.ml @@ -71,7 +71,11 @@ let of_fd fd = object (_ : ) method read_methods = [] method copy src = copy src fd - method pread ~file_offset bufs = Low_level.preadv ~file_offset fd (Array.of_list bufs) + method pread ~file_offset bufs = + let got = Low_level.preadv ~file_offset fd (Array.of_list bufs) in + if got = 0 then raise End_of_file + else got + method pwrite ~file_offset bufs = Low_level.pwritev ~file_offset fd (Array.of_list bufs) method stat = fstat fd diff --git a/lib_eio_windows/flow.ml b/lib_eio_windows/flow.ml index c3bc2b7fa..dccf0aafa 100755 --- a/lib_eio_windows/flow.ml +++ b/lib_eio_windows/flow.ml @@ -65,7 +65,11 @@ let of_fd fd = object (_ : ) method read_methods = [] method copy src = copy src fd - method pread ~file_offset bufs = Low_level.preadv ~file_offset fd (Array.of_list bufs) + method pread ~file_offset bufs = + let got = Low_level.preadv ~file_offset fd (Array.of_list bufs) in + if got = 0 then raise End_of_file + else got + method pwrite ~file_offset bufs = Low_level.pwritev ~file_offset fd (Array.of_list bufs) method stat = fstat fd diff --git a/tests/fs.md b/tests/fs.md index 579fea1d5..cc91d46e4 100644 --- a/tests/fs.md +++ b/tests/fs.md @@ -552,6 +552,27 @@ Check reading and writing vectors at arbitrary offsets: - : unit = () ``` +Reading at the end of a file: + +```ocaml +# run @@ fun env -> + let cwd = Eio.Stdenv.cwd env in + let path = cwd / "test.txt" in + Path.with_open_out path ~create:(`Or_truncate 0o600) @@ fun file -> + Eio.Flow.copy_string "abc" file; + let buf = Cstruct.create 10 in + let got = Eio.File.pread file [buf] ~file_offset:(Int63.of_int 0) in + traceln "Read %S" (Cstruct.to_string buf ~len:got); + try + ignore (Eio.File.pread file [buf] ~file_offset:(Int63.of_int 3) : int); + assert false + with End_of_file -> + traceln "End-of-file";; ++Read "abc" ++End-of-file +- : unit = () +``` + # Cancelling while readable Ensure reads can be cancelled promptly, even if there is no need to wait: