[project @ 1997-08-25 22:38:16 by sof]
[ghc-hetmet.git] / ghc / lib / required / Directory.lhs
index 3f8b365..69c81f3 100644 (file)
@@ -1,8 +1,7 @@
 %
 %
-% (c) The AQUA Project, Glasgow University, 1994-1996
+% (c) The AQUA Project, Glasgow University, 1994-1997
 %
 %
-
-\section[Directory]{Module @Directory@}
+\section[Directory]{Directory interface}
 
 A directory contains a series of entries, each of which is a named
 reference to a file system object (file, directory etc.).  Some
 
 A directory contains a series of entries, each of which is a named
 reference to a file system object (file, directory etc.).  Some
@@ -18,16 +17,37 @@ some operating systems, it may also be possible to have paths which
 are relative to the current directory.
 
 \begin{code}
 are relative to the current directory.
 
 \begin{code}
-module Directory ( 
-    createDirectory, removeDirectory, removeFile, 
-    renameDirectory, renameFile, getDirectoryContents,
-    getCurrentDirectory, setCurrentDirectory
-  ) where
-
+{-# OPTIONS -#include <sys/stat.h> #-}
+module Directory 
+   ( 
+    Permissions(Permissions),
+
+    createDirectory, 
+    removeDirectory, 
+    renameDirectory, 
+    getDirectoryContents,
+    getCurrentDirectory, 
+    setCurrentDirectory,
+
+    removeFile, 
+    renameFile, 
+
+    doesFileExist,
+    doesDirectoryExist,
+    getPermissions, 
+    setPermissions,
+    getModificationTime
+   ) where
+
+import PrelBase
 import Foreign
 import IOBase
 import Foreign
 import IOBase
-import STBase          ( PrimIO )
-import PackedString    ( packCBytesST, unpackPS )
+import STBase
+import UnsafeST                ( unsafePerformPrimIO )
+import ArrBase
+import PackBase                ( unpackNBytesST )
+import Time             ( ClockTime(..) )
+
 \end{code}
 
 %*********************************************************
 \end{code}
 
 %*********************************************************
@@ -45,44 +65,67 @@ renameFile          :: FilePath -> FilePath -> IO ()
 getDirectoryContents   :: FilePath -> IO [FilePath]
 getCurrentDirectory    :: IO FilePath
 setCurrentDirectory    :: FilePath -> IO ()
 getDirectoryContents   :: FilePath -> IO [FilePath]
 getCurrentDirectory    :: IO FilePath
 setCurrentDirectory    :: FilePath -> IO ()
+doesFileExist           :: FilePath -> IO Bool
+doesDirectoryExist      :: FilePath -> IO Bool
+getPermissions          :: FilePath -> IO Permissions
+setPermissions          :: FilePath -> Permissions -> IO ()
+getModificationTime     :: FilePath -> IO ClockTime
 \end{code}
 
 
 %*********************************************************
 %*                                                     *
 \end{code}
 
 
 %*********************************************************
 %*                                                     *
-\subsection{Signatures}
+\subsection{Permissions}
 %*                                                     *
 %*********************************************************
 
 %*                                                     *
 %*********************************************************
 
-$createDirectory dir$ creates a new directory
-{\em dir} which is initially empty, or as near to empty as the
-operating system allows.
+The @Permissions@ type is used to record whether certain
+operations are permissible on a file/directory:
+[to whom? - owner/group/world - the Report don't say much]
+
+\begin{code}
+data Permissions
+ = Permissions {
+    readable,   writeable, 
+    executable, searchable :: Bool 
+   } deriving (Eq, Ord, Read, Show)
+\end{code}
+
+%*********************************************************
+%*                                                     *
+\subsection{Implementation}
+%*                                                     *
+%*********************************************************
+
+@createDirectory dir@ creates a new directory {\em dir} which is
+initially empty, or as near to empty as the operating system
+allows.
 
 The operation may fail with:
 
 The operation may fail with:
+
 \begin{itemize}
 \begin{itemize}
-\item $AlreadyExists$
+\item @isPermissionError@ / @PermissionDenied@
+The process has insufficient privileges to perform the operation.
+@[EROFS, EACCES]@
+\item @isAlreadyExistsError@ / @AlreadyExists@
 The operand refers to a directory that already exists.  
 The operand refers to a directory that already exists.  
-[$EEXIST$]
-\item $HardwareFault$
+@ [EEXIST]@
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+@ [EIO]@
+\item @InvalidArgument@
 The operand is not a valid directory name.
 The operand is not a valid directory name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @NoSuchThing@
 There is no path to the directory. 
 There is no path to the directory. 
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
-The process has insufficient privileges to perform the operation.
-[$EROFS$, $EACCES$]
-\item $ResourceExhausted$
+@[ENOENT, ENOTDIR]@
+\item @ResourceExhausted@
 Insufficient resources (virtual memory, process file descriptors,
 physical disk space, etc.) are available to perform the operation.
 Insufficient resources (virtual memory, process file descriptors,
 physical disk space, etc.) are available to perform the operation.
-[$EDQUOT$, $ENOSPC$, $ENOMEM$, 
-$EMLINK$] 
-\item $InappropriateType$
+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
+\item @InappropriateType@
 The path refers to an existing non-directory object.
 The path refers to an existing non-directory object.
-[$EEXIST$]
+@[EEXIST]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -94,7 +137,7 @@ createDirectory path =
         constructErrorAndFail "createDirectory"
 \end{code}
 
         constructErrorAndFail "createDirectory"
 \end{code}
 
-$removeDirectory dir$ removes an existing directory {\em dir}.  The
+@removeDirectory dir@ removes an existing directory {\em dir}.  The
 implementation may specify additional constraints which must be
 satisfied before a directory can be removed (e.g. the directory has to
 be empty, or may not be in use by other processes).  It is not legal
 implementation may specify additional constraints which must be
 satisfied before a directory can be removed (e.g. the directory has to
 be empty, or may not be in use by other processes).  It is not legal
@@ -105,27 +148,27 @@ directory).
 
 The operation may fail with:
 \begin{itemize}
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+[@EIO@]
+\item @InvalidArgument@
 The operand is not a valid directory name.
 The operand is not a valid directory name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExist@ / @NoSuchThing@
 The directory does not exist. 
 The directory does not exist. 
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EROFS$, $EACCES$, $EPERM$]
-\item $UnsatisfiedConstraints$
+@[EROFS, EACCES, EPERM]@
+\item @UnsatisfiedConstraints@
 Implementation-dependent constraints are not satisfied.  
 Implementation-dependent constraints are not satisfied.  
