1 -----------------------------------------------------------------------------
3 -- Module : System.Directory
4 -- Copyright : (c) The University of Glasgow 2001
5 -- License : BSD-style (see the file libraries/base/LICENSE)
7 -- Maintainer : libraries@haskell.org
9 -- Portability : portable
11 -- System-independent interface to directory manipulation.
13 -----------------------------------------------------------------------------
15 module System.Directory
19 -- * Actions on directories
20 createDirectory -- :: FilePath -> IO ()
21 , createDirectoryIfMissing -- :: Bool -> FilePath -> IO ()
22 , removeDirectory -- :: FilePath -> IO ()
23 , removeDirectoryRecursive -- :: FilePath -> IO ()
24 , renameDirectory -- :: FilePath -> FilePath -> IO ()
26 , getDirectoryContents -- :: FilePath -> IO [FilePath]
27 , getCurrentDirectory -- :: IO FilePath
28 , setCurrentDirectory -- :: FilePath -> IO ()
30 -- * Pre-defined directories
32 , getAppUserDataDirectory
33 , getUserDocumentsDirectory
34 , getTemporaryDirectory
37 , removeFile -- :: FilePath -> IO ()
38 , renameFile -- :: FilePath -> FilePath -> IO ()
39 , copyFile -- :: FilePath -> FilePath -> IO ()
45 , doesFileExist -- :: FilePath -> IO Bool
46 , doesDirectoryExist -- :: FilePath -> IO Bool
54 readable, -- :: Permissions -> Bool
55 writable, -- :: Permissions -> Bool
56 executable, -- :: Permissions -> Bool
57 searchable -- :: Permissions -> Bool
60 , getPermissions -- :: FilePath -> IO Permissions
61 , setPermissions -- :: FilePath -> Permissions -> IO ()
65 , getModificationTime -- :: FilePath -> IO ClockTime
68 import System.Directory.Internals
69 import System.Environment ( getEnv )
70 import System.IO.Error
71 import Control.Monad ( when, unless )
80 import Control.Exception ( bracket )
84 #ifdef __GLASGOW_HASKELL__
87 import Control.Exception ( bracket )
88 import System.Posix.Types
89 import System.Posix.Internals
90 import System.Time ( ClockTime(..) )
95 import GHC.IOBase ( IOException(..), IOErrorType(..), ioException )
98 A directory contains a series of entries, each of which is a named
99 reference to a file system object (file, directory etc.). Some
100 entries may be hidden, inaccessible, or have some administrative
101 function (e.g. `.' or `..' under POSIX
102 <http://www.opengroup.org/onlinepubs/007904975/toc.htm>), but in
103 this standard all such entries are considered to form part of the
104 directory contents. Entries in sub-directories are not, however,
105 considered to form part of the directory contents.
107 Each file system object is referenced by a /path/. There is
108 normally at least one absolute path to each file system object. In
109 some operating systems, it may also be possible to have paths which
110 are relative to the current directory.
113 -----------------------------------------------------------------------------
118 The 'Permissions' type is used to record whether certain operations are
119 permissible on a file\/directory. 'getPermissions' and 'setPermissions'
120 get and set these permissions, respectively. Permissions apply both to
121 files and directories. For directories, the executable field will be
122 'False', and for files the searchable field will be 'False'. Note that
123 directories may be searchable without being readable, if permission has
124 been given to use them as part of a path, but not to examine the
127 Note that to change some, but not all permissions, a construct on the following lines must be used.
129 > makeReadable f = do
130 > p <- getPermissions f
131 > setPermissions f (p {readable = True})
138 executable, searchable :: Bool
139 } deriving (Eq, Ord, Read, Show)
141 {- |The 'getPermissions' operation returns the
142 permissions for the file or directory.
144 The operation may fail with:
146 * 'isPermissionError' if the user is not permitted to access
149 * 'isDoesNotExistError' if the file or directory does not exist.
153 getPermissions :: FilePath -> IO Permissions
154 getPermissions name = do
155 withCString name $ \s -> do
156 read <- c_access s r_OK
157 write <- c_access s w_OK
158 exec <- c_access s x_OK
159 withFileStatus "getPermissions" name $ \st -> do
160 is_dir <- isDirectory st
163 readable = read == 0,
164 writable = write == 0,
165 executable = not is_dir && exec == 0,
166 searchable = is_dir && exec == 0
170 {- |The 'setPermissions' operation sets the
171 permissions for the file or directory.
173 The operation may fail with:
175 * 'isPermissionError' if the user is not permitted to set
178 * 'isDoesNotExistError' if the file or directory does not exist.
182 setPermissions :: FilePath -> Permissions -> IO ()
183 setPermissions name (Permissions r w e s) = do
184 allocaBytes sizeof_stat $ \ p_stat -> do
185 withCString name $ \p_name -> do
186 throwErrnoIfMinus1_ "setPermissions" $ do
188 mode <- st_mode p_stat
189 let mode1 = modifyBit r mode s_IRUSR
190 let mode2 = modifyBit w mode1 s_IWUSR
191 let mode3 = modifyBit (e || s) mode2 s_IXUSR
195 modifyBit :: Bool -> CMode -> CMode -> CMode
196 modifyBit False m b = m .&. (complement b)
197 modifyBit True m b = m .|. b
199 -----------------------------------------------------------------------------
202 {- |@'createDirectory' dir@ creates a new directory @dir@ which is
203 initially empty, or as near to empty as the operating system
206 The operation may fail with:
208 * 'isPermissionError' \/ 'PermissionDenied'
209 The process has insufficient privileges to perform the operation.
212 * 'isAlreadyExistsError' \/ 'AlreadyExists'
213 The operand refers to a directory that already exists.
217 A physical I\/O error has occurred.
221 The operand is not a valid directory name.
222 @[ENAMETOOLONG, ELOOP]@
225 There is no path to the directory.
228 * 'ResourceExhausted'
229 Insufficient resources (virtual memory, process file descriptors,
230 physical disk space, etc.) are available to perform the operation.
231 @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
233 * 'InappropriateType'
234 The path refers to an existing non-directory object.
239 createDirectory :: FilePath -> IO ()
240 createDirectory path = do
241 modifyIOError (`ioeSetFileName` path) $
242 withCString path $ \s -> do
243 throwErrnoIfMinus1Retry_ "createDirectory" $
247 -- | @'createDirectoryIfMissing' parents dir@ creates a new directory
248 -- @dir@ if it doesn\'t exist. If the first argument is 'True'
249 -- the function will also create all parent directories if they are missing.
250 createDirectoryIfMissing :: Bool -- ^ Create its parents too?
251 -> FilePath -- ^ The path to the directory you want to make
253 createDirectoryIfMissing parents file = do
254 b <- doesDirectoryExist file
255 case (b,parents, file) of
256 (_, _, "") -> return ()
257 (True, _, _) -> return ()
258 (_, True, _) -> mapM_ (createDirectoryIfMissing False) (tail (pathParents file))
259 (_, False, _) -> createDirectory file
261 #if __GLASGOW_HASKELL__
262 {- | @'removeDirectory' dir@ removes an existing directory /dir/. The
263 implementation may specify additional constraints which must be
264 satisfied before a directory can be removed (e.g. the directory has to
265 be empty, or may not be in use by other processes). It is not legal
266 for an implementation to partially remove a directory unless the
267 entire directory is removed. A conformant implementation need not
268 support directory removal in all situations (e.g. removal of the root
271 The operation may fail with:
274 A physical I\/O error has occurred.
278 The operand is not a valid directory name.
279 [ENAMETOOLONG, ELOOP]
281 * 'isDoesNotExistError' \/ 'NoSuchThing'
282 The directory does not exist.
285 * 'isPermissionError' \/ 'PermissionDenied'
286 The process has insufficient privileges to perform the operation.
287 @[EROFS, EACCES, EPERM]@
289 * 'UnsatisfiedConstraints'
290 Implementation-dependent constraints are not satisfied.
291 @[EBUSY, ENOTEMPTY, EEXIST]@
293 * 'UnsupportedOperation'
294 The implementation does not support removal in this situation.
297 * 'InappropriateType'
298 The operand refers to an existing non-directory object.
303 removeDirectory :: FilePath -> IO ()
304 removeDirectory path = do
305 modifyIOError (`ioeSetFileName` path) $
306 withCString path $ \s ->
307 throwErrnoIfMinus1Retry_ "removeDirectory" (c_rmdir s)
310 -- | @'removeDirectoryRecursive' dir@ removes an existing directory /dir/
311 -- together with its content and all subdirectories. Be careful,
312 -- if the directory contains symlinks, the function will follow them.
313 removeDirectoryRecursive :: FilePath -> IO ()
314 removeDirectoryRecursive startLoc = do
315 cont <- getDirectoryContents startLoc
316 sequence_ [rm (startLoc `joinFileName` x) | x <- cont, x /= "." && x /= ".."]
317 removeDirectory startLoc
319 rm :: FilePath -> IO ()
320 rm f = do temp <- try (removeFile f)
322 Left e -> do isDir <- doesDirectoryExist f
323 -- If f is not a directory, re-throw the error
324 unless isDir $ ioError e
325 removeDirectoryRecursive f
328 #if __GLASGOW_HASKELL__
329 {- |'removeFile' /file/ removes the directory entry for an existing file
330 /file/, where /file/ is not itself a directory. The
331 implementation may specify additional constraints which must be
332 satisfied before a file can be removed (e.g. the file may not be in
333 use by other processes).
335 The operation may fail with:
338 A physical I\/O error has occurred.
342 The operand is not a valid file name.
343 @[ENAMETOOLONG, ELOOP]@
345 * 'isDoesNotExistError' \/ 'NoSuchThing'
346 The file does not exist.
349 * 'isPermissionError' \/ 'PermissionDenied'
350 The process has insufficient privileges to perform the operation.
351 @[EROFS, EACCES, EPERM]@
353 * 'UnsatisfiedConstraints'
354 Implementation-dependent constraints are not satisfied.
357 * 'InappropriateType'
358 The operand refers to an existing directory.
363 removeFile :: FilePath -> IO ()
365 modifyIOError (`ioeSetFileName` path) $
366 withCString path $ \s ->
367 throwErrnoIfMinus1Retry_ "removeFile" (c_unlink s)
369 {- |@'renameDirectory' old new@ changes the name of an existing
370 directory from /old/ to /new/. If the /new/ directory
371 already exists, it is atomically replaced by the /old/ directory.
372 If the /new/ directory is neither the /old/ directory nor an
373 alias of the /old/ directory, it is removed as if by
374 'removeDirectory'. A conformant implementation need not support
375 renaming directories in all situations (e.g. renaming to an existing
376 directory, or across different physical devices), but the constraints
379 On Win32 platforms, @renameDirectory@ fails if the /new/ directory already
382 The operation may fail with:
385 A physical I\/O error has occurred.
389 Either operand is not a valid directory name.
390 @[ENAMETOOLONG, ELOOP]@
392 * 'isDoesNotExistError' \/ 'NoSuchThing'
393 The original directory does not exist, or there is no path to the target.
396 * 'isPermissionError' \/ 'PermissionDenied'
397 The process has insufficient privileges to perform the operation.
398 @[EROFS, EACCES, EPERM]@
400 * 'ResourceExhausted'
401 Insufficient resources are available to perform the operation.
402 @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
404 * 'UnsatisfiedConstraints'
405 Implementation-dependent constraints are not satisfied.
406 @[EBUSY, ENOTEMPTY, EEXIST]@
408 * 'UnsupportedOperation'
409 The implementation does not support renaming in this situation.
412 * 'InappropriateType'
413 Either path refers to an existing non-directory object.
418 renameDirectory :: FilePath -> FilePath -> IO ()
419 renameDirectory opath npath =
420 withFileStatus "renameDirectory" opath $ \st -> do
421 is_dir <- isDirectory st
423 then ioException (IOError Nothing InappropriateType "renameDirectory"
424 ("not a directory") (Just opath))
427 withCString opath $ \s1 ->
428 withCString npath $ \s2 ->
429 throwErrnoIfMinus1Retry_ "renameDirectory" (c_rename s1 s2)
431 {- |@'renameFile' old new@ changes the name of an existing file system
432 object from /old/ to /new/. If the /new/ object already
433 exists, it is atomically replaced by the /old/ object. Neither
434 path may refer to an existing directory. A conformant implementation
435 need not support renaming files in all situations (e.g. renaming
436 across different physical devices), but the constraints must be
439 The operation may fail with:
442 A physical I\/O error has occurred.
446 Either operand is not a valid file name.
447 @[ENAMETOOLONG, ELOOP]@
449 * 'isDoesNotExistError' \/ 'NoSuchThing'
450 The original file does not exist, or there is no path to the target.
453 * 'isPermissionError' \/ 'PermissionDenied'
454 The process has insufficient privileges to perform the operation.
455 @[EROFS, EACCES, EPERM]@
457 * 'ResourceExhausted'
458 Insufficient resources are available to perform the operation.
459 @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
461 * 'UnsatisfiedConstraints'
462 Implementation-dependent constraints are not satisfied.
465 * 'UnsupportedOperation'
466 The implementation does not support renaming in this situation.
469 * 'InappropriateType'
470 Either path refers to an existing directory.
471 @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@
475 renameFile :: FilePath -> FilePath -> IO ()
476 renameFile opath npath =
477 withFileOrSymlinkStatus "renameFile" opath $ \st -> do
478 is_dir <- isDirectory st
480 then ioException (IOError Nothing InappropriateType "renameFile"
481 "is a directory" (Just opath))
484 withCString opath $ \s1 ->
485 withCString npath $ \s2 ->
486 throwErrnoIfMinus1Retry_ "renameFile" (c_rename s1 s2)
488 #endif /* __GLASGOW_HASKELL__ */
490 {- |@'copyFile' old new@ copies the existing file from /old/ to /new/.
491 If the /new/ file already exists, it is atomically replaced by the /old/ file.
492 Neither path may refer to an existing directory.
494 copyFile :: FilePath -> FilePath -> IO ()
495 copyFile fromFPath toFPath =
496 #if defined(__HUGS__)
497 (bracket (openBinaryFile fromFPath ReadMode) hClose $ \hFrom ->
498 bracket (openBinaryFile toFPath WriteMode) hClose $ \hTo -> do
499 hGetContents hFrom >>= hPutStr hTo
500 try (getPermissions fromFPath >>= setPermissions toFPath)
501 return ()) `catch` \err ->
502 ioError (annotateIOError err "copyFile" Nothing Nothing)
503 #elif (!defined(__GLASGOW_HASKELL__) || __GLASGOW_HASKELL__ <= 600)
504 do readFile fromFPath >>= writeFile toFPath
505 try (getPermissions fromFPath >>= setPermissions toFPath)
508 (bracket (openBinaryFile fromFPath ReadMode) hClose $ \hFrom ->
509 bracket (openBinaryFile toFPath WriteMode) hClose $ \hTo ->
510 allocaBytes bufferSize $ \buffer -> do
511 copyContents hFrom hTo buffer
512 try (getPermissions fromFPath >>= setPermissions toFPath)
513 return ()) `catch` (ioError . changeFunName)
517 changeFunName (IOError h iot fun str mb_fp) = IOError h iot "copyFile" str mb_fp
519 copyContents hFrom hTo buffer = do
520 count <- hGetBuf hFrom buffer bufferSize
521 when (count > 0) $ do
522 hPutBuf hTo buffer count
523 copyContents hFrom hTo buffer
526 #ifdef __GLASGOW_HASKELL__
527 -- | Given path referring to a file or directory, returns a
528 -- canonicalized path, with the intent that two paths referring
529 -- to the same file\/directory will map to the same canonicalized
530 -- path. Note that it is impossible to guarantee that the
531 -- implication (same file\/dir \<=\> same canonicalizedPath) holds
532 -- in either direction: this function can make only a best-effort
534 canonicalizePath :: FilePath -> IO FilePath
535 canonicalizePath fpath =
536 withCString fpath $ \pInPath ->
537 allocaBytes long_path_size $ \pOutPath ->
538 #if defined(mingw32_HOST_OS)
539 alloca $ \ppFilePart ->
540 do c_GetFullPathName pInPath (fromIntegral long_path_size) pOutPath ppFilePart
542 do c_realpath pInPath pOutPath
546 #if defined(mingw32_HOST_OS)
547 foreign import stdcall unsafe "GetFullPathName"
548 c_GetFullPathName :: CString
554 foreign import ccall unsafe "realpath"
555 c_realpath :: CString
559 #else /* !__GLASGOW_HASKELL__ */
560 -- dummy implementation
561 canonicalizePath :: FilePath -> IO FilePath
562 canonicalizePath fpath = return fpath
563 #endif /* !__GLASGOW_HASKELL__ */
565 -- | Given an executable file name, searches for such file
566 -- in the directories listed in system PATH. The returned value
567 -- is the path to the found executable or Nothing if there isn't
568 -- such executable. For example (findExecutable \"ghc\")
569 -- gives you the path to GHC.
570 findExecutable :: String -> IO (Maybe FilePath)
571 findExecutable binary = do
572 path <- getEnv "PATH"
573 search (parseSearchPath path)
575 fileName = binary `joinFileExt` exeExtension
577 search :: [FilePath] -> IO (Maybe FilePath)
578 search [] = return Nothing
580 let path = d `joinFileName` fileName
581 b <- doesFileExist path
582 if b then return (Just path)
585 #ifdef __GLASGOW_HASKELL__
586 {- |@'getDirectoryContents' dir@ returns a list of /all/ entries
589 The operation may fail with:
592 A physical I\/O error has occurred.
596 The operand is not a valid directory name.
597 @[ENAMETOOLONG, ELOOP]@
599 * 'isDoesNotExistError' \/ 'NoSuchThing'
600 The directory does not exist.
603 * 'isPermissionError' \/ 'PermissionDenied'
604 The process has insufficient privileges to perform the operation.
607 * 'ResourceExhausted'
608 Insufficient resources are available to perform the operation.
611 * 'InappropriateType'
612 The path refers to an existing non-directory object.
617 getDirectoryContents :: FilePath -> IO [FilePath]
618 getDirectoryContents path = do
619 modifyIOError (`ioeSetFileName` path) $
620 alloca $ \ ptr_dEnt ->
622 (withCString path $ \s ->
623 throwErrnoIfNullRetry desc (c_opendir s))
624 (\p -> throwErrnoIfMinus1_ desc (c_closedir p))
625 (\p -> loop ptr_dEnt p)
627 desc = "getDirectoryContents"
629 loop :: Ptr (Ptr CDirent) -> Ptr CDir -> IO [String]
630 loop ptr_dEnt dir = do
632 r <- readdir dir ptr_dEnt
635 dEnt <- peek ptr_dEnt
639 entry <- (d_name dEnt >>= peekCString)
641 entries <- loop ptr_dEnt dir
642 return (entry:entries)
643 else do errno <- getErrno
644 if (errno == eINTR) then loop ptr_dEnt dir else do
645 let (Errno eo) = errno
646 if (eo == end_of_dir)
652 {- |If the operating system has a notion of current directories,
653 'getCurrentDirectory' returns an absolute path to the
654 current directory of the calling process.
656 The operation may fail with:
659 A physical I\/O error has occurred.
662 * 'isDoesNotExistError' \/ 'NoSuchThing'
663 There is no path referring to the current directory.
664 @[EPERM, ENOENT, ESTALE...]@
666 * 'isPermissionError' \/ 'PermissionDenied'
667 The process has insufficient privileges to perform the operation.
670 * 'ResourceExhausted'
671 Insufficient resources are available to perform the operation.
673 * 'UnsupportedOperation'
674 The operating system has no notion of current directory.
678 getCurrentDirectory :: IO FilePath
679 getCurrentDirectory = do
680 p <- mallocBytes long_path_size
682 where go p bytes = do
683 p' <- c_getcwd p (fromIntegral bytes)
685 then do s <- peekCString p'
688 else do errno <- getErrno
690 then do let bytes' = bytes * 2
691 p' <- reallocBytes p bytes'
693 else throwErrno "getCurrentDirectory"
695 {- |If the operating system has a notion of current directories,
696 @'setCurrentDirectory' dir@ changes the current
697 directory of the calling process to /dir/.
699 The operation may fail with:
702 A physical I\/O error has occurred.
706 The operand is not a valid directory name.
707 @[ENAMETOOLONG, ELOOP]@
709 * 'isDoesNotExistError' \/ 'NoSuchThing'
710 The directory does not exist.
713 * 'isPermissionError' \/ 'PermissionDenied'
714 The process has insufficient privileges to perform the operation.
717 * 'UnsupportedOperation'
718 The operating system has no notion of current directory, or the
719 current directory cannot be dynamically changed.
721 * 'InappropriateType'
722 The path refers to an existing non-directory object.
727 setCurrentDirectory :: FilePath -> IO ()
728 setCurrentDirectory path = do
729 modifyIOError (`ioeSetFileName` path) $
730 withCString path $ \s ->
731 throwErrnoIfMinus1Retry_ "setCurrentDirectory" (c_chdir s)
732 -- ToDo: add path to error
734 {- |The operation 'doesDirectoryExist' returns 'True' if the argument file
735 exists and is a directory, and 'False' otherwise.
738 doesDirectoryExist :: FilePath -> IO Bool
739 doesDirectoryExist name =
741 (withFileStatus "doesDirectoryExist" name $ \st -> isDirectory st)
742 (\ _ -> return False)
744 {- |The operation 'doesFileExist' returns 'True'
745 if the argument file exists and is not a directory, and 'False' otherwise.
748 doesFileExist :: FilePath -> IO Bool
749 doesFileExist name = do
751 (withFileStatus "doesFileExist" name $ \st -> do b <- isDirectory st; return (not b))
752 (\ _ -> return False)
754 {- |The 'getModificationTime' operation returns the
755 clock time at which the file or directory was last modified.
757 The operation may fail with:
759 * 'isPermissionError' if the user is not permitted to access
760 the modification time; or
762 * 'isDoesNotExistError' if the file or directory does not exist.
766 getModificationTime :: FilePath -> IO ClockTime
767 getModificationTime name =
768 withFileStatus "getModificationTime" name $ \ st ->
771 withFileStatus :: String -> FilePath -> (Ptr CStat -> IO a) -> IO a
772 withFileStatus loc name f = do
773 modifyIOError (`ioeSetFileName` name) $
774 allocaBytes sizeof_stat $ \p ->
775 withCString (fileNameEndClean name) $ \s -> do
776 throwErrnoIfMinus1Retry_ loc (c_stat s p)
779 withFileOrSymlinkStatus :: String -> FilePath -> (Ptr CStat -> IO a) -> IO a
780 withFileOrSymlinkStatus loc name f = do
781 modifyIOError (`ioeSetFileName` name) $
782 allocaBytes sizeof_stat $ \p ->
783 withCString name $ \s -> do
784 throwErrnoIfMinus1Retry_ loc (lstat s p)
787 modificationTime :: Ptr CStat -> IO ClockTime
788 modificationTime stat = do
789 mtime <- st_mtime stat
790 let realToInteger = round . realToFrac :: Real a => a -> Integer
791 return (TOD (realToInteger (mtime :: CTime)) 0)
793 isDirectory :: Ptr CStat -> IO Bool
794 isDirectory stat = do
796 return (s_isdir mode)
798 fileNameEndClean :: String -> String
799 fileNameEndClean name =
800 if i > 0 && (ec == '\\' || ec == '/') then
801 fileNameEndClean (take i name)
805 i = (length name) - 1
808 foreign import ccall unsafe "__hscore_long_path_size"
809 long_path_size :: Int
811 foreign import ccall unsafe "__hscore_R_OK" r_OK :: CMode
812 foreign import ccall unsafe "__hscore_W_OK" w_OK :: CMode
813 foreign import ccall unsafe "__hscore_X_OK" x_OK :: CMode
815 foreign import ccall unsafe "__hscore_S_IRUSR" s_IRUSR :: CMode
816 foreign import ccall unsafe "__hscore_S_IWUSR" s_IWUSR :: CMode
817 foreign import ccall unsafe "__hscore_S_IXUSR" s_IXUSR :: CMode
819 #endif /* __GLASGOW_HASKELL__ */
821 {- | Returns the current user's home directory.
823 The directory returned is expected to be writable by the current user,
824 but note that it isn't generally considered good practice to store
825 application-specific data here; use 'getAppUserDataDirectory'
828 On Unix, 'getHomeDirectory' returns the value of the @HOME@
829 environment variable. On Windows, the system is queried for a
830 suitable path; a typical path might be
831 @C:/Documents And Settings/user@.
833 The operation may fail with:
835 * 'UnsupportedOperation'
836 The operating system has no notion of home directory.
838 * 'isDoesNotExistError'
839 The home directory for the current user does not exist, or
842 getHomeDirectory :: IO FilePath
844 #if __GLASGOW_HASKELL__ && defined(mingw32_HOST_OS)
845 allocaBytes long_path_size $ \pPath -> do
846 r <- c_SHGetFolderPath nullPtr csidl_PROFILE nullPtr 0 pPath
848 then c_SHGetFolderPath nullPtr csidl_WINDOWS nullPtr 0 pPath
855 {- | Returns the pathname of a directory in which application-specific
856 data for the current user can be stored. The result of
857 'getAppUserDataDirectory' for a given application is specific to
860 The argument should be the name of the application, which will be used
861 to construct the pathname (so avoid using unusual characters that
862 might result in an invalid pathname).
864 Note: the directory may not actually exist, and may need to be created
865 first. It is expected that the parent directory exists and is
868 On Unix, this function returns @$HOME\/.appName@. On Windows, a
869 typical path might be
871 > C:/Documents And Settings/user/Application Data/appName
873 The operation may fail with:
875 * 'UnsupportedOperation'
876 The operating system has no notion of application-specific data directory.
878 * 'isDoesNotExistError'
879 The home directory for the current user does not exist, or
882 getAppUserDataDirectory :: String -> IO FilePath
883 getAppUserDataDirectory appName = do
884 #if __GLASGOW_HASKELL__ && defined(mingw32_HOST_OS)
885 allocaBytes long_path_size $ \pPath -> do
886 r <- c_SHGetFolderPath nullPtr csidl_APPDATA nullPtr 0 pPath
887 s <- peekCString pPath
888 return (s++'\\':appName)
890 path <- getEnv "HOME"
891 return (path++'/':'.':appName)
894 {- | Returns the current user's document directory.
896 The directory returned is expected to be writable by the current user,
897 but note that it isn't generally considered good practice to store
898 application-specific data here; use 'getAppUserDataDirectory'
901 On Unix, 'getUserDocumentsDirectory' returns the value of the @HOME@
902 environment variable. On Windows, the system is queried for a
903 suitable path; a typical path might be
904 @C:\/Documents and Settings\/user\/My Documents@.
906 The operation may fail with:
908 * 'UnsupportedOperation'
909 The operating system has no notion of document directory.
911 * 'isDoesNotExistError'
912 The document directory for the current user does not exist, or
915 getUserDocumentsDirectory :: IO FilePath
916 getUserDocumentsDirectory = do
917 #if __GLASGOW_HASKELL__ && defined(mingw32_HOST_OS)
918 allocaBytes long_path_size $ \pPath -> do
919 r <- c_SHGetFolderPath nullPtr csidl_PERSONAL nullPtr 0 pPath
925 {- | Returns the current directory for temporary files.
927 On Unix, 'getTemporaryDirectory' returns the value of the @TMPDIR@
928 environment variable or \"\/tmp\" if the variable isn\'t defined.
929 On Windows, the function checks for the existence of environment variables in
930 the following order and uses the first path found:
933 TMP environment variable.
936 TEMP environment variable.
939 USERPROFILE environment variable.
942 The Windows directory
944 The operation may fail with:
946 * 'UnsupportedOperation'
947 The operating system has no notion of temporary directory.
949 The function doesn\'t verify whether the path exists.
951 getTemporaryDirectory :: IO FilePath
952 getTemporaryDirectory = do
953 #if __GLASGOW_HASKELL__ && defined(mingw32_HOST_OS)
954 allocaBytes long_path_size $ \pPath -> do
955 r <- c_GetTempPath (fromIntegral long_path_size) pPath
958 catch (getEnv "TMPDIR") (\ex -> return "/tmp")
961 #if __GLASGOW_HASKELL__ && defined(mingw32_HOST_OS)
962 foreign import stdcall unsafe "SHGetFolderPath"
963 c_SHGetFolderPath :: Ptr ()
969 foreign import ccall unsafe "__hscore_CSIDL_PROFILE" csidl_PROFILE :: CInt
970 foreign import ccall unsafe "__hscore_CSIDL_APPDATA" csidl_APPDATA :: CInt
971 foreign import ccall unsafe "__hscore_CSIDL_WINDOWS" csidl_WINDOWS :: CInt
972 foreign import ccall unsafe "__hscore_CSIDL_PERSONAL" csidl_PERSONAL :: CInt
974 foreign import stdcall unsafe "GetTempPath" c_GetTempPath :: CInt -> CString -> IO CInt