Add more generic exceptions

This is to avoid depending on backend-specific exceptions in the tests.
This commit is contained in:
Thomas Leonard 2021-07-26 18:27:58 +01:00
parent 88d61e9fbd
commit 76c32e0e46
5 changed files with 39 additions and 23 deletions

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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 ".."

View File

@ -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: