package plato

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

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