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 , removeDirectory -- :: FilePath -> IO ()
22 , renameDirectory -- :: FilePath -> FilePath -> IO ()
24 , getDirectoryContents -- :: FilePath -> IO [FilePath]
25 , getCurrentDirectory -- :: IO FilePath
26 , setCurrentDirectory -- :: FilePath -> IO ()
28 -- * Pre-defined directories
30 , getAppUserDataDirectory
31 , getUserDocumentsDirectory
32 , getTemporaryDirectory
35 , removeFile -- :: FilePath -> IO ()
36 , renameFile -- :: FilePath -> FilePath -> IO ()
37 , copyFile -- :: FilePath -> FilePath -> IO ()
43 , doesFileExist -- :: FilePath -> IO Bool
44 , doesDirectoryExist -- :: FilePath -> IO Bool
52 readable, -- :: Permissions -> Bool
53 writable, -- :: Permissions -> Bool
54 executable, -- :: Permissions -> Bool
55 searchable -- :: Permissions -> Bool
58 , getPermissions -- :: FilePath -> IO Permissions
59 , setPermissions -- :: FilePath -> Permissions -> IO ()
63 , getModificationTime -- :: FilePath -> IO ClockTime
66 import System.Environment ( getEnv )
67 import System.FilePath
68 import System.IO.Error
79 #ifdef __GLASGOW_HASKELL__
82 import Control.Exception ( bracket )
83 import Control.Monad ( when )
84 import System.Posix.Types
85 import System.Posix.Internals
86 import System.Time ( ClockTime(..) )
91 import GHC.IOBase ( IOException(..), IOErrorType(..), ioException )
94 A directory contains a series of entries, each of which is a named
95 reference to a file system object (file, directory etc.). Some
96 entries may be hidden, inaccessible, or have some administrative
97 function (e.g. `.' or `..' under POSIX
98 <http://www.opengroup.org/onlinepubs/007904975/toc.htm>), but in
99 this standard all such entries are considered to form part of the
100 directory contents. Entries in sub-directories are not, however,
101 considered to form part of the directory contents.
103 Each file system object is referenced by a /path/. There is
104 normally at least one absolute path to each file system object. In
105 some operating systems, it may also be possible to have paths which
106 are relative to the current directory.
109 -----------------------------------------------------------------------------
114 The 'Permissions' type is used to record whether certain operations are
115 permissible on a file\/directory. 'getPermissions' and 'setPermissions'
116 get and set these permissions, respectively. Permissions apply both to
117 files and directories. For directories, the executable field will be
118 'False', and for files the searchable field will be 'False'. Note that
119 directories may be searchable without being readable, if permission has
120 been given to use them as part of a path, but not to examine the
123 Note that to change some, but not all permissions, a construct on the following lines must be used.
125 > makeReadable f = do
126 > p <- getPermissions f
127 > setPermissions f (p {readable = True})
134 executable, searchable :: Bool
135 } deriving (Eq, Ord, Read, Show)
137 {- |The 'getPermissions' operation returns the
138 permissions for the file or directory.
140 The operation may fail with:
142 * 'isPermissionError' if the user is not permitted to access
145 * 'isDoesNotExistError' if the file or directory does not exist.
149 getPermissions :: FilePath -> IO Permissions
150 getPermissions name = do
151 withCString name $ \s -> do
152 read <- c_access s r_OK
153 write <- c_access s w_OK
154 exec <- c_access s x_OK
155 withFileStatus "getPermissions" name $ \st -> do
156 is_dir <- isDirectory st
159 readable = read == 0,
160 writable = write == 0,
161 executable = not is_dir && exec == 0,
162 searchable = is_dir && exec == 0
166 {- |The 'setPermissions' operation sets the
167 permissions for the file or directory.
169 The operation may fail with:
171 * 'isPermissionError' if the user is not permitted to set
174 * 'isDoesNotExistError' if the file or directory does not exist.
178 setPermissions :: FilePath -> Permissions -> IO ()
179 setPermissions name (Permissions r w e s) = do
180 allocaBytes sizeof_stat $ \ p_stat -> do
181 withCString name $ \p_name -> do
182 throwErrnoIfMinus1_ "setPermissions" $ do
184 mode <- st_mode p_stat
185 let mode1 = modifyBit r mode s_IRUSR
186 let mode2 = modifyBit w mode1 s_IWUSR
187 let mode3 = modifyBit (e || s) mode2 s_IXUSR
191 modifyBit :: Bool -> CMode -> CMode -> CMode
192 modifyBit False m b = m .&. (complement b)
193 modifyBit True m b = m .|. b
195 -----------------------------------------------------------------------------
198 {- |@'createDirectory' dir@ creates a new directory @dir@ which is
199 initially empty, or as near to empty as the operating system
202 The operation may fail with:
204 * 'isPermissionError' \/ 'PermissionDenied'
205 The process has insufficient privileges to perform the operation.
208 * 'isAlreadyExistsError' \/ 'AlreadyExists'
209 The operand refers to a directory that already exists.
213 A physical I\/O error has occurred.
217 The operand is not a valid directory name.
218 @[ENAMETOOLONG, ELOOP]@
221 There is no path to the directory.
224 * 'ResourceExhausted'
225 Insufficient resources (virtual memory, process file descriptors,
226 physical disk space, etc.) are available to perform the operation.
227 @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
229 * 'InappropriateType'
230 The path refers to an existing non-directory object.
235 createDirectory :: FilePath -> IO ()
236 createDirectory path = do
237 withCString path $ \s -> do
238 throwErrnoIfMinus1Retry_ "createDirectory" $
241 {- | @'removeDirectory' dir@ removes an existing directory /dir/. The
242 implementation may specify additional constraints which must be
243 satisfied before a directory can be removed (e.g. the directory has to
244 be empty, or may not be in use by other processes). It is not legal
245 for an implementation to partially remove a directory unless the
246 entire directory is removed. A conformant implementation need not
247 support directory removal in all situations (e.g. removal of the root
250 The operation may fail with:
253 A physical I\/O error has occurred.
257 The operand is not a valid directory name.
258 [ENAMETOOLONG, ELOOP]
260 * 'isDoesNotExistError' \/ 'NoSuchThing'
261 The directory does not exist.
264 * 'isPermissionError' \/ 'PermissionDenied'
265 The process has insufficient privileges to perform the operation.
266 @[EROFS, EACCES, EPERM]@
268 * 'UnsatisfiedConstraints'
269 Implementation-dependent constraints are not satisfied.
270 @[EBUSY, ENOTEMPTY, EEXIST]@
272 * 'UnsupportedOperation'
273 The implementation does not support removal in this situation.
276 * 'InappropriateType'
277 The operand refers to an existing non-directory object.
282 removeDirectory :: FilePath -> IO ()
283 removeDirectory path = do
284 modifyIOError (`ioeSetFileName` path) $
285 withCString path $ \s ->
286 throwErrnoIfMinus1Retry_ "removeDirectory" (c_rmdir s)
288 {- |'removeFile' /file/ removes the directory entry for an existing file
289 /file/, where /file/ is not itself a directory. The
290 implementation may specify additional constraints which must be
291 satisfied before a file can be removed (e.g. the file may not be in
292 use by other processes).
294 The operation may fail with:
297 A physical I\/O error has occurred.
301 The operand is not a valid file name.
302 @[ENAMETOOLONG, ELOOP]@
304 * 'isDoesNotExistError' \/ 'NoSuchThing'
305 The file does not exist.
308 * 'isPermissionError' \/ 'PermissionDenied'
309 The process has insufficient privileges to perform the operation.
310 @[EROFS, EACCES, EPERM]@
312 * 'UnsatisfiedConstraints'
313 Implementation-dependent constraints are not satisfied.
316 * 'InappropriateType'
317 The operand refers to an existing directory.
322 removeFile :: FilePath -> IO ()
324 modifyIOError (`ioeSetFileName` path) $
325 withCString path $ \s ->
326 throwErrnoIfMinus1Retry_ "removeFile" (c_unlink s)
328 {- |@'renameDirectory' old new@ changes the name of an existing
329 directory from /old/ to /new/. If the /new/ directory
330 already exists, it is atomically replaced by the /old/ directory.
331 If the /new/ directory is neither the /old/ directory nor an
332 alias of the /old/ directory, it is removed as if by
333 'removeDirectory'. A conformant implementation need not support
334 renaming directories in all situations (e.g. renaming to an existing
335 directory, or across different physical devices), but the constraints
338 On Win32 platforms, @renameDirectory@ fails if the /new/ directory already
341 The operation may fail with:
344 A physical I\/O error has occurred.
348 Either operand is not a valid directory name.
349 @[ENAMETOOLONG, ELOOP]@
351 * 'isDoesNotExistError' \/ 'NoSuchThing'
352 The original directory does not exist, or there is no path to the target.
355 * 'isPermissionError' \/ 'PermissionDenied'
356 The process has insufficient privileges to perform the operation.
357 @[EROFS, EACCES, EPERM]@
359 * 'ResourceExhausted'
360 Insufficient resources are available to perform the operation.
361 @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
363 * 'UnsatisfiedConstraints'
364 Implementation-dependent constraints are not satisfied.
365 @[EBUSY, ENOTEMPTY, EEXIST]@
367 * 'UnsupportedOperation'
368 The implementation does not support renaming in this situation.
371 * 'InappropriateType'
372 Either path refers to an existing non-directory object.
377 renameDirectory :: FilePath -> FilePath -> IO ()
378 renameDirectory opath npath =
379 withFileStatus "renameDirectory" opath $ \st -> do
380 is_dir <- isDirectory st
382 then ioException (IOError Nothing InappropriateType "renameDirectory"
383 ("not a directory") (Just opath))
386 withCString opath $ \s1 ->
387 withCString npath $ \s2 ->
388 throwErrnoIfMinus1Retry_ "renameDirectory" (c_rename s1 s2)
390 {- |@'renameFile' old new@ changes the name of an existing file system
391 object from /old/ to /new/. If the /new/ object already
392 exists, it is atomically replaced by the /old/ object. Neither
393 path may refer to an existing directory. A conformant implementation
394 need not support renaming files in all situations (e.g. renaming
395 across different physical devices), but the constraints must be
398 The operation may fail with:
401 A physical I\/O error has occurred.
405 Either operand is not a valid file name.
406 @[ENAMETOOLONG, ELOOP]@
408 * 'isDoesNotExistError' \/ 'NoSuchThing'
409 The original file does not exist, or there is no path to the target.
412 * 'isPermissionError' \/ 'PermissionDenied'
413 The process has insufficient privileges to perform the operation.
414 @[EROFS, EACCES, EPERM]@
416 * 'ResourceExhausted'
417 Insufficient resources are available to perform the operation.
418 @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@
420 * 'UnsatisfiedConstraints'
421 Implementation-dependent constraints are not satisfied.
424 * 'UnsupportedOperation'
425 The implementation does not support renaming in this situation.
428 * 'InappropriateType'
429 Either path refers to an existing directory.
430 @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@
434 renameFile :: FilePath -> FilePath -> IO ()
435 renameFile opath npath =
436 withFileOrSymlinkStatus "renameFile" opath $ \st -> do
437 is_dir <- isDirectory st
439 then ioException (IOError Nothing InappropriateType "renameFile"
440 "is a directory" (Just opath))
443 withCString opath $ \s1 ->
444 withCString npath $ \s2 ->
445 throwErrnoIfMinus1Retry_ "renameFile" (c_rename s1 s2)
447 #endif /* __GLASGOW_HASKELL__ */
449 {- |@'copyFile' old new@ copies the existing file from /old/ to /new/.
450 If the /new/ file already exists, it is atomically replaced by the /old/ file.
451 Neither path may refer to an existing directory.
453 copyFile :: FilePath -> FilePath -> IO ()
454 copyFile fromFPath toFPath =
455 #if (!(defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ > 600))
456 do readFile fromFPath >>= writeFile toFPath
457 try (getPermissions fromFPath >>= setPermissions toFPath)
460 (bracket (openBinaryFile fromFPath ReadMode) hClose $ \hFrom ->
461 bracket (openBinaryFile toFPath WriteMode) hClose $ \hTo ->
462 allocaBytes bufferSize $ \buffer -> do
463 copyContents hFrom hTo buffer
464 try (getPermissions fromFPath >>= setPermissions toFPath)
465 return ()) `catch` (ioError . changeFunName)
469 changeFunName (IOError h iot fun str mb_fp) = IOError h iot "copyFile" str mb_fp
471 copyContents hFrom hTo buffer = do
472 count <- hGetBuf hFrom buffer bufferSize
473 when (count > 0) $ do
474 hPutBuf hTo buffer count
475 copyContents hFrom hTo buffer
478 #ifdef __GLASGOW_HASKELL__
479 -- | Given path referring to a file or directory, returns a
480 -- canonicalized path, with the intent that two paths referring
481 -- to the same file\/directory will map to the same canonicalized
482 -- path. Note that it is impossible to guarantee that the
483 -- implication (same file\/dir <=> same canonicalizedPath) holds
484 -- in either direction: this function can make only a best-effort
486 canonicalizePath :: FilePath -> IO FilePath
487 canonicalizePath fpath =
488 withCString fpath $ \pInPath ->
489 allocaBytes long_path_size $ \pOutPath ->
490 #if defined(mingw32_TARGET_OS)
491 alloca $ \ppFilePart ->
492 do c_GetFullPathName pInPath (fromIntegral long_path_size) pOutPath ppFilePart
494 do c_realpath pInPath pOutPath
498 #if defined(mingw32_TARGET_OS)
499 foreign import stdcall unsafe "GetFullPathName"
500 c_GetFullPathName :: CString
506 foreign import ccall unsafe "realpath"
507 c_realpath :: CString
511 #else /* !__GLASGOW_HASKELL__ */
512 -- dummy implementation
513 canonicalizePath :: FilePath -> IO FilePath
514 canonicalizePath fpath = return fpath
515 #endif /* !__GLASGOW_HASKELL__ */
517 -- | Given an executable file name, searches for such file
518 -- in the directories listed in system PATH. The returned value
519 -- is the path to the found executable or Nothing if there isn't
520 -- such executable. For example (findExecutable \"ghc\")
521 -- gives you the path to GHC.
522 findExecutable :: String -> IO (Maybe FilePath)
523 findExecutable binary = do
524 path <- getEnv "PATH"
525 search (parseSearchPath path)
527 fileName = binary `joinFileExt` exeExtension
529 search :: [FilePath] -> IO (Maybe FilePath)
530 search [] = return Nothing
532 let path = d `joinFileName` fileName
533 b <- doesFileExist path
534 if b then return (Just path)
537 #ifdef __GLASGOW_HASKELL__
538 {- |@'getDirectoryContents' dir@ returns a list of /all/ entries
541 The operation may fail with:
544 A physical I\/O error has occurred.
548 The operand is not a valid directory name.
549 @[ENAMETOOLONG, ELOOP]@
551 * 'isDoesNotExistError' \/ 'NoSuchThing'
552 The directory does not exist.
555 * 'isPermissionError' \/ 'PermissionDenied'
556 The process has insufficient privileges to perform the operation.
559 * 'ResourceExhausted'
560 Insufficient resources are available to perform the operation.
563 * 'InappropriateType'
564 The path refers to an existing non-directory object.
569 getDirectoryContents :: FilePath -> IO [FilePath]
570 getDirectoryContents path = do
571 modifyIOError (`ioeSetFileName` path) $
572 alloca $ \ ptr_dEnt ->
574 (withCString path $ \s ->
575 throwErrnoIfNullRetry desc (c_opendir s))
576 (\p -> throwErrnoIfMinus1_ desc (c_closedir p))
577 (\p -> loop ptr_dEnt p)
579 desc = "getDirectoryContents"
581 loop :: Ptr (Ptr CDirent) -> Ptr CDir -> IO [String]
582 loop ptr_dEnt dir = do
584 r <- readdir dir ptr_dEnt
587 dEnt <- peek ptr_dEnt
591 entry <- (d_name dEnt >>= peekCString)
593 entries <- loop ptr_dEnt dir
594 return (entry:entries)
595 else do errno <- getErrno
596 if (errno == eINTR) then loop ptr_dEnt dir else do
597 let (Errno eo) = errno
598 if (eo == end_of_dir)
604 {- |If the operating system has a notion of current directories,
605 'getCurrentDirectory' returns an absolute path to the
606 current directory of the calling process.
608 The operation may fail with:
611 A physical I\/O error has occurred.
614 * 'isDoesNotExistError' \/ 'NoSuchThing'
615 There is no path referring to the current directory.
616 @[EPERM, ENOENT, ESTALE...]@
618 * 'isPermissionError' \/ 'PermissionDenied'
619 The process has insufficient privileges to perform the operation.
622 * 'ResourceExhausted'
623 Insufficient resources are available to perform the operation.
625 * 'UnsupportedOperation'
626 The operating system has no notion of current directory.
630 getCurrentDirectory :: IO FilePath
631 getCurrentDirectory = do
632 p <- mallocBytes long_path_size
634 where go p bytes = do
635 p' <- c_getcwd p (fromIntegral bytes)
637 then do s <- peekCString p'
640 else do errno <- getErrno
642 then do let bytes' = bytes * 2
643 p' <- reallocBytes p bytes'
645 else throwErrno "getCurrentDirectory"
647 {- |If the operating system has a notion of current directories,
648 @'setCurrentDirectory' dir@ changes the current
649 directory of the calling process to /dir/.
651 The operation may fail with:
654 A physical I\/O error has occurred.
658 The operand is not a valid directory name.
659 @[ENAMETOOLONG, ELOOP]@
661 * 'isDoesNotExistError' \/ 'NoSuchThing'
662 The directory does not exist.
665 * 'isPermissionError' \/ 'PermissionDenied'
666 The process has insufficient privileges to perform the operation.
669 * 'UnsupportedOperation'
670 The operating system has no notion of current directory, or the
671 current directory cannot be dynamically changed.
673 * 'InappropriateType'
674 The path refers to an existing non-directory object.
679 setCurrentDirectory :: FilePath -> IO ()
680 setCurrentDirectory path = do
681 modifyIOError (`ioeSetFileName` path) $
682 withCString path $ \s ->
683 throwErrnoIfMinus1Retry_ "setCurrentDirectory" (c_chdir s)
684 -- ToDo: add path to error
686 {- |The operation 'doesDirectoryExist' returns 'True' if the argument file
687 exists and is a directory, and 'False' otherwise.
690 doesDirectoryExist :: FilePath -> IO Bool
691 doesDirectoryExist name =
693 (withFileStatus "doesDirectoryExist" name $ \st -> isDirectory st)
694 (\ _ -> return False)
696 {- |The operation 'doesFileExist' returns 'True'
697 if the argument file exists and is not a directory, and 'False' otherwise.
700 doesFileExist :: FilePath -> IO Bool
701 doesFileExist name = do
703 (withFileStatus "doesFileExist" name $ \st -> do b <- isDirectory st; return (not b))
704 (\ _ -> return False)
706 {- |The 'getModificationTime' operation returns the
707 clock time at which the file or directory was last modified.
709 The operation may fail with:
711 * 'isPermissionError' if the user is not permitted to access
712 the modification time; or
714 * 'isDoesNotExistError' if the file or directory does not exist.
718 getModificationTime :: FilePath -> IO ClockTime
719 getModificationTime name =
720 withFileStatus "getModificationTime" name $ \ st ->
723 withFileStatus :: String -> FilePath -> (Ptr CStat -> IO a) -> IO a
724 withFileStatus loc name f = do
725 modifyIOError (`ioeSetFileName` name) $
726 allocaBytes sizeof_stat $ \p ->
727 withCString (fileNameEndClean name) $ \s -> do
728 throwErrnoIfMinus1Retry_ loc (c_stat s p)
731 withFileOrSymlinkStatus :: String -> FilePath -> (Ptr CStat -> IO a) -> IO a
732 withFileOrSymlinkStatus loc name f = do
733 modifyIOError (`ioeSetFileName` name) $
734 allocaBytes sizeof_stat $ \p ->
735 withCString name $ \s -> do
736 throwErrnoIfMinus1Retry_ loc (lstat s p)
739 modificationTime :: Ptr CStat -> IO ClockTime
740 modificationTime stat = do
741 mtime <- st_mtime stat
742 let realToInteger = round . realToFrac :: Real a => a -> Integer
743 return (TOD (realToInteger (mtime :: CTime)) 0)
745 isDirectory :: Ptr CStat -> IO Bool
746 isDirectory stat = do
748 return (s_isdir mode)
750 fileNameEndClean :: String -> String
751 fileNameEndClean name =
752 if i > 0 && (ec == '\\' || ec == '/') then
753 fileNameEndClean (take i name)
757 i = (length name) - 1
760 foreign import ccall unsafe "__hscore_long_path_size"
761 long_path_size :: Int
763 foreign import ccall unsafe "__hscore_R_OK" r_OK :: CMode
764 foreign import ccall unsafe "__hscore_W_OK" w_OK :: CMode
765 foreign import ccall unsafe "__hscore_X_OK" x_OK :: CMode
767 foreign import ccall unsafe "__hscore_S_IRUSR" s_IRUSR :: CMode
768 foreign import ccall unsafe "__hscore_S_IWUSR" s_IWUSR :: CMode
769 foreign import ccall unsafe "__hscore_S_IXUSR" s_IXUSR :: CMode
771 #endif /* __GLASGOW_HASKELL__ */
773 {- | Returns the current user's home directory.
775 The directory returned is expected to be writable by the current user,
776 but note that it isn't generally considered good practice to store
777 application-specific data here; use 'getAppUserDataDirectory'
780 On Unix, 'getHomeDirectory' returns the value of the @HOME@
781 environment variable. On Windows, the system is queried for a
782 suitable path; a typical path might be
783 @C:/Documents And Settings/user@.
785 The operation may fail with:
787 * 'UnsupportedOperation'
788 The operating system has no notion of home directory.
790 * 'isDoesNotExistError'
791 The home directory for the current user does not exist, or
794 getHomeDirectory :: IO FilePath
796 #if __GLASGOW_HASKELL__ && defined(mingw32_TARGET_OS)
797 allocaBytes long_path_size $ \pPath -> do
798 r <- c_SHGetFolderPath nullPtr csidl_PROFILE nullPtr 0 pPath
800 then c_SHGetFolderPath nullPtr csidl_WINDOWS nullPtr 0 pPath
807 {- | Returns the pathname of a directory in which application-specific
808 data for the current user can be stored. The result of
809 'getAppUserDataDirectory' for a given application is specific to
812 The argument should be the name of the application, which will be used
813 to construct the pathname (so avoid using unusual characters that
814 might result in an invalid pathname).
816 Note: the directory may not actually exist, and may need to be created
817 first. It is expected that the parent directory exists and is
820 On Unix, this function returns @$HOME\/.appName@. On Windows, a
821 typical path might be
823 > C:/Documents And Settings/user/Application Data/appName
825 The operation may fail with:
827 * 'UnsupportedOperation'
828 The operating system has no notion of application-specific data directory.
830 * 'isDoesNotExistError'
831 The home directory for the current user does not exist, or
834 getAppUserDataDirectory :: String -> IO FilePath
835 getAppUserDataDirectory appName = do
836 #if __GLASGOW_HASKELL__ && defined(mingw32_TARGET_OS)
837 allocaBytes long_path_size $ \pPath -> do
838 r <- c_SHGetFolderPath nullPtr csidl_APPDATA nullPtr 0 pPath
839 s <- peekCString pPath
840 return (s++'\\':appName)
842 path <- getEnv "HOME"
843 return (path++'/':'.':appName)
846 {- | Returns the current user's document directory.
848 The directory returned is expected to be writable by the current user,
849 but note that it isn't generally considered good practice to store
850 application-specific data here; use 'getAppUserDataDirectory'
853 On Unix, 'getUserDocumentsDirectory' returns the value of the @HOME@
854 environment variable. On Windows, the system is queried for a
855 suitable path; a typical path might be
856 @C:\/Documents and Settings\/user\/My Documents@.
858 The operation may fail with:
860 * 'UnsupportedOperation'
861 The operating system has no notion of document directory.
863 * 'isDoesNotExistError'
864 The document directory for the current user does not exist, or
867 getUserDocumentsDirectory :: IO FilePath
868 getUserDocumentsDirectory = do
869 #if __GLASGOW_HASKELL__ && defined(mingw32_TARGET_OS)
870 allocaBytes long_path_size $ \pPath -> do
871 r <- c_SHGetFolderPath nullPtr csidl_PERSONAL nullPtr 0 pPath
877 {- | Returns the current directory for temporary files.
879 On Unix, 'getTemporaryDirectory' returns the value of the @TMPDIR@
880 environment variable or \"\/tmp\" if the variable isn\'t defined.
881 On Windows, the function checks for the existence of environment variables in
882 the following order and uses the first path found:
885 TMP environment variable.
888 TEMP environment variable.
891 USERPROFILE environment variable.
894 The Windows directory
896 The operation may fail with:
898 * 'UnsupportedOperation'
899 The operating system has no notion of temporary directory.
901 The function doesn\'t verify whether the path exists.
903 getTemporaryDirectory :: IO FilePath
904 getTemporaryDirectory = do
905 #if __GLASGOW_HASKELL__ && defined(mingw32_TARGET_OS)
906 allocaBytes long_path_size $ \pPath -> do
907 r <- c_GetTempPath (fromIntegral long_path_size) pPath
910 catch (getEnv "TMPDIR") (\ex -> return "/tmp")
913 #if __GLASGOW_HASKELL__ && defined(mingw32_TARGET_OS)
914 foreign import stdcall unsafe "SHGetFolderPath"
915 c_SHGetFolderPath :: Ptr ()
921 foreign import ccall unsafe "__hscore_CSIDL_PROFILE" csidl_PROFILE :: CInt
922 foreign import ccall unsafe "__hscore_CSIDL_APPDATA" csidl_APPDATA :: CInt
923 foreign import ccall unsafe "__hscore_CSIDL_WINDOWS" csidl_WINDOWS :: CInt
924 foreign import ccall unsafe "__hscore_CSIDL_PERSONAL" csidl_PERSONAL :: CInt
926 foreign import stdcall unsafe "GetTempPath" c_GetTempPath :: CInt -> CString -> IO CInt