mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-08-29 00:03:47 -04:00
Add libuv readdir feature
This commit is contained in:
parent
751e2b4e68
commit
c64fc76135
@ -24,6 +24,7 @@ class virtual t = object
|
||||
path -> <rw; Flow.close>
|
||||
method virtual mkdir : perm:Unix_perm.t -> path -> unit
|
||||
method virtual open_dir : sw:Switch.t -> path -> t_with_close
|
||||
method virtual read_dir : path -> string list
|
||||
end
|
||||
and virtual t_with_close = object
|
||||
(* This dummy class avoids an "Error: The type < .. > is not an object type" error from the compiler. *)
|
||||
@ -35,6 +36,7 @@ let open_in ~sw (t:#t) = t#open_in ~sw
|
||||
let open_out ~sw ?(append=false) ~create (t:#t) path = t#open_out ~sw ~append ~create path
|
||||
let open_dir ~sw (t:#t) = t#open_dir ~sw
|
||||
let mkdir (t:#t) = t#mkdir
|
||||
let read_dir (t:#t) path = t#read_dir path
|
||||
|
||||
let with_open_in (t:#t) path fn =
|
||||
Switch.run @@ fun sw -> fn (open_in ~sw t path)
|
||||
|
@ -1118,6 +1118,7 @@ module Dir : sig
|
||||
path -> <rw; Flow.close>
|
||||
method virtual mkdir : perm:Unix_perm.t -> path -> unit
|
||||
method virtual open_dir : sw:Switch.t -> path -> t_with_close
|
||||
method virtual read_dir : path -> path list
|
||||
end
|
||||
and virtual t_with_close : object
|
||||
inherit t
|
||||
@ -1183,6 +1184,9 @@ module Dir : sig
|
||||
val with_open_dir : #t -> path -> (<t; Flow.close> -> 'a) -> 'a
|
||||
(** [with_open_dir] is like [open_dir], but calls [fn dir] with the new directory and closes
|
||||
it automatically when [fn] returns (if it hasn't already been closed by then). *)
|
||||
|
||||
val read_dir : #t -> path -> string list
|
||||
(** [read_dir t path] reads directory entries for [t/path].*)
|
||||
end
|
||||
|
||||
(** The standard environment of a process. *)
|
||||
|
@ -1077,6 +1077,10 @@ class dir fd = object
|
||||
method mkdir ~perm path =
|
||||
Low_level.mkdir_beneath ~perm ?dir:fd path
|
||||
|
||||
method read_dir _path =
|
||||
(* TODO(patricoferris): Once liburing supports getdents64 https://github.com/axboe/liburing/issues/111 *)
|
||||
assert false
|
||||
|
||||
method close =
|
||||
FD.close (Option.get fd)
|
||||
end
|
||||
|
@ -252,6 +252,31 @@ module Low_level = struct
|
||||
let request = Luv.File.Request.make () in
|
||||
await_with_cancel ~request (fun loop -> Luv.File.mkdir ~loop ~request ~mode path)
|
||||
|
||||
let opendir path =
|
||||
let request = Luv.File.Request.make () in
|
||||
await_with_cancel ~request (fun loop -> Luv.File.opendir ~loop ~request path)
|
||||
|
||||
let closedir path =
|
||||
let request = Luv.File.Request.make () in
|
||||
await_with_cancel ~request (fun loop -> Luv.File.closedir ~loop ~request path)
|
||||
|
||||
let with_dir_to_read path fn =
|
||||
match opendir path with
|
||||
| Ok dir ->
|
||||
Fun.protect ~finally:(fun () -> closedir dir |> or_raise) @@ fun () -> fn dir
|
||||
| Error _ as e -> e
|
||||
|
||||
let readdir path =
|
||||
let fn dir =
|
||||
let request = Luv.File.Request.make () in
|
||||
match await_with_cancel ~request (fun loop -> Luv.File.readdir ~loop ~request dir) with
|
||||
| Ok dirents ->
|
||||
let dirs = Array.map (fun v -> v.Luv.File.Dirent.name) dirents |> Array.to_list in
|
||||
Ok dirs
|
||||
| Error _ as e -> e
|
||||
in
|
||||
with_dir_to_read path fn
|
||||
|
||||
let to_unix op t =
|
||||
let os_fd = Luv.File.get_osfhandle (get "to_unix" t) |> or_raise in
|
||||
let fd = Luv_unix.Os_fd.Fd.to_unix os_fd in
|
||||
@ -724,6 +749,10 @@ class dir dir_path = object (self)
|
||||
let real_path = self#resolve_new path in
|
||||
File.mkdir ~mode:[`NUMERIC perm] real_path |> or_raise_path path
|
||||
|
||||
method read_dir path =
|
||||
let path = self#resolve path in
|
||||
File.readdir path |> or_raise_path path
|
||||
|
||||
method close = ()
|
||||
end
|
||||
|
||||
|
@ -67,6 +67,8 @@ module Low_level : sig
|
||||
val mkdir : mode:Luv.File.Mode.t list -> string -> unit or_error
|
||||
(** Wraps {!Luv.File.mkdir} *)
|
||||
|
||||
val readdir : string -> string list or_error
|
||||
(** Wraps {!Luv.File.readdir}. [readdir] opens and closes the directory for reading for the user. *)
|
||||
end
|
||||
|
||||
module Random : sig
|
||||
|
@ -31,6 +31,11 @@ let try_mkdir dir path =
|
||||
| () -> traceln "mkdir %S -> ok" path
|
||||
| exception ex -> traceln "mkdir %S -> %a" path Fmt.exn ex
|
||||
|
||||
let try_read_dir dir path =
|
||||
match Eio.Dir.read_dir dir path with
|
||||
| names -> traceln "read_dir [ %a ] -> ok" Fmt.(list ~sep:Fmt.comma string) names
|
||||
| exception ex -> traceln "read_dir %a" Fmt.exn ex
|
||||
|
||||
let chdir path =
|
||||
traceln "chdir %S" path;
|
||||
Unix.chdir path
|
||||
@ -221,6 +226,30 @@ Using `cwd` we can't access the parent, but using `fs` we can:
|
||||
- : unit = ()
|
||||
```
|
||||
|
||||
Reading directory entries under `cwd` and outside of `cwd`.
|
||||
|
||||
```ocaml
|
||||
# run @@ fun env ->
|
||||
let cwd = Eio.Stdenv.cwd env in
|
||||
try_mkdir cwd "readdir";
|
||||
chdir "readdir";
|
||||
Fun.protect ~finally:(fun () -> chdir "..") (fun () ->
|
||||
try_mkdir cwd "test-1";
|
||||
try_mkdir cwd "test-2";
|
||||
let _entries = try_read_dir cwd "." in
|
||||
let _perm_denied = try_read_dir cwd ".." in
|
||||
()
|
||||
);;
|
||||
+mkdir "readdir" -> ok
|
||||
+chdir "readdir"
|
||||
+mkdir "test-1" -> ok
|
||||
+mkdir "test-2" -> ok
|
||||
+read_dir [ test-1, test-2 ] -> ok
|
||||
+read_dir Eio.Dir.Permission_denied ("..", _)
|
||||
+chdir ".."
|
||||
- : unit = ()
|
||||
```
|
||||
|
||||
Can use `fs` to access absolute paths:
|
||||
|
||||
```ocaml
|
||||
|
Loading…
x
Reference in New Issue
Block a user