Skip to content

Commit 082bf00

Browse files
authored
Merge pull request #626 from talex5/file-ops
Add Eio.File.{seek,sync,truncate}
2 parents 1ef8ad4 + 482d247 commit 082bf00

File tree

12 files changed

+181
-24
lines changed

12 files changed

+181
-24
lines changed

lib_eio/file.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ module Pi = struct
7272

7373
val pread : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
7474
val stat : t -> Stat.t
75+
val seek : t -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
7576
val close : t -> unit
7677
end
7778

@@ -80,6 +81,8 @@ module Pi = struct
8081
include READ with type t := t
8182

8283
val pwrite : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
84+
val sync : t -> unit
85+
val truncate : t -> Optint.Int63.t -> unit
8386
end
8487

8588
type (_, _, _) Resource.pi +=
@@ -140,3 +143,15 @@ let pwrite_all (Resource.T (t, ops)) ~file_offset bufs =
140143
)
141144
in
142145
aux ~file_offset bufs
146+
147+
let seek (Resource.T (t, ops)) off cmd =
148+
let module X = (val (Resource.get ops Pi.Read)) in
149+
X.seek t off cmd
150+
151+
let sync (Resource.T (t, ops)) =
152+
let module X = (val (Resource.get ops Pi.Write)) in
153+
X.sync t
154+
155+
let truncate (Resource.T (t, ops)) len =
156+
let module X = (val (Resource.get ops Pi.Write)) in
157+
X.truncate t len

lib_eio/file.mli

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
open Std
22

3+
(** {2 Types} *)
4+
35
(** Traditional Unix permissions. *)
46
module Unix_perm : sig
57
type t = int
@@ -54,37 +56,16 @@ type rw_ty = [ro_ty | Flow.sink_ty]
5456
type 'a rw = ([> rw_ty] as 'a) r
5557
(** A file opened for reading and writing. *)
5658

57-
module Pi : sig
58-
module type READ = sig
59-
include Flow.Pi.SOURCE
60-
61-
val pread : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
62-
val stat : t -> Stat.t
63-
val close : t -> unit
64-
end
65-
66-
module type WRITE = sig
67-
include Flow.Pi.SINK
68-
include READ with type t := t
69-
70-
val pwrite : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
71-
end
72-
73-
type (_, _, _) Resource.pi +=
74-
| Read : ('t, (module READ with type t = 't), [> ro_ty]) Resource.pi
75-
| Write : ('t, (module WRITE with type t = 't), [> rw_ty]) Resource.pi
76-
77-
val ro : (module READ with type t = 't) -> ('t, ro_ty) Resource.handler
78-
79-
val rw : (module WRITE with type t = 't) -> ('t, rw_ty) Resource.handler
80-
end
59+
(** {2 Metadata} *)
8160

8261
val stat : _ ro -> Stat.t
8362
(** [stat t] returns the {!Stat.t} record associated with [t]. *)
8463

8564
val size : _ ro -> Optint.Int63.t
8665
(** [size t] returns the size of [t]. *)
8766

