Source file os.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
[@@@warning "@A"]
type stat_results = Unix.stats
let stat (filename: string) : stat_results =
match Unix.stat filename with
| stat -> stat
| exception Unix.Unix_error (Unix.ENOENT, _, filename) ->
raise (
Exn.FileNotFoundError (
Format.asprintf "No such file or directory: '%s'" filename)
)
let lstat (filename: string) : stat_results =
match Unix.lstat filename with
| stat -> stat
| exception Unix.Unix_error (Unix.ENOENT, _, filename) ->
raise (
Exn.FileNotFoundError (
Format.asprintf "No such file or directory: '%s'" filename)
)
let openfile = Unix.openfile
let close = Unix.close
let listdir : string -> string array = Sys.readdir
let chmod = Unix.chmod
let lchmod _pathobj _mode =
raise (Exn.NotImplementedError "lchmod() not available on this system")
let mkdir = Unix.mkdir
let unlink = Unix.unlink
let link = Unix.link
let rmdir = Unix.rmdir
let rename = Unix.rename
let replace = Unix.rename
let symlink = Unix.link
let utime = Unix.utimes
let readlink = Unix.readlink
let getcwd = Sys.getcwd
module type PATH =
(sig
val join: string -> string list -> string
val same_stat: stat_results -> stat_results -> bool
val normpath: string -> string
end)
let path : (module PATH) = if Sys.unix then (module PosixPath) else (module NtPath)
module Path : PATH = (val path)
module type DIR_ENTRY =
(sig
type t
val name: t -> string
val path: t -> string
val inode: t -> int
val is_dir: ?follow_symlinks: bool -> t -> bool
val is_file: ?follow_symlinks: bool -> t -> bool
val is_symlink: t -> bool
val stat: ?follow_symlinks: bool -> t -> stat_results
end)
module DirEntry =
(struct
type t = {
name: string;
path: string;
stat: stat_results;
symlink: stat_results option;
}
let name ({name; _}: t) : string =
name
let path ({path; name; _} : t) : string =
Path.join path [name]
let inode ({stat; _} : t) : int =
stat.Unix.st_ino
let is_dir ?(follow_symlinks: bool = true) (t: t) : bool =
let open Unix in
match follow_symlinks, t with
| true, {symlink = None; stat; _} -> stat.st_kind = S_DIR
| true, {symlink = Some s; _} -> s.st_kind = S_DIR
| false, {stat; _} -> stat.st_kind = S_DIR
let is_file ?(follow_symlinks: bool = true) (t: t) : bool =
let open Unix in
match follow_symlinks, t with
| true, {symlink = None; stat; _} -> stat.st_kind = S_REG
| true, {symlink = Some s; _} -> s.st_kind = S_REG
| false, {stat; _} -> stat.st_kind = S_REG
let is_symlink ({symlink; _}: t) : bool =
symlink <> None
let stat ?(follow_symlinks: bool = true) (t: t) : stat_results =
match follow_symlinks, t with
| true, {symlink = None; stat; _} -> stat
| true, {symlink = Some s; _} -> s
| false, {stat; _} -> stat
end)
let scandir ?(path: string = ".") ((): unit) : DirEntry.t array =
let files = listdir path in
let make_dir_entry (filename: string) : DirEntry.t =
let link_stat = Path.join path [filename] |> lstat in
if Unix.(link_stat.st_kind = S_LNK) then
let target = Path.join path [filename] |> Unix.readlink in
let stat = stat target in
{DirEntry.name = filename; path; stat; symlink = Some link_stat}
else
{DirEntry.name = filename; path; stat = link_stat; symlink = None}
in
Stdcompat.Array.map make_dir_entry files