mirror of
https://github.com/ocaml-multicore/eio.git
synced 2025-07-19 00:01:28 -04:00
Compare commits
4 Commits
9256754fe8
...
1ef8ad4913
Author | SHA1 | Date | |
---|---|---|---|
|
1ef8ad4913 | ||
|
7c94ccbd28 | ||
|
f169082a47 | ||
|
e14ebca077 |
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -536,23 +536,34 @@ end = struct
|
||||
else Float.pred f
|
||||
|
||||
let stat t ~follow path =
|
||||
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;
|
||||
{ Eio.File.Stat.
|
||||
dev = X.dev x;
|
||||
ino = X.ino x;
|
||||
kind = X.kind x;
|
||||
perm = X.perm x;
|
||||
nlink = X.nlink x;
|
||||
uid = X.uid x;
|
||||
gid = X.gid x;
|
||||
rdev = X.rdev x;
|
||||
size = X.size x |> Optint.Int63.of_int64;
|
||||
atime = float_of_time (X.atime_sec x) (X.atime_nsec x);
|
||||
mtime = float_of_time (X.mtime_sec x) (X.mtime_nsec x);
|
||||
ctime = float_of_time (X.ctime_sec x) (X.ctime_nsec x);
|
||||
}
|
||||
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;
|
||||
{ Eio.File.Stat.
|
||||
dev = X.dev x;
|
||||
ino = X.ino x;
|
||||
kind = X.kind x;
|
||||
perm = X.perm x;
|
||||
nlink = X.nlink x;
|
||||
uid = X.uid x;
|
||||
gid = X.gid x;
|
||||
rdev = X.rdev x;
|
||||
size = X.size x |> Optint.Int63.of_int64;
|
||||
atime = float_of_time (X.atime_sec x) (X.atime_nsec x);
|
||||
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
|
||||
|
@ -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
|
||||
|
12
tests/fs.md
12
tests/fs.md
@ -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 = ()
|
||||
```
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user