Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / basis-library / system / file-sys.sml
CommitLineData
7f918cf1
CE
1(* os-filesys.sml
2 *
3 * COPYRIGHT (c) 1995 AT&T Bell Laboratories.
4 *
5 * The Posix implementation of the generic file system interface.
6 *
7 *)
8
9structure OS_FileSys =
10 struct
11 structure P_FSys = Posix.FileSys
12
13 val sysWordToWord = Word.fromLargeWord o SysWord.toLargeWord
14
15 type dirstream = P_FSys.dirstream
16
17 val openDir = P_FSys.opendir
18 val readDir = P_FSys.readdir
19 val rewindDir = P_FSys.rewinddir
20 val closeDir = P_FSys.closedir
21
22 val chDir = P_FSys.chdir
23 val getDir = P_FSys.getcwd
24 local
25 structure S = P_FSys.S
26 val mode777 = S.flags[S.irwxu, S.irwxg, S.irwxo]
27 in
28 fun mkDir path = P_FSys.mkdir(path, mode777)
29 end
30 val rmDir = P_FSys.rmdir
31 val isDir = P_FSys.ST.isDir o P_FSys.stat
32
33 val isLink = P_FSys.ST.isLink o P_FSys.lstat
34 val readLink = P_FSys.readlink
35
36 (* the maximum number of links allowed *)
37 val maxLinks: int = 64
38
39 structure P = OS_Path
40
41 val isMinGW = let open Primitive.MLton.Platform.OS in host = MinGW end
42
43 (* An implementation of fullPath which works on Unix and Windows (Cygwin and MinGW) *)
44 fun fullPath p =
45 let
46 val oldCWD = getDir()
47 fun mkPath (pathFromRoot, vol) =
48 P.toString {arcs = List.rev pathFromRoot,
49 isAbs = true,
50 vol = vol}
51 fun walkPath (n, pathFromRoot, arcs, vol) =
52 if n = 0
53 then raise PosixError.SysErr ("too many links", NONE)
54 else
55 case arcs of
56 [] => mkPath (pathFromRoot, vol)
57 | arc :: al =>
58 if arc = "" orelse arc = "."
59 then walkPath (n, pathFromRoot, al, vol)
60 else if arc = ".."
61 then
62 case pathFromRoot of
63 [] => walkPath (n, [], al, vol)
64 | _ :: r =>
65 (chDir ".."; walkPath (n, r, al, vol))
66 else
67 if isLink arc
68 then expandLink (n, pathFromRoot, arc, al, vol)
69 else
70 case al of
71 [] => mkPath (arc :: pathFromRoot, vol)
72 | _ =>
73 (chDir arc
74 ; walkPath (n, arc :: pathFromRoot, al, vol))
75 and expandLink (n, pathFromRoot, link, rest, vol) =
76 let
77 val {isAbs, arcs, ...} = P.fromString (readLink link)
78 val arcs = List.@ (arcs, rest)
79 in
80 if isAbs
81 then gotoRoot (n-1, arcs, vol)
82 else walkPath (n-1, pathFromRoot, arcs, vol)
83 end
84 (* If the volume is not empty, chDir to it rather than to "/" *)
85 and gotoRoot (n, arcs, vol) =
86 (if vol <> "" andalso vol <> "/"
87 then chDir (vol ^ (if isMinGW then "\\" else "/"))
88 else chDir "/"
89 ; walkPath (n, [], arcs, vol))
90 fun computeFullPath (arcs, vol) =
91 (gotoRoot (maxLinks, arcs, vol) before chDir oldCWD)
92 handle ex => (chDir oldCWD; raise ex)
93 in
94 case (P.fromString p)
95 of {isAbs=false, arcs, vol} =>
96 let
97 val {arcs=arcs', vol=vol, ...} = P.fromString(oldCWD)
98 in
99 computeFullPath (List.@(arcs', arcs), vol)
100 end
101 | {isAbs=true, arcs, vol} => computeFullPath (arcs, vol)
102 end
103
104 fun realPath p =
105 if P.isAbsolute p
106 then fullPath p
107 else P.mkRelative {path = fullPath p,
108 relativeTo = fullPath (getDir ())}
109
110 val fileSize = P_FSys.ST.size o P_FSys.stat
111
112 val modTime = P_FSys.ST.mtime o P_FSys.stat
113
114 fun setTime (path, t) =
115 P_FSys.utime (path, Option.map (fn t => {actime = t, modtime = t}) t)
116
117 val remove = P_FSys.unlink
118
119 val rename = P_FSys.rename
120
121 datatype access_mode = datatype Posix.FileSys.access_mode
122
123 fun access (path, al) =
124 let
125 fun cvt A_READ = P_FSys.A_READ
126 | cvt A_WRITE = P_FSys.A_WRITE
127 | cvt A_EXEC = P_FSys.A_EXEC
128 in
129 P_FSys.access (path, List.map cvt al)
130 end
131
132 datatype file_id = FID of {dev: SysWord.word, ino: SysWord.word}
133
134 fun fileId fname = let
135 val st = P_FSys.stat fname
136 in
137 FID{
138 dev = P_FSys.devToWord(P_FSys.ST.dev st),
139 ino = P_FSys.inoToWord(P_FSys.ST.ino st)
140 }
141 end
142
143 fun hash (FID{dev, ino}) = sysWordToWord(SysWord.+(SysWord.<<(dev, 0w16), ino))
144
145 fun compare (FID{dev=d1, ino=i1}, FID{dev=d2, ino=i2}) =
146 if (SysWord.<(d1, d2))
147 then General.LESS
148 else if (SysWord.>(d1, d2))
149 then General.GREATER
150 else if (SysWord.<(i1, i2))
151 then General.LESS
152 else if (SysWord.>(i1, i2))
153 then General.GREATER
154 else General.EQUAL
155
156 end
157
158(*
159 * $Log: os-filesys.sml, v $
160 * Revision 1.3 1997/06/07 15:27:51 jhr
161 * SML'97 Basis Library changes (phase 3; Posix changes)
162 *
163 * Revision 1.2 1997/02/26 21:00:32 george
164 * Defined a new top level Option structure. All 'a option related
165 * functions have been moved out of General.
166 *
167 * Revision 1.1.1.1 1997/01/14 01:38:25 george
168 * Version 109.24
169 *
170 *)