mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-08-29 00:03:47 -04:00
Add more generic exceptions
This is to avoid depending on backend-specific exceptions in the tests.
This commit is contained in:
parent
88d61e9fbd
commit
76c32e0e46
@ -178,6 +178,8 @@ end
|
||||
module Dir = struct
|
||||
type path = string
|
||||
|
||||
exception Already_exists of path * exn
|
||||
exception Not_found of path * exn
|
||||
exception Permission_denied of path * exn
|
||||
|
||||
type create = [`Never | `If_missing of Unix.file_perm | `Or_truncate of Unix.file_perm | `Exclusive of Unix.file_perm]
|
||||
|
@ -400,6 +400,8 @@ end
|
||||
module Dir : sig
|
||||
type path = string
|
||||
|
||||
exception Already_exists of path * exn
|
||||
exception Not_found of path * exn
|
||||
exception Permission_denied of path * exn
|
||||
|
||||
type create = [`Never | `If_missing of Unix.file_perm | `Or_truncate of Unix.file_perm | `Exclusive of Unix.file_perm]
|
||||
|
@ -29,6 +29,12 @@ type amount = Exactly of int | Upto of int
|
||||
|
||||
let system_thread = Ctf.mint_id ()
|
||||
|
||||
let wrap_errors path fn =
|
||||
try fn () with
|
||||
| Unix.Unix_error(Unix.EEXIST, _, _) as ex -> raise @@ Eio.Dir.Already_exists (path, ex)
|
||||
| Unix.Unix_error(Unix.ENOENT, _, _) as ex -> raise @@ Eio.Dir.Not_found (path, ex)
|
||||
| Unix.Unix_error(Unix.EXDEV, _, _) as ex -> raise @@ Eio.Dir.Permission_denied (path, ex)
|
||||
|
||||
let rec skip_empty = function
|
||||
| c :: cs when Cstruct.length c = 0 -> skip_empty cs
|
||||
| x -> x
|
||||
@ -554,13 +560,12 @@ let openfile ~sw path flags mode =
|
||||
FD.of_unix ~sw ~seekable:(FD.is_seekable fd) fd
|
||||
|
||||
let openat2 ~sw ?seekable ~access ~flags ~perm ~resolve ?dir path =
|
||||
wrap_errors path @@ fun () ->
|
||||
let res = enter (enqueue_openat2 (sw, access, flags, perm, resolve, dir, path)) in
|
||||
Log.debug (fun l -> l "openat2 returned");
|
||||
if res < 0 then (
|
||||
Switch.check sw; (* If cancelled, report that instead. *)
|
||||
let ex = Unix.Unix_error (Uring.error_of_errno res, "openat2", "") in
|
||||
if res = -18 then raise (Eio.Dir.Permission_denied (path, ex))
|
||||
else raise ex
|
||||
raise @@ Unix.Unix_error (Uring.error_of_errno res, "openat2", "")
|
||||
);
|
||||
let fd : Unix.file_descr = Obj.magic res in
|
||||
let seekable =
|
||||
@ -577,6 +582,7 @@ external eio_mkdirat : Unix.file_descr -> string -> Unix.file_perm -> unit = "ca
|
||||
|
||||
(* We ignore [sw] because this isn't a uring operation yet. *)
|
||||
let mkdirat ?sw:_ ~perm dir path =
|
||||
wrap_errors path @@ fun () ->
|
||||
match dir with
|
||||
| None -> Unix.mkdir path perm
|
||||
| Some dir -> eio_mkdirat (FD.get "mkdirat" dir) path perm
|
||||
@ -586,7 +592,9 @@ let mkdir_beneath ?sw ~perm ?dir path =
|
||||
let leaf = Filename.basename path in
|
||||
(* [mkdir] is really an operation on [path]'s parent. Get a reference to that first: *)
|
||||
Switch.sub_opt sw (fun sw ->
|
||||
let parent = openat2 ~sw ~seekable:false ?dir dir_path
|
||||
let parent =
|
||||
wrap_errors dir_path @@ fun () ->
|
||||
openat2 ~sw ~seekable:false ?dir dir_path
|
||||
~access:`R
|
||||
~flags:Uring.Open_flags.(cloexec + path + directory)
|
||||
~perm:0
|
||||
|
@ -7,6 +7,14 @@
|
||||
```
|
||||
|
||||
```ocaml
|
||||
let () =
|
||||
Printexc.register_printer (function
|
||||
| Eio.Dir.Permission_denied (path, _) -> Some (Fmt.str "Eio.Dir.Permission_denied (%S, _)" path)
|
||||
| Eio.Dir.Already_exists (path, _) -> Some (Fmt.str "Eio.Dir.Already_exists (%S, _)" path)
|
||||
| Eio.Dir.Not_found (path, _) -> Some (Fmt.str "Eio.Dir.Not_found (%S, _)" path)
|
||||
| _ -> None
|
||||
)
|
||||
|
||||
open Eio.Std
|
||||
|
||||
let run (fn : sw:Switch.t -> Eio.Stdenv.t -> unit) =
|
||||
@ -68,9 +76,7 @@ Trying to use cwd to access a file outside of that subtree fails:
|
||||
let cwd = Eio.Stdenv.cwd env in
|
||||
write_file ~sw ~create:(`Exclusive 0o666) cwd "../test-file" "my-data";
|
||||
failwith "Should have failed"
|
||||
Exception:
|
||||
Eio.Dir.Permission_denied ("../test-file",
|
||||
Unix.Unix_error (Unix.EXDEV, "openat2", "")).
|
||||
Exception: Eio.Dir.Permission_denied ("../test-file", _)
|
||||
```
|
||||
|
||||
Trying to use cwd to access an absolute path fails:
|
||||
@ -79,9 +85,7 @@ Trying to use cwd to access an absolute path fails:
|
||||
let cwd = Eio.Stdenv.cwd env in
|
||||
write_file ~sw ~create:(`Exclusive 0o666) cwd "/tmp/test-file" "my-data";
|
||||
failwith "Should have failed"
|
||||
Exception:
|
||||
Eio.Dir.Permission_denied ("/tmp/test-file",
|
||||
Unix.Unix_error (Unix.EXDEV, "openat2", "")).
|
||||
Exception: Eio.Dir.Permission_denied ("/tmp/test-file", _)
|
||||
```
|
||||
|
||||
# Creation modes
|
||||
@ -93,7 +97,7 @@ Exclusive create fails if already exists:
|
||||
write_file ~sw ~create:(`Exclusive 0o666) cwd "test-file" "first-write";
|
||||
write_file ~sw ~create:(`Exclusive 0o666) cwd "test-file" "first-write";
|
||||
failwith "Should have failed"
|
||||
Exception: Unix.Unix_error(Unix.EEXIST, "openat2", "")
|
||||
Exception: Eio.Dir.Already_exists ("test-file", _)
|
||||
```
|
||||
|
||||
If-missing create succeeds if already exists:
|
||||
@ -126,7 +130,7 @@ Error if no create and doesn't exist:
|
||||
let cwd = Eio.Stdenv.cwd env in
|
||||
write_file ~sw ~create:`Never cwd "test-file" "1st-write-original";
|
||||
traceln "Got %S" @@ read_file ~sw cwd "test-file"
|
||||
Exception: Unix.Unix_error(Unix.ENOENT, "openat2", "")
|
||||
Exception: Eio.Dir.Not_found ("test-file", _)
|
||||
```
|
||||
|
||||
Appending to an existing file:
|
||||
@ -177,10 +181,10 @@ Creating directories with nesting, symlinks, etc:
|
||||
()
|
||||
+mkdir "subdir" -> ok
|
||||
+mkdir "to-subdir/nested" -> ok
|
||||
+mkdir "to-root/tmp/foo" -> Eio.Dir.Permission_denied("to-root/tmp", _)
|
||||
+mkdir "../foo" -> Eio.Dir.Permission_denied("..", _)
|
||||
+mkdir "to-subdir" -> Unix.Unix_error(Unix.EEXIST, "mkdirat", "to-subdir")
|
||||
+mkdir "dangle/foo" -> Unix.Unix_error(Unix.ENOENT, "openat2", "")
|
||||
+mkdir "to-root/tmp/foo" -> Eio.Dir.Permission_denied ("to-root/tmp", _)
|
||||
+mkdir "../foo" -> Eio.Dir.Permission_denied ("..", _)
|
||||
+mkdir "to-subdir" -> Eio.Dir.Already_exists ("to-subdir", _)
|
||||
+mkdir "dangle/foo" -> Eio.Dir.Not_found ("dangle", _)
|
||||
- : unit = ()
|
||||
```
|
||||
|
||||
@ -196,7 +200,7 @@ Create a sandbox, write a file with it, then read it from outside:
|
||||
try_mkdir subdir "../new-sandbox";
|
||||
traceln "Got %S" @@ read_file ~sw cwd "sandbox/test-file"
|
||||
+mkdir "sandbox" -> ok
|
||||
+mkdir "../new-sandbox" -> Eio.Dir.Permission_denied("..", _)
|
||||
+mkdir "../new-sandbox" -> Eio.Dir.Permission_denied ("..", _)
|
||||
+Got "data"
|
||||
- : unit = ()
|
||||
```
|
||||
@ -221,8 +225,8 @@ Using `cwd` we can't access the parent, but using `fs` we can:
|
||||
Unix.rmdir "outside-cwd"
|
||||
+mkdir "fs-test" -> ok
|
||||
+chdir "fs-test"
|
||||
+mkdir "../outside-cwd" -> Eio.Dir.Permission_denied("..", _)
|
||||
+write "../test-file" -> Eio.Dir.Permission_denied("../test-file", _)
|
||||
+mkdir "../outside-cwd" -> Eio.Dir.Permission_denied ("..", _)
|
||||
+write "../test-file" -> Eio.Dir.Permission_denied ("../test-file", _)
|
||||
+mkdir "../outside-cwd" -> ok
|
||||
+write "../test-file" -> ok
|
||||
+chdir ".."
|
||||
|
@ -61,7 +61,7 @@ let test_address addr ~net sw =
|
||||
(fun () ->
|
||||
run_client ~sw ~net ~addr;
|
||||
traceln "Client finished - cancelling server";
|
||||
Switch.turn_off sw (Failure "Test is over")
|
||||
Switch.turn_off sw Graceful_shutdown
|
||||
)
|
||||
```
|
||||
|
||||
@ -74,7 +74,7 @@ Handling one connection, then cancelling the server:
|
||||
+Server received: "Hello from client"
|
||||
+Client received: "Bye"
|
||||
+Client finished - cancelling server
|
||||
Exception: Failure "Test is over".
|
||||
Exception: Graceful_shutdown.
|
||||
```
|
||||
|
||||
Handling one connection on a Unix domain socket:
|
||||
@ -86,7 +86,7 @@ Handling one connection on a Unix domain socket:
|
||||
+Server received: "Hello from client"
|
||||
+Client received: "Bye"
|
||||
+Client finished - cancelling server
|
||||
Exception: Failure "Test is over".
|
||||
Exception: Graceful_shutdown.
|
||||
```
|
||||
|
||||
Handling one connection on an abstract Unix domain socket:
|
||||
@ -98,7 +98,7 @@ Handling one connection on an abstract Unix domain socket:
|
||||
+Server received: "Hello from client"
|
||||
+Client received: "Bye"
|
||||
+Client finished - cancelling server
|
||||
Exception: Failure "Test is over".
|
||||
Exception: Graceful_shutdown.
|
||||
```
|
||||
|
||||
Cancelling the read:
|
||||
|
Loading…
x
Reference in New Issue
Block a user