-[$EBUSY$, $ENOTEMPTY$, $EEXIST$]
-\item $UnsupportedOperation$
+@[EBUSY, ENOTEMPTY, EEXIST]@
+\item @UnsupportedOperation@
 The implementation does not support removal in this situation.
 The implementation does not support removal in this situation.
-[$EINVAL$]
-\item $InappropriateType$
+@[EINVAL]@
+\item @InappropriateType@
 The operand refers to an existing non-directory object.
 The operand refers to an existing non-directory object.
-[$ENOTDIR$]
+@[ENOTDIR]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -137,7 +180,7 @@ removeDirectory path =
         constructErrorAndFail "removeDirectory"
 \end{code}
 
         constructErrorAndFail "removeDirectory"
 \end{code}
 
-$removeFile file$ removes the directory entry for an existing file
+@removeFile file@ removes the directory entry for an existing file
 {\em file}, where {\em file} is not itself a directory. The
 implementation may specify additional constraints which must be
 satisfied before a file can be removed (e.g. the file may not be in
 {\em file}, where {\em file} is not itself a directory. The
 implementation may specify additional constraints which must be
 satisfied before a file can be removed (e.g. the file may not be in
@@ -145,24 +188,24 @@ use by other processes).
 
 The operation may fail with:
 \begin{itemize}
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+@[EIO]@
+\item @InvalidArgument@
 The operand is not a valid file name.
 The operand is not a valid file name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExist@ / @NoSuchThing@
 The file does not exist. 
 The file does not exist. 
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EROFS$, $EACCES$, $EPERM$]
-\item $UnsatisfiedConstraints$
+@[EROFS, EACCES, EPERM]@
+\item @UnsatisfiedConstraints@
 Implementation-dependent constraints are not satisfied.  
 Implementation-dependent constraints are not satisfied.  
