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