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