-[$EBUSY$]
-\item $InappropriateType$
+@[EBUSY]@
+\item @InappropriateType@
 The operand refers to an existing directory.
 The operand refers to an existing directory.
-[$EPERM$, $EINVAL$]
+@[EPERM, EINVAL]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -174,7 +217,7 @@ removeFile path =
         constructErrorAndFail "removeFile"
 \end{code}
 
         constructErrorAndFail "removeFile"
 \end{code}
 
-$renameDirectory old$ {\em new} changes the name of an existing
+@renameDirectory old@ {\em new} changes the name of an existing
 directory from {\em old} to {\em new}.  If the {\em new} directory
 already exists, it is atomically replaced by the {\em old} directory.
 If the {\em new} directory is neither the {\em old} directory nor an
 directory from {\em old} to {\em new}.  If the {\em new} directory
 already exists, it is atomically replaced by the {\em old} directory.
 If the {\em new} directory is neither the {\em old} directory nor an
@@ -186,31 +229,30 @@ must be documented.
 
 The operation may fail with:
 \begin{itemize}
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+@[EIO]@
+\item @InvalidArgument@
 Either operand is not a valid directory name.
 Either operand is not a valid directory name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
 The original directory does not exist, or there is no path to the target.
 The original directory does not exist, or there is no path to the target.
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EROFS$, $EACCES$, $EPERM$]
-\item $ResourceExhausted$
+@[EROFS, EACCES, EPERM]@
+\item @ResourceExhausted@
 Insufficient resources are available to perform the operation.  
 Insufficient resources are available to perform the operation.  
-[$EDQUOT$, $ENOSPC$, $ENOMEM$, 
-$EMLINK$]
-\item $UnsatisfiedConstraints$
+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
+\item @UnsatisfiedConstraints@
 Implementation-dependent constraints are not satisfied.
 Implementation-dependent constraints are not satisfied.
-[$EBUSY$, $ENOTEMPTY$, $EEXIST$]
-\item $UnsupportedOperation$
+@[EBUSY, ENOTEMPTY, EEXIST]@
+\item @UnsupportedOperation@
 The implementation does not support renaming in this situation.
 The implementation does not support renaming in this situation.
-[$EINVAL$, $EXDEV$]
-\item $InappropriateType$
+@[EINVAL, EXDEV]@
+\item @InappropriateType@
 Either path refers to an existing non-directory object.
 Either path refers to an existing non-directory object.
-[$ENOTDIR$, $EISDIR$]
+@[ENOTDIR, EISDIR]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -222,7 +264,7 @@ renameDirectory opath npath =
         constructErrorAndFail "renameDirectory"
 \end{code}
 
         constructErrorAndFail "renameDirectory"
 \end{code}
 
-$renameFile old$ {\em new} changes the name of an existing file system
+@renameFile old@ {\em new} changes the name of an existing file system
 object from {\em old} to {\em new}.  If the {\em new} object already
 exists, it is atomically replaced by the {\em old} object.  Neither
 path may refer to an existing directory.  A conformant implementation
 object from {\em old} to {\em new}.  If the {\em new} object already
 exists, it is atomically replaced by the {\em old} object.  Neither
 path may refer to an existing directory.  A conformant implementation
@@ -232,32 +274,30 @@ documented.
 
 The operation may fail with:
 \begin{itemize}
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+@[EIO]@
+\item @InvalidArgument@
 Either operand is not a valid file name.
 Either operand is not a valid file name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
 The original file does not exist, or there is no path to the target.
 The original file does not exist, or there is no path to the target.
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EROFS$, $EACCES$, $EPERM$]
-\item $ResourceExhausted$
+@[EROFS, EACCES, EPERM]@
+\item @ResourceExhausted@
 Insufficient resources are available to perform the operation.  
 Insufficient resources are available to perform the operation.  
