Commit | Line | Data |
---|---|---|
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 | ||
9 | structure 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 | *) |