Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib_eio/unix/eio_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module Ipaddr = Net.Ipaddr

module Process = Process
module Net = Net
module File = File
module Pty = Pty
module Cap = Cap
module Pi = Pi
Expand Down
4 changes: 4 additions & 0 deletions lib_eio/unix/eio_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ end
module Net = Net
(** Extended network API with support for file descriptors. *)

module File = File
(** Extended file API with support for file descriptors. *)

type source_ty = [`Unix_fd | Eio.Resource.close_ty | Eio.Flow.source_ty]
type sink_ty = [`Unix_fd | Eio.Resource.close_ty | Eio.Flow.sink_ty]
type 'a source = ([> source_ty] as 'a) r
Expand Down Expand Up @@ -137,6 +140,7 @@ module Private : sig
| Await_writable : Unix.file_descr -> unit Effect.t (** See {!await_writable} *)
| Get_monotonic_clock : Eio.Time.Mono.ty r Effect.t
| Pipe : Eio.Switch.t -> (source_ty r * sink_ty r) Effect.t (** See {!pipe} *)
| Import_file : Fd.t -> File.rw_ty r Effect.t (** See {!File.import_rw} *)

module Rcfd = Rcfd

Expand Down
14 changes: 14 additions & 0 deletions lib_eio/unix/file.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
open Eio.Std

type rw_ty = [`Unix_fd | Eio.File.rw_ty]
type ro_ty = [`Unix_fd | Eio.File.ro_ty]

let open_type s = (s : rw_ty r :> [< rw_ty] r)

let import_rw ~sw ~close_unix fd =
let fd = Fd.of_unix ~sw ~close_unix fd in
(* The backend may set [fd] to be non-blocking.
This is OK, because [Fd] checks for it lazily and we haven't asked it yet. *)
open_type @@ Effect.perform (Private.Import_file fd)

let import_ro = import_rw
17 changes: 17 additions & 0 deletions lib_eio/unix/file.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
open Eio.Std

type rw_ty = [`Unix_fd | Eio.File.rw_ty]
type ro_ty = [`Unix_fd | Eio.File.ro_ty]

val import_rw : sw:Switch.t -> close_unix:bool -> Unix.file_descr -> [< rw_ty ] r
(** [import_rw ~sw ~close_unix fd] is a read/write Eio file that uses [fd].

The file resource will be closed when [sw] finishes.

The backend takes ownership of [fd] and may change whether it is
non-blocking.

The [close_unix] and [sw] arguments are passed to {!Fd.of_unix}. *)

val import_ro : sw:Switch.t -> close_unix:bool -> Unix.file_descr -> [< ro_ty ] r
(** [import_ro] is like {!import_rw}, but casts the result to be read-only. *)
1 change: 1 addition & 0 deletions lib_eio/unix/private.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type _ Effect.t +=
| Await_writable : Unix.file_descr -> unit Effect.t
| Get_monotonic_clock : Eio.Time.Mono.ty r Effect.t
| Pipe : Switch.t -> (source_ty r * sink_ty r) Effect.t
| Import_file : Fd.t -> [`Unix_fd | Eio.File.rw_ty] r Effect.t

let await_readable fd = Effect.perform (Await_readable fd)
let await_writable fd = Effect.perform (Await_writable fd)
Expand Down
3 changes: 3 additions & 0 deletions lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ let run_event_loop (type a) ?fallback config (main : _ -> a) arg : a =
effc = fun (type a) (e : a Effect.t) : ((a, Sched.exit) continuation -> Sched.exit) option ->
match e with
| Eio_unix.Private.Get_monotonic_clock -> Some (fun k -> continue k Time.mono_clock)
| Eio_unix.Private.Import_file fd -> Some (fun k ->
continue k (Flow.of_fd fd :> Eio_unix.File.rw_ty r)
)
| Eio_unix.Net.Import_socket_stream (sw, close_unix, fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~seekable:false ~close_unix fd in
continue k (Flow.of_fd fd :> _ Eio_unix.Net.stream_socket)
Expand Down
4 changes: 4 additions & 0 deletions lib_eio_posix/domain_mgr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ let run_event_loop fn x =
effc = fun (type a) (e : a Effect.t) : ((a, Sched.exit) continuation -> Sched.exit) option ->
match e with
| Eio_unix.Private.Get_monotonic_clock -> Some (fun k -> continue k Time.mono_clock)
| Eio_unix.Private.Import_file fd -> Some (fun k ->
Fd.use_exn "Import_file" fd Unix.set_nonblock;
continue k (Flow.of_fd fd :> Eio_unix.File.rw_ty r)
)
| Eio_unix.Net.Import_socket_stream (sw, close_unix, unix_fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix unix_fd in
Unix.set_nonblock unix_fd;
Expand Down
4 changes: 4 additions & 0 deletions lib_eio_windows/domain_mgr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ let run_event_loop fn x =
effc = fun (type a) (e : a Effect.t) : ((a, Sched.exit) continuation -> Sched.exit) option ->
match e with
| Eio_unix.Private.Get_monotonic_clock -> Some (fun k -> continue k Time.mono_clock)
| Eio_unix.Private.Import_file fd -> Some (fun k ->
Fd.use_exn "Import_file" fd Unix.set_nonblock;
continue k (Flow.of_fd fd :> Eio_unix.File.rw_ty r)
)
| Eio_unix.Net.Import_socket_stream (sw, close_unix, unix_fd) -> Some (fun k ->
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix unix_fd in
(* TODO: On Windows, if the FD from Unix.pipe () is passed this will fail *)
Expand Down
22 changes: 22 additions & 0 deletions tests/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1547,3 +1547,25 @@ Exception: Failure "Simulated error".
+"/" / "" = "/"
- : unit = ()
```

# Importing files from FDs

```ocaml
# run ~clear:["unix-file"] @@ fun env ->
let path = env#cwd / "unix-file" in
Switch.run (fun sw ->
Unix.openfile (Eio.Path.native_exn path) [O_CREAT; O_RDWR] 0o600
|> Eio_unix.File.import_rw ~sw ~close_unix:true
|> Eio.Flow.copy_string "test-data"
);
Switch.run (fun sw ->
let file =
Unix.openfile (Eio.Path.native_exn path) [O_RDONLY] 0
|> Eio_unix.File.import_ro ~sw ~close_unix:true
in
let buf = Cstruct.create 6 in
Eio.File.pread_exact file ~file_offset:(Optint.Int63.of_int 1) [buf];
Cstruct.to_string buf
);;
- : string = "est-da"
```
Loading