-[$EDQUOT$, $ENOSPC$, $ENOMEM$, 
-$EMLINK$]
-\item $UnsatisfiedConstraints$
+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
+\item @UnsatisfiedConstraints@
 Implementation-dependent constraints are not satisfied.
 Implementation-dependent constraints are not satisfied.
-[$EBUSY$]
-\item $UnsupportedOperation$
+@[EBUSY]@
+\item @UnsupportedOperation@
 The implementation does not support renaming in this situation.
 The implementation does not support renaming in this situation.
-[$EXDEV$]
-\item $InappropriateType$
+@[EXDEV]@
+\item @InappropriateType@
 Either path refers to an existing directory.
 Either path refers to an existing directory.
-[$ENOTDIR$, $EISDIR$, $EINVAL$, 
-$EEXIST$, $ENOTEMPTY$]
+@[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -269,29 +309,29 @@ renameFile opath npath =
         constructErrorAndFail  "renameFile"
 \end{code}
 
         constructErrorAndFail  "renameFile"
 \end{code}
 
-$getDirectoryContents dir$ returns a list of
-<i>all</i> entries in {\em dir}.
+@getDirectoryContents dir@ returns a list of {\em all} entries
+in {\em dir}. 
 
 The operation may fail with:
 \begin{itemize}
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+@[EIO]@
+\item @InvalidArgument@
 The operand is not a valid directory name.
 The operand is not a valid directory name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
 The directory does not exist.
 The directory does not exist.
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EACCES$]
-\item $ResourceExhausted$
+@[EACCES]@
+\item @ResourceExhausted@
 Insufficient resources are available to perform the operation.
 Insufficient resources are available to perform the operation.
-[$EMFILE$, $ENFILE$]
-\item $InappropriateType$
+@[EMFILE, ENFILE]@
+\item @InappropriateType@
 The path refers to an existing non-directory object.
 The path refers to an existing non-directory object.
-[$ENOTDIR$]
+@[ENOTDIR]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -311,30 +351,30 @@ getDirectoryContents path =
             return []
         else
             _ccall_ strlen str                     >>= \ len ->
             return []
         else
             _ccall_ strlen str                     >>= \ len ->
-           packCBytesST len str                    >>= \ entry ->
+           unpackNBytesST str len                  >>= \ entry ->
             _ccall_ free str                       >>= \ () ->
             getEntries ptr (n+1)                   >>= \ entries ->
             _ccall_ free str                       >>= \ () ->
             getEntries ptr (n+1)                   >>= \ entries ->
-           return (unpackPS entry : entries)
+           return (entry : entries)
 \end{code}
 
 If the operating system has a notion of current directories,
 \end{code}
 
 If the operating system has a notion of current directories,
-$getCurrentDirectory$ returns an absolute path to the
+@getCurrentDirectory@ returns an absolute path to the
 current directory of the calling process.
 
 The operation may fail with:
 \begin{itemize}
 current directory of the calling process.
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $NoSuchThing$
+@[EIO]@
+\item @isDoesNotExistError@ / @NoSuchThing@
 There is no path referring to the current directory.
 There is no path referring to the current directory.
-[$EPERM$, $ENOENT$, $ESTALE$...]
-\item $PermissionDenied$
+@[EPERM, ENOENT, ESTALE...]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EACCES$]
-\item $ResourceExhausted$
+@[EACCES]@
+\item @ResourceExhausted@
 Insufficient resources are available to perform the operation.
 Insufficient resources are available to perform the operation.
-\item $UnsupportedOperation$
+\item @UnsupportedOperation@
 The operating system has no notion of current directory.
 \end{itemize}
 
 The operating system has no notion of current directory.
 \end{itemize}
 
