Skip to content

Commit

Permalink
stat: add more singleton accessor functions to File/Path
Browse files Browse the repository at this point in the history
  • Loading branch information
avsm committed Aug 21, 2023
1 parent ae063ae commit 28169b5
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 44 deletions.
46 changes: 20 additions & 26 deletions lib_eio/file.ml
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,23 @@ module Stat = struct
| `Socket -> Fmt.string ppf "socket"

type 'a f =
| Dev : int64 f
| Ino : int64 f
| Kind : kind f
| Perm : int f
| Nlink : int64 f
| Uid : int64 f
| Gid : int64 f
| Rdev : int64 f
| Size : int64 f
| Atime : float f
| Ctime : float f
| Mtime : float f
| Dev : int64 f
| Ino : int64 f
| Kind : kind f
| Perm : int f
| Nlink : int64 f
| Uid : int64 f
| Gid : int64 f
| Rdev : int64 f
| Size : int64 f
| Atime : float f
| Ctime : float f
| Mtime : float f

type ('a, 'ty) t =
| [] : ('ty, 'ty) t
| (::) : 'a f * ('b, 'ty) t -> ('a -> 'b, 'ty) t

let dev = Dev
let ino = Ino
let kind = Kind
let perm = Perm
let nlink = Nlink
let uid = Uid
let gid = Gid
let rdev = Rdev
let size = Size
let atime = Atime
let ctime = Ctime
let mtime = Mtime
end

type ro_ty = [`File | Flow.source_ty | Resource.close_ty]
Expand Down Expand Up @@ -105,8 +93,14 @@ let stat (Resource.T (t, ops)) =
let module X = (val (Resource.get ops Pi.Read)) in
X.stat t

let size t =
stat t [Stat.size] (fun s -> Optint.Int63.of_int64 s)
let kind t = stat t [Stat.Kind] Fun.id
let perm t = stat t [Stat.Perm] Fun.id
let uid t = stat t [Stat.Uid] Fun.id
let gid t = stat t [Stat.Gid] Fun.id
let size t = stat t [Stat.Size] (fun s -> Optint.Int63.of_int64 s)
let atime t = stat t [Stat.Atime] Fun.id
let ctime t = stat t [Stat.Ctime] Fun.id
let mtime t = stat t [Stat.Mtime] Fun.id

let pread (Resource.T (t, ops)) ~file_offset bufs =
let module X = (val (Resource.get ops Pi.Read)) in
Expand Down
66 changes: 51 additions & 15 deletions lib_eio/file.mli
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,6 @@ module Stat : sig
| [] : ('ty, 'ty) t
| (::) : 'a f * ('b, 'ty) t -> ('a -> 'b, 'ty) t

val dev : int64 f
val ino : int64 f
val kind : kind f
val perm : int f
val nlink : int64 f
val uid : int64 f
val gid : int64 f
val rdev : int64 f
val size : int64 f
val atime : float f
val ctime : float f
val mtime : float f
end

