Compare commits

...

4 Commits

Author SHA1 Message Date
Thomas Leonard
1ef8ad4913
Merge pull request #624 from talex5/statx-fallback
eio_linux: add fallback for statx on older kernels
2023-09-27 12:07:41 +01:00
Thomas Leonard
7c94ccbd28 eio_linux: add fallback for statx on older kernels
If statx isn't available, open the path and use fstat instead.

See: io-uring: Make statx API stable
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1b6fe6e0dfecf8c82a64fb87148ad9333fa2f62e
2023-09-27 11:43:25 +01:00
Thomas Leonard
f169082a47
Merge pull request #623 from talex5/kind
Add Eio.Path.{kind, is_file, is_directory}
2023-09-27 11:43:08 +01:00
Thomas Leonard
e14ebca077 Add Eio.Path.{kind, is_file, is_directory} 2023-09-26 17:43:22 +01:00
5 changed files with 63 additions and 24 deletions

View File

@ -69,6 +69,16 @@ let stat ~follow t =
let bt = Printexc.get_raw_backtrace () in
Exn.reraise_with_context ex bt "examining %a" pp t
let kind ~follow t =
try ((stat ~follow t).kind :> [File.Stat.kind | `Not_found])
with Exn.Io (Fs.E Not_found _, _) -> `Not_found
let is_file t =
kind ~follow:true t = `Regular_file
let is_directory t =
kind ~follow:true t = `Directory
let with_open_in path fn =
Switch.run @@ fun sw -> fn (open_in ~sw path)

View File

@ -128,7 +128,7 @@ val read_dir : _ t -> string list
Note: The special Unix entries "." and ".." are not included in the results. *)
(** {2 Metadata} *)
(** {1 Metadata} *)
val stat : follow:bool -> _ t -> File.Stat.t
(** [stat ~follow t] returns metadata about the file [t].
@ -136,6 +136,21 @@ val stat : follow:bool -> _ t -> File.Stat.t
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself. *)
val kind : follow:bool -> _ t -> [ File.Stat.kind | `Not_found ]
(** [kind ~follow t] is the type of [t], or [`Not_found] if it doesn't exist.
@param follow If [true] and [t] is a symlink, return the type of the target rather than [`Symbolic_link]. *)
val is_file : _ t -> bool
(** [is_file t] is [true] if [t] is a regular file, and [false] if it doesn't exist or has a different type.
[is_file t] is [kind ~follow:true t = `Regular_file]. *)
val is_directory : _ t -> bool
(** [is_directory t] is [true] if [t] is a directory, and [false] if it doesn't exist or has a different type.
[is_directory t] is [kind ~follow:true t = `Directory]. *)
(** {1 Other} *)
val unlink : _ t -> unit

View File

@ -536,6 +536,7 @@ end = struct
else Float.pred f
let stat t ~follow path =
if !Sched.statx_works then (
let module X = Uring.Statx in
let x = X.create () in
Low_level.statx_confined ~follow ~mask:X.Mask.basic_stats t.fd path x;
@ -553,6 +554,16 @@ end = struct
mtime = float_of_time (X.mtime_sec x) (X.mtime_nsec x);
ctime = float_of_time (X.ctime_sec x) (X.ctime_nsec x);
}
) else (
(* Linux < 5.18 *)
Switch.run @@ fun sw ->
let fd = Low_level.openat ~sw ~seekable:false t.fd (if path = "" then "." else path)
~access:`R
~flags:Uring.Open_flags.(cloexec + path + (if follow then empty else nofollow))
~perm:0
in
Flow.stat fd
)
let rename t old_path t2 new_path =
match get_dir_fd_opt t2 with

View File

@ -11,6 +11,8 @@ module Lf_queue = Eio_utils.Lf_queue
let system_thread = Ctf.mint_id ()
let statx_works = ref false (* Before Linux 5.18, statx is unreliable *)
type exit = [`Exit_scheduler]
type file_offset = [
@ -526,6 +528,7 @@ let with_sched ?(fallback=no_fallback) config fn =
Uring.exit uring;
fallback (`Msg "Linux >= 5.11 is required for io_uring support")
) else (
statx_works := Uring.op_supported probe Uring.Op.msg_ring;
match
let mem =
let fixed_buf_len = block_size * n_blocks in

View File

@ -59,10 +59,6 @@ let try_rmdir path =
let chdir path =
traceln "chdir %S" path;
Unix.chdir path
let assert_kind path kind =
Path.with_open_in path @@ fun file ->
assert ((Eio.File.stat file).kind = kind)
```
# Basic test cases
@ -224,7 +220,9 @@ You can remove a file using unlink:
Path.save ~create:(`Exclusive 0o600) (cwd / "subdir/file2") "data2";
try_read_file (cwd / "file");
try_read_file (cwd / "subdir/file2");
assert (Eio.Path.kind ~follow:true (cwd / "file") = `Regular_file);
try_unlink (cwd / "file");
assert (Eio.Path.kind ~follow:true (cwd / "file") = `Not_found);
try_unlink (cwd / "subdir/file2");
try_read_file (cwd / "file");
try_read_file (cwd / "subdir/file2");
@ -541,9 +539,9 @@ let try_stat path =
let cwd = Eio.Stdenv.cwd env in
Switch.run @@ fun sw ->
try_mkdir (cwd / "stat_subdir");
assert_kind (cwd / "stat_subdir") `Directory;
assert (Eio.Path.is_directory (cwd / "stat_subdir"));
try_write_file (cwd / "stat_reg") "kingbula" ~create:(`Exclusive 0o600);
assert_kind (cwd / "stat_reg") `Regular_file;;
assert (Eio.Path.is_file (cwd / "stat_reg"));
+mkdir <cwd:stat_subdir> -> ok
+write <cwd:stat_reg> -> ok
- : unit = ()
@ -565,6 +563,7 @@ Fstatat:
try_stat (cwd / "..");
Unix.symlink ".." "parent-symlink";
try_stat (cwd / "parent-symlink");
try_stat (cwd / "missing1" / "missing2");
+mkdir <cwd:stat_subdir2> -> ok
+<cwd:stat_subdir2> -> directory
+<cwd:symlink> -> symbolic link / directory
@ -572,6 +571,7 @@ Fstatat:
+<cwd> -> directory
+<cwd:..> -> Fs Permission_denied _
+<cwd:parent-symlink> -> symbolic link / Fs Permission_denied _
+<cwd:missing1/missing2> -> Fs Not_found _
- : unit = ()
```