@@ -343,37 +383,37 @@ getCurrentDirectory =
     _ccall_ getCurrentDirectory            `thenIO_Prim` \ str ->
     if str /= ``NULL'' then
         _ccall_ strlen str             `thenIO_Prim` \ len ->
     _ccall_ getCurrentDirectory            `thenIO_Prim` \ str ->
     if str /= ``NULL'' then
         _ccall_ strlen str             `thenIO_Prim` \ len ->
-        stToIO (packCBytesST len str)  >>=         \ pwd ->
+        stToIO (unpackNBytesST len str)        >>=           \ pwd ->
         _ccall_ free str               `thenIO_Prim` \ () ->
         _ccall_ free str               `thenIO_Prim` \ () ->
-        return (unpackPS pwd)
+        return pwd
     else
         constructErrorAndFail "getCurrentDirectory"
 \end{code}
 
 If the operating system has a notion of current directories,
     else
         constructErrorAndFail "getCurrentDirectory"
 \end{code}
 
 If the operating system has a notion of current directories,
-$setCurrentDirectory dir$ changes the current
+@setCurrentDirectory dir@ changes the current
 directory of the calling process to {\em dir}.
 
 The operation may fail with:
 \begin{itemize}
 directory of the calling process to {\em dir}.
 
 The operation may fail with:
 \begin{itemize}
-\item $HardwareFault$
+\item @HardwareFault@
 A physical I/O error has occurred.
 A physical I/O error has occurred.
-[$EIO$]
-\item $InvalidArgument$
+@[EIO]@
+\item @InvalidArgument@
 The operand is not a valid directory name.
 The operand is not a valid directory name.
-[$ENAMETOOLONG$, $ELOOP$]
-\item $NoSuchThing$
+@[ENAMETOOLONG, ELOOP]@
+\item @isDoesNotExistError@ / @NoSuchThing@
 The directory does not exist.
 The directory does not exist.
-[$ENOENT$, $ENOTDIR$]
-\item $PermissionDenied$
+@[ENOENT, ENOTDIR]@
+\item @isPermissionError@ / @PermissionDenied@
 The process has insufficient privileges to perform the operation.
 The process has insufficient privileges to perform the operation.
-[$EACCES$]
-\item $UnsupportedOperation$
+@[EACCES]@
+\item @UnsupportedOperation@
 The operating system has no notion of current directory, or the
 current directory cannot be dynamically changed.
 The operating system has no notion of current directory, or the
 current directory cannot be dynamically changed.
-\item $InappropriateType$
+\item @InappropriateType@
 The path refers to an existing non-directory object.
 The path refers to an existing non-directory object.
-[$ENOTDIR$]
+@[ENOTDIR]@
 \end{itemize}
 
 \begin{code}
 \end{itemize}
 
 \begin{code}
@@ -386,3 +426,130 @@ setCurrentDirectory path =
 \end{code}
 
 
 \end{code}
 
 