type ro_ty = [`File | Flow.source_ty | Resource.close_ty]
Expand Down Expand Up @@ -93,11 +81,59 @@ end

val stat : _ ro -> ('a, 'b) Stat.t -> 'a -> 'b
(** [stat t fields fn] will retrieve the file statistics for the specified
[fields] and apply them as arguments to [fn]. *)
[fields] and apply them as arguments to [fn].
For example, to print the kind of a file along with its size and last
modified time:
{[ File.stat t File.Stat.[ Kind; Size; Mtime ]
(fun kind size mtime ->
traceln "kind: %a size: %Ld mtime: %f"
File.Stat.pp_kind size mtime)
]}
*)

val kind : _ ro -> Stat.kind
(** [kind t] returns the kind of file that [t] is.
Equivalent to [stat t [File.Kind] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val size : _ ro -> Optint.Int63.t
(** [size t] returns the size of [t].
Equivalent to [stat t [File.size] Fun.id]. *)
(** [size t] returns the size of [t]. Equivalent to [stat t [File.size] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val perm : _ ro -> int
(** [perm t] returns the file permissions of [t].
Equivalent to [stat t [File.Perm] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val uid : _ ro -> int64
(** [uid t] returns the user id associated with [t].
Equivalent to [stat t [File.Uid] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val gid : _ ro -> int64
(** [gid t] returns the group id associated with [t].
Equivalent to [stat t [File.Gid] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val atime : _ ro -> float
(** [atime t] returns the last access time of [t] as the seconds
since the start of the epoch.
Equivalent to [stat t [File.Atime] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val mtime : _ ro -> float
(** [mtime t] returns the last modified time of [t] as the seconds
since the start of the epoch.
Equivalent to [stat t [File.Mtime] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val ctime : _ ro -> float
(** [ctime t] returns the creation time of [t] as the seconds
since the start of the epoch.
Equivalent to [stat t [File.Ctime] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val pread : _ ro -> file_offset:Optint.Int63.t -> Cstruct.t list -> int
(** [pread t ~file_offset bufs] performs a single read of [t] at [file_offset] into [bufs].
Expand Down
9 changes: 9 additions & 0 deletions lib_eio/path.ml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ 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 = stat ~follow t [File.Stat.Kind] Fun.id
let size ~follow t = stat ~follow t [File.Stat.Size] Fun.id
let perm ~follow t = stat ~follow t [File.Stat.Perm] Fun.id
let uid ~follow t = stat ~follow t [File.Stat.Uid] Fun.id
let gid ~follow t = stat ~follow t [File.Stat.Gid] Fun.id
let atime ~follow t = stat ~follow t [File.Stat.Atime] Fun.id
let mtime ~follow t = stat ~follow t [File.Stat.Mtime] Fun.id
let ctime ~follow t = stat ~follow t [File.Stat.Ctime] Fun.id

let with_open_in path fn =
Switch.run @@ fun sw -> fn (open_in ~sw path)

Expand Down
87 changes: 86 additions & 1 deletion lib_eio/path.mli
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,92 @@ val stat : follow:bool -> _ t -> ('a, 'b) File.Stat.t -> 'a -> 'b
(** [stat ~follow t] returns metadata about the file [t].
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself. *)
otherwise it is about the link itself.
For example, to follow a symlink and print the kind, size and last modified
time of its target:
{[ Path.stat ~follow:true t File.Stat.[ Kind; Size; Mtime ]
(fun kind size mtime ->
traceln "kind: %a size: %Ld mtime: %f"
File.Stat.pp_kind size mtime)
]}
*)

val kind : follow:bool -> _ t -> File.Stat.kind
(** [kind ~follow t] returns the kind of file that [t] is.
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Kind] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val size : follow:bool -> _ t -> int64
(** [size ~follow t] returns the size of [t].
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.size] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val perm : follow:bool -> _ t -> int
(** [perm ~follow t] returns the file permissions of [t].
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Perm] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val uid : follow:bool -> _ t -> int64
(** [uid ~follow t] returns the user id associated with [t].
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Uid] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val gid : follow:bool -> _ t -> int64
(** [gid ~follow t] returns the group id associated with [t].
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Gid] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val atime : follow:bool -> _ t -> float
(** [atime ~follow t] returns the last access time of [t] as the seconds
since the start of the epoch.
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Atime] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val mtime : follow:bool -> _ t -> float
(** [mtime ~follow t] returns the last modified time of [t] as the seconds
since the start of the epoch.
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Mtime] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

val ctime : follow:bool -> _ t -> float
(** [ctime t] returns the creation time of [t] as the seconds
since the start of the epoch.
If [t] is a symlink, the information returned is about the target if [follow = true],
otherwise it is about the link itself.
Equivalent to [stat ~follow t [File.Ctime] Fun.id],
so use {!stat} to query multiple items from a file in one call. *)

(** {1 Other} *)

Expand Down
4 changes: 2 additions & 2 deletions tests/fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ let chdir path =
let assert_kind path kind =
Path.with_open_in path @@ fun file ->
assert (Eio.File.(stat file [Stat.kind] ((=) kind)))
assert (Eio.File.kind file = kind)
```

# Basic test cases
Expand Down Expand Up @@ -541,7 +541,7 @@ Fstatat:
let cwd = Eio.Stdenv.cwd env in
Switch.run @@ fun sw ->
try_mkdir (cwd / "stat_subdir2");
Eio.Path.stat ~follow:true (cwd / "stat_subdir2") [Eio.File.Stat.kind] Fun.id
Eio.Path.kind ~follow:true (cwd / "stat_subdir2")
+mkdir <cwd:stat_subdir2> -> ok
- : Eio.File.Stat.kind = `Directory
```
Expand Down

0 comments on commit 28169b5

Please sign in to comment.