67+
(** {2 Reading and writing} *)
68+
8869
val pread : _ ro -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
8970
(** [pread t ~file_offset bufs] performs a single read of [t] at [file_offset] into [bufs].
9071
@@ -108,3 +89,48 @@ val pwrite_single : _ rw -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
10889

10990
val pwrite_all : _ rw -> file_offset:Optint.Int63.t -> Cstruct.t list -> unit
11091
(** [pwrite_all t ~file_offset bufs] writes all the data in [bufs] to location [file_offset] in [t]. *)
92+
93+
val seek : _ ro -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
94+
(** Set and/or get the current file position.
95+
96+
Like {!Unix.lseek}. *)
97+
98+
val sync : _ rw -> unit
99+
(** Flush file buffers to disk.
100+
101+
Like {!Unix.fsync}. *)
102+
103+
val truncate : _ rw -> Optint.Int63.t -> unit
104+
(** Set the length of a file.
105+
106+
Like {!Unix.ftruncate}. *)
107+
108+
(** {2 Provider Interface} *)
109+
110+
module Pi : sig
111+
module type READ = sig
112+
include Flow.Pi.SOURCE
113+
114+
val pread : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
115+
val stat : t -> Stat.t
116+
val seek : t -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
117+
val close : t -> unit
118+
end
119+
120+
module type WRITE = sig
121+
include Flow.Pi.SINK
122+
include READ with type t := t
123+
124+
val pwrite : t -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
125+
val sync : t -> unit
126+
val truncate : t -> Optint.Int63.t -> unit
127+
end
128+
129+
type (_, _, _) Resource.pi +=
130+
| Read : ('t, (module READ with type t = 't), [> ro_ty]) Resource.pi
131+
| Write : ('t, (module WRITE with type t = 't), [> rw_ty]) Resource.pi
132+
133+
val ro : (module READ with type t = 't) -> ('t, ro_ty) Resource.handler
134+
135+
val rw : (module WRITE with type t = 't) -> ('t, rw_ty) Resource.handler
136+
end

lib_eio_linux/eio_linux.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,10 @@ module Flow = struct
192192
let recv_msg_with_fds t ~sw ~max_fds data =
193193
let _addr, n, fds = Low_level.recv_msg_with_fds t ~sw ~max_fds data in
194194
n, fds
195+
196+
let seek = Low_level.lseek
197+
let sync = Low_level.fsync
198+
let truncate = Low_level.ftruncate
195199
end
196200

197201
let flow_handler = Eio_unix.Pi.flow_handler (module Flow)

lib_eio_linux/eio_linux.mli

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,21 @@ module Low_level : sig
167167
The entries are not returned in any particular order
168168
(not even necessarily the order in which Linux returns them). *)
169169

170+
val lseek : fd -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
171+
(** Set and/or get the current file position.
172+
173+
Like {!Unix.lseek}. *)
174+
175+
val fsync : fd -> unit
176+
(** Flush file buffers to disk.
177+
178+
Like {!Unix.fsync}. *)
179+
180+
val ftruncate : fd -> Optint.Int63.t -> unit
181+
(** Set the length of a file.
182+
183+
Like {!Unix.ftruncate}. *)
184+
170185
(** {1 Sockets} *)
171186

172187
val accept : sw:Switch.t -> fd -> (fd * Unix.sockaddr)

lib_eio_linux/low_level.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,27 @@ external eio_getrandom : Cstruct.buffer -> int -> int -> int = "caml_eio_getrand
341341

342342
external eio_getdents : Unix.file_descr -> string list = "caml_eio_getdents"
343343

