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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
(* os-filesys.sml
*
* COPYRIGHT (c) 1995 AT&T Bell Laboratories.
*
* The Posix implementation of the generic file system interface.
*
*)
structure OS_FileSys =
struct
structure P_FSys = Posix.FileSys
val sysWordToWord = Word.fromLargeWord o SysWord.toLargeWord
type dirstream = P_FSys.dirstream
val openDir = P_FSys.opendir
val readDir = P_FSys.readdir
val rewindDir = P_FSys.rewinddir
val closeDir = P_FSys.closedir
val chDir = P_FSys.chdir
val getDir = P_FSys.getcwd
local
structure S = P_FSys.S
val mode777 = S.flags[S.irwxu, S.irwxg, S.irwxo]
in
fun mkDir path = P_FSys.mkdir(path, mode777)
end
val rmDir = P_FSys.rmdir
val isDir = P_FSys.ST.isDir o P_FSys.stat
val isLink = P_FSys.ST.isLink o P_FSys.lstat
val readLink = P_FSys.readlink
(* the maximum number of links allowed *)
val maxLinks: int = 64
structure P = OS_Path
val isMinGW = let open Primitive.MLton.Platform.OS in host = MinGW end
(* An implementation of fullPath which works on Unix and Windows (Cygwin and MinGW) *)
fun fullPath p =
let
val oldCWD = getDir()
fun mkPath (pathFromRoot, vol) =
P.toString {arcs = List.rev pathFromRoot,
isAbs = true,
vol = vol}
fun walkPath (n, pathFromRoot, arcs, vol) =
if n = 0
then raise PosixError.SysErr ("too many links", NONE)
else
case arcs of
[] => mkPath (pathFromRoot, vol)
| arc :: al =>
if arc = "" orelse arc = "."
then walkPath (n, pathFromRoot, al, vol)
else if arc = ".."
then
case pathFromRoot of
[] => walkPath (n, [], al, vol)
| _ :: r =>
(chDir ".."; walkPath (n, r, al, vol))
else
if isLink arc
then expandLink (n, pathFromRoot, arc, al, vol)
else
case al of
[] => mkPath (arc :: pathFromRoot, vol)
| _ =>
(chDir arc
; walkPath (n, arc :: pathFromRoot, al, vol))
and expandLink (n, pathFromRoot, link, rest, vol) =
let
val {isAbs, arcs, ...} = P.fromString (readLink link)
val arcs = List.@ (arcs, rest)
in
if isAbs
then gotoRoot (n-1, arcs, vol)
else walkPath (n-1, pathFromRoot, arcs, vol)
end
(* If the volume is not empty, chDir to it rather than to "/" *)
and gotoRoot (n, arcs, vol) =
(if vol <> "" andalso vol <> "/"
then chDir (vol ^ (if isMinGW then "\\" else "/"))
else chDir "/"
; walkPath (n, [], arcs, vol))
fun computeFullPath (arcs, vol) =
(gotoRoot (maxLinks, arcs, vol) before chDir oldCWD)
handle ex => (chDir oldCWD; raise ex)
in
case (P.fromString p)
of {isAbs=false, arcs, vol} =>
let
val {arcs=arcs', vol=vol, ...} = P.fromString(oldCWD)
in
computeFullPath (List.@(arcs', arcs), vol)
end
| {isAbs=true, arcs, vol} => computeFullPath (arcs, vol)
end
fun realPath p =
if P.isAbsolute p
then fullPath p
else P.mkRelative {path = fullPath p,
relativeTo = fullPath (getDir ())}
val fileSize = P_FSys.ST.size o P_FSys.stat
val modTime = P_FSys.ST.mtime o P_FSys.stat
fun setTime (path, t) =
P_FSys.utime (path, Option.map (fn t => {actime = t, modtime = t}) t)
val remove = P_FSys.unlink
val rename = P_FSys.rename
datatype access_mode = datatype Posix.FileSys.access_mode
fun access (path, al) =
let
fun cvt A_READ = P_FSys.A_READ
| cvt A_WRITE = P_FSys.A_WRITE
| cvt A_EXEC = P_FSys.A_EXEC
in
P_FSys.access (path, List.map cvt al)
end
datatype file_id = FID of {dev: SysWord.word, ino: SysWord.word}
fun fileId fname = let
val st = P_FSys.stat fname
in
FID{
dev = P_FSys.devToWord(P_FSys.ST.dev st),
ino = P_FSys.inoToWord(P_FSys.ST.ino st)
}
end
fun hash (FID{dev, ino}) = sysWordToWord(SysWord.+(SysWord.<<(dev, 0w16), ino))
fun compare (FID{dev=d1, ino=i1}, FID{dev=d2, ino=i2}) =
if (SysWord.<(d1, d2))
then General.LESS
else if (SysWord.>(d1, d2))
then General.GREATER
else if (SysWord.<(i1, i2))
then General.LESS
else if (SysWord.>(i1, i2))
then General.GREATER
else General.EQUAL
end
(*
* $Log: os-filesys.sml, v $
* Revision 1.3 1997/06/07 15:27:51 jhr
* SML'97 Basis Library changes (phase 3; Posix changes)
*
* Revision 1.2 1997/02/26 21:00:32 george
* Defined a new top level Option structure. All 'a option related
* functions have been moved out of General.
*
* Revision 1.1.1.1 1997/01/14 01:38:25 george
* Version 109.24
*
*)
|