+
+\begin{code}
+--doesFileExist :: FilePath -> IO Bool
+doesFileExist name =
+  _ccall_ access name (``F_OK''::Int)      `thenIO_Prim` \ rc ->
+  return (rc == 0)
+
+--doesDirectoryExist :: FilePath -> IO Bool
+doesDirectoryExist name = 
+ (getFileStatus name >>= \ st -> return (isDirectory st))  
+   `catch` 
+ (\ _ -> return False)
+
+--getModificationTime :: FilePath -> IO ClockTime
+getModificationTime name =
+ getFileStatus name >>= \ st ->
+ modificationTime st
+
+--getPermissions :: FilePath -> IO Permissions
+getPermissions name =
+  getFileStatus name >>= \ st ->
+  let
+   fm = fileMode st
+   isect v = intersectFileMode v fm == v
+  in
+  return (
+    Permissions {
+      readable   = isect ownerReadMode,
+      writeable  = isect ownerWriteMode,
+      executable = not (isDirectory st)   && isect ownerExecuteMode,
+      searchable = not (isRegularFile st) && isect ownerExecuteMode
+    }
+  )
+
+--setPermissions :: FilePath -> Permissions -> IO ()
+setPermissions name (Permissions r w e s) = 
+    let
+     read#  = case (if r then ownerReadMode else ``0'') of { W# x# -> x# }
+     write# = case (if w then ownerWriteMode else ``0'') of { W# x# -> x# }
+     exec#  = case (if e || s then ownerExecuteMode else ``0'') of { W# x# -> x# }
+
+     mode  = I# (word2Int# (read# `or#` write# `or#` exec#))
+    in
+    _ccall_ chmod name mode                        `thenIO_Prim` \ rc ->
+    if rc == 0 then
+       return ()
+    else
+       fail (IOError Nothing SystemError "Directory.setPermissions")
+
+\end{code}
+
+
+(Sigh)..copied from Posix.Files to avoid dep. on posix library
+
+\begin{code}
+type FileStatus = ByteArray Int
+
+getFileStatus :: FilePath -> IO FileStatus
+getFileStatus name =
+    newCharArray (0,``sizeof(struct stat)'')        `thenIO_Prim` \ bytes ->
+    _casm_ ``%r = stat(%0,(struct stat *)%1);'' name bytes
+                                                   `thenIO_Prim` \ rc ->
+    if rc == 0 then
+       unsafeFreezeByteArray bytes                 `thenIO_Prim` \ stat ->
+       return stat
+    else
+       fail (IOError Nothing SystemError "Directory.getFileStatus")
+
+modificationTime :: FileStatus -> IO ClockTime
+modificationTime stat =
+    malloc1                                               `thenIO_Prim` \ i1 ->
+    _casm_ ``((unsigned long *)%1)[0] = ((struct stat *)%0)->st_mtime;'' stat i1 `thenIO_Prim` \ () ->
+    cvtUnsigned i1                                         `thenIO_Prim` \ secs ->
+    return (TOD secs 0)
+  where
+    malloc1 = ST $ \ (S# s#) ->
+       case newIntArray# 1# s# of 
+          StateAndMutableByteArray# s2# barr# -> (MutableByteArray bnds barr#, S# s2#)
+
+    bnds = (0,1)
+    -- The C routine fills in an unsigned word.  We don't have `unsigned2Integer#,'
+    -- so we freeze the data bits and use them for an MP_INT structure.  Note that
+    -- zero is still handled specially, although (J# 1# 1# (ptr to 0#)) is probably
+    -- acceptable to gmp.
+
+    cvtUnsigned (MutableByteArray _ arr#) = ST $ \ (S# s#) ->
+       case readIntArray# arr# 0# s# of 
+         StateAndInt# s2# r# ->
+            if r# ==# 0# then
+                (0, S# s2#)
+            else
+                case unsafeFreezeByteArray# arr# s2# of
+                  StateAndByteArray# s3# frozen# -> (J# 1# 1# frozen#, S# s3#)
+
+isDirectory :: FileStatus -> Bool
+isDirectory stat = unsafePerformPrimIO $
+    _casm_ ``%r = S_ISDIR(((struct stat *)%0)->st_mode);'' stat >>= \ rc ->
+    return (rc /= 0)
+
+isRegularFile :: FileStatus -> Bool
+isRegularFile stat = unsafePerformPrimIO $
+    _casm_ ``%r = S_ISREG(((struct stat *)%0)->st_mode);'' stat >>= \ rc ->
+    return (rc /= 0)
+
+
+\end{code}
+
+\begin{code}
+type FileMode = Word
+ownerReadMode :: FileMode
+ownerReadMode = ``S_IRUSR''
+
+ownerWriteMode :: FileMode
+ownerWriteMode = ``S_IWUSR''
+
+ownerExecuteMode :: FileMode
+ownerExecuteMode = ``S_IXUSR''
+
+intersectFileMode :: FileMode -> FileMode -> FileMode
+intersectFileMode (W# m1#) (W# m2#) = W# (m1# `and#` m2#)
+
+fileMode :: FileStatus -> FileMode
+fileMode stat = unsafePerformPrimIO $
+    _casm_ ``%r = ((struct stat *)%0)->st_mode;'' stat >>= \ mode ->
+    return mode
+
+\end{code}