344+
let lseek fd off cmd =
345+
Fd.use_exn "lseek" fd @@ fun fd ->
346+
let cmd =
347+
match cmd with
348+
| `Set -> Unix.SEEK_SET
349+
| `Cur -> Unix.SEEK_CUR
350+
| `End -> Unix.SEEK_END
351+
in
352+
Unix.LargeFile.lseek fd (Optint.Int63.to_int64 off) cmd
353+
|> Optint.Int63.of_int64
354+
355+
let fsync fd =
356+
(* todo: https://github.com/ocaml-multicore/ocaml-uring/pull/103 *)
357+
Eio_unix.run_in_systhread @@ fun () ->
358+
Fd.use_exn "fsync" fd Unix.fsync
359+
360+
let ftruncate fd len =
361+
Eio_unix.run_in_systhread @@ fun () ->
362+
Fd.use_exn "ftruncate" fd @@ fun fd ->
363+
Unix.LargeFile.ftruncate fd (Optint.Int63.to_int64 len)
364+
344365
let getrandom { Cstruct.buffer; off; len } =
345366
let rec loop n =
346367
if n = len then

lib_eio_posix/flow.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ module Impl = struct
7979
let _addr, n, fds = Low_level.recv_msg_with_fds t ~sw ~max_fds (Array.of_list data) in
8080
n, fds
8181

82+
let seek = Low_level.lseek
83+
let sync = Low_level.fsync
84+
let truncate = Low_level.ftruncate
85+
8286
let fd t = t
8387

8488
let close = Eio_unix.Fd.close

lib_eio_posix/low_level.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,26 @@ external atime_nsec : stat -> int = "ocaml_eio_posix_stat_atime_nsec" [@@noalloc
256256
external ctime_nsec : stat -> int = "ocaml_eio_posix_stat_ctime_nsec" [@@noalloc]
257257
external mtime_nsec : stat -> int = "ocaml_eio_posix_stat_mtime_nsec" [@@noalloc]
258258

259+
let lseek fd off cmd =
260+
Fd.use_exn "lseek" fd @@ fun fd ->
261+
let cmd =
262+
match cmd with
263+
| `Set -> Unix.SEEK_SET
264+
| `Cur -> Unix.SEEK_CUR
265+
| `End -> Unix.SEEK_END
266+
in
267+
Unix.LargeFile.lseek fd (Optint.Int63.to_int64 off) cmd
268+
|> Optint.Int63.of_int64
269+
270+
let fsync fd =
271+
Eio_unix.run_in_systhread @@ fun () ->
272+
Fd.use_exn "fsync" fd Unix.fsync
273+
274+
let ftruncate fd len =
275+
Eio_unix.run_in_systhread @@ fun () ->
276+
Fd.use_exn "ftruncate" fd @@ fun fd ->
277+
Unix.LargeFile.ftruncate fd (Optint.Int63.to_int64 len)
278+
259279
let pipe ~sw =
260280
let unix_r, unix_w = Unix.pipe ~cloexec:true () in
261281
let r = Fd.of_unix ~sw ~blocking:false ~close_unix:true unix_r in

lib_eio_posix/low_level.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ val send_msg : fd -> ?fds:fd list -> ?dst:Unix.sockaddr -> Cstruct.t array -> in
3535

3636
val getrandom : Cstruct.t -> unit
3737

38+
val lseek : fd -> Optint.Int63.t -> [`Set | `Cur | `End] -> Optint.Int63.t
39+
val fsync : fd -> unit
40+
val ftruncate : fd -> Optint.Int63.t -> unit
41+
3842
type stat
3943

4044
val create_stat : unit -> stat

lib_eio_windows/flow.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ module Impl = struct
7676

7777
let recv_msg_with_fds _t ~sw:_ ~max_fds:_ _data = failwith "Not implemented on Windows"
7878

79+
let seek = Low_level.lseek
80+
let sync = Low_level.fsync
81+
let truncate = Low_level.ftruncate
82+
7983
let fd t = t
8084

8185
let close = Eio_unix.Fd.close

lib_eio_windows/low_level.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,26 @@ let rename ?old_dir old_path ?new_dir new_path =
231231
in_worker_thread @@ fun () ->
232232
eio_renameat old_dir old_path new_dir new_path
233233

234+
let lseek fd off cmd =
235+
Fd.use_exn "lseek" fd @@ fun fd ->
236+
let cmd =
237+
match cmd with
238+
| `Set -> Unix.SEEK_SET
239+
| `Cur -> Unix.SEEK_CUR
240+
| `End -> Unix.SEEK_END
241+
in
242+
Unix.LargeFile.lseek fd (Optint.Int63.to_int64 off) cmd
243+
|> Optint.Int63.of_int64
244+
245+
let fsync fd =
246+
Eio_unix.run_in_systhread @@ fun () ->
247+
Fd.use_exn "fsync" fd Unix.fsync
248+
249+
let ftruncate fd len =
250+
Eio_unix.run_in_systhread @@ fun () ->
251+
Fd.use_exn "ftruncate" fd @@ fun fd ->
252+
Unix.LargeFile.ftruncate fd (Optint.Int63.to_int64 len)
253+
234254
let pipe ~sw =
235255
let unix_r, unix_w = Unix.pipe ~cloexec:true () in
236256
let r = Fd.of_unix ~sw ~blocking:false ~close_unix:true unix_r in

0 commit comments

Comments
 (0)