[project @ 1996-06-27 16:55:06 by partain]
[ghc-hetmet.git] / ghc / lib / required / Directory.hs
1 {-
2 %
3 % (c) The GRASP/AQUA Project, Glasgow University, 1995-1996
4 %
5 \section[LibDirectory]{Haskell 1.3 Directory Operations}
6
7 A directory contains a series of entries, each of which is a named
8 reference to a file system object (file, directory etc.).  Some
9 entries may be hidden, inaccessible, or have some administrative
10 function (e.g. "." or ".." under POSIX), but in this standard all such
11 entries are considered to form part of the directory contents.
12 Entries in sub-directories are not, however, considered to form part
13 of the directory contents.
14
15 Each file system object is referenced by a {\em path}.  There is
16 normally at least one absolute path to each file system object.  In
17 some operating systems, it may also be possible to have paths which
18 are relative to the current directory.
19 -}
20 module Directory ( 
21     createDirectory, removeDirectory, removeFile, 
22     renameDirectory, renameFile, getDirectoryContents,
23     getCurrentDirectory, setCurrentDirectory ) where
24
25 import GHCio
26 import PreludeGlaST
27 import GHCps    ( packCBytesST, unpackPS )
28
29 createDirectory         :: FilePath -> IO ()
30 removeDirectory         :: FilePath -> IO ()
31 removeFile              :: FilePath -> IO ()
32 renameDirectory         :: FilePath -> FilePath -> IO ()
33 renameFile              :: FilePath -> FilePath -> IO ()
34 getDirectoryContents    :: FilePath -> IO [FilePath]
35 getCurrentDirectory     :: IO FilePath
36 setCurrentDirectory     :: FilePath -> IO ()
37
38 --------------------
39 {-
40 $createDirectory dir$ creates a new directory
41 {\em dir} which is initially empty, or as near to empty as the
42 operating system allows.
43
44 The operation may fail with:
45 \begin{itemize}
46 \item $AlreadyExists$
47 The operand refers to a directory that already exists.  
48 [$EEXIST$]
49 \item $HardwareFault$
50 A physical I/O error has occurred.
51 [$EIO$]
52 \item $InvalidArgument$
53 The operand is not a valid directory name.
54 [$ENAMETOOLONG$, $ELOOP$]
55 \item $NoSuchThing$
56 There is no path to the directory. 
57 [$ENOENT$, $ENOTDIR$]
58 \item $PermissionDenied$
59 The process has insufficient privileges to perform the operation.
60 [$EROFS$, $EACCES$]
61 \item $ResourceExhausted$
62 Insufficient resources (virtual memory, process file descriptors,
63 physical disk space, etc.) are available to perform the operation.
64 [$EDQUOT$, $ENOSPC$, $ENOMEM$, 
65 $EMLINK$] 
66 \item $InappropriateType$
67 The path refers to an existing non-directory object.
68 [$EEXIST$]
69 \end{itemize}
70 -}
71
72 createDirectory path =
73     _ccall_ createDirectory path    `stThen` \ rc ->
74     if rc == 0 then
75         return ()
76     else
77         constructErrorAndFail "createDirectory"
78
79 ------------------------
80 {-
81 $removeDirectory dir$ removes an existing directory {\em dir}.  The
82 implementation may specify additional constraints which must be
83 satisfied before a directory can be removed (e.g. the directory has to
84 be empty, or may not be in use by other processes).  It is not legal
85 for an implementation to partially remove a directory unless the
86 entire directory is removed. A conformant implementation need not
87 support directory removal in all situations (e.g. removal of the root
88 directory).
89
90 The operation may fail with:
91 \begin{itemize}
92 \item $HardwareFault$
93 A physical I/O error has occurred.
94 [$EIO$]
95 \item $InvalidArgument$
96 The operand is not a valid directory name.
97 [$ENAMETOOLONG$, $ELOOP$]
98 \item $NoSuchThing$
99 The directory does not exist. 
100 [$ENOENT$, $ENOTDIR$]
101 \item $PermissionDenied$
102 The process has insufficient privileges to perform the operation.
103 [$EROFS$, $EACCES$, $EPERM$]
104 \item $UnsatisfiedConstraints$
105 Implementation-dependent constraints are not satisfied.  
106 [$EBUSY$, $ENOTEMPTY$, $EEXIST$]
107 \item $UnsupportedOperation$
108 The implementation does not support removal in this situation.
109 [$EINVAL$]
110 \item $InappropriateType$
111 The operand refers to an existing non-directory object.
112 [$ENOTDIR$]
113 \end{itemize}
114 -}
115 removeDirectory path =
116     _ccall_ removeDirectory path    `stThen` \ rc ->
117     if rc == 0 then
118         return ()
119     else
120         constructErrorAndFail "removeDirectory"
121
122 ----------------------------
123 {-
124 $removeFile file$ removes the directory entry for an existing file
125 {\em file}, where {\em file} is not itself a directory. The
126 implementation may specify additional constraints which must be
127 satisfied before a file can be removed (e.g. the file may not be in
128 use by other processes).
129
130 The operation may fail with:
131 \begin{itemize}
132 \item $HardwareFault$
133 A physical I/O error has occurred.
134 [$EIO$]
135 \item $InvalidArgument$
136 The operand is not a valid file name.
137 [$ENAMETOOLONG$, $ELOOP$]
138 \item $NoSuchThing$
139 The file does not exist. 
140 [$ENOENT$, $ENOTDIR$]
141 \item $PermissionDenied$
142 The process has insufficient privileges to perform the operation.
143 [$EROFS$, $EACCES$, $EPERM$]
144 \item $UnsatisfiedConstraints$
145 Implementation-dependent constraints are not satisfied.  
146 [$EBUSY$]
147 \item $InappropriateType$
148 The operand refers to an existing directory.
149 [$EPERM$, $EINVAL$]
150 \end{itemize}
151 -}
152 removeFile path =
153     _ccall_ removeFile path `stThen` \ rc ->
154     if rc == 0 then
155         return ()
156     else
157         constructErrorAndFail "removeFile"
158
159 ---------------------------
160 {-
161 $renameDirectory old$ {\em new} changes the name of an existing
162 directory from {\em old} to {\em new}.  If the {\em new} directory
163 already exists, it is atomically replaced by the {\em old} directory.
164 If the {\em new} directory is neither the {\em old} directory nor an
165 alias of the {\em old} directory, it is removed as if by
166 $removeDirectory$.  A conformant implementation need not support
167 renaming directories in all situations (e.g. renaming to an existing
168 directory, or across different physical devices), but the constraints
169 must be documented.
170
171 The operation may fail with:
172 \begin{itemize}
173 \item $HardwareFault$
174 A physical I/O error has occurred.
175 [$EIO$]
176 \item $InvalidArgument$
177 Either operand is not a valid directory name.
178 [$ENAMETOOLONG$, $ELOOP$]
179 \item $NoSuchThing$
180 The original directory does not exist, or there is no path to the target.
181 [$ENOENT$, $ENOTDIR$]
182 \item $PermissionDenied$
183 The process has insufficient privileges to perform the operation.
184 [$EROFS$, $EACCES$, $EPERM$]
185 \item $ResourceExhausted$
186 Insufficient resources are available to perform the operation.  
187 [$EDQUOT$, $ENOSPC$, $ENOMEM$, 
188 $EMLINK$]
189 \item $UnsatisfiedConstraints$
190 Implementation-dependent constraints are not satisfied.
191 [$EBUSY$, $ENOTEMPTY$, $EEXIST$]
192 \item $UnsupportedOperation$
193 The implementation does not support renaming in this situation.
194 [$EINVAL$, $EXDEV$]
195 \item $InappropriateType$
196 Either path refers to an existing non-directory object.
197 [$ENOTDIR$, $EISDIR$]
198 \end{itemize}
199 -}
200 renameDirectory opath npath =
201     _ccall_ renameDirectory opath npath `stThen` \ rc ->
202     if rc == 0 then
203         return ()
204     else
205         constructErrorAndFail "renameDirectory"
206
207 -----------------------------
208 {-
209 $renameFile old$ {\em new} changes the name of an existing file system
210 object from {\em old} to {\em new}.  If the {\em new} object already
211 exists, it is atomically replaced by the {\em old} object.  Neither
212 path may refer to an existing directory.  A conformant implementation
213 need not support renaming files in all situations (e.g. renaming
214 across different physical devices), but the constraints must be
215 documented.
216
217 The operation may fail with:
218 \begin{itemize}
219 \item $HardwareFault$
220 A physical I/O error has occurred.
221 [$EIO$]
222 \item $InvalidArgument$
223 Either operand is not a valid file name.
224 [$ENAMETOOLONG$, $ELOOP$]
225 \item $NoSuchThing$
226 The original file does not exist, or there is no path to the target.
227 [$ENOENT$, $ENOTDIR$]
228 \item $PermissionDenied$
229 The process has insufficient privileges to perform the operation.
230 [$EROFS$, $EACCES$, $EPERM$]
231 \item $ResourceExhausted$
232 Insufficient resources are available to perform the operation.  
233 [$EDQUOT$, $ENOSPC$, $ENOMEM$, 
234 $EMLINK$]
235 \item $UnsatisfiedConstraints$
236 Implementation-dependent constraints are not satisfied.
237 [$EBUSY$]
238 \item $UnsupportedOperation$
239 The implementation does not support renaming in this situation.
240 [$EXDEV$]
241 \item $InappropriateType$
242 Either path refers to an existing directory.
243 [$ENOTDIR$, $EISDIR$, $EINVAL$, 
244 $EEXIST$, $ENOTEMPTY$]
245 \end{itemize}
246 -}
247 renameFile opath npath =
248     _ccall_ renameFile opath npath  `stThen` \ rc ->
249     if rc == 0 then
250         return ()
251     else
252         constructErrorAndFail   "renameFile"
253
254 ---------------------------
255 {-
256 $getDirectoryContents dir$ returns a list of
257 <i>all</i> entries in {\em dir}.
258
259 The operation may fail with:
260 \begin{itemize}
261 \item $HardwareFault$
262 A physical I/O error has occurred.
263 [$EIO$]
264 \item $InvalidArgument$
265 The operand is not a valid directory name.
266 [$ENAMETOOLONG$, $ELOOP$]
267 \item $NoSuchThing$
268 The directory does not exist.
269 [$ENOENT$, $ENOTDIR$]
270 \item $PermissionDenied$
271 The process has insufficient privileges to perform the operation.
272 [$EACCES$]
273 \item $ResourceExhausted$
274 Insufficient resources are available to perform the operation.
275 [$EMFILE$, $ENFILE$]
276 \item $InappropriateType$
277 The path refers to an existing non-directory object.
278 [$ENOTDIR$]
279 \end{itemize}
280 -}
281 getDirectoryContents path =
282     _ccall_ getDirectoryContents path   `stThen` \ ptr ->
283     if ptr == ``NULL'' then
284         constructErrorAndFail "getDirectoryContents"
285     else
286         stToIO (getEntries ptr 0)       >>= \ entries ->
287         _ccall_ free ptr                `stThen` \ () ->
288         return entries
289   where
290     getEntries :: Addr -> Int -> PrimIO [FilePath]
291     getEntries ptr n =
292         _casm_ ``%r = ((char **)%0)[%1];'' ptr n    >>= \ str ->
293         if str == ``NULL'' then 
294             return []
295         else
296             _ccall_ strlen str                      >>= \ len ->
297             packCBytesST len str                    >>= \ entry ->
298             _ccall_ free str                        >>= \ () ->
299             getEntries ptr (n+1)                    >>= \ entries ->
300             return (unpackPS entry : entries)
301
302 ---------------------
303 {-
304 If the operating system has a notion of current directories,
305 $getCurrentDirectory$ returns an absolute path to the
306 current directory of the calling process.
307
308 The operation may fail with:
309 \begin{itemize}
310 \item $HardwareFault$
311 A physical I/O error has occurred.
312 [$EIO$]
313 \item $NoSuchThing$
314 There is no path referring to the current directory.
315 [$EPERM$, $ENOENT$, $ESTALE$...]
316 \item $PermissionDenied$
317 The process has insufficient privileges to perform the operation.
318 [$EACCES$]
319 \item $ResourceExhausted$
320 Insufficient resources are available to perform the operation.
321 \item $UnsupportedOperation$
322 The operating system has no notion of current directory.
323 \end{itemize}
324 -}
325 getCurrentDirectory =
326     _ccall_ getCurrentDirectory     `stThen` \ str ->
327     if str /= ``NULL'' then
328         _ccall_ strlen str              `stThen` \ len ->
329         stToIO (packCBytesST len str)   >>=         \ pwd ->
330         _ccall_ free str                `stThen` \ () ->
331         return (unpackPS pwd)
332     else
333         constructErrorAndFail "getCurrentDirectory"
334
335 --------------------------
336 {-
337 If the operating system has a notion of current directories,
338 $setCurrentDirectory dir$ changes the current
339 directory of the calling process to {\em dir}.
340
341 The operation may fail with:
342 \begin{itemize}
343 \item $HardwareFault$
344 A physical I/O error has occurred.
345 [$EIO$]
346 \item $InvalidArgument$
347 The operand is not a valid directory name.
348 [$ENAMETOOLONG$, $ELOOP$]
349 \item $NoSuchThing$
350 The directory does not exist.
351 [$ENOENT$, $ENOTDIR$]
352 \item $PermissionDenied$
353 The process has insufficient privileges to perform the operation.
354 [$EACCES$]
355 \item $UnsupportedOperation$
356 The operating system has no notion of current directory, or the
357 current directory cannot be dynamically changed.
358 \item $InappropriateType$
359 The path refers to an existing non-directory object.
360 [$ENOTDIR$]
361 \end{itemize}
362 -}
363 setCurrentDirectory path =
364     _ccall_ setCurrentDirectory path    `stThen` \ rc ->
365     if rc == 0 then
366         return ()
367     else
368         constructErrorAndFail "setCurrentDirectory"
369
370
371