directory 1.3.0.0 → 1.3.11.0
raw patch · 55 files changed
Files
- HsDirectoryConfig.h.in +11/−3
- README.md +6/−5
- System/Directory.hs +1352/−1948
- System/Directory/Internal.hs +14/−12
- System/Directory/Internal/C_utimensat.hsc +6/−8
- System/Directory/Internal/Common.hs +353/−0
- System/Directory/Internal/Config.hs +4/−7
- System/Directory/Internal/Posix.hsc +404/−4
- System/Directory/Internal/Prelude.hs +21/−43
- System/Directory/Internal/Windows.hsc +670/−118
- System/Directory/Internal/utility.h +0/−6
- System/Directory/Internal/windows_ext.h +33/−0
- System/Directory/OsPath.hs +1669/−0
- changelog.md +249/−3
- configure +4423/−4375
- configure.ac +2/−0
- directory.buildinfo +0/−1
- directory.cabal +30/−19
- tests/CanonicalizePath.hs +102/−88
- tests/CopyFile001.hs +19/−7
- tests/CopyFile002.hs +11/−6
- tests/CopyFileWithMetadata.hs +16/−11
- tests/CreateDirectory001.hs +7/−3
- tests/CreateDirectoryIfMissing001.hs +36/−25
- tests/CurrentDirectory001.hs +7/−3
- tests/Directory001.hs +7/−3
- tests/DoesDirectoryExist001.hs +14/−7
- tests/DoesPathExist.hs +32/−11
- tests/FileTime.hs +22/−11
- tests/FindExecutable.hs +27/−0
- tests/FindFile001.hs +53/−5
- tests/GetDirContents001.hs +15/−10
- tests/GetDirContents002.hs +7/−3
- tests/GetFileSize.hs +10/−8
- tests/GetHomeDirectory001.hs +9/−4
- tests/GetHomeDirectory002.hs +22/−0
- tests/GetPermissions001.hs +35/−14
- tests/LongPaths.hs +65/−0
- tests/Main.hs +12/−2
- tests/MakeAbsolute.hs +34/−14
- tests/MinimizeNameConflicts.hs +39/−0
- tests/PathIsSymbolicLink.hs +31/−13
- tests/RemoveDirectoryRecursive001.hs +32/−27
- tests/RemovePathForcibly.hs +42/−28
- tests/RenameDirectory.hs +8/−4
- tests/RenameFile001.hs +11/−6
- tests/RenamePath.hs +13/−8
- tests/Safe.hs +0/−7
- tests/Simplify.hs +44/−0
- tests/T8482.hs +13/−8
- tests/TestUtils.hs +78/−53
- tests/Util.hs +107/−47
- tests/WithCurrentDirectory.hs +13/−8
- tests/Xdg.hs +65/−0
- tests/util.inl +0/−7
HsDirectoryConfig.h.in view
@@ -3,6 +3,9 @@ /* Filename extension of executable files */ #undef EXE_EXTENSION +/* Define to 1 if you have the `CreateSymbolicLinkW' function. */+#undef HAVE_CREATESYMBOLICLINKW+ /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H @@ -15,12 +18,15 @@ /* Define to 1 if you have the <limits.h> header file. */ #undef HAVE_LIMITS_H -/* Define to 1 if you have the <memory.h> header file. */-#undef HAVE_MEMORY_H+/* Define to 1 if you have the `realpath' function. */+#undef HAVE_REALPATH /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the <stdio.h> header file. */+#undef HAVE_STDIO_H+ /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -63,5 +69,7 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* Define to 1 if you have the ANSI C header files. */+/* Define to 1 if all of the C90 standard headers exist (not just the ones+ required in a freestanding environment). This macro is provided for+ backward compatibility; new code need not use it. */ #undef STDC_HEADERS
README.md view
@@ -3,9 +3,10 @@ [![Hackage][hi]][hl] [![Build status][bi]][bl]-[![Windows build status][wi]][wl]+[![Dependencies status][di]][dl] Documentation can be found on [Hackage][hl].+Changes between versions are recorded in the [change log](changelog.md). Building from Git repository ----------------------------@@ -22,8 +23,8 @@ [hi]: https://img.shields.io/hackage/v/directory.svg [hl]: https://hackage.haskell.org/package/directory-[bi]: https://travis-ci.org/haskell/directory.svg?branch=master-[bl]: https://travis-ci.org/haskell/directory-[wi]: https://ci.appveyor.com/api/projects/status/github/haskell/directory?branch=master&svg=true-[wl]: https://ci.appveyor.com/project/hvr/directory+[bi]: https://github.com/haskell/directory/actions/workflows/build.yml/badge.svg+[bl]: https://github.com/haskell/directory/actions+[di]: https://img.shields.io/hackage-deps/v/directory.svg+[dl]: http://packdeps.haskellers.com/feed?needle=exact:directory [ac]: https://gnu.org/software/autoconf
System/Directory.hs view
@@ -1,1948 +1,1352 @@-{-# LANGUAGE CPP #-}--#if !(MIN_VERSION_base(4,8,0))--- In base-4.8.0 the Foreign module became Safe-{-# LANGUAGE Trustworthy #-}-#endif---------------------------------------------------------------------------------- |--- Module : System.Directory--- Copyright : (c) The University of Glasgow 2001--- License : BSD-style (see the file libraries/base/LICENSE)------ Maintainer : libraries@haskell.org--- Stability : stable--- Portability : portable------ System-independent interface to directory manipulation.-----------------------------------------------------------------------------------#include <HsDirectoryConfig.h>-module System.Directory- (- -- $intro-- -- * Actions on directories- createDirectory- , createDirectoryIfMissing- , removeDirectory- , removeDirectoryRecursive- , removePathForcibly- , renameDirectory- , listDirectory- , getDirectoryContents- -- ** Current working directory- , getCurrentDirectory- , setCurrentDirectory- , withCurrentDirectory-- -- * Pre-defined directories- , getHomeDirectory- , XdgDirectory(..)- , getXdgDirectory- , getAppUserDataDirectory- , getUserDocumentsDirectory- , getTemporaryDirectory-- -- * Actions on files- , removeFile- , renameFile- , renamePath- , copyFile- , copyFileWithMetadata-- , canonicalizePath- , makeAbsolute- , makeRelativeToCurrentDirectory- , findExecutable- , findExecutables- , findExecutablesInDirectories- , findFile- , findFiles- , findFileWith- , findFilesWith- , exeExtension-- , getFileSize-- -- * Existence tests- , doesPathExist- , doesFileExist- , doesDirectoryExist-- -- * Symbolic links- , pathIsSymbolicLink-- -- * Permissions-- -- $permissions-- , Permissions- , emptyPermissions- , readable- , writable- , executable- , searchable- , setOwnerReadable- , setOwnerWritable- , setOwnerExecutable- , setOwnerSearchable-- , getPermissions- , setPermissions- , copyPermissions-- -- * Timestamps-- , getAccessTime- , getModificationTime- , setAccessTime- , setModificationTime-- -- * Deprecated- , isSymbolicLink-- ) where-import Prelude ()-import System.Directory.Internal-import System.Directory.Internal.Prelude-import System.FilePath-import Data.Time (UTCTime)-import Data.Time.Clock.POSIX- ( posixSecondsToUTCTime- , utcTimeToPOSIXSeconds- , POSIXTime- )-#ifdef mingw32_HOST_OS-import qualified System.Win32 as Win32-#else-import qualified GHC.Foreign as GHC-import qualified System.Posix as Posix-#endif--{- $intro-A directory contains a series of entries, each of which is a named-reference to a file system object (file, directory etc.). Some-entries may be hidden, inaccessible, or have some administrative-function (e.g. @.@ or @..@ under-<http://www.opengroup.org/onlinepubs/009695399 POSIX>), but in-this standard all such entries are considered to form part of the-directory contents. Entries in sub-directories are not, however,-considered to form part of the directory contents.--Each file system object is referenced by a /path/. There is-normally at least one absolute path to each file system object. In-some operating systems, it may also be possible to have paths which-are relative to the current directory.--}---------------------------------------------------------------------------------- Permissions--{- $permissions-- The 'Permissions' type is used to record whether certain operations are- permissible on a file\/directory. 'getPermissions' and 'setPermissions'- get and set these permissions, respectively. Permissions apply both to- files and directories. For directories, the executable field will be- 'False', and for files the searchable field will be 'False'. Note that- directories may be searchable without being readable, if permission has- been given to use them as part of a path, but not to examine the- directory contents.--Note that to change some, but not all permissions, a construct on the following lines must be used.--> makeReadable f = do-> p <- getPermissions f-> setPermissions f (p {readable = True})---}--data Permissions- = Permissions {- readable, writable,- executable, searchable :: Bool- } deriving (Eq, Ord, Read, Show)--emptyPermissions :: Permissions-emptyPermissions = Permissions {- readable = False,- writable = False,- executable = False,- searchable = False- }--setOwnerReadable :: Bool -> Permissions -> Permissions-setOwnerReadable b p = p { readable = b }--setOwnerWritable :: Bool -> Permissions -> Permissions-setOwnerWritable b p = p { writable = b }--setOwnerExecutable :: Bool -> Permissions -> Permissions-setOwnerExecutable b p = p { executable = b }--setOwnerSearchable :: Bool -> Permissions -> Permissions-setOwnerSearchable b p = p { searchable = b }--{- |The 'getPermissions' operation returns the-permissions for the file or directory.--The operation may fail with:--* 'isPermissionError' if the user is not permitted to access- the permissions; or--* 'isDoesNotExistError' if the file or directory does not exist.---}--getPermissions :: FilePath -> IO Permissions-getPermissions name =-#ifdef mingw32_HOST_OS- -- issue #9: Windows doesn't like trailing path separators- withFilePath (dropTrailingPathSeparator name) $ \s ->- -- stat() does a better job of guessing the permissions on Windows- -- than access() does. e.g. for execute permission, it looks at the- -- filename extension :-)- --- -- I tried for a while to do this properly, using the Windows security API,- -- and eventually gave up. getPermissions is a flawed API anyway. -- SimonM- allocaBytes sizeof_stat $ \ p_stat -> do- throwErrnoIfMinus1_ "getPermissions" $ c_stat s p_stat- mode <- st_mode p_stat- let usr_read = mode .&. s_IRUSR- let usr_write = mode .&. s_IWUSR- let usr_exec = mode .&. s_IXUSR- let is_dir = mode .&. s_IFDIR- return (- Permissions {- readable = usr_read /= 0,- writable = usr_write /= 0,- executable = is_dir == 0 && usr_exec /= 0,- searchable = is_dir /= 0 && usr_exec /= 0- }- )-#else- do- read_ok <- Posix.fileAccess name True False False- write_ok <- Posix.fileAccess name False True False- exec_ok <- Posix.fileAccess name False False True- stat <- Posix.getFileStatus name- let is_dir = Posix.isDirectory stat- return (- Permissions {- readable = read_ok,- writable = write_ok,- executable = not is_dir && exec_ok,- searchable = is_dir && exec_ok- }- )-#endif--{- |The 'setPermissions' operation sets the-permissions for the file or directory.--The operation may fail with:--* 'isPermissionError' if the user is not permitted to set- the permissions; or--* 'isDoesNotExistError' if the file or directory does not exist.---}--setPermissions :: FilePath -> Permissions -> IO ()-setPermissions name (Permissions r w e s) =-#ifdef mingw32_HOST_OS- allocaBytes sizeof_stat $ \ p_stat ->- withFilePath name $ \p_name -> do- throwErrnoIfMinus1_ "setPermissions" $- c_stat p_name p_stat-- throwErrnoIfMinus1_ "setPermissions" $ do- mode <- st_mode p_stat- let mode1 = modifyBit r mode s_IRUSR- let mode2 = modifyBit w mode1 s_IWUSR- let mode3 = modifyBit (e || s) mode2 s_IXUSR- c_wchmod p_name mode3- where- modifyBit :: Bool -> CMode -> CMode -> CMode- modifyBit False m b = m .&. (complement b)- modifyBit True m b = m .|. b-#else- do- stat <- Posix.getFileStatus name- let mode = Posix.fileMode stat- let mode1 = modifyBit r mode Posix.ownerReadMode- let mode2 = modifyBit w mode1 Posix.ownerWriteMode- let mode3 = modifyBit (e || s) mode2 Posix.ownerExecuteMode- Posix.setFileMode name mode3- where- modifyBit :: Bool -> FileMode -> FileMode -> FileMode- modifyBit False m b = m .&. (complement b)- modifyBit True m b = m .|. b-#endif--copyPermissions :: FilePath -> FilePath -> IO ()-copyPermissions source dest =-#ifdef mingw32_HOST_OS- allocaBytes sizeof_stat $ \ p_stat ->- withFilePath source $ \p_source ->- withFilePath dest $ \p_dest -> do- throwErrnoIfMinus1_ "copyPermissions" $ c_stat p_source p_stat- mode <- st_mode p_stat- throwErrnoIfMinus1_ "copyPermissions" $ c_wchmod p_dest mode-#else- do- stat <- Posix.getFileStatus source- copyPermissionsFromStatus stat dest-#endif--#ifndef mingw32_HOST_OS-copyPermissionsFromStatus :: Posix.FileStatus -> FilePath -> IO ()-copyPermissionsFromStatus st dst = do- Posix.setFileMode dst (Posix.fileMode st)-#endif---------------------------------------------------------------------------------- Implementation--{- |@'createDirectory' dir@ creates a new directory @dir@ which is-initially empty, or as near to empty as the operating system-allows.--The operation may fail with:--* 'isPermissionError' \/ 'PermissionDenied'-The process has insufficient privileges to perform the operation.-@[EROFS, EACCES]@--* 'isAlreadyExistsError' \/ 'AlreadyExists'-The operand refers to a directory that already exists.-@ [EEXIST]@--* 'HardwareFault'-A physical I\/O error has occurred.-@[EIO]@--* 'InvalidArgument'-The operand is not a valid directory name.-@[ENAMETOOLONG, ELOOP]@--* 'NoSuchThing'-There is no path to the directory.-@[ENOENT, ENOTDIR]@--* 'ResourceExhausted'-Insufficient resources (virtual memory, process file descriptors,-physical disk space, etc.) are available to perform the operation.-@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@--* 'InappropriateType'-The path refers to an existing non-directory object.-@[EEXIST]@---}--createDirectory :: FilePath -> IO ()-createDirectory path = do-#ifdef mingw32_HOST_OS- Win32.createDirectory path Nothing-#else- Posix.createDirectory path 0o777-#endif---- | @'createDirectoryIfMissing' parents dir@ creates a new directory--- @dir@ if it doesn\'t exist. If the first argument is 'True'--- the function will also create all parent directories if they are missing.-createDirectoryIfMissing :: Bool -- ^ Create its parents too?- -> FilePath -- ^ The path to the directory you want to make- -> IO ()-createDirectoryIfMissing create_parents path0- | create_parents = createDirs (parents path0)- | otherwise = createDirs (take 1 (parents path0))- where- parents = reverse . scanl1 (</>) . splitDirectories . normalise-- createDirs [] = return ()- createDirs (dir:[]) = createDir dir ioError- createDirs (dir:dirs) =- createDir dir $ \_ -> do- createDirs dirs- createDir dir ioError-- createDir dir notExistHandler = do- r <- tryIOError (createDirectory dir)- case r of- Right () -> return ()- Left e- | isDoesNotExistError e -> notExistHandler e- -- createDirectory (and indeed POSIX mkdir) does not distinguish- -- between a dir already existing and a file already existing. So we- -- check for it here. Unfortunately there is a slight race condition- -- here, but we think it is benign. It could report an exeption in- -- the case that the dir did exist but another process deletes the- -- directory and creates a file in its place before we can check- -- that the directory did indeed exist.- -- We also follow this path when we get a permissions error, as- -- trying to create "." when in the root directory on Windows- -- fails with- -- CreateDirectory ".": permission denied (Access is denied.)- -- This caused GHCi to crash when loading a module in the root- -- directory.- | isAlreadyExistsError e- || isPermissionError e -> do- canIgnore <- isDir `catchIOError` \ _ ->- return (isAlreadyExistsError e)- unless canIgnore (ioError e)- | otherwise -> ioError e- where-#ifdef mingw32_HOST_OS- isDir = withFileStatus "createDirectoryIfMissing" dir isDirectory-#else- isDir = (Posix.isDirectory <$> Posix.getFileStatus dir)-#endif---- | * @'NotDirectory'@: not a directory.--- * @'Directory'@: a true directory (not a symbolic link).--- * @'DirectoryLink'@: a directory symbolic link (only exists on Windows).-data DirectoryType = NotDirectory- | Directory- | DirectoryLink- deriving (Enum, Eq, Ord, Read, Show)---- | Obtain the type of a directory.-getDirectoryType :: FilePath -> IO DirectoryType-getDirectoryType path =- (`ioeAddLocation` "getDirectoryType") `modifyIOError` do-#ifdef mingw32_HOST_OS- isDir <- withFileStatus "getDirectoryType" path isDirectory- if isDir- then do- isLink <- pathIsSymbolicLink path- if isLink- then return DirectoryLink- else return Directory- else do- return NotDirectory-#else- stat <- Posix.getSymbolicLinkStatus path- return $ if Posix.isDirectory stat- then Directory- else NotDirectory-#endif--{- | @'removeDirectory' dir@ removes an existing directory /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-for an implementation to partially remove a directory unless the-entire directory is removed. A conformant implementation need not-support directory removal in all situations (e.g. removal of the root-directory).--The operation may fail with:--* 'HardwareFault'-A physical I\/O error has occurred.-@[EIO]@--* 'InvalidArgument'-The operand is not a valid directory name.-@[ENAMETOOLONG, ELOOP]@--* 'isDoesNotExistError' \/ 'NoSuchThing'-The directory does not exist.-@[ENOENT, ENOTDIR]@--* 'isPermissionError' \/ 'PermissionDenied'-The process has insufficient privileges to perform the operation.-@[EROFS, EACCES, EPERM]@--* 'UnsatisfiedConstraints'-Implementation-dependent constraints are not satisfied.-@[EBUSY, ENOTEMPTY, EEXIST]@--* 'UnsupportedOperation'-The implementation does not support removal in this situation.-@[EINVAL]@--* 'InappropriateType'-The operand refers to an existing non-directory object.-@[ENOTDIR]@---}--removeDirectory :: FilePath -> IO ()-removeDirectory path =-#ifdef mingw32_HOST_OS- Win32.removeDirectory path-#else- Posix.removeDirectory path-#endif---- | @'removeDirectoryRecursive' dir@ removes an existing directory /dir/--- together with its contents and subdirectories. Within this directory,--- symbolic links are removed without affecting their targets.------ On Windows, the operation fails if /dir/ is a directory symbolic link.-removeDirectoryRecursive :: FilePath -> IO ()-removeDirectoryRecursive path =- (`ioeAddLocation` "removeDirectoryRecursive") `modifyIOError` do- dirType <- getDirectoryType path- case dirType of- Directory ->- removeContentsRecursive path- DirectoryLink ->- ioError (err `ioeSetErrorString` "is a directory symbolic link")- NotDirectory ->- ioError (err `ioeSetErrorString` "not a directory")- where err = mkIOError InappropriateType "" Nothing (Just path)---- | @'removePathRecursive' path@ removes an existing file or directory at--- /path/ together with its contents and subdirectories. Symbolic links are--- removed without affecting their the targets.-removePathRecursive :: FilePath -> IO ()-removePathRecursive path =- (`ioeAddLocation` "removePathRecursive") `modifyIOError` do- dirType <- getDirectoryType path- case dirType of- NotDirectory -> removeFile path- Directory -> removeContentsRecursive path- DirectoryLink -> removeDirectory path---- | @'removeContentsRecursive' dir@ removes the contents of the directory--- /dir/ recursively. Symbolic links are removed without affecting their the--- targets.-removeContentsRecursive :: FilePath -> IO ()-removeContentsRecursive path =- (`ioeAddLocation` "removeContentsRecursive") `modifyIOError` do- cont <- listDirectory path- mapM_ removePathRecursive [path </> x | x <- cont]- removeDirectory path---- | Removes a file or directory at /path/ together with its contents and--- subdirectories. Symbolic links are removed without affecting their--- targets. If the path does not exist, nothing happens.------ Unlike other removal functions, this function will also attempt to delete--- files marked as read-only or otherwise made unremovable due to permissions.--- As a result, if the removal is incomplete, the permissions or attributes on--- the remaining files may be altered.------ If an entry within the directory vanishes while @removePathForcibly@ is--- running, it is silently ignored.------ If an exception occurs while removing an entry, @removePathForcibly@ will--- still try to remove as many entries as it can before failing with an--- exception. The first exception that it encountered is re-thrown.------ @since 1.2.7.0-removePathForcibly :: FilePath -> IO ()-removePathForcibly path =- (`ioeAddLocation` "removePathForcibly") `modifyIOError` do- makeRemovable path `catchIOError` \ _ -> return ()- ignoreDoesNotExistError $ do- dirType <- getDirectoryType path- case dirType of- NotDirectory -> removeFile path- DirectoryLink -> removeDirectory path- Directory -> do- names <- listDirectory path- sequenceWithIOErrors_ $- [ removePathForcibly (path </> name) | name <- names ] ++- [ removeDirectory path ]- where-- ignoreDoesNotExistError :: IO () -> IO ()- ignoreDoesNotExistError action = do- _ <- tryIOErrorType isDoesNotExistError action- return ()-- makeRemovable :: FilePath -> IO ()- makeRemovable p = do- perms <- getPermissions p- setPermissions path perms{ readable = True- , searchable = True- , writable = True }--sequenceWithIOErrors_ :: [IO ()] -> IO ()-sequenceWithIOErrors_ actions = go (Right ()) actions- where-- go :: Either IOError () -> [IO ()] -> IO ()- go (Left e) [] = ioError e- go (Right ()) [] = return ()- go s (m : ms) = s `seq` do- r <- tryIOError m- go (thenEither s r) ms-- -- equivalent to (*>) for Either, defined here to retain compatibility- -- with base prior to 4.3- thenEither :: Either b a -> Either b a -> Either b a- thenEither x@(Left _) _ = x- thenEither _ y = y--{- |'removeFile' /file/ removes the directory entry for an existing file-/file/, where /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-use by other processes).--The operation may fail with:--* 'HardwareFault'-A physical I\/O error has occurred.-@[EIO]@--* 'InvalidArgument'-The operand is not a valid file name.-@[ENAMETOOLONG, ELOOP]@--* 'isDoesNotExistError' \/ 'NoSuchThing'-The file does not exist.-@[ENOENT, ENOTDIR]@--* 'isPermissionError' \/ 'PermissionDenied'-The process has insufficient privileges to perform the operation.-@[EROFS, EACCES, EPERM]@--* 'UnsatisfiedConstraints'-Implementation-dependent constraints are not satisfied.-@[EBUSY]@--* 'InappropriateType'-The operand refers to an existing directory.-@[EPERM, EINVAL]@---}--removeFile :: FilePath -> IO ()-removeFile path =-#ifdef mingw32_HOST_OS- Win32.deleteFile path-#else- Posix.removeLink path-#endif--{- |@'renameDirectory' old new@ changes the name of an existing-directory from /old/ to /new/. If the /new/ directory-already exists, it is atomically replaced by the /old/ directory.-If the /new/ directory is neither the /old/ directory nor an-alias of the /old/ directory, it is removed as if by-'removeDirectory'. A conformant implementation need not support-renaming directories in all situations (e.g. renaming to an existing-directory, or across different physical devices), but the constraints-must be documented.--On Win32 platforms, @renameDirectory@ fails if the /new/ directory already-exists.--The operation may fail with:--* 'HardwareFault'-A physical I\/O error has occurred.-@[EIO]@--* 'InvalidArgument'-Either operand is not a valid directory name.-@[ENAMETOOLONG, ELOOP]@--* 'isDoesNotExistError' \/ 'NoSuchThing'-The original directory does not exist, or there is no path to the target.-@[ENOENT, ENOTDIR]@--* 'isPermissionError' \/ 'PermissionDenied'-The process has insufficient privileges to perform the operation.-@[EROFS, EACCES, EPERM]@--* 'ResourceExhausted'-Insufficient resources are available to perform the operation.-@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@--* 'UnsatisfiedConstraints'-Implementation-dependent constraints are not satisfied.-@[EBUSY, ENOTEMPTY, EEXIST]@--* 'UnsupportedOperation'-The implementation does not support renaming in this situation.-@[EINVAL, EXDEV]@--* 'InappropriateType'-Either path refers to an existing non-directory object.-@[ENOTDIR, EISDIR]@---}--renameDirectory :: FilePath -> FilePath -> IO ()-renameDirectory opath npath =- -- XXX this test isn't performed atomically with the following rename-#ifdef mingw32_HOST_OS- -- ToDo: use Win32 API- withFileStatus "renameDirectory" opath $ \st -> do- is_dir <- isDirectory st-#else- do- stat <- Posix.getFileStatus opath- let is_dir = Posix.fileMode stat .&. Posix.directoryMode /= 0-#endif- when (not is_dir) $ do- ioError . (`ioeSetErrorString` "not a directory") $- (mkIOError InappropriateType "renameDirectory" Nothing (Just opath))- renamePath opath npath--{- |@'renameFile' old new@ changes the name of an existing file system-object from /old/ to /new/. If the /new/ object already-exists, it is atomically replaced by the /old/ object. Neither-path may refer to an existing directory. A conformant implementation-need not support renaming files in all situations (e.g. renaming-across different physical devices), but the constraints must be-documented.--The operation may fail with:--* 'HardwareFault'-A physical I\/O error has occurred.-@[EIO]@--* 'InvalidArgument'-Either operand is not a valid file name.-@[ENAMETOOLONG, ELOOP]@--* 'isDoesNotExistError' \/ 'NoSuchThing'-The original file does not exist, or there is no path to the target.-@[ENOENT, ENOTDIR]@--* 'isPermissionError' \/ 'PermissionDenied'-The process has insufficient privileges to perform the operation.-@[EROFS, EACCES, EPERM]@--* 'ResourceExhausted'-Insufficient resources are available to perform the operation.-@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@--* 'UnsatisfiedConstraints'-Implementation-dependent constraints are not satisfied.-@[EBUSY]@--* 'UnsupportedOperation'-The implementation does not support renaming in this situation.-@[EXDEV]@--* 'InappropriateType'-Either path refers to an existing directory.-@[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@---}--renameFile :: FilePath -> FilePath -> IO ()-renameFile opath npath = (`ioeAddLocation` "renameFile") `modifyIOError` do- -- XXX the tests are not performed atomically with the rename- checkNotDir opath- renamePath opath npath- -- The underlying rename implementation can throw odd exceptions when the- -- destination is a directory. For example, Windows typically throws a- -- permission error, while POSIX systems may throw a resource busy error- -- if one of the paths refers to the current directory. In these cases,- -- we check if the destination is a directory and, if so, throw an- -- InappropriateType error.- `catchIOError` \ err -> do- checkNotDir npath- ioError err- where checkNotDir path = do- dirType <- getDirectoryType path- `catchIOError` \ _ -> return NotDirectory- case dirType of- Directory -> errIsDir path- DirectoryLink -> errIsDir path- NotDirectory -> return ()- errIsDir path = ioError . (`ioeSetErrorString` "is a directory") $- mkIOError InappropriateType "" Nothing (Just path)---- | Rename a file or directory. If the destination path already exists, it--- is replaced atomically. The destination path must not point to an existing--- directory. A conformant implementation need not support renaming files in--- all situations (e.g. renaming across different physical devices), but the--- constraints must be documented.------ The operation may fail with:------ * 'HardwareFault'--- A physical I\/O error has occurred.--- @[EIO]@------ * 'InvalidArgument'--- Either operand is not a valid file name.--- @[ENAMETOOLONG, ELOOP]@------ * 'isDoesNotExistError' \/ 'NoSuchThing'--- The original file does not exist, or there is no path to the target.--- @[ENOENT, ENOTDIR]@------ * 'isPermissionError' \/ 'PermissionDenied'--- The process has insufficient privileges to perform the operation.--- @[EROFS, EACCES, EPERM]@------ * 'ResourceExhausted'--- Insufficient resources are available to perform the operation.--- @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@------ * 'UnsatisfiedConstraints'--- Implementation-dependent constraints are not satisfied.--- @[EBUSY]@------ * 'UnsupportedOperation'--- The implementation does not support renaming in this situation.--- @[EXDEV]@------ * 'InappropriateType'--- Either the destination path refers to an existing directory, or one of the--- parent segments in the destination path is not a directory.--- @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@------ @since 1.2.7.0-renamePath :: FilePath -- ^ Old path- -> FilePath -- ^ New path- -> IO ()-renamePath opath npath = (`ioeAddLocation` "renamePath") `modifyIOError` do-#ifdef mingw32_HOST_OS- Win32.moveFileEx opath npath Win32.mOVEFILE_REPLACE_EXISTING-#else- Posix.rename opath npath-#endif---- | Copy a file with its permissions. If the destination file already exists,--- it is replaced atomically. Neither path may refer to an existing--- directory. No exceptions are thrown if the permissions could not be--- copied.-copyFile :: FilePath -- ^ Source filename- -> FilePath -- ^ Destination filename- -> IO ()-copyFile fromFPath toFPath =- (`ioeAddLocation` "copyFile") `modifyIOError` do- atomicCopyFileContents fromFPath toFPath- (ignoreIOExceptions . copyPermissions fromFPath)--#ifndef mingw32_HOST_OS--- | Truncate the destination file and then copy the contents of the source--- file to the destination file. If the destination file already exists, its--- attributes shall remain unchanged. Otherwise, its attributes are reset to--- the defaults.-copyFileContents :: FilePath -- ^ Source filename- -> FilePath -- ^ Destination filename- -> IO ()-copyFileContents fromFPath toFPath =- (`ioeAddLocation` "copyFileContents") `modifyIOError` do- withBinaryFile toFPath WriteMode $ \ hTo ->- copyFileToHandle fromFPath hTo-#endif---- | Copy the contents of a source file to a destination file, replacing the--- destination file atomically via 'withReplacementFile', resetting the--- attributes of the destination file to the defaults.-atomicCopyFileContents :: FilePath -- ^ Source filename- -> FilePath -- ^ Destination filename- -> (FilePath -> IO ()) -- ^ Post-action- -> IO ()-atomicCopyFileContents fromFPath toFPath postAction =- (`ioeAddLocation` "atomicCopyFileContents") `modifyIOError` do- withReplacementFile toFPath postAction $ \ hTo -> do- copyFileToHandle fromFPath hTo---- | A helper function useful for replacing files in an atomic manner. The--- function creates a temporary file in the directory of the destination file,--- opens it, performs the main action with its handle, closes it, performs the--- post-action with its path, and finally replaces the destination file with--- the temporary file. If an error occurs during any step of this process,--- the temporary file is removed and the destination file remains untouched.-withReplacementFile :: FilePath -- ^ Destination file- -> (FilePath -> IO ()) -- ^ Post-action- -> (Handle -> IO a) -- ^ Main action- -> IO a-withReplacementFile path postAction action =- (`ioeAddLocation` "withReplacementFile") `modifyIOError` do- mask $ \ restore -> do- (tmpFPath, hTmp) <- openBinaryTempFile (takeDirectory path)- ".copyFile.tmp"- (`onException` ignoreIOExceptions (removeFile tmpFPath)) $ do- r <- (`onException` ignoreIOExceptions (hClose hTmp)) $ do- restore (action hTmp)- hClose hTmp- restore (postAction tmpFPath)- renameFile tmpFPath path- return r---- | Attempt to perform the given action, silencing any IO exception thrown by--- it.-ignoreIOExceptions :: IO () -> IO ()-ignoreIOExceptions io = io `catchIOError` (\_ -> return ())---- | Copy all data from a file to a handle.-copyFileToHandle :: FilePath -- ^ Source file- -> Handle -- ^ Destination handle- -> IO ()-copyFileToHandle fromFPath hTo =- (`ioeAddLocation` "copyFileToHandle") `modifyIOError` do- withBinaryFile fromFPath ReadMode $ \ hFrom ->- copyHandleData hFrom hTo---- | Copy data from one handle to another until end of file.-copyHandleData :: Handle -- ^ Source handle- -> Handle -- ^ Destination handle- -> IO ()-copyHandleData hFrom hTo =- (`ioeAddLocation` "copyData") `modifyIOError` do- allocaBytes bufferSize go- where- bufferSize = 1024- go buffer = do- count <- hGetBuf hFrom buffer bufferSize- when (count > 0) $ do- hPutBuf hTo buffer count- go buffer---- | Copy a file with its associated metadata. If the destination file--- already exists, it is overwritten. There is no guarantee of atomicity in--- the replacement of the destination file. Neither path may refer to an--- existing directory. If the source and/or destination are symbolic links,--- the copy is performed on the targets of the links.------ On Windows, it behaves like the Win32 function--- <https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851.aspx CopyFile>,--- which copies various kinds of metadata including file attributes and--- security resource properties.------ On Unix-like systems, permissions, access time, and modification time are--- preserved. If possible, the owner and group are also preserved. Note that--- the very act of copying can change the access time of the source file,--- hence the access times of the two files may differ after the operation--- completes.------ @since 1.2.6.0-copyFileWithMetadata :: FilePath -- ^ Source file- -> FilePath -- ^ Destination file- -> IO ()-copyFileWithMetadata src dst =- (`ioeAddLocation` "copyFileWithMetadata") `modifyIOError` doCopy- where-#ifdef mingw32_HOST_OS- doCopy = Win32.copyFile src dst False-#else- doCopy = do- st <- Posix.getFileStatus src- copyFileContents src dst- copyMetadataFromStatus st dst-#endif--#ifndef mingw32_HOST_OS-copyMetadataFromStatus :: Posix.FileStatus -> FilePath -> IO ()-copyMetadataFromStatus st dst = do- tryCopyOwnerAndGroupFromStatus st dst- copyPermissionsFromStatus st dst- copyFileTimesFromStatus st dst-#endif--#ifndef mingw32_HOST_OS-tryCopyOwnerAndGroupFromStatus :: Posix.FileStatus -> FilePath -> IO ()-tryCopyOwnerAndGroupFromStatus st dst = do- ignoreIOExceptions (copyOwnerFromStatus st dst)- ignoreIOExceptions (copyGroupFromStatus st dst)-#endif--#ifndef mingw32_HOST_OS-copyOwnerFromStatus :: Posix.FileStatus -> FilePath -> IO ()-copyOwnerFromStatus st dst = do- Posix.setOwnerAndGroup dst (Posix.fileOwner st) (-1)-#endif--#ifndef mingw32_HOST_OS-copyGroupFromStatus :: Posix.FileStatus -> FilePath -> IO ()-copyGroupFromStatus st dst = do- Posix.setOwnerAndGroup dst (-1) (Posix.fileGroup st)-#endif--#ifndef mingw32_HOST_OS-copyFileTimesFromStatus :: Posix.FileStatus -> FilePath -> IO ()-copyFileTimesFromStatus st dst = do- let (atime, mtime) = fileTimesFromStatus st- setFileTimes dst (Just atime, Just mtime)-#endif---- | Make a path absolute, 'normalise' the path, and remove as many--- indirections from it as possible. Any trailing path separators are--- discarded via 'dropTrailingPathSeparator'. Additionally, on Windows the--- letter case of the path is canonicalized.------ __Note__: This function is a very big hammer. If you only need an absolute--- path, 'makeAbsolute' is sufficient for removing dependence on the current--- working directory.------ Indirections include the two special directories @.@ and @..@, as well as--- any symbolic links. The input path need not point to an existing file or--- directory. Canonicalization is performed on the longest prefix of the path--- that points to an existing file or directory. The remaining portion of the--- path that does not point to an existing file or directory will still--- undergo 'normalise', but case canonicalization and indirection removal are--- skipped as they are impossible to do on a nonexistent path.------ Most programs should not worry about the canonicity of a path. In--- particular, despite the name, the function does not truly guarantee--- canonicity of the returned path due to the presence of hard links, mount--- points, etc.------ If the path points to an existing file or directory, then the output path--- shall also point to the same file or directory, subject to the condition--- that the relevant parts of the file system do not change while the function--- is still running. In other words, the function is definitively not atomic.--- The results can be utterly wrong if the portions of the path change while--- this function is running.------ Since symbolic links (and, on non-Windows systems, parent directories @..@)--- are dependent on the state of the existing filesystem, the function can--- only make a conservative attempt by removing such indirections from the--- longest prefix of the path that still points to an existing file or--- directory.------ Note that on Windows parent directories @..@ are always fully expanded--- before the symbolic links, as consistent with the rest of the Windows API--- (such as @GetFullPathName@). In contrast, on POSIX systems parent--- directories @..@ are expanded alongside symbolic links from left to right.--- To put this more concretely: if @L@ is a symbolic link for @R/P@, then on--- Windows @L\\..@ refers to @.@, whereas on other operating systems @L/..@--- refers to @R@.------ Similar to 'normalise', passing an empty path is equivalent to passing the--- current directory.------ /Known bugs/: When the path contains an existing symbolic link, but the--- target of the link does not exist, then the path is not dereferenced (bug--- #64). Symbolic link expansion is not performed on Windows XP or earlier--- due to the absence of @GetFinalPathNameByHandle@.------ /Changes since 1.2.3.0:/ The function has been altered to be more robust--- and has the same exception behavior as 'makeAbsolute'.------ /Changes since 1.3.0.0:/ The function no longer preserves the trailing path--- separator. File symbolic links that appear in the middle of a path are--- properly dereferenced. Case canonicalization and symbolic link expansion--- are now performed on Windows.----canonicalizePath :: FilePath -> IO FilePath-canonicalizePath = \ path ->- modifyIOError ((`ioeAddLocation` "canonicalizePath") .- (`ioeSetFileName` path)) $- -- normalise does more stuff, like upper-casing the drive letter- dropTrailingPathSeparator . normalise <$>- (transform =<< prependCurrentDirectory path)- where--#if defined(mingw32_HOST_OS)- transform path =- attemptRealpath getFinalPathName =<<- (Win32.getFullPathName path `catchIOError` \ _ -> return path)-#else- transform path = do- encoding <- getFileSystemEncoding- let realpath path' =- GHC.withCString encoding path'- (`withRealpath` GHC.peekCString encoding)- attemptRealpath realpath path-#endif-- attemptRealpath realpath path =- realpathPrefix realpath (reverse (zip prefixes suffixes)) path- where segments = splitDirectories path- prefixes = scanl1 (</>) segments- suffixes = tail (scanr (</>) "" segments)-- -- call realpath on the largest possible prefix- realpathPrefix realpath ((prefix, suffix) : rest) path = do- exist <- doesPathExist prefix- if exist -- never call realpath on an inaccessible path- then ((</> suffix) <$> realpath prefix)- `catchIOError` \ _ -> realpathPrefix realpath rest path- else realpathPrefix realpath rest path- realpathPrefix _ _ path = return path---- | Convert a path into an absolute path. If the given path is relative, the--- current directory is prepended and then the combined result is--- 'normalise'd. If the path is already absolute, the path is simply--- 'normalise'd. The function preserves the presence or absence of the--- trailing path separator unless the path refers to the root directory @/@.------ If the path is already absolute, the operation never fails. Otherwise, the--- operation may fail with the same exceptions as 'getCurrentDirectory'.------ @since 1.2.2.0----makeAbsolute :: FilePath -> IO FilePath-makeAbsolute path =- modifyIOError ((`ioeAddLocation` "makeAbsolute") .- (`ioeSetFileName` path)) $- matchTrailingSeparator path . normalise <$> prependCurrentDirectory path---- | Convert a path into an absolute path. If the given path is relative, the--- current directory is prepended. If the path is already absolute, the path--- is returned unchanged. The function preserves the presence or absence of--- the trailing path separator.------ If the path is already absolute, the operation never fails. Otherwise, the--- operation may fail with the same exceptions as 'getCurrentDirectory'.------ (internal API)-prependCurrentDirectory :: FilePath -> IO FilePath-prependCurrentDirectory path =- modifyIOError ((`ioeAddLocation` "prependCurrentDirectory") .- (`ioeSetFileName` path)) $- if isRelative path -- avoid the call to `getCurrentDirectory` if we can- then (</> path) <$> getCurrentDirectory- else return path---- | Add or remove the trailing path separator in the second path so as to--- match its presence in the first path.------ (internal API)-matchTrailingSeparator :: FilePath -> FilePath -> FilePath-matchTrailingSeparator path- | hasTrailingPathSeparator path = addTrailingPathSeparator- | otherwise = dropTrailingPathSeparator---- | Construct a path relative to the current directory, similar to--- 'makeRelative'.------ The operation may fail with the same exceptions as 'getCurrentDirectory'.-makeRelativeToCurrentDirectory :: FilePath -> IO FilePath-makeRelativeToCurrentDirectory x = do- cur <- getCurrentDirectory- return $ makeRelative cur x---- | Given an executable file name, searches for such file in the--- directories listed in system PATH. The returned value is the path--- to the found executable or Nothing if an executable with the given--- name was not found. For example (findExecutable \"ghc\") gives you--- the path to GHC.------ The path returned by 'findExecutable' corresponds to the--- program that would be executed by 'System.Process.createProcess'--- when passed the same string (as a RawCommand, not a ShellCommand).------ On Windows, 'findExecutable' calls the Win32 function 'SearchPath',--- which may search other places before checking the directories in--- @PATH@. Where it actually searches depends on registry settings,--- but notably includes the directory containing the current--- executable. See--- <http://msdn.microsoft.com/en-us/library/aa365527.aspx> for more--- details.----findExecutable :: String -> IO (Maybe FilePath)-findExecutable binary = do-#if defined(mingw32_HOST_OS)- Win32.searchPath Nothing binary exeExtension-#else- path <- getPath- findFileWith isExecutable path (binary <.> exeExtension)-#endif---- | Given a file name, searches for the file and returns a list of all--- occurences that are executable.------ On Windows, this only returns the first ocurrence, if any. It uses the--- @SearchPath@ from the Win32 API, so the caveats noted in 'findExecutable'--- apply here as well.------ @since 1.2.2.0-findExecutables :: String -> IO [FilePath]-findExecutables binary = do-#if defined(mingw32_HOST_OS)- file <- findExecutable binary- return $ maybeToList file-#else- path <- getPath- findExecutablesInDirectories path binary-#endif--#ifndef mingw32_HOST_OS--- | Get the contents of the @PATH@ environment variable.-getPath :: IO [FilePath]-getPath = do- path <- getEnv "PATH"- return (splitSearchPath path)-#endif---- | Given a file name, searches for the file on the given paths and returns a--- list of all occurences that are executable.------ @since 1.2.4.0-findExecutablesInDirectories :: [FilePath] -> String -> IO [FilePath]-findExecutablesInDirectories path binary =- findFilesWith isExecutable path (binary <.> exeExtension)---- | Test whether a file is executable.-isExecutable :: FilePath -> IO Bool-isExecutable file = do- perms <- getPermissions file- return (executable perms)---- | Search through the given set of directories for the given file.-findFile :: [FilePath] -> String -> IO (Maybe FilePath)-findFile = findFileWith (\_ -> return True)---- | Search through the given set of directories for the given file and--- returns a list of paths where the given file exists.------ @since 1.2.1.0-findFiles :: [FilePath] -> String -> IO [FilePath]-findFiles = findFilesWith (\_ -> return True)---- | Search through the given set of directories for the given file and--- with the given property (usually permissions) and returns the file path--- where the given file exists and has the property.------ @since 1.2.6.0-findFileWith :: (FilePath -> IO Bool) -> [FilePath] -> String -> IO (Maybe FilePath)-findFileWith f ds name = asumMaybeT (map (findFileWithIn f name) ds)---- | 'Data.Foldable.asum' for 'Control.Monad.Trans.Maybe.MaybeT', essentially.------ Returns the first 'Just' in the list or 'Nothing' if there aren't any.-asumMaybeT :: Monad m => [m (Maybe a)] -> m (Maybe a)-asumMaybeT = foldr attempt (return Nothing)- where- attempt mmx mx' = do- mx <- mmx- case mx of- Nothing -> mx'- Just _ -> return mx---- | Search through the given set of directories for the given file and--- with the given property (usually permissions) and returns a list of--- paths where the given file exists and has the property.------ @since 1.2.1.0-findFilesWith :: (FilePath -> IO Bool) -> [FilePath] -> String -> IO [FilePath]-findFilesWith f ds name = do- mfiles <- mapM (findFileWithIn f name) ds- return (catMaybes mfiles)---- | Like 'findFileWith', but searches only a single directory.-findFileWithIn :: (FilePath -> IO Bool) -> String -> FilePath -> IO (Maybe FilePath)-findFileWithIn f name d = do- let path = d </> name- exist <- doesFileExist path- if exist- then do- ok <- f path- if ok- then return (Just path)- else return Nothing- else return Nothing---- | Similar to 'listDirectory', but always includes the special entries (@.@--- and @..@). (This applies to Windows as well.)------ The operation may fail with the same exceptions as 'listDirectory'.-getDirectoryContents :: FilePath -> IO [FilePath]-getDirectoryContents path =- modifyIOError ((`ioeSetFileName` path) .- (`ioeAddLocation` "getDirectoryContents")) $ do-#ifndef mingw32_HOST_OS- bracket- (Posix.openDirStream path)- Posix.closeDirStream- start- where- start dirp =- loop id- where- loop acc = do- e <- Posix.readDirStream dirp- if null e- then return (acc [])- else loop (acc . (e:))-#else- bracket- (Win32.findFirstFile (path </> "*"))- (\(h,_) -> Win32.findClose h)- (\(h,fdat) -> loop h fdat [])- where- -- we needn't worry about empty directories: adirectory always- -- has at least "." and ".." entries- loop :: Win32.HANDLE -> Win32.FindData -> [FilePath] -> IO [FilePath]- loop h fdat acc = do- filename <- Win32.getFindDataFileName fdat- more <- Win32.findNextFile h fdat- if more- then loop h fdat (filename:acc)- else return (filename:acc)- -- no need to reverse, ordering is undefined-#endif /* mingw32 */---- | @'listDirectory' dir@ returns a list of /all/ entries in /dir/ without--- the special entries (@.@ and @..@).------ The operation may fail with:------ * 'HardwareFault'--- A physical I\/O error has occurred.--- @[EIO]@------ * 'InvalidArgument'--- The operand is not a valid directory name.--- @[ENAMETOOLONG, ELOOP]@------ * 'isDoesNotExistError' \/ 'NoSuchThing'--- The directory does not exist.--- @[ENOENT, ENOTDIR]@------ * 'isPermissionError' \/ 'PermissionDenied'--- The process has insufficient privileges to perform the operation.--- @[EACCES]@------ * 'ResourceExhausted'--- Insufficient resources are available to perform the operation.--- @[EMFILE, ENFILE]@------ * 'InappropriateType'--- The path refers to an existing non-directory object.--- @[ENOTDIR]@------ @since 1.2.5.0----listDirectory :: FilePath -> IO [FilePath]-listDirectory path =- (filter f) <$> (getDirectoryContents path)- where f filename = filename /= "." && filename /= ".."---- | Obtain the current working directory as an absolute path.------ In a multithreaded program, the current working directory is a global state--- shared among all threads of the process. Therefore, when performing--- filesystem operations from multiple threads, it is highly recommended to--- use absolute rather than relative paths (see: 'makeAbsolute').------ The operation may fail with:------ * 'HardwareFault'--- A physical I\/O error has occurred.--- @[EIO]@------ * 'isDoesNotExistError' or 'NoSuchThing'--- There is no path referring to the working directory.--- @[EPERM, ENOENT, ESTALE...]@------ * 'isPermissionError' or 'PermissionDenied'--- The process has insufficient privileges to perform the operation.--- @[EACCES]@------ * 'ResourceExhausted'--- Insufficient resources are available to perform the operation.------ * 'UnsupportedOperation'--- The operating system has no notion of current working directory.----getCurrentDirectory :: IO FilePath-getCurrentDirectory =- modifyIOError (`ioeAddLocation` "getCurrentDirectory") $- specializeErrorString- "Current working directory no longer exists"- isDoesNotExistError- getCwd- where-#ifdef mingw32_HOST_OS- getCwd = Win32.getCurrentDirectory-#else- getCwd = Posix.getWorkingDirectory-#endif---- | Change the working directory to the given path.------ In a multithreaded program, the current working directory is a global state--- shared among all threads of the process. Therefore, when performing--- filesystem operations from multiple threads, it is highly recommended to--- use absolute rather than relative paths (see: 'makeAbsolute').------ The operation may fail with:------ * 'HardwareFault'--- A physical I\/O error has occurred.--- @[EIO]@------ * 'InvalidArgument'--- The operand is not a valid directory name.--- @[ENAMETOOLONG, ELOOP]@------ * 'isDoesNotExistError' or 'NoSuchThing'--- The directory does not exist.--- @[ENOENT, ENOTDIR]@------ * 'isPermissionError' or 'PermissionDenied'--- The process has insufficient privileges to perform the operation.--- @[EACCES]@------ * 'UnsupportedOperation'--- The operating system has no notion of current working directory, or the--- working directory cannot be dynamically changed.------ * 'InappropriateType'--- The path refers to an existing non-directory object.--- @[ENOTDIR]@----setCurrentDirectory :: FilePath -> IO ()-setCurrentDirectory =-#ifdef mingw32_HOST_OS- Win32.setCurrentDirectory-#else- Posix.changeWorkingDirectory-#endif---- | Run an 'IO' action with the given working directory and restore the--- original working directory afterwards, even if the given action fails due--- to an exception.------ The operation may fail with the same exceptions as 'getCurrentDirectory'--- and 'setCurrentDirectory'.------ @since 1.2.3.0----withCurrentDirectory :: FilePath -- ^ Directory to execute in- -> IO a -- ^ Action to be executed- -> IO a-withCurrentDirectory dir action =- bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do- setCurrentDirectory dir- action---- | Obtain the size of a file in bytes.------ @since 1.2.7.0-getFileSize :: FilePath -> IO Integer-getFileSize path =- (`ioeAddLocation` "getFileSize") `modifyIOError` do-#ifdef mingw32_HOST_OS- fromIntegral <$> withFileStatus "" path st_size-#else- fromIntegral . Posix.fileSize <$> Posix.getFileStatus path-#endif---- | Test whether the given path points to an existing filesystem object. If--- the user lacks necessary permissions to search the parent directories, this--- function may return false even if the file does actually exist.------ @since 1.2.7.0-doesPathExist :: FilePath -> IO Bool-doesPathExist path =-#ifdef mingw32_HOST_OS- (withFileStatus "" path $ \ _ -> return True)-#else- (Posix.getFileStatus path >> return True)-#endif- `catchIOError` \ _ -> return False--{- |The operation 'doesDirectoryExist' returns 'True' if the argument file-exists and is either a directory or a symbolic link to a directory,-and 'False' otherwise.--}--doesDirectoryExist :: FilePath -> IO Bool-doesDirectoryExist name =-#ifdef mingw32_HOST_OS- (withFileStatus "doesDirectoryExist" name $ \st -> isDirectory st)-#else- (do stat <- Posix.getFileStatus name- return (Posix.isDirectory stat))-#endif- `catchIOError` \ _ -> return False--{- |The operation 'doesFileExist' returns 'True'-if the argument file exists and is not a directory, and 'False' otherwise.--}--doesFileExist :: FilePath -> IO Bool-doesFileExist name =-#ifdef mingw32_HOST_OS- (withFileStatus "doesFileExist" name $ \st -> do b <- isDirectory st; return (not b))-#else- (do stat <- Posix.getFileStatus name- return (not (Posix.isDirectory stat)))-#endif- `catchIOError` \ _ -> return False---- | Check whether the path refers to a symbolic link. On Windows, this tests--- for @FILE_ATTRIBUTE_REPARSE_POINT@.------ @since 1.3.0.0-pathIsSymbolicLink :: FilePath -> IO Bool-pathIsSymbolicLink path =- (`ioeAddLocation` "getDirectoryType") `modifyIOError` do-#ifdef mingw32_HOST_OS- isReparsePoint <$> Win32.getFileAttributes path- where- isReparsePoint attr = attr .&. win32_fILE_ATTRIBUTE_REPARSE_POINT /= 0-#else- Posix.isSymbolicLink <$> Posix.getSymbolicLinkStatus path-#endif--{-# DEPRECATED isSymbolicLink "Use 'pathIsSymbolicLink' instead" #-}-isSymbolicLink :: FilePath -> IO Bool-isSymbolicLink = pathIsSymbolicLink--#ifdef mingw32_HOST_OS--- | Open the handle of an existing file or directory.-openFileHandle :: String -> Win32.AccessMode -> IO Win32.HANDLE-openFileHandle path mode = Win32.createFile path mode share Nothing- Win32.oPEN_EXISTING flags Nothing- where share = win32_fILE_SHARE_DELETE- .|. Win32.fILE_SHARE_READ- .|. Win32.fILE_SHARE_WRITE- flags = Win32.fILE_ATTRIBUTE_NORMAL- .|. Win32.fILE_FLAG_BACKUP_SEMANTICS -- required for directories-#endif---- | Obtain the time at which the file or directory was last accessed.------ The operation may fail with:------ * 'isPermissionError' if the user is not permitted to read--- the access time; or------ * 'isDoesNotExistError' if the file or directory does not exist.------ Caveat for POSIX systems: This function returns a timestamp with sub-second--- resolution only if this package is compiled against @unix-2.6.0.0@ or later--- and the underlying filesystem supports them.------ @since 1.2.3.0----getAccessTime :: FilePath -> IO UTCTime-getAccessTime = modifyIOError (`ioeAddLocation` "getAccessTime") .- (fst <$>) . getFileTimes---- | Obtain the time at which the file or directory was last modified.------ The operation may fail with:------ * 'isPermissionError' if the user is not permitted to read--- the modification time; or------ * 'isDoesNotExistError' if the file or directory does not exist.------ Caveat for POSIX systems: This function returns a timestamp with sub-second--- resolution only if this package is compiled against @unix-2.6.0.0@ or later--- and the underlying filesystem supports them.----getModificationTime :: FilePath -> IO UTCTime-getModificationTime = modifyIOError (`ioeAddLocation` "getModificationTime") .- (snd <$>) . getFileTimes--getFileTimes :: FilePath -> IO (UTCTime, UTCTime)-getFileTimes path =- modifyIOError (`ioeAddLocation` "getFileTimes") .- modifyIOError (`ioeSetFileName` path) $- getTimes- where- path' = normalise path -- handle empty paths-#ifdef mingw32_HOST_OS- getTimes =- bracket (openFileHandle path' Win32.gENERIC_READ)- Win32.closeHandle $ \ handle ->- alloca $ \ atime ->- alloca $ \ mtime -> do- Win32.failIf_ not "" $- Win32.c_GetFileTime handle nullPtr atime mtime- ((,) `on` posixSecondsToUTCTime . windowsToPosixTime)- <$> peek atime- <*> peek mtime-#else- getTimes = fileTimesFromStatus <$> Posix.getFileStatus path'-#endif--#ifndef mingw32_HOST_OS-fileTimesFromStatus :: Posix.FileStatus -> (UTCTime, UTCTime)-fileTimesFromStatus st =-# if MIN_VERSION_unix(2, 6, 0)- ( posixSecondsToUTCTime (Posix.accessTimeHiRes st)- , posixSecondsToUTCTime (Posix.modificationTimeHiRes st) )-# else- ( posixSecondsToUTCTime (realToFrac (Posix.accessTime st))- , posixSecondsToUTCTime (realToFrac (Posix.modificationTime st)) )-# endif-#endif---- | Change the time at which the file or directory was last accessed.------ The operation may fail with:------ * 'isPermissionError' if the user is not permitted to alter the--- access time; or------ * 'isDoesNotExistError' if the file or directory does not exist.------ Some caveats for POSIX systems:------ * Not all systems support @utimensat@, in which case the function can only--- emulate the behavior by reading the modification time and then setting--- both the access and modification times together. On systems where--- @utimensat@ is supported, the access time is set atomically with--- nanosecond precision.------ * If compiled against a version of @unix@ prior to @2.7.0.0@, the function--- would not be able to set timestamps with sub-second resolution. In this--- case, there would also be loss of precision in the modification time.------ @since 1.2.3.0----setAccessTime :: FilePath -> UTCTime -> IO ()-setAccessTime path atime =- modifyIOError (`ioeAddLocation` "setAccessTime") $- setFileTimes path (Just atime, Nothing)---- | Change the time at which the file or directory was last modified.------ The operation may fail with:------ * 'isPermissionError' if the user is not permitted to alter the--- modification time; or------ * 'isDoesNotExistError' if the file or directory does not exist.------ Some caveats for POSIX systems:------ * Not all systems support @utimensat@, in which case the function can only--- emulate the behavior by reading the access time and then setting both the--- access and modification times together. On systems where @utimensat@ is--- supported, the modification time is set atomically with nanosecond--- precision.------ * If compiled against a version of @unix@ prior to @2.7.0.0@, the function--- would not be able to set timestamps with sub-second resolution. In this--- case, there would also be loss of precision in the access time.------ @since 1.2.3.0----setModificationTime :: FilePath -> UTCTime -> IO ()-setModificationTime path mtime =- modifyIOError (`ioeAddLocation` "setModificationTime") $- setFileTimes path (Nothing, Just mtime)--setFileTimes :: FilePath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()-setFileTimes _ (Nothing, Nothing) = return ()-setFileTimes path (atime, mtime) =- modifyIOError (`ioeAddLocation` "setFileTimes") .- modifyIOError (`ioeSetFileName` path) $- setTimes (utcTimeToPOSIXSeconds <$> atime, utcTimeToPOSIXSeconds <$> mtime)- where- path' = normalise path -- handle empty paths-- setTimes :: (Maybe POSIXTime, Maybe POSIXTime) -> IO ()-#ifdef mingw32_HOST_OS- setTimes (atime', mtime') =- bracket (openFileHandle path' Win32.gENERIC_WRITE)- Win32.closeHandle $ \ handle ->- maybeWith with (posixToWindowsTime <$> atime') $ \ atime'' ->- maybeWith with (posixToWindowsTime <$> mtime') $ \ mtime'' ->- Win32.failIf_ not "" $- Win32.c_SetFileTime handle nullPtr atime'' mtime''-#elif defined HAVE_UTIMENSAT- setTimes (atime', mtime') =- withFilePath path' $ \ path'' ->- withArray [ maybe utimeOmit toCTimeSpec atime'- , maybe utimeOmit toCTimeSpec mtime' ] $ \ times ->- throwErrnoPathIfMinus1_ "" path' $- c_utimensat c_AT_FDCWD path'' times 0-#else- setTimes (Just atime', Just mtime') = setFileTimes' path' atime' mtime'- setTimes (atime', mtime') = do- (atimeOld, mtimeOld) <- fileTimesFromStatus <$> Posix.getFileStatus path'- setFileTimes' path'- (fromMaybe (utcTimeToPOSIXSeconds atimeOld) atime')- (fromMaybe (utcTimeToPOSIXSeconds mtimeOld) mtime')-- setFileTimes' :: FilePath -> POSIXTime -> POSIXTime -> IO ()-# if MIN_VERSION_unix(2, 7, 0)- setFileTimes' = Posix.setFileTimesHiRes-# else- setFileTimes' pth atime' mtime' =- Posix.setFileTimes pth- (fromInteger (truncate atime'))- (fromInteger (truncate mtime'))-# endif-#endif--#ifdef mingw32_HOST_OS--- | Difference between the Windows and POSIX epochs in units of 100ns.-windowsPosixEpochDifference :: Num a => a-windowsPosixEpochDifference = 116444736000000000---- | Convert from Windows time to POSIX time.-windowsToPosixTime :: Win32.FILETIME -> POSIXTime-windowsToPosixTime (Win32.FILETIME t) =- (fromIntegral t - windowsPosixEpochDifference) / 10000000---- | Convert from POSIX time to Windows time. This is lossy as Windows time--- has a resolution of only 100ns.-posixToWindowsTime :: POSIXTime -> Win32.FILETIME-posixToWindowsTime t = Win32.FILETIME $- truncate (t * 10000000 + windowsPosixEpochDifference)-#endif--#ifdef mingw32_HOST_OS-withFileStatus :: String -> FilePath -> (Ptr CStat -> IO a) -> IO a-withFileStatus loc name f = do- modifyIOError (`ioeSetFileName` name) $- allocaBytes sizeof_stat $ \p ->- withFilePath (fileNameEndClean name) $ \s -> do- throwErrnoIfMinus1Retry_ loc (c_stat s p)- f p--isDirectory :: Ptr CStat -> IO Bool-isDirectory stat = do- mode <- st_mode stat- return (s_isdir mode)--fileNameEndClean :: String -> String-fileNameEndClean name = if isDrive name then addTrailingPathSeparator name- else dropTrailingPathSeparator name-#endif--{- | Returns the current user's home directory.--The directory returned is expected to be writable by the current user,-but note that it isn't generally considered good practice to store-application-specific data here; use 'getXdgDirectory' or-'getAppUserDataDirectory' instead.--On Unix, 'getHomeDirectory' returns the value of the @HOME@-environment variable. On Windows, the system is queried for a-suitable path; a typical path might be @C:\/Users\//\<user\>/@.--The operation may fail with:--* 'UnsupportedOperation'-The operating system has no notion of home directory.--* 'isDoesNotExistError'-The home directory for the current user does not exist, or-cannot be found.--}-getHomeDirectory :: IO FilePath-getHomeDirectory = modifyIOError (`ioeAddLocation` "getHomeDirectory") get- where-#if defined(mingw32_HOST_OS)- get = getFolderPath Win32.cSIDL_PROFILE `catchIOError` \ _ ->- getFolderPath Win32.cSIDL_WINDOWS- getFolderPath what = Win32.sHGetFolderPath nullPtr what nullPtr 0-#else- get = getEnv "HOME"-#endif---- | Special directories for storing user-specific application data,--- configuration, and cache files, as specified by the--- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.------ Note: On Windows, 'XdgData' and 'XdgConfig' map to the same directory.------ @since 1.2.3.0-data XdgDirectory- = XdgData- -- ^ For data files (e.g. images).- -- Defaults to @~\/.local\/share@ and can be- -- overridden by the @XDG_DATA_HOME@ environment variable.- -- On Windows, it is @%APPDATA%@- -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming@).- -- Can be considered as the user-specific equivalent of @\/usr\/share@.- | XdgConfig- -- ^ For configuration files.- -- Defaults to @~\/.config@ and can be- -- overridden by the @XDG_CONFIG_HOME@ environment variable.- -- On Windows, it is @%APPDATA%@- -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming@).- -- Can be considered as the user-specific equivalent of @\/etc@.- | XdgCache- -- ^ For non-essential files (e.g. cache).- -- Defaults to @~\/.cache@ and can be- -- overridden by the @XDG_CACHE_HOME@ environment variable.- -- On Windows, it is @%LOCALAPPDATA%@- -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Local@).- -- Can be considered as the user-specific equivalent of @\/var\/cache@.- deriving (Bounded, Enum, Eq, Ord, Read, Show)---- | Obtain the paths to special directories for storing user-specific--- application data, configuration, and cache files, conforming to the--- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.--- Compared with 'getAppUserDataDirectory', this function provides a more--- fine-grained hierarchy as well as greater flexibility for the user.------ It also works on Windows, although in that case 'XdgData' and 'XdgConfig'--- will map to the same directory.------ The second argument is usually the name of the application. Since it--- will be integrated into the path, it must consist of valid path--- characters.------ Note: The directory may not actually exist, in which case you would need--- to create it with file mode @700@ (i.e. only accessible by the owner).------ @since 1.2.3.0-getXdgDirectory :: XdgDirectory -- ^ which special directory- -> FilePath -- ^ a relative path that is appended- -- to the path; if empty, the base- -- path is returned- -> IO FilePath-getXdgDirectory xdgDir suffix =- modifyIOError (`ioeAddLocation` "getXdgDirectory") $- normalise . (</> suffix) <$>- case xdgDir of- XdgData -> get False "XDG_DATA_HOME" ".local/share"- XdgConfig -> get False "XDG_CONFIG_HOME" ".config"- XdgCache -> get True "XDG_CACHE_HOME" ".cache"- where-#if defined(mingw32_HOST_OS)- get isLocal _ _ = Win32.sHGetFolderPath nullPtr which nullPtr 0- where which | isLocal = win32_cSIDL_LOCAL_APPDATA- | otherwise = Win32.cSIDL_APPDATA-#else- get _ name fallback = do- env <- lookupEnv name- case env of- Nothing -> fallback'- Just path | isRelative path -> fallback'- | otherwise -> return path- where fallback' = (</> fallback) <$> getHomeDirectory---- | Return the value of an environment variable, or 'Nothing' if there is no--- such value. (Equivalent to "lookupEnv" from base-4.6.)-lookupEnv :: String -> IO (Maybe String)-lookupEnv name = do- env <- tryIOErrorType isDoesNotExistError (getEnv name)- case env of- Left _ -> return Nothing- Right value -> return (Just value)-#endif---- | Similar to 'try' but only catches a specify kind of 'IOError' as--- specified by the predicate.-tryIOErrorType :: (IOError -> Bool) -> IO a -> IO (Either IOError a)-tryIOErrorType check action = do- result <- tryIOError action- case result of- Left err -> if check err then return (Left err) else ioError err- Right val -> return (Right val)--specializeErrorString :: String -> (IOError -> Bool) -> IO a -> IO a-specializeErrorString str errType action = do- mx <- tryIOErrorType errType action- case mx of- Left e -> ioError (ioeSetErrorString e str)- Right x -> return x---- | Obtain the path to a special directory for storing user-specific--- application data (traditional Unix location). Newer applications may--- prefer the the XDG-conformant location provided by 'getXdgDirectory'--- (<https://github.com/haskell/directory/issues/6#issuecomment-96521020 migration guide>).------ The argument is usually the name of the application. Since it will be--- integrated into the path, it must consist of valid path characters.------ * On Unix-like systems, the path is @~\/./\<app\>/@.--- * On Windows, the path is @%APPDATA%\//\<app\>/@--- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming\//\<app\>/@)------ Note: the directory may not actually exist, in which case you would need--- to create it. It is expected that the parent directory exists and is--- writable.------ The operation may fail with:------ * 'UnsupportedOperation'--- The operating system has no notion of application-specific data--- directory.------ * 'isDoesNotExistError'--- The home directory for the current user does not exist, or cannot be--- found.----getAppUserDataDirectory :: FilePath -- ^ a relative path that is appended- -- to the path- -> IO FilePath-getAppUserDataDirectory appName = do- modifyIOError (`ioeAddLocation` "getAppUserDataDirectory") $ do-#if defined(mingw32_HOST_OS)- s <- Win32.sHGetFolderPath nullPtr Win32.cSIDL_APPDATA nullPtr 0- return (s++'\\':appName)-#else- path <- getEnv "HOME"- return (path++'/':'.':appName)-#endif--{- | Returns the current user's document directory.--The directory returned is expected to be writable by the current user,-but note that it isn't generally considered good practice to store-application-specific data here; use 'getXdgDirectory' or-'getAppUserDataDirectory' instead.--On Unix, 'getUserDocumentsDirectory' returns the value of the @HOME@-environment variable. On Windows, the system is queried for a-suitable path; a typical path might be @C:\/Users\//\<user\>/\/Documents@.--The operation may fail with:--* 'UnsupportedOperation'-The operating system has no notion of document directory.--* 'isDoesNotExistError'-The document directory for the current user does not exist, or-cannot be found.--}-getUserDocumentsDirectory :: IO FilePath-getUserDocumentsDirectory = do- modifyIOError (`ioeAddLocation` "getUserDocumentsDirectory") $ do-#if defined(mingw32_HOST_OS)- Win32.sHGetFolderPath nullPtr Win32.cSIDL_PERSONAL nullPtr 0-#else- getEnv "HOME"-#endif--{- | Returns the current directory for temporary files.--On Unix, 'getTemporaryDirectory' returns the value of the @TMPDIR@-environment variable or \"\/tmp\" if the variable isn\'t defined.-On Windows, the function checks for the existence of environment variables in-the following order and uses the first path found:--*-TMP environment variable.--*-TEMP environment variable.--*-USERPROFILE environment variable.--*-The Windows directory--The operation may fail with:--* 'UnsupportedOperation'-The operating system has no notion of temporary directory.--The function doesn\'t verify whether the path exists.--}-getTemporaryDirectory :: IO FilePath-getTemporaryDirectory =-#if defined(mingw32_HOST_OS)- Win32.getTemporaryDirectory-#else- getEnv "TMPDIR" `catchIOError` \ err ->- if isDoesNotExistError err then return "/tmp" else ioError err-#endif--ioeAddLocation :: IOError -> String -> IOError-ioeAddLocation e loc = do- ioeSetLocation e newLoc- where- newLoc = loc <> if null oldLoc then "" else ":" <> oldLoc- oldLoc = ioeGetLocation e+-----------------------------------------------------------------------------+-- |+-- Module : System.Directory+-- Copyright : (c) The University of Glasgow 2001+-- License : BSD-style (see the file libraries/base/LICENSE)+--+-- Maintainer : libraries@haskell.org+-- Stability : stable+-- Portability : portable+--+-- System-independent interface to directory manipulation (FilePath API).+--+-----------------------------------------------------------------------------++module System.Directory+ (+ -- $intro++ -- * Actions on directories+ createDirectory+ , createDirectoryIfMissing+ , removeDirectory+ , removeDirectoryRecursive+ , removePathForcibly+ , renameDirectory+ , listDirectory+ , getDirectoryContents+ -- ** Current working directory+ , getCurrentDirectory+ , setCurrentDirectory+ , withCurrentDirectory++ -- * Pre-defined directories+ , getHomeDirectory+ , XdgDirectory(..)+ , getXdgDirectory+ , XdgDirectoryList(..)+ , getXdgDirectoryList+ , getAppUserDataDirectory+ , getUserDocumentsDirectory+ , getTemporaryDirectory++ -- * PATH+ , getExecSearchPath++ -- * Actions on files+ , removeFile+ , renameFile+ , renamePath+ , copyFile+ , copyFileWithMetadata+ , getFileSize++ , canonicalizePath+ , makeAbsolute+ , makeRelativeToCurrentDirectory++ -- * Existence tests+ , doesPathExist+ , doesFileExist+ , doesDirectoryExist++ , findExecutable+ , findExecutables+ , findExecutablesInDirectories+ , findFile+ , findFiles+ , findFileWith+ , findFilesWith+ , exeExtension++ -- * Symbolic links+ , createFileLink+ , createDirectoryLink+ , removeDirectoryLink+ , pathIsSymbolicLink+ , getSymbolicLinkTarget++ -- * Permissions++ -- $permissions++ , Permissions+ , emptyPermissions+ , readable+ , writable+ , executable+ , searchable+ , setOwnerReadable+ , setOwnerWritable+ , setOwnerExecutable+ , setOwnerSearchable++ , getPermissions+ , setPermissions+ , copyPermissions++ -- * Timestamps++ , getAccessTime+ , getModificationTime+ , setAccessTime+ , setModificationTime++ -- * Deprecated+ , isSymbolicLink++ ) where+import Prelude ()+import System.Directory.Internal+import System.Directory.Internal.Prelude+import Data.Time (UTCTime)+import System.OsPath (decodeFS, encodeFS)+import qualified System.Directory.OsPath as D++{- $intro+A directory contains a series of entries, each of which is a named+reference to a file system object (file, directory etc.). Some+entries may be hidden, inaccessible, or have some administrative+function (e.g. @.@ or @..@ under+<http://www.opengroup.org/onlinepubs/009695399 POSIX>), but in+this standard all such entries are considered to form part of the+directory contents. Entries in sub-directories are not, however,+considered to form part of the directory contents.++Each file system object is referenced by a /path/. There is+normally at least one absolute path to each file system object. In+some operating systems, it may also be possible to have paths which+are relative to the current directory.++Unless otherwise documented:++* 'IO' operations in this package may throw any 'IOError'. No other types of+ exceptions shall be thrown.++* The list of possible 'IOErrorType's in the API documentation is not+ exhaustive. The full list may vary by platform and/or evolve over time.++-}++-----------------------------------------------------------------------------+-- Permissions++{- $permissions++directory offers a limited (and quirky) interface for reading and setting file+and directory permissions; see 'getPermissions' and 'setPermissions' for a+discussion of their limitations. Because permissions are very difficult to+implement portably across different platforms, users who wish to do more+sophisticated things with permissions are advised to use other,+platform-specific libraries instead. For example, if you are only interested+in permissions on POSIX-like platforms,+<https://hackage.haskell.org/package/unix/docs/System-Posix-Files.html unix>+offers much more flexibility.++ The 'Permissions' type is used to record whether certain operations are+ permissible on a file\/directory. 'getPermissions' and 'setPermissions'+ get and set these permissions, respectively. Permissions apply both to+ files and directories. For directories, the executable field will be+ 'False', and for files the searchable field will be 'False'. Note that+ directories may be searchable without being readable, if permission has+ been given to use them as part of a path, but not to examine the+ directory contents.++Note that to change some, but not all permissions, a construct on the+following lines must be used.++> makeReadable f = do+> p <- getPermissions f+> setPermissions f (p {readable = True})++-}++emptyPermissions :: Permissions+emptyPermissions = Permissions {+ readable = False,+ writable = False,+ executable = False,+ searchable = False+ }++setOwnerReadable :: Bool -> Permissions -> Permissions+setOwnerReadable b p = p { readable = b }++setOwnerWritable :: Bool -> Permissions -> Permissions+setOwnerWritable b p = p { writable = b }++setOwnerExecutable :: Bool -> Permissions -> Permissions+setOwnerExecutable b p = p { executable = b }++setOwnerSearchable :: Bool -> Permissions -> Permissions+setOwnerSearchable b p = p { searchable = b }++-- | Get the permissions of a file or directory.+--+-- On Windows, the 'writable' permission corresponds to the "read-only"+-- attribute. The 'executable' permission is set if the file extension is of+-- an executable file type. The 'readable' permission is always set.+--+-- On POSIX systems, this returns the result of @access@.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to access the+-- permissions, or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+getPermissions :: FilePath -> IO Permissions+getPermissions = encodeFS >=> D.getPermissions++-- | Set the permissions of a file or directory.+--+-- On Windows, this is only capable of changing the 'writable' permission,+-- which corresponds to the "read-only" attribute. Changing the other+-- permissions has no effect.+--+-- On POSIX systems, this sets the /owner/ permissions.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to set the permissions,+-- or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+setPermissions :: FilePath -> Permissions -> IO ()+setPermissions path p = encodeFS path >>= (`D.setPermissions` p)++-- | Copy the permissions of one file to another. This reproduces the+-- permissions more accurately than using 'getPermissions' followed by+-- 'setPermissions'.+--+-- On Windows, this copies only the read-only attribute.+--+-- On POSIX systems, this is equivalent to @stat@ followed by @chmod@.+copyPermissions :: FilePath -> FilePath -> IO ()+copyPermissions src dst = do+ src' <- encodeFS src+ dst' <- encodeFS dst+ D.copyPermissions src' dst'+++-----------------------------------------------------------------------------+-- Implementation++{- |@'createDirectory' dir@ creates a new directory @dir@ which is+initially empty, or as near to empty as the operating system+allows.++The operation may fail with:++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES]@++* 'isAlreadyExistsError'+The operand refers to a directory that already exists.+@ [EEXIST]@++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+The operand is not a valid directory name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+There is no path to the directory.+@[ENOENT, ENOTDIR]@++* 'System.IO.isFullError'+Insufficient resources (virtual memory, process file descriptors,+physical disk space, etc.) are available to perform the operation.+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@++* @InappropriateType@+The path refers to an existing non-directory object.+@[EEXIST]@++-}++createDirectory :: FilePath -> IO ()+createDirectory = encodeFS >=> D.createDirectory++-- | @'createDirectoryIfMissing' parents dir@ creates a new directory+-- @dir@ if it doesn\'t exist. If the first argument is 'True'+-- the function will also create all parent directories if they are missing.+createDirectoryIfMissing+ :: Bool -- ^ Create its parents too?+ -> FilePath -- ^ The path to the directory you want to make+ -> IO ()+createDirectoryIfMissing cp = encodeFS >=> D.createDirectoryIfMissing cp+++{- | @'removeDirectory' dir@ removes an existing directory /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+for an implementation to partially remove a directory unless the+entire directory is removed. A conformant implementation need not+support directory removal in all situations (e.g. removal of the root+directory).++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+The operand is not a valid directory name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The directory does not exist.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY, ENOTEMPTY, EEXIST]@++* @UnsupportedOperation@+The implementation does not support removal in this situation.+@[EINVAL]@++* @InappropriateType@+The operand refers to an existing non-directory object.+@[ENOTDIR]@++-}++removeDirectory :: FilePath -> IO ()+removeDirectory = encodeFS >=> D.removeDirectory++-- | @'removeDirectoryRecursive' dir@ removes an existing directory /dir/+-- together with its contents and subdirectories. Within this directory,+-- symbolic links are removed without affecting their targets.+--+-- On Windows, the operation fails if /dir/ is a directory symbolic link.+--+-- This operation is reported to be flaky on Windows so retry logic may+-- be advisable. See: https://github.com/haskell/directory/pull/108+removeDirectoryRecursive :: FilePath -> IO ()+removeDirectoryRecursive = encodeFS >=> D.removeDirectoryRecursive++-- | Removes a file or directory at /path/ together with its contents and+-- subdirectories. Symbolic links are removed without affecting their+-- targets. If the path does not exist, nothing happens.+--+-- Unlike other removal functions, this function will also attempt to delete+-- files marked as read-only or otherwise made unremovable due to permissions.+-- As a result, if the removal is incomplete, the permissions or attributes on+-- the remaining files may be altered. If there are hard links in the+-- directory, then permissions on all related hard links may be altered.+--+-- If an entry within the directory vanishes while @removePathForcibly@ is+-- running, it is silently ignored.+--+-- If an exception occurs while removing an entry, @removePathForcibly@ will+-- still try to remove as many entries as it can before failing with an+-- exception. The first exception that it encountered is re-thrown.+--+-- @since 1.2.7.0+removePathForcibly :: FilePath -> IO ()+removePathForcibly = encodeFS >=> D.removePathForcibly++{- |'removeFile' /file/ removes the directory entry for an existing file+/file/, where /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+use by other processes).++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+The operand is not a valid file name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The file does not exist.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY]@++* @InappropriateType@+The operand refers to an existing directory.+@[EPERM, EINVAL]@++-}++removeFile :: FilePath -> IO ()+removeFile = encodeFS >=> D.removeFile++{- |@'renameDirectory' old new@ changes the name of an existing+directory from /old/ to /new/. If the /new/ directory+already exists, it is atomically replaced by the /old/ directory.+If the /new/ directory is neither the /old/ directory nor an+alias of the /old/ directory, it is removed as if by+'removeDirectory'. A conformant implementation need not support+renaming directories in all situations (e.g. renaming to an existing+directory, or across different physical devices), but the constraints+must be documented.++On Win32 platforms, @renameDirectory@ fails if the /new/ directory already+exists.++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+Either operand is not a valid directory name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The original directory does not exist, or there is no path to the target.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* 'System.IO.isFullError'+Insufficient resources are available to perform the operation.+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY, ENOTEMPTY, EEXIST]@++* @UnsupportedOperation@+The implementation does not support renaming in this situation.+@[EINVAL, EXDEV]@++* @InappropriateType@+Either path refers to an existing non-directory object.+@[ENOTDIR, EISDIR]@++-}++renameDirectory :: FilePath -> FilePath -> IO ()+renameDirectory opath npath = do+ opath' <- encodeFS opath+ npath' <- encodeFS npath+ D.renameDirectory opath' npath'++{- |@'renameFile' old new@ changes the name of an existing file system+object from /old/ to /new/. If the /new/ object already exists, it is+replaced by the /old/ object. Neither path may refer to an existing+directory.++A conformant implementation need not support renaming files in all situations+(e.g. renaming across different physical devices), but the constraints must be+documented. On Windows, this does not support renaming across different physical+devices; if you are looking to do so, consider using 'copyFileWithMetadata' and+'removeFile'.++On Windows, this calls @MoveFileEx@ with @MOVEFILE_REPLACE_EXISTING@ set,+which is not guaranteed to be atomic+(<https://github.com/haskell/directory/issues/109>).++On other platforms, this operation is atomic.++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+Either operand is not a valid file name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The original file does not exist, or there is no path to the target.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* 'System.IO.isFullError'+Insufficient resources are available to perform the operation.+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY]@++* @UnsupportedOperation@+The implementation does not support renaming in this situation.+@[EXDEV]@++* @InappropriateType@+Either path refers to an existing directory.+@[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@++-}++renameFile :: FilePath -> FilePath -> IO ()+renameFile opath npath = do+ opath' <- encodeFS opath+ npath' <- encodeFS npath+ D.renameFile opath' npath'++-- | Rename a file or directory. If the destination path already exists, it+-- is replaced atomically. The destination path must not point to an existing+-- directory. A conformant implementation need not support renaming files in+-- all situations (e.g. renaming across different physical devices), but the+-- constraints must be documented.+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * @InvalidArgument@+-- Either operand is not a valid file name.+-- @[ENAMETOOLONG, ELOOP]@+--+-- * 'isDoesNotExistError'+-- The original file does not exist, or there is no path to the target.+-- @[ENOENT, ENOTDIR]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EROFS, EACCES, EPERM]@+--+-- * 'System.IO.isFullError'+-- Insufficient resources are available to perform the operation.+-- @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@+--+-- * @UnsatisfiedConstraints@+-- Implementation-dependent constraints are not satisfied.+-- @[EBUSY]@+--+-- * @UnsupportedOperation@+-- The implementation does not support renaming in this situation.+-- @[EXDEV]@+--+-- * @InappropriateType@+-- Either the destination path refers to an existing directory, or one of the+-- parent segments in the destination path is not a directory.+-- @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@+--+-- @since 1.2.7.0+renamePath :: FilePath -- ^ Old path+ -> FilePath -- ^ New path+ -> IO ()+renamePath opath npath = do+ opath' <- encodeFS opath+ npath' <- encodeFS npath+ D.renamePath opath' npath'++-- | Copy a file with its permissions. If the destination file already exists,+-- it is replaced atomically. Neither path may refer to an existing+-- directory. No exceptions are thrown if the permissions could not be+-- copied.+copyFile :: FilePath -- ^ Source filename+ -> FilePath -- ^ Destination filename+ -> IO ()+copyFile fromFPath toFPath = do+ fromFPath' <- encodeFS fromFPath+ toFPath' <- encodeFS toFPath+ D.copyFile fromFPath' toFPath'++-- | Copy a file with its associated metadata. If the destination file+-- already exists, it is overwritten. There is no guarantee of atomicity in+-- the replacement of the destination file. Neither path may refer to an+-- existing directory. If the source and/or destination are symbolic links,+-- the copy is performed on the targets of the links.+--+-- On Windows, it behaves like the Win32 function+-- <https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851.aspx CopyFile>,+-- which copies various kinds of metadata including file attributes and+-- security resource properties.+--+-- On Unix-like systems, permissions, access time, and modification time are+-- preserved. If possible, the owner and group are also preserved. Note that+-- the very act of copying can change the access time of the source file,+-- hence the access times of the two files may differ after the operation+-- completes.+--+-- @since 1.2.6.0+copyFileWithMetadata :: FilePath -- ^ Source file+ -> FilePath -- ^ Destination file+ -> IO ()+copyFileWithMetadata src dst = do+ src' <- encodeFS src+ dst' <- encodeFS dst+ D.copyFileWithMetadata src' dst'+++-- | Make a path absolute, normalize the path, and remove as many indirections+-- from it as possible. Any trailing path separators are discarded via+-- 'dropTrailingPathSeparator'. Additionally, on Windows the letter case of+-- the path is canonicalized.+--+-- __Note__: This function is a very big hammer. If you only need an absolute+-- path, 'makeAbsolute' is sufficient for removing dependence on the current+-- working directory.+--+-- Indirections include the two special directories @.@ and @..@, as well as+-- any symbolic links (and junction points on Windows). The input path need+-- not point to an existing file or directory. Canonicalization is performed+-- on the longest prefix of the path that points to an existing file or+-- directory. The remaining portion of the path that does not point to an+-- existing file or directory will still be normalized, but case+-- canonicalization and indirection removal are skipped as they are impossible+-- to do on a nonexistent path.+--+-- Most programs should not worry about the canonicity of a path. In+-- particular, despite the name, the function does not truly guarantee+-- canonicity of the returned path due to the presence of hard links, mount+-- points, etc.+--+-- If the path points to an existing file or directory, then the output path+-- shall also point to the same file or directory, subject to the condition+-- that the relevant parts of the file system do not change while the function+-- is still running. In other words, the function is definitively not atomic.+-- The results can be utterly wrong if the portions of the path change while+-- this function is running.+--+-- Since some indirections (symbolic links on all systems, @..@ on non-Windows+-- systems, and junction points on Windows) are dependent on the state of the+-- existing filesystem, the function can only make a conservative attempt by+-- removing such indirections from the longest prefix of the path that still+-- points to an existing file or directory.+--+-- Note that on Windows parent directories @..@ are always fully expanded+-- before the symbolic links, as consistent with the rest of the Windows API+-- (such as @GetFullPathName@). In contrast, on POSIX systems parent+-- directories @..@ are expanded alongside symbolic links from left to right.+-- To put this more concretely: if @L@ is a symbolic link for @R/P@, then on+-- Windows @L\\..@ refers to @.@, whereas on other operating systems @L/..@+-- refers to @R@.+--+-- Similar to 'System.FilePath.normalise', passing an empty path is equivalent+-- to passing the current directory.+--+-- @canonicalizePath@ can resolve at least 64 indirections in a single path,+-- more than what is supported by most operating systems. Therefore, it may+-- return the fully resolved path even though the operating system itself+-- would have long given up.+--+-- On Windows XP or earlier systems, junction expansion is not performed due+-- to their lack of @GetFinalPathNameByHandle@.+--+-- /Changes since 1.2.3.0:/ The function has been altered to be more robust+-- and has the same exception behavior as 'makeAbsolute'.+--+-- /Changes since 1.3.0.0:/ The function no longer preserves the trailing path+-- separator. File symbolic links that appear in the middle of a path are+-- properly dereferenced. Case canonicalization and symbolic link expansion+-- are now performed on Windows.+--+canonicalizePath :: FilePath -> IO FilePath+canonicalizePath = encodeFS >=> D.canonicalizePath >=> decodeFS++-- | Convert a path into an absolute path. If the given path is relative, the+-- current directory is prepended and then the combined result is normalized.+-- If the path is already absolute, the path is simply normalized. The+-- function preserves the presence or absence of the trailing path separator+-- unless the path refers to the root directory @/@.+--+-- If the path is already absolute, the operation never fails. Otherwise, the+-- operation may fail with the same exceptions as 'getCurrentDirectory'.+--+-- @since 1.2.2.0+--+makeAbsolute :: FilePath -> IO FilePath+makeAbsolute = encodeFS >=> D.makeAbsolute >=> decodeFS++-- | Construct a path relative to the current directory, similar to+-- 'makeRelative'.+--+-- The operation may fail with the same exceptions as 'getCurrentDirectory'.+makeRelativeToCurrentDirectory :: FilePath -> IO FilePath+makeRelativeToCurrentDirectory =+ encodeFS >=> D.makeRelativeToCurrentDirectory >=> decodeFS++-- | Given the name or path of an executable file, 'findExecutable' searches+-- for such a file in a list of system-defined locations, which generally+-- includes @PATH@ and possibly more. The full path to the executable is+-- returned if found. For example, @(findExecutable \"ghc\")@ would normally+-- give you the path to GHC.+--+-- The path returned by @'findExecutable' name@ corresponds to the program+-- that would be executed by+-- @<http://hackage.haskell.org/package/process/docs/System-Process.html#v:createProcess createProcess>@+-- when passed the same string (as a @RawCommand@, not a @ShellCommand@),+-- provided that @name@ is not a relative path with more than one segment.+--+-- On Windows, 'findExecutable' calls the Win32 function+-- @<https://msdn.microsoft.com/en-us/library/aa365527.aspx SearchPath>@,+-- which may search other places before checking the directories in the @PATH@+-- environment variable. Where it actually searches depends on registry+-- settings, but notably includes the directory containing the current+-- executable.+--+-- On non-Windows platforms, the behavior is equivalent to 'findFileWith'+-- using the search directories from the @PATH@ environment variable and+-- testing each file for executable permissions. Details can be found in the+-- documentation of 'findFileWith'.+findExecutable :: String -> IO (Maybe FilePath)+findExecutable = encodeFS >=> D.findExecutable >=> (`for` decodeFS)++-- | Search for executable files in a list of system-defined locations, which+-- generally includes @PATH@ and possibly more.+--+-- On Windows, this /only returns the first occurrence/, if any. Its behavior+-- is therefore equivalent to 'findExecutable'.+--+-- On non-Windows platforms, the behavior is equivalent to+-- 'findExecutablesInDirectories' using the search directories from the @PATH@+-- environment variable. Details can be found in the documentation of+-- 'findExecutablesInDirectories'.+--+-- @since 1.2.2.0+findExecutables :: String -> IO [FilePath]+findExecutables = encodeFS >=> D.findExecutables >=> (`for` decodeFS)++-- | Given a name or path, 'findExecutable' appends the 'exeExtension' to the+-- query and searches for executable files in the list of given search+-- directories and returns all occurrences.+--+-- The behavior is equivalent to 'findFileWith' using the given search+-- directories and testing each file for executable permissions. Details can+-- be found in the documentation of 'findFileWith'.+--+-- Unlike other similarly named functions, 'findExecutablesInDirectories' does+-- not use @SearchPath@ from the Win32 API. The behavior of this function on+-- Windows is therefore equivalent to those on non-Windows platforms.+--+-- @since 1.2.4.0+findExecutablesInDirectories :: [FilePath] -> String -> IO [FilePath]+findExecutablesInDirectories path binary = do+ path' <- for path encodeFS+ binary' <- encodeFS binary+ D.findExecutablesInDirectories path' binary'+ >>= (`for` decodeFS)++-- | Search through the given list of directories for the given file.+--+-- The behavior is equivalent to 'findFileWith', returning only the first+-- occurrence. Details can be found in the documentation of 'findFileWith'.+findFile :: [FilePath] -> String -> IO (Maybe FilePath)+findFile = findFileWith (\ _ -> pure True)++-- | Search through the given list of directories for the given file and+-- returns all paths where the given file exists.+--+-- The behavior is equivalent to 'findFilesWith'. Details can be found in the+-- documentation of 'findFilesWith'.+--+-- @since 1.2.1.0+findFiles :: [FilePath] -> String -> IO [FilePath]+findFiles = findFilesWith (\ _ -> pure True)++-- | Search through a given list of directories for a file that has the given+-- name and satisfies the given predicate and return the path of the first+-- occurrence. The directories are checked in a left-to-right order.+--+-- This is essentially a more performant version of 'findFilesWith' that+-- always returns the first result, if any. Details can be found in the+-- documentation of 'findFilesWith'.+--+-- @since 1.2.6.0+findFileWith+ :: (FilePath -> IO Bool) -> [FilePath] -> String -> IO (Maybe FilePath)+findFileWith f ds name = do+ ds' <- for ds encodeFS+ name' <- encodeFS name+ D.findFileWith (decodeFS >=> f) ds' name'+ >>= (`for` decodeFS)++-- | @findFilesWith predicate dirs name@ searches through the list of+-- directories (@dirs@) for files that have the given @name@ and satisfy the+-- given @predicate@ and returns the paths of those files. The directories+-- are checked in a left-to-right order and the paths are returned in the same+-- order.+--+-- If the @name@ is a relative path, then for every search directory @dir@,+-- the function checks whether @dir '</>' name@ exists and satisfies the+-- predicate. If so, @dir '</>' name@ is returned as one of the results. In+-- other words, the returned paths can be either relative or absolute+-- depending on the search directories were used. If there are no search+-- directories, no results are ever returned.+--+-- If the @name@ is an absolute path, then the function will return a single+-- result if the file exists and satisfies the predicate and no results+-- otherwise. This is irrespective of what search directories were given.+--+-- @since 1.2.1.0+findFilesWith :: (FilePath -> IO Bool) -> [FilePath] -> String -> IO [FilePath]+findFilesWith f ds name = do+ ds' <- for ds encodeFS+ name' <- encodeFS name+ res <- D.findFilesWith (decodeFS >=> f) ds' name'+ for res decodeFS++-- | Filename extension for executable files (including the dot if any)+-- (usually @\"\"@ on POSIX systems and @\".exe\"@ on Windows or OS\/2).+--+-- @since 1.2.4.0+exeExtension :: String+exeExtension = so D.exeExtension++-- | Similar to 'listDirectory', but always includes the special entries (@.@+-- and @..@). (This applies to Windows as well.)+--+-- The operation may fail with the same exceptions as 'listDirectory'.+getDirectoryContents :: FilePath -> IO [FilePath]+getDirectoryContents = encodeFS >=> D.getDirectoryContents >=> (`for` decodeFS)++-- | @'listDirectory' dir@ returns a list of /all/ entries in /dir/ without+-- the special entries (@.@ and @..@).+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * @InvalidArgument@+-- The operand is not a valid directory name.+-- @[ENAMETOOLONG, ELOOP]@+--+-- * 'isDoesNotExistError'+-- The directory does not exist.+-- @[ENOENT, ENOTDIR]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EACCES]@+--+-- * 'System.IO.isFullError'+-- Insufficient resources are available to perform the operation.+-- @[EMFILE, ENFILE]@+--+-- * @InappropriateType@+-- The path refers to an existing non-directory object.+-- @[ENOTDIR]@+--+-- @since 1.2.5.0+--+listDirectory :: FilePath -> IO [FilePath]+listDirectory = encodeFS >=> D.listDirectory >=> (`for` decodeFS)++-- | Obtain the current working directory as an absolute path.+--+-- In a multithreaded program, the current working directory is a global state+-- shared among all threads of the process. Therefore, when performing+-- filesystem operations from multiple threads, it is highly recommended to+-- use absolute rather than relative paths (see: 'makeAbsolute').+--+-- Note that 'getCurrentDirectory' is not guaranteed to return the same path+-- received by 'setCurrentDirectory'. On POSIX systems, the path returned will+-- always be fully dereferenced (not contain any symbolic links). For more+-- information, refer to the documentation of+-- <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html getcwd>.+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * 'isDoesNotExistError'+-- There is no path referring to the working directory.+-- @[EPERM, ENOENT, ESTALE...]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EACCES]@+--+-- * 'System.IO.isFullError'+-- Insufficient resources are available to perform the operation.+--+-- * @UnsupportedOperation@+-- The operating system has no notion of current working directory.+--+getCurrentDirectory :: IO FilePath+getCurrentDirectory = D.getCurrentDirectory >>= decodeFS++-- | Change the working directory to the given path.+--+-- In a multithreaded program, the current working directory is a global state+-- shared among all threads of the process. Therefore, when performing+-- filesystem operations from multiple threads, it is highly recommended to+-- use absolute rather than relative paths (see: 'makeAbsolute').+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * @InvalidArgument@+-- The operand is not a valid directory name.+-- @[ENAMETOOLONG, ELOOP]@+--+-- * 'isDoesNotExistError'+-- The directory does not exist.+-- @[ENOENT, ENOTDIR]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EACCES]@+--+-- * @UnsupportedOperation@+-- The operating system has no notion of current working directory, or the+-- working directory cannot be dynamically changed.+--+-- * @InappropriateType@+-- The path refers to an existing non-directory object.+-- @[ENOTDIR]@+--+setCurrentDirectory :: FilePath -> IO ()+setCurrentDirectory = encodeFS >=> D.setCurrentDirectory++-- | Run an 'IO' action with the given working directory and restore the+-- original working directory afterwards, even if the given action fails due+-- to an exception.+--+-- The operation may fail with the same exceptions as 'getCurrentDirectory'+-- and 'setCurrentDirectory'.+--+-- @since 1.2.3.0+--+withCurrentDirectory :: FilePath -- ^ Directory to execute in+ -> IO a -- ^ Action to be executed+ -> IO a+withCurrentDirectory dir action =+ encodeFS dir >>= (`D.withCurrentDirectory` action)++-- | Obtain the size of a file in bytes.+--+-- @since 1.2.7.0+getFileSize :: FilePath -> IO Integer+getFileSize = encodeFS >=> D.getFileSize++-- | Test whether the given path points to an existing filesystem object. If+-- the user lacks necessary permissions to search the parent directories, this+-- function may return false even if the file does actually exist.+--+-- @since 1.2.7.0+doesPathExist :: FilePath -> IO Bool+doesPathExist = encodeFS >=> D.doesPathExist++{- |The operation 'doesDirectoryExist' returns 'True' if the argument file+exists and is either a directory or a symbolic link to a directory,+and 'False' otherwise.+-}++doesDirectoryExist :: FilePath -> IO Bool+doesDirectoryExist = encodeFS >=> D.doesDirectoryExist++{- |The operation 'doesFileExist' returns 'True'+if the argument file exists and is not a directory, and 'False' otherwise.+-}++doesFileExist :: FilePath -> IO Bool+doesFileExist = encodeFS >=> D.doesFileExist+++-- | Create a /file/ symbolic link. The target path can be either absolute or+-- relative and need not refer to an existing file. The order of arguments+-- follows the POSIX convention.+--+-- To remove an existing file symbolic link, use 'removeFile'.+--+-- Although the distinction between /file/ symbolic links and /directory/+-- symbolic links does not exist on POSIX systems, on Windows this is an+-- intrinsic property of every symbolic link and cannot be changed without+-- recreating the link. A file symbolic link that actually points to a+-- directory will fail to dereference and vice versa. Moreover, creating+-- symbolic links on Windows may require privileges unavailable to users+-- outside the Administrators group. Portable programs that use symbolic+-- links should take both into consideration.+--+-- On Windows, the function is implemented using @CreateSymbolicLink@. Since+-- 1.3.3.0, the @SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE@ flag is included+-- if supported by the operating system. On POSIX, the function uses @symlink@+-- and is therefore atomic.+--+-- Windows-specific errors: This operation may fail with 'permissionErrorType'+-- if the user lacks the privileges to create symbolic links. It may also+-- fail with 'illegalOperationErrorType' if the file system does not support+-- symbolic links.+--+-- @since 1.3.1.0+createFileLink+ :: FilePath -- ^ path to the target file+ -> FilePath -- ^ path of the link to be created+ -> IO ()+createFileLink target link = do+ target' <- encodeFS target+ link' <- encodeFS link+ D.createFileLink target' link'+++-- | Create a /directory/ symbolic link. The target path can be either+-- absolute or relative and need not refer to an existing directory. The+-- order of arguments follows the POSIX convention.+--+-- To remove an existing directory symbolic link, use 'removeDirectoryLink'.+--+-- Although the distinction between /file/ symbolic links and /directory/+-- symbolic links does not exist on POSIX systems, on Windows this is an+-- intrinsic property of every symbolic link and cannot be changed without+-- recreating the link. A file symbolic link that actually points to a+-- directory will fail to dereference and vice versa. Moreover, creating+-- symbolic links on Windows may require privileges unavailable to users+-- outside the Administrators group. Portable programs that use symbolic+-- links should take both into consideration.+--+-- On Windows, the function is implemented using @CreateSymbolicLink@ with+-- @SYMBOLIC_LINK_FLAG_DIRECTORY@. Since 1.3.3.0, the+-- @SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE@ flag is also included if+-- supported by the operating system. On POSIX, this is an alias for+-- 'createFileLink' and is therefore atomic.+--+-- Windows-specific errors: This operation may fail with 'permissionErrorType'+-- if the user lacks the privileges to create symbolic links. It may also+-- fail with 'illegalOperationErrorType' if the file system does not support+-- symbolic links.+--+-- @since 1.3.1.0+createDirectoryLink+ :: FilePath -- ^ path to the target directory+ -> FilePath -- ^ path of the link to be created+ -> IO ()+createDirectoryLink target link = do+ target' <- encodeFS target+ link' <- encodeFS link+ D.createDirectoryLink target' link'++-- | Remove an existing /directory/ symbolic link.+--+-- On Windows, this is an alias for 'removeDirectory'. On POSIX systems, this+-- is an alias for 'removeFile'.+--+-- See also: 'removeFile', which can remove an existing /file/ symbolic link.+--+-- @since 1.3.1.0+removeDirectoryLink :: FilePath -> IO ()+removeDirectoryLink = encodeFS >=> D.removeDirectoryLink++-- | Check whether an existing @path@ is a symbolic link. If @path@ is a+-- regular file or directory, 'False' is returned. If @path@ does not exist+-- or is otherwise inaccessible, an exception is thrown (see below).+--+-- On Windows, this checks for @FILE_ATTRIBUTE_REPARSE_POINT@. In addition to+-- symbolic links, the function also returns true on junction points. On+-- POSIX systems, this checks for @S_IFLNK@.+--+-- The operation may fail with:+--+-- * 'isDoesNotExistError' if the symbolic link does not exist; or+--+-- * 'isPermissionError' if the user is not permitted to read the symbolic+-- link.+--+-- @since 1.3.0.0+pathIsSymbolicLink :: FilePath -> IO Bool+pathIsSymbolicLink = encodeFS >=> D.pathIsSymbolicLink++{-# DEPRECATED isSymbolicLink "Use 'pathIsSymbolicLink' instead" #-}+isSymbolicLink :: FilePath -> IO Bool+isSymbolicLink = pathIsSymbolicLink++-- | Retrieve the target path of either a file or directory symbolic link.+-- The returned path may not be absolute, may not exist, and may not even be a+-- valid path.+--+-- On Windows systems, this calls @DeviceIoControl@ with+-- @FSCTL_GET_REPARSE_POINT@. In addition to symbolic links, the function+-- also works on junction points. On POSIX systems, this calls @readlink@.+--+-- Windows-specific errors: This operation may fail with+-- 'illegalOperationErrorType' if the file system does not support symbolic+-- links.+--+-- @since 1.3.1.0+getSymbolicLinkTarget :: FilePath -> IO FilePath+getSymbolicLinkTarget = encodeFS >=> D.getSymbolicLinkTarget >=> decodeFS++-- | Obtain the time at which the file or directory was last accessed.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to read+-- the access time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- Caveat for POSIX systems: This function returns a timestamp with sub-second+-- resolution only if this package is compiled against @unix-2.6.0.0@ or later+-- and the underlying filesystem supports them.+--+-- @since 1.2.3.0+--+getAccessTime :: FilePath -> IO UTCTime+getAccessTime = encodeFS >=> D.getAccessTime++-- | Obtain the time at which the file or directory was last modified.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to read+-- the modification time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- Caveat for POSIX systems: This function returns a timestamp with sub-second+-- resolution only if this package is compiled against @unix-2.6.0.0@ or later+-- and the underlying filesystem supports them.+--+getModificationTime :: FilePath -> IO UTCTime+getModificationTime = encodeFS >=> D.getModificationTime++-- | Change the time at which the file or directory was last accessed.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to alter the+-- access time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- Some caveats for POSIX systems:+--+-- * Not all systems support @utimensat@, in which case the function can only+-- emulate the behavior by reading the modification time and then setting+-- both the access and modification times together. On systems where+-- @utimensat@ is supported, the access time is set atomically with+-- nanosecond precision.+--+-- * If compiled against a version of @unix@ prior to @2.7.0.0@, the function+-- would not be able to set timestamps with sub-second resolution. In this+-- case, there would also be loss of precision in the modification time.+--+-- @since 1.2.3.0+--+setAccessTime :: FilePath -> UTCTime -> IO ()+setAccessTime path atime = encodeFS path >>= (`D.setAccessTime` atime)++-- | Change the time at which the file or directory was last modified.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to alter the+-- modification time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- * 'InvalidArgument' on FAT32 file system if the time is before+-- DOS Epoch (1 January 1980).+--+-- Some caveats for POSIX systems:+--+-- * Not all systems support @utimensat@, in which case the function can only+-- emulate the behavior by reading the access time and then setting both the+-- access and modification times together. On systems where @utimensat@ is+-- supported, the modification time is set atomically with nanosecond+-- precision.+--+-- * If compiled against a version of @unix@ prior to @2.7.0.0@, the function+-- would not be able to set timestamps with sub-second resolution. In this+-- case, there would also be loss of precision in the access time.+--+-- @since 1.2.3.0+--+setModificationTime :: FilePath -> UTCTime -> IO ()+setModificationTime path mtime =+ encodeFS path >>= (`D.setModificationTime` mtime)++{- | Returns the current user's home directory.++The directory returned is expected to be writable by the current user,+but note that it isn't generally considered good practice to store+application-specific data here; use 'getXdgDirectory' or+'getAppUserDataDirectory' instead.++On Unix, 'getHomeDirectory' behaves as follows:++* Returns $HOME env variable if set (including to an empty string).+* Otherwise uses home directory returned by @getpwuid_r@ using the UID of the+ current process' user. This basically reads the @\/etc\/passwd@ file. An+ empty home directory field is considered valid.++On Windows, the system is queried for a suitable path; a typical path might be+@C:\/Users\//\<user\>/@.++The operation may fail with:++* @UnsupportedOperation@+The operating system has no notion of home directory.++* 'isDoesNotExistError'+The home directory for the current user does not exist, or+cannot be found.+-}+getHomeDirectory :: IO FilePath+getHomeDirectory = D.getHomeDirectory >>= decodeFS++-- | Obtain the paths to special directories for storing user-specific+-- application data, configuration, and cache files, conforming to the+-- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.+-- Compared with 'getAppUserDataDirectory', this function provides a more+-- fine-grained hierarchy as well as greater flexibility for the user.+--+-- On Windows, 'XdgData' and 'XdgConfig' usually map to the same directory+-- unless overridden.+--+-- Refer to the docs of 'XdgDirectory' for more details.+--+-- The second argument is usually the name of the application. Since it+-- will be integrated into the path, it must consist of valid path+-- characters. Note: if the second argument is an absolute path, it will+-- just return the second argument.+--+-- Note: The directory may not actually exist, in which case you would need+-- to create it with file mode @700@ (i.e. only accessible by the owner).+--+-- As of 1.3.5.0, the environment variable is ignored if set to a relative+-- path, per revised XDG Base Directory Specification. See+-- <https://github.com/haskell/directory/issues/100 #100>.+--+-- @since 1.2.3.0+getXdgDirectory :: XdgDirectory -- ^ which special directory+ -> FilePath -- ^ a relative path that is appended+ -- to the path; if empty, the base+ -- path is returned+ -> IO FilePath+getXdgDirectory xdgDir = encodeFS >=> D.getXdgDirectory xdgDir >=> decodeFS++-- | Similar to 'getXdgDirectory' but retrieves the entire list of XDG+-- directories.+--+-- On Windows, 'XdgDataDirs' and 'XdgConfigDirs' usually map to the same list+-- of directories unless overridden.+--+-- Refer to the docs of 'XdgDirectoryList' for more details.+getXdgDirectoryList :: XdgDirectoryList -- ^ which special directory list+ -> IO [FilePath]+getXdgDirectoryList = D.getXdgDirectoryList >=> (`for` decodeFS)++-- | Obtain the path to a special directory for storing user-specific+-- application data (traditional Unix location). Newer applications may+-- prefer the the XDG-conformant location provided by 'getXdgDirectory'+-- (<https://github.com/haskell/directory/issues/6#issuecomment-96521020 migration guide>).+--+-- The argument is usually the name of the application. Since it will be+-- integrated into the path, it must consist of valid path characters.+--+-- * On Unix-like systems, the path is @~\/./\<app\>/@.+-- * On Windows, the path is @%APPDATA%\//\<app\>/@+-- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming\//\<app\>/@)+--+-- Note: the directory may not actually exist, in which case you would need+-- to create it. It is expected that the parent directory exists and is+-- writable.+--+-- The operation may fail with:+--+-- * @UnsupportedOperation@+-- The operating system has no notion of application-specific data+-- directory.+--+-- * 'isDoesNotExistError'+-- The home directory for the current user does not exist, or cannot be+-- found.+--+getAppUserDataDirectory :: FilePath -- ^ a relative path that is appended+ -- to the path+ -> IO FilePath+getAppUserDataDirectory = encodeFS >=> D.getAppUserDataDirectory >=>decodeFS++{- | Returns the current user's document directory.++The directory returned is expected to be writable by the current user,+but note that it isn't generally considered good practice to store+application-specific data here; use 'getXdgDirectory' or+'getAppUserDataDirectory' instead.++On Unix, 'getUserDocumentsDirectory' returns the value of the @HOME@+environment variable. On Windows, the system is queried for a+suitable path; a typical path might be @C:\/Users\//\<user\>/\/Documents@.++The operation may fail with:++* @UnsupportedOperation@+The operating system has no notion of document directory.++* 'isDoesNotExistError'+The document directory for the current user does not exist, or+cannot be found.+-}+getUserDocumentsDirectory :: IO FilePath+getUserDocumentsDirectory = D.getUserDocumentsDirectory >>= decodeFS++{- | Returns the current directory for temporary files.++On Unix, 'getTemporaryDirectory' returns the value of the @TMPDIR@+environment variable or \"\/tmp\" if the variable isn\'t defined.+On Windows, the function checks for the existence of environment variables in+the following order and uses the first path found:++*+TMP environment variable.++*+TEMP environment variable.++*+USERPROFILE environment variable.++*+The Windows directory++The operation may fail with:++* @UnsupportedOperation@+The operating system has no notion of temporary directory.++The function doesn\'t verify whether the path exists.+-}+getTemporaryDirectory :: IO FilePath+getTemporaryDirectory = D.getTemporaryDirectory >>= decodeFS++-- | Get the contents of the @PATH@ environment variable.+getExecSearchPath :: IO [FilePath]+getExecSearchPath = D.getExecSearchPath >>= (`for` decodeFS)
System/Directory/Internal.hs view
@@ -1,28 +1,30 @@ {-# LANGUAGE CPP #-}-{-# OPTIONS_HADDOCK hide #-}+{-# OPTIONS_HADDOCK not-home #-}+-- |+-- Stability: unstable+-- Portability: unportable+--+-- Internal modules are always subject to change from version to version.+-- The contents of this module are also platform-dependent, hence what is+-- shown in the Hackage documentation may differ from what is actually+-- available on your system.+ #include <HsDirectoryConfig.h> module System.Directory.Internal- ( module System.Directory.Internal.Config--#ifdef HAVE_UTIMENSAT- , module System.Directory.Internal.C_utimensat-#endif+ ( module System.Directory.Internal.Common -#ifdef mingw32_HOST_OS+#if defined(mingw32_HOST_OS) , module System.Directory.Internal.Windows #else , module System.Directory.Internal.Posix #endif ) where-import System.Directory.Internal.Config -#ifdef HAVE_UTIMENSAT-import System.Directory.Internal.C_utimensat-#endif+import System.Directory.Internal.Common -#ifdef mingw32_HOST_OS+#if defined(mingw32_HOST_OS) import System.Directory.Internal.Windows #else import System.Directory.Internal.Posix
System/Directory/Internal/C_utimensat.hsc view
@@ -1,3 +1,5 @@+{-# LANGUAGE CApiFFI #-}+ module System.Directory.Internal.C_utimensat where #include <HsDirectoryConfig.h> #ifdef HAVE_UTIMENSAT@@ -10,17 +12,16 @@ #ifdef HAVE_SYS_STAT_H # include <sys/stat.h> #endif-#include <System/Directory/Internal/utility.h> import Prelude () import System.Directory.Internal.Prelude import Data.Time.Clock.POSIX (POSIXTime)+import qualified System.Posix as Posix data CTimeSpec = CTimeSpec EpochTime CLong instance Storable CTimeSpec where sizeOf _ = #{size struct timespec}- -- workaround (hsc2hs for GHC < 8.0 doesn't support #{alignment ...})- alignment _ = #{size char[alignof(struct timespec)] }+ alignment _ = #{alignment struct timespec} poke p (CTimeSpec sec nsec) = do (#poke struct timespec, tv_sec) p sec (#poke struct timespec, tv_nsec) p nsec@@ -29,9 +30,6 @@ nsec <- #{peek struct timespec, tv_nsec} p return (CTimeSpec sec nsec) -c_AT_FDCWD :: CInt-c_AT_FDCWD = (#const AT_FDCWD)- utimeOmit :: CTimeSpec utimeOmit = CTimeSpec (CTime 0) (#const UTIME_OMIT) @@ -41,7 +39,7 @@ (sec, frac) = if frac' < 0 then (sec' - 1, frac' + 1) else (sec', frac') (sec', frac') = properFraction (toRational t) -foreign import ccall "utimensat" c_utimensat- :: CInt -> CString -> Ptr CTimeSpec -> CInt -> IO CInt+foreign import capi "sys/stat.h utimensat" c_utimensat+ :: Posix.Fd -> CString -> Ptr CTimeSpec -> CInt -> IO CInt #endif
+ System/Directory/Internal/Common.hs view
@@ -0,0 +1,353 @@+{-# LANGUAGE CPP #-}+module System.Directory.Internal.Common+ ( module System.Directory.Internal.Common+ , OsPath+ , OsString+ ) where+import Prelude ()+import System.Directory.Internal.Prelude+import GHC.IO.Encoding.Failure (CodingFailureMode(TransliterateCodingFailure))+import GHC.IO.Encoding.UTF16 (mkUTF16le)+import GHC.IO.Encoding.UTF8 (mkUTF8)+import qualified System.File.OsPath.Internal as File+import System.OsPath+ ( OsPath+ , OsString+ , addTrailingPathSeparator+ , decodeUtf+ , decodeWith+ , encodeUtf+ , hasTrailingPathSeparator+ , isPathSeparator+ , isRelative+ , joinDrive+ , joinPath+ , normalise+ , pack+ , pathSeparator+ , pathSeparators+ , splitDirectories+ , splitDrive+ , toChar+ , unpack+ , unsafeFromChar+ )++-- | A generator with side-effects.+newtype ListT m a = ListT { unListT :: m (Maybe (a, ListT m a)) }++emptyListT :: Applicative m => ListT m a+emptyListT = ListT (pure Nothing)++maybeToListT :: Applicative m => m (Maybe a) -> ListT m a+maybeToListT m = ListT (((\ x -> (x, emptyListT)) <$>) <$> m)++listToListT :: Applicative m => [a] -> ListT m a+listToListT [] = emptyListT+listToListT (x : xs) = ListT (pure (Just (x, listToListT xs)))++liftJoinListT :: Monad m => m (ListT m a) -> ListT m a+liftJoinListT m = ListT (m >>= unListT)++listTHead :: Functor m => ListT m a -> m (Maybe a)+listTHead (ListT m) = (fst <$>) <$> m++listTToList :: Monad m => ListT m a -> m [a]+listTToList (ListT m) = do+ mx <- m+ case mx of+ Nothing -> pure []+ Just (x, m') -> do+ xs <- listTToList m'+ pure (x : xs)++andM :: Monad m => m Bool -> m Bool -> m Bool+andM mx my = do+ x <- mx+ if x+ then my+ else pure x++sequenceWithIOErrors_ :: [IO ()] -> IO ()+sequenceWithIOErrors_ actions = go (Right ()) actions+ where++ go :: Either IOError () -> [IO ()] -> IO ()+ go (Left e) [] = ioError e+ go (Right ()) [] = pure ()+ go s (m : ms) = s `seq` do+ r <- tryIOError m+ go (s *> r) ms++-- | Similar to 'try' but only catches a specify kind of 'IOError' as+-- specified by the predicate.+tryIOErrorType :: (IOError -> Bool) -> IO a -> IO (Either IOError a)+tryIOErrorType check action = do+ result <- tryIOError action+ case result of+ Left err -> if check err then pure (Left err) else throwIO err+ Right val -> pure (Right val)++-- | Attempt to perform the given action, silencing any IO exception thrown by+-- it.+ignoreIOExceptions :: IO () -> IO ()+ignoreIOExceptions io = io `catchIOError` (\_ -> pure ())++specializeErrorString :: String -> (IOError -> Bool) -> IO a -> IO a+specializeErrorString str errType action = do+ mx <- tryIOErrorType errType action+ case mx of+ Left e -> throwIO (ioeSetErrorString e str)+ Right x -> pure x++ioeAddLocation :: IOError -> String -> IOError+ioeAddLocation e loc = do+ ioeSetLocation e newLoc+ where+ newLoc = loc <> if null oldLoc then "" else ":" <> oldLoc+ oldLoc = ioeGetLocation e++rightOrError :: Exception e => Either e a -> a+rightOrError (Left e) = error (displayException e)+rightOrError (Right a) = a++-- | Fallibly converts String to OsString. Only intended to be used on literals.+os :: String -> OsString+os = rightOrError . encodeUtf++-- | Fallibly converts OsString to String. Only intended to be used on literals.+so :: OsString -> String+so = rightOrError . decodeUtf++ioeSetOsPath :: IOError -> OsPath -> IOError+ioeSetOsPath err =+ ioeSetFileName err .+ rightOrError .+ decodeWith+ (mkUTF8 TransliterateCodingFailure)+ (mkUTF16le TransliterateCodingFailure)++dropSpecialDotDirs :: [OsPath] -> [OsPath]+dropSpecialDotDirs = filter f+ where f filename = filename /= os "." && filename /= os ".."++-- | Given a list of path segments, expand @.@ and @..@. The path segments+-- must not contain path separators.+expandDots :: [OsPath] -> [OsPath]+expandDots = reverse . go []+ where+ go ys' xs' =+ case xs' of+ [] -> ys'+ x : xs+ | x == os "." -> go ys' xs+ | x == os ".." ->+ case ys' of+ [] -> go (x : ys') xs+ y : ys+ | y == os ".." -> go (x : ys') xs+ | otherwise -> go ys xs+ | otherwise -> go (x : ys') xs++-- | Convert to the right kind of slashes.+normalisePathSeps :: OsPath -> OsPath+normalisePathSeps p = pack (normaliseChar <$> unpack p)+ where normaliseChar c = if isPathSeparator c then pathSeparator else c++-- | Remove redundant trailing slashes and pick the right kind of slash.+normaliseTrailingSep :: OsPath -> OsPath+normaliseTrailingSep path = do+ let path' = reverse (unpack path)+ let (sep, path'') = span isPathSeparator path'+ let addSep = if null sep then id else (pathSeparator :)+ pack (reverse (addSep path''))++-- | Convert empty paths to the current directory, otherwise leave it+-- unchanged.+emptyToCurDir :: OsPath -> OsPath+emptyToCurDir path+ | path == mempty = os "."+ | otherwise = path++-- | Similar to 'normalise' but empty paths stay empty.+simplifyPosix :: OsPath -> OsPath+simplifyPosix path+ | path == mempty = mempty+ | otherwise = normalise path++-- | Similar to 'normalise' but:+--+-- * empty paths stay empty,+-- * parent dirs (@..@) are expanded, and+-- * paths starting with @\\\\@ are preserved.+--+-- The goal is to preserve the meaning of paths better than 'normalise'.+simplifyWindows :: OsPath -> OsPath+simplifyWindows path+ | path == mempty = mempty+ | otherwise = case toChar <$> unpack drive' of+ '\\' : '\\' : _ -> drive' <> subpath+ _ -> simplifiedPath+ where+ simplifiedPath = joinDrive drive' subpath'+ (drive, subpath) = splitDrive path+ drive' = upperDrive (normaliseTrailingSep (normalisePathSeps drive))+ subpath' = appendSep . avoidEmpty . prependSep . joinPath .+ stripPardirs . expandDots . skipSeps .+ splitDirectories $ subpath++ upperDrive d = case unpack d of+ c : k : s+ | isAlpha (toChar c), toChar k == ':', all isPathSeparator s ->+ -- unsafeFromChar is safe here since all characters are ASCII.+ pack (unsafeFromChar (toUpper (toChar c)) : unsafeFromChar ':' : s)+ _ -> d+ skipSeps =+ (pack <$>) .+ filter (not . (`elem` (pure <$> pathSeparators))) .+ (unpack <$>)+ stripPardirs | pathIsAbsolute || subpathIsAbsolute = dropWhile (== os "..")+ | otherwise = id+ prependSep | subpathIsAbsolute = (pack [pathSeparator] <>)+ | otherwise = id+ avoidEmpty | not pathIsAbsolute+ , drive == mempty || hasTrailingPathSep -- prefer "C:" over "C:."+ = emptyToCurDir+ | otherwise = id+ appendSep p | hasTrailingPathSep, not (pathIsAbsolute && p == mempty)+ = addTrailingPathSeparator p+ | otherwise = p+ pathIsAbsolute = not (isRelative path)+ subpathIsAbsolute = any isPathSeparator (take 1 (unpack subpath))+ hasTrailingPathSep = hasTrailingPathSeparator subpath++data WhetherFollow = NoFollow | FollowLinks deriving (Show)++isNoFollow :: WhetherFollow -> Bool+isNoFollow NoFollow = True+isNoFollow FollowLinks = False++data FileType+ = File+ | SymbolicLink -- ^ POSIX: either file or directory link; Windows: file link+ | Directory+ | DirectoryLink -- ^ Windows only: directory link+ deriving (Bounded, Enum, Eq, Ord, Read, Show)++-- | Check whether the given 'FileType' is considered a directory by the+-- operating system. This affects the choice of certain functions+-- e.g. 'System.Directory.removeDirectory' vs 'System.Directory.removeFile'.+fileTypeIsDirectory :: FileType -> Bool+fileTypeIsDirectory Directory = True+fileTypeIsDirectory DirectoryLink = True+fileTypeIsDirectory _ = False++-- | Return whether the given 'FileType' is a link.+fileTypeIsLink :: FileType -> Bool+fileTypeIsLink SymbolicLink = True+fileTypeIsLink DirectoryLink = True+fileTypeIsLink _ = False++data Permissions+ = Permissions+ { readable :: Bool+ , writable :: Bool+ , executable :: Bool+ , searchable :: Bool+ } deriving (Eq, Ord, Read, Show)++withBinaryFile :: OsPath -> IOMode -> (Handle -> IO r) -> IO r+withBinaryFile path mode =+ bracket (File.openFileWithCloseOnExec path mode) hClose++openTempFile' :: String -> OsPath -> OsString -> Bool -> CMode -> Bool+ -> IO (OsPath, Handle)+openTempFile' loc tmpDir template binary mode _cloExec =+ File.openTempFile' loc tmpDir template binary mode+#if MIN_VERSION_file_io(0, 2, 0)+ _cloExec+#endif++-- | Copy data from one handle to another until end of file.+copyHandleData :: Handle -- ^ Source handle+ -> Handle -- ^ Destination handle+ -> IO ()+copyHandleData hFrom hTo =+ (`ioeAddLocation` "copyData") `modifyIOError` do+ allocaBytes bufferSize go+ where+ -- 128 KiB, as coreutils `cp` uses as of May 2014 (see ioblksize.h)+ bufferSize = 131072+ go buffer = do+ count <- hGetBuf hFrom buffer bufferSize+ when (count > 0) $ do+ hPutBuf hTo buffer count+ go buffer++-- | Special directories for storing user-specific application data,+-- configuration, and cache files, as specified by the+-- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.+--+-- Note: On Windows, 'XdgData' and 'XdgConfig' usually map to the same+-- directory.+--+-- @since 1.2.3.0+data XdgDirectory+ = XdgData+ -- ^ For data files (e.g. images).+ -- It uses the @XDG_DATA_HOME@ environment variable.+ -- On non-Windows systems, the default is @~\/.local\/share@.+ -- On Windows, the default is @%APPDATA%@+ -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming@).+ -- Can be considered as the user-specific equivalent of @\/usr\/share@.+ | XdgConfig+ -- ^ For configuration files.+ -- It uses the @XDG_CONFIG_HOME@ environment variable.+ -- On non-Windows systems, the default is @~\/.config@.+ -- On Windows, the default is @%APPDATA%@+ -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming@).+ -- Can be considered as the user-specific equivalent of @\/etc@.+ | XdgCache+ -- ^ For non-essential files (e.g. cache).+ -- It uses the @XDG_CACHE_HOME@ environment variable.+ -- On non-Windows systems, the default is @~\/.cache@.+ -- On Windows, the default is @%LOCALAPPDATA%@+ -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Local@).+ -- Can be considered as the user-specific equivalent of @\/var\/cache@.+ | XdgState+ -- ^ For data that should persist between (application) restarts,+ -- but that is not important or portable enough to the user that it+ -- should be stored in 'XdgData'.+ -- It uses the @XDG_STATE_HOME@ environment variable.+ -- On non-Windows systems, the default is @~\/.local\/state@. On+ -- Windows, the default is @%LOCALAPPDATA%@+ -- (e.g. @C:\/Users\//\<user\>/\/AppData\/Local@).+ --+ -- @since 1.3.7.0+ deriving (Bounded, Enum, Eq, Ord, Read, Show)++-- | Search paths for various application data, as specified by the+-- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.+--+-- The list of paths is split using 'System.FilePath.searchPathSeparator',+-- which on Windows is a semicolon.+--+-- Note: On Windows, 'XdgDataDirs' and 'XdgConfigDirs' usually yield the same+-- result.+--+-- @since 1.3.2.0+data XdgDirectoryList+ = XdgDataDirs+ -- ^ For data files (e.g. images).+ -- It uses the @XDG_DATA_DIRS@ environment variable.+ -- On non-Windows systems, the default is @\/usr\/local\/share\/@ and+ -- @\/usr\/share\/@.+ -- On Windows, the default is @%PROGRAMDATA%@ or @%ALLUSERSPROFILE%@+ -- (e.g. @C:\/ProgramData@).+ | XdgConfigDirs+ -- ^ For configuration files.+ -- It uses the @XDG_CONFIG_DIRS@ environment variable.+ -- On non-Windows systems, the default is @\/etc\/xdg@.+ -- On Windows, the default is @%PROGRAMDATA%@ or @%ALLUSERSPROFILE%@+ -- (e.g. @C:\/ProgramData@).+ deriving (Bounded, Enum, Eq, Ord, Read, Show)
System/Directory/Internal/Config.hs view
@@ -1,13 +1,10 @@ {-# LANGUAGE CPP #-}-#include <HsDirectoryConfig.h> module System.Directory.Internal.Config where+#include <HsDirectoryConfig.h>+import System.Directory.Internal.Common --- | Filename extension for executable files (including the dot if any)--- (usually @\"\"@ on POSIX systems and @\".exe\"@ on Windows or OS\/2).------ @since 1.2.4.0-exeExtension :: String-exeExtension = EXE_EXTENSION+exeExtension :: OsString+exeExtension = os EXE_EXTENSION -- We avoid using #const_str from hsc because it breaks cross-compilation -- builds, so we use this ugly workaround where we simply paste the C string -- literal directly in here. This will probably break if the EXE_EXTENSION
System/Directory/Internal/Posix.hsc view
@@ -1,12 +1,99 @@+{-# LANGUAGE CApiFFI #-} module System.Directory.Internal.Posix where #include <HsDirectoryConfig.h>-#ifndef mingw32_HOST_OS+#if !defined(mingw32_HOST_OS)+#include <fcntl.h> #ifdef HAVE_LIMITS_H # include <limits.h> #endif+#ifdef HAVE_SYS_STAT_H+# include <sys/stat.h>+#endif import Prelude () import System.Directory.Internal.Prelude+#ifdef HAVE_UTIMENSAT+import System.Directory.Internal.C_utimensat+#endif+import System.Directory.Internal.Common+import System.Directory.Internal.Config (exeExtension)+import Data.Time (UTCTime)+import Data.Time.Clock.POSIX (POSIXTime)+import System.OsPath ((</>), isRelative, splitSearchPath)+import System.OsString.Internal.Types (OsString(OsString, getOsString))+import qualified Data.Time.Clock.POSIX as POSIXTime+import qualified System.OsPath.Internal as OsPath+import qualified System.Posix.Directory.Fd as Posix+import qualified System.Posix.Directory.PosixPath as Posix+import qualified System.Posix.Env.PosixString as Posix+import qualified System.Posix.Files as Posix (FileStatus(..))+import qualified System.Posix.Files.PosixString as Posix+import qualified System.Posix.Internals as Posix (CStat)+import qualified System.Posix.IO.PosixString as Posix+import qualified System.Posix.PosixPath.FilePath as Posix+import qualified System.Posix.Types as Posix+import qualified System.Posix.User.ByteString as Posix +c_AT_FDCWD :: Posix.Fd+c_AT_FDCWD = Posix.Fd (#const AT_FDCWD)++c_AT_SYMLINK_NOFOLLOW :: CInt+c_AT_SYMLINK_NOFOLLOW = (#const AT_SYMLINK_NOFOLLOW)++atWhetherFollow :: WhetherFollow -> CInt+atWhetherFollow NoFollow = c_AT_SYMLINK_NOFOLLOW+atWhetherFollow FollowLinks = 0++defaultOpenFlags :: Posix.OpenFileFlags+defaultOpenFlags =+ Posix.defaultFileFlags+ { Posix.noctty = True+ , Posix.nonBlock = True+ , Posix.cloexec = True+ }++type RawHandle = Posix.Fd++openRaw :: WhetherFollow -> Maybe RawHandle -> OsPath -> IO RawHandle+openRaw whetherFollow dir (OsString path) =+ Posix.openFdAt dir path Posix.ReadOnly flags+ where+ flags = defaultOpenFlags { Posix.nofollow = isNoFollow whetherFollow }++closeRaw :: RawHandle -> IO ()+closeRaw = Posix.closeFd++createDirectoryInternal :: OsPath -> IO ()+createDirectoryInternal (OsString path) = Posix.createDirectory path 0o777++foreign import ccall "unistd.h unlinkat" c_unlinkat+ :: Posix.Fd -> CString -> CInt -> IO CInt++removePathAt :: FileType -> Maybe RawHandle -> OsPath -> IO ()+removePathAt ty dir (OsString path) =+ Posix.withFilePath path $ \ pPath -> do+ Posix.throwErrnoPathIfMinus1_ "unlinkat" path+ (c_unlinkat (fromMaybe c_AT_FDCWD dir) pPath flag)+ pure ()+ where+ flag | fileTypeIsDirectory ty = (#const AT_REMOVEDIR)+ | otherwise = 0++removePathInternal :: Bool -> OsPath -> IO ()+removePathInternal True = Posix.removeDirectory . getOsString+removePathInternal False = Posix.removeLink . getOsString++renamePathInternal :: OsPath -> OsPath -> IO ()+renamePathInternal (OsString p1) (OsString p2) = Posix.rename p1 p2++-- On POSIX, the removability of a file is only affected by the attributes of+-- the containing directory.+filesAlwaysRemovable :: Bool+filesAlwaysRemovable = True++-- | On POSIX, equivalent to 'simplifyPosix'.+simplify :: OsPath -> OsPath+simplify = simplifyPosix+ -- we use the 'free' from the standard library here since it's not entirely -- clear whether Haskell's 'free' corresponds to the same one foreign import ccall unsafe "free" c_free :: Ptr a -> IO ()@@ -16,14 +103,30 @@ c_PATH_MAX | c_PATH_MAX' > toInteger maxValue = Nothing | otherwise = Just (fromInteger c_PATH_MAX') where c_PATH_MAX' = (#const PATH_MAX)- maxValue = maxBound `asTypeOf` case c_PATH_MAX of ~(Just x) -> x+ maxValue = maxBound `asTypeInMaybe` c_PATH_MAX+ asTypeInMaybe :: a -> Maybe a -> a+ asTypeInMaybe = const #else c_PATH_MAX = Nothing #endif -foreign import ccall "realpath" c_realpath- :: CString -> CString -> IO CString+#if !defined(HAVE_REALPATH) +c_realpath :: CString -> CString -> IO CString+c_realpath _ _ =+ throwIO+ (mkIOError+ UnsupportedOperation+ "platform does not support realpath"+ Nothing+ Nothing)++#else++foreign import ccall "realpath" c_realpath :: CString -> CString -> IO CString++#endif+ withRealpath :: CString -> (CString -> IO a) -> IO a withRealpath path action = case c_PATH_MAX of Nothing ->@@ -34,5 +137,302 @@ -- allocate one extra just to be safe allocaBytes (pathMax + 1) (realpath >=> action) where realpath = throwErrnoIfNull "" . c_realpath path++realPath :: OsPath -> IO OsPath+realPath (OsString path') =+ Posix.withFilePath path'+ (`withRealpath` ((OsString <$>) . Posix.peekFilePath))++canonicalizePathSimplify :: OsPath -> IO OsPath+canonicalizePathSimplify = pure++findExecutablesLazyInternal :: ([OsPath] -> OsString -> ListT IO OsPath)+ -> OsString+ -> ListT IO OsPath+findExecutablesLazyInternal findExecutablesInDirectoriesLazy binary =+ liftJoinListT $ do+ path <- getPath+ pure (findExecutablesInDirectoriesLazy path binary)++getPath :: IO [OsPath]+getPath = splitSearchPath <$> getEnvOs (os "PATH")++exeExtensionInternal :: OsString+exeExtensionInternal = exeExtension++openDirFromFd :: Posix.Fd -> IO Posix.DirStream+openDirFromFd fd = Posix.unsafeOpenDirStreamFd =<< Posix.dup fd++readDirStreamToEnd :: Posix.DirStream -> IO [OsPath]+readDirStreamToEnd stream = loop id+ where+ loop acc = do+ e <- Posix.readDirStream stream+ if e == mempty+ then pure (acc [])+ else loop (acc . (OsString e :))++readDirToEnd :: RawHandle -> IO [OsPath]+readDirToEnd fd =+ bracket (openDirFromFd fd) Posix.closeDirStream readDirStreamToEnd++getDirectoryContentsInternal :: OsPath -> IO [OsPath]+getDirectoryContentsInternal (OsString path) =+ bracket (Posix.openDirStream path) Posix.closeDirStream readDirStreamToEnd++getCurrentDirectoryInternal :: IO OsPath+getCurrentDirectoryInternal = OsString <$> Posix.getWorkingDirectory++-- | Convert a path into an absolute path. If the given path is relative, the+-- current directory is prepended and the path may or may not be simplified.+-- If the path is already absolute, the path is returned unchanged. The+-- function preserves the presence or absence of the trailing path separator.+--+-- If the path is already absolute, the operation never fails. Otherwise, the+-- operation may throw exceptions.+--+-- Empty paths are treated as the current directory.+prependCurrentDirectory :: OsPath -> IO OsPath+prependCurrentDirectory path+ | isRelative path =+ ((`ioeAddLocation` "prependCurrentDirectory") .+ (`ioeSetOsPath` path)) `modifyIOError` do+ (</> path) <$> getCurrentDirectoryInternal+ | otherwise = pure path++setCurrentDirectoryInternal :: OsPath -> IO ()+setCurrentDirectoryInternal = Posix.changeWorkingDirectory . getOsString++linkToDirectoryIsDirectory :: Bool+linkToDirectoryIsDirectory = False++createHardLink :: OsPath -> OsPath -> IO ()+createHardLink (OsString p1) (OsString p2) = Posix.createLink p1 p2++createSymbolicLink :: Bool -> OsPath -> OsPath -> IO ()+createSymbolicLink _ (OsString p1) (OsString p2) =+ Posix.createSymbolicLink p1 p2++readSymbolicLink :: OsPath -> IO OsPath+readSymbolicLink = (OsString <$>) . Posix.readSymbolicLink . getOsString++type Metadata = Posix.FileStatus++foreign import capi "sys/stat.h fstatat" c_fstatat+ :: Posix.Fd -> CString -> Ptr Posix.CStat -> CInt -> IO CInt++getMetadataAt :: WhetherFollow -> Maybe RawHandle -> OsPath -> IO Metadata+getMetadataAt whetherFollow dir (OsString path) =+ Posix.withFilePath path $ \ pPath -> do+ stat <- mallocForeignPtrBytes (#const sizeof(struct stat))+ withForeignPtr stat $ \ pStat -> do+ Posix.throwErrnoPathIfMinus1_ "fstatat" path $ do+ c_fstatat (fromMaybe c_AT_FDCWD dir) pPath pStat flags+ pure (Posix.FileStatus stat)+ where+ flags = atWhetherFollow whetherFollow++getSymbolicLinkMetadata :: OsPath -> IO Metadata+getSymbolicLinkMetadata = Posix.getSymbolicLinkStatus . getOsString++getFileMetadata :: OsPath -> IO Metadata+getFileMetadata = Posix.getFileStatus . getOsString++fileTypeFromMetadata :: Metadata -> FileType+fileTypeFromMetadata stat+ | isLink = SymbolicLink+ | isDir = Directory+ | otherwise = File+ where+ isLink = Posix.isSymbolicLink stat+ isDir = Posix.isDirectory stat++fileSizeFromMetadata :: Metadata -> Integer+fileSizeFromMetadata = fromIntegral . Posix.fileSize++accessTimeFromMetadata :: Metadata -> UTCTime+accessTimeFromMetadata =+ POSIXTime.posixSecondsToUTCTime . Posix.accessTimeHiRes++modificationTimeFromMetadata :: Metadata -> UTCTime+modificationTimeFromMetadata =+ POSIXTime.posixSecondsToUTCTime . Posix.modificationTimeHiRes++type Mode = Posix.FileMode++modeFromMetadata :: Metadata -> Mode+modeFromMetadata = Posix.fileMode++allWriteMode :: Posix.FileMode+allWriteMode =+ Posix.ownerWriteMode .|.+ Posix.groupWriteMode .|.+ Posix.otherWriteMode++hasWriteMode :: Mode -> Bool+hasWriteMode m = m .&. allWriteMode /= 0++setWriteMode :: Bool -> Mode -> Mode+setWriteMode False m = m .&. complement allWriteMode+setWriteMode True m = m .|. allWriteMode++setForceRemoveMode :: Mode -> Mode+setForceRemoveMode m = m .|. Posix.ownerModes++foreign import capi "sys/stat.h fchmodat" c_fchmodat+ :: Posix.Fd -> CString -> Posix.FileMode -> CInt -> IO CInt++setModeAt :: Maybe RawHandle -> OsPath -> Mode -> IO ()+setModeAt dir (OsString path) mode = do+ Posix.withFilePath path $ \ pPath ->+ Posix.throwErrnoPathIfMinus1_ "fchmodat" path $ do+ c_fchmodat (fromMaybe c_AT_FDCWD dir) pPath mode 0++setFileMode :: OsPath -> Mode -> IO ()+setFileMode = Posix.setFileMode . getOsString++setFilePermissions :: OsPath -> Mode -> IO ()+setFilePermissions = setFileMode++getAccessPermissions :: OsPath -> IO Permissions+getAccessPermissions path = do+ m <- getFileMetadata path+ let isDir = fileTypeIsDirectory (fileTypeFromMetadata m)+ let OsString path' = path+ r <- Posix.fileAccess path' True False False+ w <- Posix.fileAccess path' False True False+ x <- Posix.fileAccess path' False False True+ pure Permissions+ { readable = r+ , writable = w+ , executable = x && not isDir+ , searchable = x && isDir+ }++setAccessPermissions :: OsPath -> Permissions -> IO ()+setAccessPermissions path (Permissions r w e s) = do+ m <- getFileMetadata path+ setFileMode path (modifyBit (e || s) Posix.ownerExecuteMode .+ modifyBit w Posix.ownerWriteMode .+ modifyBit r Posix.ownerReadMode .+ modeFromMetadata $ m)+ where+ modifyBit :: Bool -> Posix.FileMode -> Posix.FileMode -> Posix.FileMode+ modifyBit False b m = m .&. complement b+ modifyBit True b m = m .|. b++copyOwnerFromStatus :: Posix.FileStatus -> OsPath -> IO ()+copyOwnerFromStatus st (OsString dst) = do+ Posix.setOwnerAndGroup dst (Posix.fileOwner st) (-1)++copyGroupFromStatus :: Posix.FileStatus -> OsPath -> IO ()+copyGroupFromStatus st (OsString dst) = do+ Posix.setOwnerAndGroup dst (-1) (Posix.fileGroup st)++tryCopyOwnerAndGroupFromStatus :: Posix.FileStatus -> OsPath -> IO ()+tryCopyOwnerAndGroupFromStatus st dst = do+ ignoreIOExceptions (copyOwnerFromStatus st dst)+ ignoreIOExceptions (copyGroupFromStatus st dst)++-- | Truncate the destination file and then copy the contents of the source+-- file to the destination file. If the destination file already exists, its+-- attributes shall remain unchanged. Otherwise, its attributes are reset to+-- the defaults.+copyFileContents :: OsPath -- ^ Source filename+ -> OsPath -- ^ Destination filename+ -> IO ()+copyFileContents fromFPath toFPath =+ (`ioeAddLocation` "copyFileContents") `modifyIOError` do+ withBinaryFile toFPath WriteMode $ \ hTo -> do+ withBinaryFile fromFPath ReadMode $ \ hFrom -> do+ copyHandleData hFrom hTo++copyFileWithMetadataInternal :: (Metadata -> OsPath -> IO ())+ -> (Metadata -> OsPath -> IO ())+ -> OsPath+ -> OsPath+ -> IO ()+copyFileWithMetadataInternal copyPermissionsFromMetadata+ copyTimesFromMetadata+ src+ dst = do+ st <- Posix.getFileStatus (getOsString src)+ copyFileContents src dst+ tryCopyOwnerAndGroupFromStatus st dst+ copyPermissionsFromMetadata st dst+ copyTimesFromMetadata st dst++setTimes :: OsPath -> (Maybe POSIXTime, Maybe POSIXTime) -> IO ()+#ifdef HAVE_UTIMENSAT+setTimes (OsString path') (atime', mtime') =+ Posix.withFilePath path' $ \ path'' ->+ withArray [ maybe utimeOmit toCTimeSpec atime'+ , maybe utimeOmit toCTimeSpec mtime' ] $ \ times ->+ Posix.throwErrnoPathIfMinus1_ "" path' $+ c_utimensat c_AT_FDCWD path'' times 0+#else+setTimes (OsString path') (Just atime', Just mtime') =+ Posix.setFileTimesHiRes path' atime' mtime'+setTimes (OsString path') (atime', mtime') = do+ m <- getFileMetadata (OsString path')+ let atimeOld = accessTimeFromMetadata m+ let mtimeOld = modificationTimeFromMetadata m+ Posix.setFileTimesHiRes path'+ (fromMaybe (POSIXTime.utcTimeToPOSIXSeconds atimeOld) atime')+ (fromMaybe (POSIXTime.utcTimeToPOSIXSeconds mtimeOld) mtime')+#endif++lookupEnvOs :: OsString -> IO (Maybe OsString)+lookupEnvOs (OsString name) = (OsString <$>) <$> Posix.getEnv name++getEnvOs :: OsString -> IO OsString+getEnvOs name = do+ env <- lookupEnvOs name+ case env of+ Nothing ->+ throwIO $+ mkIOError+ doesNotExistErrorType+ ("env var " <> show name <> " not found")+ Nothing+ Nothing+ Just value -> pure value++-- | $HOME is preferred, because the user has control over it. However, POSIX+-- doesn't define it as a mandatory variable, so fall back to `getpwuid_r`.+getHomeDirectoryInternal :: IO OsPath+getHomeDirectoryInternal = do+ e <- lookupEnvOs (os "HOME")+ case e of+ Just fp -> pure fp+ Nothing ->+ OsPath.fromBytes . Posix.homeDirectory =<<+ Posix.getUserEntryForID =<<+ Posix.getEffectiveUserID++getXdgDirectoryFallback :: IO OsPath -> XdgDirectory -> IO OsPath+getXdgDirectoryFallback getHomeDirectory xdgDir = do+ (<$> getHomeDirectory) $ flip (</>) $ case xdgDir of+ XdgData -> os ".local/share"+ XdgConfig -> os ".config"+ XdgCache -> os ".cache"+ XdgState -> os ".local/state"++getXdgDirectoryListFallback :: XdgDirectoryList -> IO [OsPath]+getXdgDirectoryListFallback xdgDirs =+ pure $ case xdgDirs of+ XdgDataDirs -> [os "/usr/local/share/", os "/usr/share/"]+ XdgConfigDirs -> [os "/etc/xdg"]++getAppUserDataDirectoryInternal :: OsPath -> IO OsPath+getAppUserDataDirectoryInternal appName =+ (\ home -> home <> (os "/" <> os "." <> appName)) <$> getHomeDirectoryInternal++getUserDocumentsDirectoryInternal :: IO OsPath+getUserDocumentsDirectoryInternal = getHomeDirectoryInternal++getTemporaryDirectoryInternal :: IO OsPath+getTemporaryDirectoryInternal =+ fromMaybe (os "/tmp") <$> lookupEnvOs (os "TMPDIR") #endif
System/Directory/Internal/Prelude.hs view
@@ -1,11 +1,12 @@-{-# LANGUAGE CPP #-} {-# OPTIONS_HADDOCK hide #-}+-- |+-- Stability: unstable+-- Portability: portable+--+-- Internal modules are always subject to change from version to version.+ module System.Directory.Internal.Prelude ( module Prelude-#if !MIN_VERSION_base(4, 8, 0)- , module Control.Applicative- , module Data.Functor-#endif , module Control.Arrow , module Control.Concurrent , module Control.Exception@@ -26,20 +27,11 @@ , module System.Exit , module System.IO , module System.IO.Error- , module System.Posix.Internals , module System.Posix.Types , module System.Timeout , Void ) where-#if !MIN_VERSION_base(4, 6, 0)-import Prelude hiding (catch)-#endif-#if MIN_VERSION_base(4, 8, 0) import Data.Void (Void)-#else-import Control.Applicative ((<*>), pure)-import Data.Functor ((<$>), (<$))-#endif import Control.Arrow (second) import Control.Concurrent ( forkIO@@ -48,11 +40,14 @@ , putMVar , readMVar , takeMVar+ , forkFinally ) import Control.Exception- ( SomeException+ ( Exception(displayException)+ , SomeException , bracket , bracket_+ , bracketOnError , catch , finally , mask@@ -60,10 +55,10 @@ , throwIO , try )-import Control.Monad ((>=>), (<=<), unless, when, replicateM_)+import Control.Monad ((>=>), (<=<), unless, when, replicateM, replicateM_) import Data.Bits ((.&.), (.|.), complement)-import Data.Char (isAlpha, isAscii, toLower)-import Data.Foldable (for_, traverse_)+import Data.Char (isAlpha, isAscii, toLower, toUpper)+import Data.Foldable (for_, sequenceA_) import Data.Function (on) import Data.Maybe (catMaybes, fromMaybe, maybeToList) import Data.Monoid ((<>), mconcat, mempty)@@ -85,11 +80,13 @@ , allocaArray , allocaBytes , allocaBytesAligned+ , mallocForeignPtrBytes , maybeWith , nullPtr , plusPtr , with , withArray+ , withForeignPtr ) import Foreign.C ( CInt(..)@@ -101,24 +98,20 @@ , CUShort(..) , CWString , CWchar(..)- , peekCString- , peekCWStringLen , throwErrnoIfMinus1Retry_ , throwErrnoIfMinus1_ , throwErrnoIfNull- , throwErrnoPathIfMinus1_- , withCString- , withCWString ) import GHC.IO.Exception ( IOErrorType ( InappropriateType+ , InvalidArgument , OtherError , UnsupportedOperation ) ) import GHC.IO.Encoding (getFileSystemEncoding)-import System.Environment (getArgs, getEnv)+import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO ( Handle@@ -129,14 +122,14 @@ , hPutBuf , hPutStr , hPutStrLn- , openBinaryTempFile , stderr , stdout- , withBinaryFile ) import System.IO.Error ( IOError , catchIOError+ , doesNotExistErrorType+ , illegalOperationErrorType , ioeGetErrorString , ioeGetErrorType , ioeGetLocation@@ -145,6 +138,7 @@ , ioeSetLocation , isAlreadyExistsError , isDoesNotExistError+ , isIllegalOperation , isPermissionError , mkIOError , modifyIOError@@ -152,21 +146,5 @@ , tryIOError , userError )-import System.Posix.Internals- ( CStat- , c_stat- , withFilePath- , s_isdir- , sizeof_stat- , st_mode- , st_size- )-import System.Posix.Types (CMode(..), EpochTime, FileMode)+import System.Posix.Types (CMode, EpochTime) import System.Timeout (timeout)--#if !MIN_VERSION_base(4, 8, 0)-data Void = Void--_unusedVoid :: Void-_unusedVoid = Void-#endif
System/Directory/Internal/Windows.hsc view
@@ -1,79 +1,156 @@ {-# LANGUAGE CPP #-} module System.Directory.Internal.Windows where #include <HsDirectoryConfig.h>-#ifdef mingw32_HOST_OS-##if defined i386_HOST_ARCH+#if defined(mingw32_HOST_OS)+##if defined(i386_HOST_ARCH) ## define WINAPI stdcall-##elif defined x86_64_HOST_ARCH+##elif defined(x86_64_HOST_ARCH) || defined(aarch64_HOST_ARCH) ## define WINAPI ccall ##else ## error unknown architecture ##endif #include <shlobj.h> #include <windows.h>-#ifdef HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif+#include <HsBaseConfig.h>+#include <System/Directory/Internal/windows_ext.h> import Prelude () import System.Directory.Internal.Prelude-import System.FilePath (isRelative, normalise, splitDirectories)-import qualified System.Win32 as Win32--win32_cSIDL_LOCAL_APPDATA :: Win32.CSIDL-#if MIN_VERSION_Win32(2, 3, 1)-win32_cSIDL_LOCAL_APPDATA = Win32.cSIDL_LOCAL_APPDATA-#else-win32_cSIDL_LOCAL_APPDATA = (#const CSIDL_LOCAL_APPDATA)+import System.Directory.Internal.Common+import System.Directory.Internal.Config (exeExtension)+import Data.Time (UTCTime)+import Data.Time.Clock.POSIX (POSIXTime, posixSecondsToUTCTime)+#ifdef __IO_MANAGER_WINIO__+import GHC.IO.SubSystem (IoSubSystem(IoPOSIX, IoNative), ioSubSystem) #endif+import System.OsPath+ ( (</>)+ , hasExtension+ , isExtensionOf+ , isPathSeparator+ , isRelative+ , pack+ , pathSeparator+ , splitDirectories+ , splitSearchPath+ , takeExtension+ , toChar+ , unpack+ )+import System.OsPath.Types (WindowsPath, WindowsString)+import System.OsString.Internal.Types (OsString(OsString, getOsString))+import qualified Data.List as List+import qualified System.Win32.WindowsString.File as Win32+import qualified System.Win32.WindowsString.Info as Win32+import qualified System.Win32.WindowsString.Shell as Win32+import qualified System.Win32.WindowsString.Time as Win32+import qualified System.Win32.WindowsString.Types as Win32+import qualified System.Win32.WindowsString.Console as Win32 -win32_fILE_ATTRIBUTE_REPARSE_POINT :: Win32.FileAttributeOrFlag-win32_fILE_ATTRIBUTE_REPARSE_POINT = (#const FILE_ATTRIBUTE_REPARSE_POINT)+type RawHandle = OsPath -win32_fILE_SHARE_DELETE :: Win32.ShareMode-#if MIN_VERSION_Win32(2, 3, 1)-win32_fILE_SHARE_DELETE = Win32.fILE_SHARE_DELETE -- added in 2.3.0.2-#else-win32_fILE_SHARE_DELETE = (#const FILE_SHARE_DELETE)-#endif+pathAt :: Maybe RawHandle -> OsPath -> OsPath+pathAt dir path = fromMaybe mempty dir </> path -win32_getLongPathName, win32_getShortPathName :: FilePath -> IO FilePath-#if MIN_VERSION_Win32(2, 4, 0)-win32_getLongPathName = Win32.getLongPathName-win32_getShortPathName = Win32.getShortPathName-#else-win32_getLongPathName path =- modifyIOError ((`ioeSetLocation` "GetLongPathName") .- (`ioeSetFileName` path)) $ do- withCWString path $ \ ptrPath -> do- getPathNameWith (c_GetLongPathName ptrPath)+openRaw :: WhetherFollow -> Maybe RawHandle -> OsPath -> IO RawHandle+openRaw _ dir path = pure (pathAt dir path) -win32_getShortPathName path =- modifyIOError ((`ioeSetLocation` "GetShortPathName") .- (`ioeSetFileName` path)) $ do- withCWString path $ \ ptrPath -> do- getPathNameWith (c_GetShortPathName ptrPath)+closeRaw :: RawHandle -> IO ()+closeRaw _ = pure () -foreign import WINAPI unsafe "windows.h GetLongPathNameW"- c_GetLongPathName- :: Ptr CWchar- -> Ptr CWchar- -> Win32.DWORD- -> IO Win32.DWORD+lookupEnvOs :: OsString -> IO (Maybe OsString)+lookupEnvOs (OsString name) = (OsString <$>) <$> Win32.getEnv name -foreign import WINAPI unsafe "windows.h GetShortPathNameW"- c_GetShortPathName- :: Ptr CWchar- -> Ptr CWchar- -> Win32.DWORD- -> IO Win32.DWORD-#endif+getEnvOs :: OsString -> IO OsString+getEnvOs name = do+ env <- lookupEnvOs name+ case env of+ Nothing ->+ throwIO $+ mkIOError+ doesNotExistErrorType+ ("env var " <> show name <> " not found")+ Nothing+ Nothing+ Just value -> pure value -win32_getFinalPathNameByHandle :: Win32.HANDLE -> Win32.DWORD -> IO FilePath-win32_getFinalPathNameByHandle _h _flags =- modifyIOError (`ioeSetLocation` "GetFinalPathNameByHandle") $ do+-- | Get the contents of the @PATH@ environment variable.+getPath :: IO [OsPath]+getPath = splitSearchPath <$> getEnvOs (os "PATH")++createDirectoryInternal :: OsPath -> IO ()+createDirectoryInternal path =+ (`ioeSetOsPath` path) `modifyIOError` do+ path' <- furnishPath path+ Win32.createDirectory path' Nothing++removePathAt :: FileType -> Maybe RawHandle -> OsPath -> IO ()+removePathAt ty dir path = removePathInternal isDir (pathAt dir path)+ where isDir = fileTypeIsDirectory ty++removePathInternal :: Bool -> OsPath -> IO ()+removePathInternal isDir path =+ (`ioeSetOsPath` path) `modifyIOError` do+ furnishPath path+ >>= if isDir then Win32.removeDirectory else Win32.deleteFile++renamePathInternal :: OsPath -> OsPath -> IO ()+renamePathInternal opath npath =+ (`ioeSetOsPath` opath) `modifyIOError` do+ opath' <- furnishPath opath+ npath' <- furnishPath npath+ Win32.moveFileEx opath' (Just npath') Win32.mOVEFILE_REPLACE_EXISTING++-- On Windows, the removability of a file may be affected by the attributes of+-- the file itself.+filesAlwaysRemovable :: Bool+filesAlwaysRemovable = False++copyFileWithMetadataInternal :: (Metadata -> OsPath -> IO ())+ -> (Metadata -> OsPath -> IO ())+ -> OsPath+ -> OsPath+ -> IO ()+copyFileWithMetadataInternal _ _ src dst =+ (`ioeSetOsPath` src) `modifyIOError` do+ src' <- furnishPath src+ dst' <- furnishPath dst+ Win32.copyFile src' dst' False++win32_cSIDL_COMMON_APPDATA :: Win32.CSIDL+win32_cSIDL_COMMON_APPDATA = (#const CSIDL_COMMON_APPDATA)++win32_eRROR_ENVVAR_NOT_FOUND :: Win32.ErrCode+win32_eRROR_ENVVAR_NOT_FOUND = (#const ERROR_ENVVAR_NOT_FOUND)++win32_eRROR_INVALID_FUNCTION :: Win32.ErrCode+win32_eRROR_INVALID_FUNCTION = (#const ERROR_INVALID_FUNCTION)++win32_eRROR_INVALID_PARAMETER :: Win32.ErrCode+win32_eRROR_INVALID_PARAMETER = (#const ERROR_INVALID_PARAMETER)++win32_eRROR_PRIVILEGE_NOT_HELD :: Win32.ErrCode+win32_eRROR_PRIVILEGE_NOT_HELD = (#const ERROR_PRIVILEGE_NOT_HELD)++win32_sYMBOLIC_LINK_FLAG_DIRECTORY :: Win32.DWORD+win32_sYMBOLIC_LINK_FLAG_DIRECTORY = 0x1++win32_sYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE :: Win32.DWORD+win32_sYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2++maxShareMode :: Win32.ShareMode+maxShareMode =+ Win32.fILE_SHARE_DELETE .|.+ Win32.fILE_SHARE_READ .|.+ Win32.fILE_SHARE_WRITE++win32_getFinalPathNameByHandle :: Win32.HANDLE -> Win32.DWORD -> IO WindowsPath #ifdef HAVE_GETFINALPATHNAMEBYHANDLEW- getPathNameWith $ \ ptr len -> do- c_GetFinalPathNameByHandle _h ptr len _flags+win32_getFinalPathNameByHandle h flags = do+ result <- peekTStringWith (#const MAX_PATH) $ \ ptr len -> do+ c_GetFinalPathNameByHandle h ptr len flags+ case result of+ Left errCode -> Win32.failWith "GetFinalPathNameByHandle" errCode+ Right path -> pure path foreign import WINAPI unsafe "windows.h GetFinalPathNameByHandleW" c_GetFinalPathNameByHandle@@ -84,96 +161,571 @@ -> IO Win32.DWORD #else- throwIO (mkIOError UnsupportedOperation- "platform does not support GetFinalPathNameByHandle"- Nothing Nothing)+win32_getFinalPathNameByHandle _ _ = throwIO $+ mkIOError+ UnsupportedOperation+ "platform does not support GetFinalPathNameByHandle"+ Nothing+ Nothing #endif -getFinalPathName :: FilePath -> IO FilePath+getFinalPathName :: OsPath -> IO OsPath getFinalPathName =- (fromExtendedLengthPath <$>) . rawGetFinalPathName . toExtendedLengthPath+ (fromExtendedLengthPath <$>) .+ rawGetFinalPathName .+ toExtendedLengthPath where #ifdef HAVE_GETFINALPATHNAMEBYHANDLEW rawGetFinalPathName path = do- let open = Win32.createFile path 0 shareMode Nothing+ let open = Win32.createFile path 0 maxShareMode Nothing Win32.oPEN_EXISTING Win32.fILE_FLAG_BACKUP_SEMANTICS Nothing bracket open Win32.closeHandle $ \ h -> do win32_getFinalPathNameByHandle h 0- shareMode =- win32_fILE_SHARE_DELETE .|.- Win32.fILE_SHARE_READ .|.- Win32.fILE_SHARE_WRITE #else- rawGetFinalPathName = win32_getLongPathName <=< win32_getShortPathName+ rawGetFinalPathName = Win32.getLongPathName <=< Win32.getShortPathName #endif --- | Add the @"\\\\?\\"@ prefix if necessary or possible.--- The path remains unchanged if the prefix is not added.-toExtendedLengthPath :: FilePath -> FilePath-toExtendedLengthPath path- | isRelative path = path- | otherwise =- case normalise path of- -- note: as of filepath-1.4.1.0 normalise doesn't honor \\?\- -- https://github.com/haskell/filepath/issues/56- -- this means we cannot trust the result of normalise on- -- paths that start with \\?\- '\\' : '\\' : '?' : '\\' : _ -> path- '\\' : '\\' : '.' : '\\' : _ -> path- '\\' : subpath@('\\' : _) -> "\\\\?\\UNC" <> subpath- normalisedPath -> "\\\\?\\" <> normalisedPath+win32_fILE_FLAG_OPEN_REPARSE_POINT :: Win32.FileAttributeOrFlag+win32_fILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 +win32_fSCTL_GET_REPARSE_POINT :: Win32.DWORD+win32_fSCTL_GET_REPARSE_POINT = 0x900a8++win32_iO_REPARSE_TAG_MOUNT_POINT, win32_iO_REPARSE_TAG_SYMLINK :: CULong+win32_iO_REPARSE_TAG_MOUNT_POINT = (#const IO_REPARSE_TAG_MOUNT_POINT)+win32_iO_REPARSE_TAG_SYMLINK = (#const IO_REPARSE_TAG_SYMLINK)++win32_mAXIMUM_REPARSE_DATA_BUFFER_SIZE :: Win32.DWORD+win32_mAXIMUM_REPARSE_DATA_BUFFER_SIZE =+ (#const MAXIMUM_REPARSE_DATA_BUFFER_SIZE)++win32_sYMLINK_FLAG_RELATIVE :: CULong+win32_sYMLINK_FLAG_RELATIVE = 0x00000001++data Win32_REPARSE_DATA_BUFFER+ = Win32_MOUNT_POINT_REPARSE_DATA_BUFFER WindowsString WindowsString+ -- ^ substituteName printName+ | Win32_SYMLINK_REPARSE_DATA_BUFFER WindowsString WindowsString Bool+ -- ^ substituteName printName isRelative+ | Win32_GENERIC_REPARSE_DATA_BUFFER++win32_alloca_REPARSE_DATA_BUFFER+ :: ((Ptr Win32_REPARSE_DATA_BUFFER, Int) -> IO a) -> IO a+win32_alloca_REPARSE_DATA_BUFFER action =+ allocaBytesAligned size align $ \ ptr ->+ action (ptr, size)+ where size = fromIntegral win32_mAXIMUM_REPARSE_DATA_BUFFER_SIZE+ align = #{alignment HsDirectory_REPARSE_DATA_BUFFER}++win32_peek_REPARSE_DATA_BUFFER+ :: Ptr Win32_REPARSE_DATA_BUFFER -> IO Win32_REPARSE_DATA_BUFFER+win32_peek_REPARSE_DATA_BUFFER p = do+ tag <- #{peek HsDirectory_REPARSE_DATA_BUFFER, ReparseTag} p+ case () of+ _ | tag == win32_iO_REPARSE_TAG_MOUNT_POINT -> do+ let buf = #{ptr HsDirectory_REPARSE_DATA_BUFFER,+ MountPointReparseBuffer.PathBuffer} p+ sni <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ MountPointReparseBuffer.SubstituteNameOffset} p+ sns <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ MountPointReparseBuffer.SubstituteNameLength} p+ sn <- peekName buf sni sns+ pni <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ MountPointReparseBuffer.PrintNameOffset} p+ pns <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ MountPointReparseBuffer.PrintNameLength} p+ pn <- peekName buf pni pns+ pure (Win32_MOUNT_POINT_REPARSE_DATA_BUFFER sn pn)+ | tag == win32_iO_REPARSE_TAG_SYMLINK -> do+ let buf = #{ptr HsDirectory_REPARSE_DATA_BUFFER,+ SymbolicLinkReparseBuffer.PathBuffer} p+ sni <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ SymbolicLinkReparseBuffer.SubstituteNameOffset} p+ sns <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ SymbolicLinkReparseBuffer.SubstituteNameLength} p+ sn <- peekName buf sni sns+ pni <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ SymbolicLinkReparseBuffer.PrintNameOffset} p+ pns <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ SymbolicLinkReparseBuffer.PrintNameLength} p+ pn <- peekName buf pni pns+ flags <- #{peek HsDirectory_REPARSE_DATA_BUFFER,+ SymbolicLinkReparseBuffer.Flags} p+ pure (Win32_SYMLINK_REPARSE_DATA_BUFFER sn pn+ (flags .&. win32_sYMLINK_FLAG_RELATIVE /= 0))+ | otherwise -> pure Win32_GENERIC_REPARSE_DATA_BUFFER+ where+ peekName :: Ptr CWchar -> CUShort -> CUShort -> IO WindowsString+ peekName buf offset size =+ Win32.peekTStringLen ( buf `plusPtr` fromIntegral offset+ , fromIntegral size `div` sizeOf (0 :: CWchar) )++deviceIoControl+ :: Win32.HANDLE+ -> Win32.DWORD+ -> (Ptr a, Int)+ -> (Ptr b, Int)+ -> Maybe Void+ -> IO (Either Win32.ErrCode Int)+deviceIoControl h code (inPtr, inSize) (outPtr, outSize) _ = do+ with 0 $ \ lenPtr -> do+ ok <- c_DeviceIoControl h code inPtr (fromIntegral inSize) outPtr+ (fromIntegral outSize) lenPtr nullPtr+ if ok+ then Right . fromIntegral <$> peek lenPtr+ else Left <$> Win32.getLastError++foreign import WINAPI unsafe "windows.h DeviceIoControl"+ c_DeviceIoControl+ :: Win32.HANDLE+ -> Win32.DWORD+ -> Ptr a+ -> Win32.DWORD+ -> Ptr b+ -> Win32.DWORD+ -> Ptr Win32.DWORD+ -> Ptr Void+ -> IO Win32.BOOL++readSymbolicLink :: OsPath -> IO OsPath+readSymbolicLink path =+ (`ioeSetOsPath` path) `modifyIOError` do+ path' <- furnishPath path+ let open = Win32.createFile path' 0 maxShareMode Nothing Win32.oPEN_EXISTING+ (Win32.fILE_FLAG_BACKUP_SEMANTICS .|.+ win32_fILE_FLAG_OPEN_REPARSE_POINT) Nothing+ bracket open Win32.closeHandle $ \ h -> do+ win32_alloca_REPARSE_DATA_BUFFER $ \ ptrAndSize@(ptr, _) -> do+ result <- deviceIoControl h win32_fSCTL_GET_REPARSE_POINT+ (nullPtr, 0) ptrAndSize Nothing+ case result of+ Left e | e == win32_eRROR_INVALID_FUNCTION -> do+ let msg = "Incorrect function. The file system " <>+ "might not support symbolic links."+ throwIO (mkIOError illegalOperationErrorType+ "DeviceIoControl" Nothing Nothing+ `ioeSetErrorString` msg)+ | otherwise -> Win32.failWith "DeviceIoControl" e+ Right _ -> pure ()+ rData <- win32_peek_REPARSE_DATA_BUFFER ptr+ strip . OsString <$> case rData of+ Win32_MOUNT_POINT_REPARSE_DATA_BUFFER sn _ -> pure sn+ Win32_SYMLINK_REPARSE_DATA_BUFFER sn _ _ -> pure sn+ _ -> throwIO (mkIOError InappropriateType+ "readSymbolicLink" Nothing Nothing)+ where+ strip sn =+ fromMaybe sn+ (pack <$> List.stripPrefix (unpack (os "\\??\\")) (unpack sn))++-- | On Windows, equivalent to 'simplifyWindows'.+simplify :: OsPath -> OsPath+simplify = simplifyWindows++-- | Normalise the path separators and prepend the @"\\\\?\\"@ prefix if+-- necessary or possible. This is used for symbolic links targets because+-- they can't handle forward slashes.+normaliseSeparators :: OsPath -> WindowsPath+normaliseSeparators path+ | isRelative path = getOsString (pack (normaliseSep <$> unpack path))+ | otherwise = toExtendedLengthPath path+ where normaliseSep c = if isPathSeparator c then pathSeparator else c++-- | 'simplify' the path and prepend the @"\\\\?\\"@ if possible. This+-- function can sometimes be used to bypass the @MAX_PATH@ length restriction+-- in Windows API calls.+toExtendedLengthPath :: OsPath -> WindowsPath+toExtendedLengthPath path =+ getOsString $+ if isRelative path+ then simplifiedPath+ else+ case toChar <$> simplifiedPath' of+ '\\' : '?' : '?' : '\\' : _ -> simplifiedPath+ '\\' : '\\' : _ -> simplifiedPath+ _ -> os "\\\\?\\" <> simplifiedPath+ where simplifiedPath = simplify path+ simplifiedPath' = unpack simplifiedPath++-- | Make a path absolute and convert to an extended length path, if possible.+--+-- Empty paths are left unchanged.+--+-- This function never fails. If it doesn't understand the path, it just+-- returns the path unchanged.+furnishPath :: OsPath -> IO WindowsPath+furnishPath path =+ (toExtendedLengthPath <$> rawPrependCurrentDirectory path)+ `catchIOError` \ _ ->+ pure (getOsString path)+ -- | Strip the @"\\\\?\\"@ prefix if possible. -- The prefix is kept if the meaning of the path would otherwise change.-fromExtendedLengthPath :: FilePath -> FilePath-fromExtendedLengthPath ePath =- case ePath of- '\\' : '\\' : '?' : '\\' : path ->+fromExtendedLengthPath :: WindowsPath -> OsPath+fromExtendedLengthPath ePath' =+ case unpack ePath of+ c1 : c2 : c3 : c4 : path+ | (toChar <$> [c1, c2, c3, c4]) == "\\\\?\\" -> case path of- 'U' : 'N' : 'C' : subpath@('\\' : _) -> "\\" <> subpath- drive : ':' : subpath+ c5 : c6 : c7 : subpath@(c8 : _)+ | (toChar <$> [c5, c6, c7, c8]) == "UNC\\" ->+ pack (c8 : subpath)+ drive : col : subpath -- if the path is not "regular", then the prefix is necessary -- to ensure the path is interpreted literally- | isAlpha drive && isAscii drive && isPathRegular subpath -> path+ | toChar col == ':', isDriveChar drive, isPathRegular subpath ->+ pack path _ -> ePath _ -> ePath where+ ePath = OsString ePath'+ isDriveChar drive = isAlpha (toChar drive) && isAscii (toChar drive) isPathRegular path =- not ('/' `elem` path ||- "." `elem` splitDirectories path ||- ".." `elem` splitDirectories path)+ not ('/' `elem` (toChar <$> path) ||+ os "." `elem` splitDirectories (pack path) ||+ os ".." `elem` splitDirectories (pack path)) -getPathNameWith :: (Ptr CWchar -> Win32.DWORD -> IO Win32.DWORD) -> IO FilePath-getPathNameWith cFunc = do- let getPathNameWithLen len = do- allocaArray (fromIntegral len) $ \ ptrPathOut -> do- len' <- Win32.failIfZero "" (cFunc ptrPathOut len)- if len' <= len- then Right <$> peekCWStringLen (ptrPathOut, fromIntegral len')- else pure (Left len')- r <- getPathNameWithLen ((#const MAX_PATH) * (#size wchar_t))- case r of- Right s -> pure s- Left len -> do- r' <- getPathNameWithLen len- case r' of- Right s -> pure s- Left _ -> ioError (mkIOError OtherError "" Nothing Nothing- `ioeSetErrorString` "path changed unexpectedly")+saturatingDouble :: Win32.DWORD -> Win32.DWORD+saturatingDouble s | s > maxBound `div` 2 = maxBound+ | otherwise = s * 2 -foreign import ccall unsafe "_wchmod"- c_wchmod :: CWString -> CMode -> IO CInt+-- Handles Windows APIs that write strings through a user-provided buffer and+-- can propose a new length when it isn't big enough. This is similar to+-- Win32.try, but also returns the precise error code.+peekTStringWith :: Win32.DWORD+ -> (Win32.LPTSTR -> Win32.DWORD -> IO Win32.DWORD)+ -- ^ Must accept a buffer and its size in TCHARs. If the+ -- buffer is large enough for the function, it must write a+ -- string to it, which need not be null-terminated, and+ -- return the length of the string, not including the null+ -- terminator if present. If the buffer is too small, it+ -- must return a proposed buffer size in TCHARs, although it+ -- need not guarantee success with the proposed size if,+ -- say, the underlying data changes in the interim. If it+ -- fails for any other reason, it must return zero and+ -- communicate the error code through GetLastError.+ -> IO (Either Win32.ErrCode WindowsPath)+peekTStringWith bufferSize cFunc = do+ outcome <- do+ allocaArray (fromIntegral bufferSize) $ \ ptr -> do+ size <- cFunc ptr bufferSize+ case size of+ 0 -> Right . Left <$> Win32.getLastError+ _ | size <= bufferSize ->+ Right . Right <$> Win32.peekTStringLen (ptr, fromIntegral size)+ | otherwise ->+ -- At least double the size to ensure fast termination.+ pure (Left (max size (saturatingDouble bufferSize)))+ case outcome of+ Left proposedSize -> peekTStringWith proposedSize cFunc+ Right result -> pure result -s_IRUSR :: CMode-s_IRUSR = (#const S_IRUSR)+realPath :: OsPath -> IO OsPath+realPath = getFinalPathName -s_IWUSR :: CMode-s_IWUSR = (#const S_IWUSR)+canonicalizePathSimplify :: OsPath -> IO OsPath+canonicalizePathSimplify path =+ getFullPathName path+ `catchIOError` \ _ ->+ pure path -s_IXUSR :: CMode-s_IXUSR = (#const S_IXUSR)+searchPathEnvForExes :: OsString -> IO (Maybe OsPath)+searchPathEnvForExes binaryPath@(OsString binary) = do+ maybePath <- search+ `catch` \e ->+ if ioeGetErrorType e == InvalidArgument+ then pure Nothing+ else throwIO e+ pure (OsString <$> maybePath >>= verify)+ where+ search = Win32.searchPath Nothing binary (Just (getOsString exeExtension))+ verify p+ | hasExtension binaryPath || exeExtension `isExtensionOf` p = Just p+ | otherwise = Nothing -s_IFDIR :: CMode-s_IFDIR = (#const S_IFDIR)+findExecutablesLazyInternal :: ([OsPath] -> OsString -> ListT IO OsPath)+ -> OsString+ -> ListT IO OsPath+findExecutablesLazyInternal _ = maybeToListT . searchPathEnvForExes++exeExtensionInternal :: OsString+exeExtensionInternal = exeExtension++readDirToEnd :: RawHandle -> IO [OsPath]+readDirToEnd = getDirectoryContentsInternal++getDirectoryContentsInternal :: OsPath -> IO [OsPath]+getDirectoryContentsInternal path = do+ query <- furnishPath (path </> os "*")+ bracket+ (Win32.findFirstFile query)+ (\ (h, _) -> Win32.findClose h)+ (\ (h, fdat) -> loop h fdat [])+ where+ -- we needn't worry about empty directories: a directory always+ -- has at least "." and ".." entries+ loop :: Win32.HANDLE -> Win32.FindData -> [OsPath] -> IO [OsPath]+ loop h fdat acc = do+ filename <- Win32.getFindDataFileName fdat+ more <- Win32.findNextFile h fdat+ if more+ then loop h fdat (OsString filename : acc)+ else pure (OsString filename : acc)+ -- no need to reverse, ordering is undefined++getCurrentDirectoryInternal :: IO OsPath+getCurrentDirectoryInternal = OsString <$> Win32.getCurrentDirectory++getFullPathName :: OsPath -> IO OsPath+getFullPathName path =+ fromExtendedLengthPath <$> Win32.getFullPathName (toExtendedLengthPath path)++-- | Similar to 'prependCurrentDirectory' but fails for empty paths.+rawPrependCurrentDirectory :: OsPath -> IO OsPath+rawPrependCurrentDirectory path+ | isRelative path =+ ((`ioeAddLocation` "prependCurrentDirectory") .+ (`ioeSetOsPath` path)) `modifyIOError` do+ getFullPathName path+ | otherwise = pure path++-- | Convert a path into an absolute path. If the given path is relative, the+-- current directory is prepended and the path may or may not be simplified.+-- If the path is already absolute, the path is returned unchanged. The+-- function preserves the presence or absence of the trailing path separator.+--+-- If the path is already absolute, the operation never fails. Otherwise, the+-- operation may throw exceptions.+--+-- Empty paths are treated as the current directory.+prependCurrentDirectory :: OsPath -> IO OsPath+prependCurrentDirectory = rawPrependCurrentDirectory . emptyToCurDir++-- SetCurrentDirectory does not support long paths even with the \\?\ prefix+-- https://ghc.haskell.org/trac/ghc/ticket/13373#comment:6+setCurrentDirectoryInternal :: OsPath -> IO ()+setCurrentDirectoryInternal = Win32.setCurrentDirectory . getOsString++createSymbolicLinkUnpriv :: WindowsPath -> WindowsPath -> Bool -> IO ()+createSymbolicLinkUnpriv link _target _isDir =+#ifdef HAVE_CREATESYMBOLICLINKW+ Win32.withTString link $ \ pLink ->+ Win32.withTString _target $ \ pTarget -> do+ let flags = if _isDir then win32_sYMBOLIC_LINK_FLAG_DIRECTORY else 0+ call pLink pTarget flags win32_sYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE+ where+ call pLink pTarget flags unpriv = do+ status <- c_CreateSymbolicLink pLink pTarget (flags .|. unpriv)+ when (status == 0) $ do+ e <- Win32.getLastError+ case () of+ _ | e == win32_eRROR_INVALID_FUNCTION -> do+ let msg = "Incorrect function. The underlying file system " <>+ "might not support symbolic links."+ throwIO (mkIOError illegalOperationErrorType+ "CreateSymbolicLink" Nothing Nothing+ `ioeSetOsPath` OsString link+ `ioeSetErrorString` msg)+ | e == win32_eRROR_PRIVILEGE_NOT_HELD -> do+ let msg = "A required privilege is not held by the client. " <>+ "Creating symbolic links usually requires " <>+ "administrative rights."+ throwIO (mkIOError permissionErrorType "CreateSymbolicLink"+ Nothing Nothing+ `ioeSetOsPath` OsString link+ `ioeSetErrorString` msg)+ | e == win32_eRROR_INVALID_PARAMETER &&+ unpriv /= 0 ->+ -- for compatibility with older versions of Windows,+ -- try it again without the flag+ call pLink pTarget flags 0+ | otherwise -> Win32.failWith "CreateSymbolicLink" e++foreign import WINAPI unsafe "windows.h CreateSymbolicLinkW"+ c_CreateSymbolicLink+ :: Ptr CWchar -> Ptr CWchar -> Win32.DWORD -> IO Win32.BYTE++#else+ throwIO . (`ioeSetErrorString` unsupportedErrorMsg)+ . (`ioeSetOsPath` OsString link) $+ mkIOError UnsupportedOperation "CreateSymbolicLink"+ Nothing Nothing+ where unsupportedErrorMsg = "Not supported on Windows XP or older"+#endif++linkToDirectoryIsDirectory :: Bool+linkToDirectoryIsDirectory = True++createSymbolicLink :: Bool -> OsPath -> OsPath -> IO ()+createSymbolicLink isDir target link =+ (`ioeSetOsPath` link) `modifyIOError` do+ -- normaliseSeparators ensures the target gets normalised properly+ link' <- furnishPath link+ createSymbolicLinkUnpriv+ link'+ (normaliseSeparators target)+ isDir++type Metadata = Win32.BY_HANDLE_FILE_INFORMATION++getMetadataAt :: WhetherFollow -> Maybe RawHandle -> OsPath -> IO Metadata+getMetadataAt NoFollow dir path = getSymbolicLinkMetadata (pathAt dir path)+getMetadataAt FollowLinks dir path = getFileMetadata (pathAt dir path)++getSymbolicLinkMetadata :: OsPath -> IO Metadata+getSymbolicLinkMetadata path =+ (`ioeSetOsPath` path) `modifyIOError` do+ path' <- furnishPath path+ let open = Win32.createFile path' 0 maxShareMode Nothing Win32.oPEN_EXISTING+ (Win32.fILE_FLAG_BACKUP_SEMANTICS .|.+ win32_fILE_FLAG_OPEN_REPARSE_POINT) Nothing+ bracket open Win32.closeHandle $ \ h -> do+ Win32.getFileInformationByHandle h++getFileMetadata :: OsPath -> IO Metadata+getFileMetadata path =+ (`ioeSetOsPath` path) `modifyIOError` do+ path' <- furnishPath path+ let open = Win32.createFile path' 0 maxShareMode Nothing Win32.oPEN_EXISTING+ Win32.fILE_FLAG_BACKUP_SEMANTICS Nothing+ bracket open Win32.closeHandle $ \ h -> do+ Win32.getFileInformationByHandle h++fileTypeFromMetadata :: Metadata -> FileType+fileTypeFromMetadata info+ | isLink = if isDir then DirectoryLink else SymbolicLink+ | isDir = Directory+ | otherwise = File+ where+ isLink = attrs .&. Win32.fILE_ATTRIBUTE_REPARSE_POINT /= 0+ isDir = attrs .&. Win32.fILE_ATTRIBUTE_DIRECTORY /= 0+ attrs = Win32.bhfiFileAttributes info++fileSizeFromMetadata :: Metadata -> Integer+fileSizeFromMetadata = fromIntegral . Win32.bhfiSize++accessTimeFromMetadata :: Metadata -> UTCTime+accessTimeFromMetadata =+ posixSecondsToUTCTime . windowsToPosixTime . Win32.bhfiLastAccessTime++modificationTimeFromMetadata :: Metadata -> UTCTime+modificationTimeFromMetadata =+ posixSecondsToUTCTime . windowsToPosixTime . Win32.bhfiLastWriteTime++-- | Difference between the Windows and POSIX epochs in units of 100ns.+windowsPosixEpochDifference :: Num a => a+windowsPosixEpochDifference = 116444736000000000++-- | Convert from Windows time to POSIX time.+windowsToPosixTime :: Win32.FILETIME -> POSIXTime+windowsToPosixTime (Win32.FILETIME t) =+ (fromIntegral t - windowsPosixEpochDifference) / 10000000++-- | Convert from POSIX time to Windows time. This is lossy as Windows time+-- has a resolution of only 100ns.+posixToWindowsTime :: POSIXTime -> Win32.FILETIME+posixToWindowsTime t = Win32.FILETIME $+ truncate (t * 10000000 + windowsPosixEpochDifference)++setTimes :: OsPath -> (Maybe POSIXTime, Maybe POSIXTime) -> IO ()+setTimes path' (atime', mtime') =+ bracket (openFileHandle path' Win32.gENERIC_WRITE)+ Win32.closeHandle $ \ handle ->+ Win32.setFileTime+ handle+ Nothing+ (posixToWindowsTime <$> atime')+ (posixToWindowsTime <$> mtime')++-- | Open the handle of an existing file or directory.+openFileHandle :: OsString -> Win32.AccessMode -> IO Win32.HANDLE+openFileHandle path mode =+ (`ioeSetOsPath` path) `modifyIOError` do+ path' <- furnishPath path+ Win32.createFile path' mode maxShareMode Nothing+ Win32.oPEN_EXISTING flags Nothing+ where flags = Win32.fILE_ATTRIBUTE_NORMAL+ .|. Win32.fILE_FLAG_BACKUP_SEMANTICS -- required for directories++type Mode = Win32.FileAttributeOrFlag++modeFromMetadata :: Metadata -> Mode+modeFromMetadata = Win32.bhfiFileAttributes++hasWriteMode :: Mode -> Bool+hasWriteMode m = m .&. Win32.fILE_ATTRIBUTE_READONLY == 0++setWriteMode :: Bool -> Mode -> Mode+setWriteMode False m = m .|. Win32.fILE_ATTRIBUTE_READONLY+setWriteMode True m = m .&. complement Win32.fILE_ATTRIBUTE_READONLY++setForceRemoveMode :: Mode -> Mode+setForceRemoveMode m = m .&. complement Win32.fILE_ATTRIBUTE_READONLY++setModeAt :: Maybe RawHandle -> OsPath -> Mode -> IO ()+setModeAt dir path = setFileMode (pathAt dir path)++setFileMode :: OsPath -> Mode -> IO ()+setFileMode path mode =+ (`ioeSetOsPath` path) `modifyIOError` do+ path' <- furnishPath path+ Win32.setFileAttributes path' mode++-- | A restricted form of 'setFileMode' that only sets the permission bits.+-- For Windows, this means only the "read-only" attribute is affected.+setFilePermissions :: OsPath -> Mode -> IO ()+setFilePermissions path m = do+ m' <- modeFromMetadata <$> getFileMetadata path+ setFileMode path ((m' .&. complement Win32.fILE_ATTRIBUTE_READONLY) .|.+ (m .&. Win32.fILE_ATTRIBUTE_READONLY))++getAccessPermissions :: OsPath -> IO Permissions+getAccessPermissions path = do+ m <- getFileMetadata path+ let isDir = fileTypeIsDirectory (fileTypeFromMetadata m)+ let w = hasWriteMode (modeFromMetadata m)+ let x = (toLower . toChar <$> unpack (takeExtension path))+ `elem` [".bat", ".cmd", ".com", ".exe"]+ pure Permissions+ { readable = True+ , writable = w+ , executable = x && not isDir+ , searchable = isDir+ }++setAccessPermissions :: OsPath -> Permissions -> IO ()+setAccessPermissions path Permissions{writable = w} = do+ setFilePermissions path (setWriteMode w 0)++getFolderPath :: Win32.CSIDL -> IO OsPath+getFolderPath what = OsString <$> Win32.sHGetFolderPath nullPtr what nullPtr 0++getHomeDirectoryInternal :: IO OsPath+getHomeDirectoryInternal =+ getFolderPath Win32.cSIDL_PROFILE `catchIOError` \ _ ->+ getFolderPath Win32.cSIDL_WINDOWS++getXdgDirectoryFallback :: IO OsPath -> XdgDirectory -> IO OsPath+getXdgDirectoryFallback _ xdgDir = do+ case xdgDir of+ XdgData -> getFolderPath Win32.cSIDL_APPDATA+ XdgConfig -> getFolderPath Win32.cSIDL_APPDATA+ XdgCache -> getFolderPath Win32.cSIDL_LOCAL_APPDATA+ XdgState -> getFolderPath Win32.cSIDL_LOCAL_APPDATA++getXdgDirectoryListFallback :: XdgDirectoryList -> IO [OsPath]+getXdgDirectoryListFallback _ =+ pure <$> getFolderPath win32_cSIDL_COMMON_APPDATA++getAppUserDataDirectoryInternal :: OsPath -> IO OsPath+getAppUserDataDirectoryInternal appName =+ (\ appData -> appData <> (os "\\" <> appName))+ <$> getXdgDirectoryFallback getHomeDirectoryInternal XdgData++getUserDocumentsDirectoryInternal :: IO OsPath+getUserDocumentsDirectoryInternal = getFolderPath Win32.cSIDL_PERSONAL++getTemporaryDirectoryInternal :: IO OsPath+getTemporaryDirectoryInternal = OsString <$> Win32.getTemporaryDirectory #endif
− System/Directory/Internal/utility.h
@@ -1,6 +0,0 @@-#if !defined alignof && __cplusplus < 201103L-# ifdef STDC_HEADERS-# include <stddef.h>-# endif-# define alignof(x) offsetof(struct { char c; x m; }, m)-#endif
+ System/Directory/Internal/windows_ext.h view
@@ -0,0 +1,33 @@+#ifndef HS_DIRECTORY_WINDOWS_EXT_H+#define HS_DIRECTORY_WINDOWS_EXT_H+#include <windows.h>++// define prototype to get size, offsets, and alignments+// (can't include <ntifs.h> because that only exists in WDK)+typedef struct {+ ULONG ReparseTag;+ USHORT ReparseDataLength;+ USHORT Reserved;+ union {+ struct {+ USHORT SubstituteNameOffset;+ USHORT SubstituteNameLength;+ USHORT PrintNameOffset;+ USHORT PrintNameLength;+ ULONG Flags;+ WCHAR PathBuffer[1];+ } SymbolicLinkReparseBuffer;+ struct {+ USHORT SubstituteNameOffset;+ USHORT SubstituteNameLength;+ USHORT PrintNameOffset;+ USHORT PrintNameLength;+ WCHAR PathBuffer[1];+ } MountPointReparseBuffer;+ struct {+ UCHAR DataBuffer[1];+ } GenericReparseBuffer;+ };+} HsDirectory_REPARSE_DATA_BUFFER;++#endif
+ System/Directory/OsPath.hs view
@@ -0,0 +1,1669 @@+-----------------------------------------------------------------------------+-- |+-- Module : System.Directory.OsPath+-- Copyright : (c) The University of Glasgow 2001+-- License : BSD-style (see the file libraries/base/LICENSE)+--+-- Maintainer : libraries@haskell.org+-- Stability : stable+-- Portability : portable+--+-- System-independent interface to directory manipulation.+--+-- @since 1.3.8.0+--+-----------------------------------------------------------------------------++module System.Directory.OsPath+ (+ -- $intro++ -- * Actions on directories+ createDirectory+ , createDirectoryIfMissing+ , removeDirectory+ , removeDirectoryRecursive+ , removePathForcibly+ , renameDirectory+ , listDirectory+ , getDirectoryContents+ -- ** Current working directory+ , getCurrentDirectory+ , setCurrentDirectory+ , withCurrentDirectory++ -- * Pre-defined directories+ , getHomeDirectory+ , XdgDirectory(..)+ , getXdgDirectory+ , XdgDirectoryList(..)+ , getXdgDirectoryList+ , getAppUserDataDirectory+ , getUserDocumentsDirectory+ , getTemporaryDirectory++ -- * PATH+ , getExecSearchPath++ -- * Actions on files+ , removeFile+ , renameFile+ , renamePath+ , copyFile+ , copyFileWithMetadata+ , getFileSize++ , canonicalizePath+ , makeAbsolute+ , makeRelativeToCurrentDirectory++ -- * Existence tests+ , doesPathExist+ , doesFileExist+ , doesDirectoryExist++ , findExecutable+ , findExecutables+ , findExecutablesInDirectories+ , findFile+ , findFiles+ , findFileWith+ , findFilesWith+ , exeExtension++ -- * Symbolic links+ , createFileLink+ , createDirectoryLink+ , removeDirectoryLink+ , pathIsSymbolicLink+ , getSymbolicLinkTarget++ -- * Permissions++ -- $permissions++ , Permissions+ , emptyPermissions+ , readable+ , writable+ , executable+ , searchable+ , setOwnerReadable+ , setOwnerWritable+ , setOwnerExecutable+ , setOwnerSearchable++ , getPermissions+ , setPermissions+ , copyPermissions++ -- * Timestamps++ , getAccessTime+ , getModificationTime+ , setAccessTime+ , setModificationTime++ ) where+import Prelude ()+import System.Directory.Internal+import System.Directory.Internal.Prelude+import System.OsPath+ ( (<.>)+ , (</>)+ , addTrailingPathSeparator+ , dropTrailingPathSeparator+ , hasTrailingPathSeparator+ , isAbsolute+ , joinPath+ , makeRelative+ , splitDirectories+ , splitSearchPath+ , takeDirectory+ , encodeWith+ )+import qualified Data.List.NonEmpty as NE+import Data.Time (UTCTime)+import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds)+import GHC.IO.Encoding.UTF8 ( mkUTF8 )+import GHC.IO.Encoding.UTF16 ( mkUTF16le )+import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )++{- $intro+A directory contains a series of entries, each of which is a named+reference to a file system object (file, directory etc.). Some+entries may be hidden, inaccessible, or have some administrative+function (e.g. @.@ or @..@ under+<http://www.opengroup.org/onlinepubs/009695399 POSIX>), but in+this standard all such entries are considered to form part of the+directory contents. Entries in sub-directories are not, however,+considered to form part of the directory contents.++Each file system object is referenced by a /path/. There is+normally at least one absolute path to each file system object. In+some operating systems, it may also be possible to have paths which+are relative to the current directory.++Unless otherwise documented:++* 'IO' operations in this package may throw any 'IOError'. No other types of+ exceptions shall be thrown.++* The list of possible 'IOErrorType's in the API documentation is not+ exhaustive. The full list may vary by platform and/or evolve over time.++-}++-----------------------------------------------------------------------------+-- Permissions++{- $permissions++directory offers a limited (and quirky) interface for reading and setting file+and directory permissions; see 'getPermissions' and 'setPermissions' for a+discussion of their limitations. Because permissions are very difficult to+implement portably across different platforms, users who wish to do more+sophisticated things with permissions are advised to use other,+platform-specific libraries instead. For example, if you are only interested+in permissions on POSIX-like platforms,+<https://hackage.haskell.org/package/unix/docs/System-Posix-Files.html unix>+offers much more flexibility.++ The 'Permissions' type is used to record whether certain operations are+ permissible on a file\/directory. 'getPermissions' and 'setPermissions'+ get and set these permissions, respectively. Permissions apply both to+ files and directories. For directories, the executable field will be+ 'False', and for files the searchable field will be 'False'. Note that+ directories may be searchable without being readable, if permission has+ been given to use them as part of a path, but not to examine the+ directory contents.++Note that to change some, but not all permissions, a construct on the+following lines must be used.++> makeReadable f = do+> p <- getPermissions f+> setPermissions f (p {readable = True})++-}++emptyPermissions :: Permissions+emptyPermissions = Permissions {+ readable = False,+ writable = False,+ executable = False,+ searchable = False+ }++setOwnerReadable :: Bool -> Permissions -> Permissions+setOwnerReadable b p = p { readable = b }++setOwnerWritable :: Bool -> Permissions -> Permissions+setOwnerWritable b p = p { writable = b }++setOwnerExecutable :: Bool -> Permissions -> Permissions+setOwnerExecutable b p = p { executable = b }++setOwnerSearchable :: Bool -> Permissions -> Permissions+setOwnerSearchable b p = p { searchable = b }++-- | Get the permissions of a file or directory.+--+-- On Windows, the 'writable' permission corresponds to the "read-only"+-- attribute. The 'executable' permission is set if the file extension is of+-- an executable file type. The 'readable' permission is always set.+--+-- On POSIX systems, this returns the result of @access@.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to access the+-- permissions, or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+getPermissions :: OsPath -> IO Permissions+getPermissions path =+ (`ioeAddLocation` "getPermissions") `modifyIOError` do+ getAccessPermissions (emptyToCurDir path)++-- | Set the permissions of a file or directory.+--+-- On Windows, this is only capable of changing the 'writable' permission,+-- which corresponds to the "read-only" attribute. Changing the other+-- permissions has no effect.+--+-- On POSIX systems, this sets the /owner/ permissions.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to set the permissions,+-- or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+setPermissions :: OsPath -> Permissions -> IO ()+setPermissions path p =+ (`ioeAddLocation` "setPermissions") `modifyIOError` do+ setAccessPermissions (emptyToCurDir path) p++-- | Copy the permissions of one file to another. This reproduces the+-- permissions more accurately than using 'getPermissions' followed by+-- 'setPermissions'.+--+-- On Windows, this copies only the read-only attribute.+--+-- On POSIX systems, this is equivalent to @stat@ followed by @chmod@.+copyPermissions :: OsPath -> OsPath -> IO ()+copyPermissions src dst =+ (`ioeAddLocation` "copyPermissions") `modifyIOError` do+ m <- getFileMetadata src+ copyPermissionsFromMetadata m dst++copyPermissionsFromMetadata :: Metadata -> OsPath -> IO ()+copyPermissionsFromMetadata m dst = do+ -- instead of setFileMode, setFilePermissions is used here+ -- this is to retain backward compatibility in copyPermissions+ setFilePermissions dst (modeFromMetadata m)++-----------------------------------------------------------------------------+-- Implementation++{- |@'createDirectory' dir@ creates a new directory @dir@ which is+initially empty, or as near to empty as the operating system+allows.++The operation may fail with:++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES]@++* 'isAlreadyExistsError'+The operand refers to a directory that already exists.+@ [EEXIST]@++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+The operand is not a valid directory name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+There is no path to the directory.+@[ENOENT, ENOTDIR]@++* 'System.IO.isFullError'+Insufficient resources (virtual memory, process file descriptors,+physical disk space, etc.) are available to perform the operation.+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@++* @InappropriateType@+The path refers to an existing non-directory object.+@[EEXIST]@++-}++createDirectory :: OsPath -> IO ()+createDirectory = createDirectoryInternal++-- | @'createDirectoryIfMissing' parents dir@ creates a new directory+-- @dir@ if it doesn\'t exist. If the first argument is 'True'+-- the function will also create all parent directories if they are missing.+createDirectoryIfMissing+ :: Bool -- ^ Create its parents too?+ -> OsPath -- ^ The path to the directory you want to make+ -> IO ()+createDirectoryIfMissing create_parents path0+ | create_parents = createDirs (parents path0)+ | otherwise = createDirs (take 1 (parents path0))+ where+ parents = reverse . scanl1 (</>) . splitDirectories . simplify++ createDirs [] = pure ()+ createDirs [dir] = createDir dir ioError+ createDirs (dir:dirs) =+ createDir dir $ \_ -> do+ createDirs dirs+ createDir dir ioError++ createDir dir notExistHandler = do+ r <- tryIOError (createDirectory dir)+ case r of+ Right () -> pure ()+ Left e+ | isDoesNotExistError e -> notExistHandler e+ -- createDirectory (and indeed POSIX mkdir) does not distinguish+ -- between a dir already existing and a file already existing. So we+ -- check for it here. Unfortunately there is a slight race condition+ -- here, but we think it is benign. It could report an exception in+ -- the case that the dir did exist but another process deletes the+ -- directory and creates a file in its place before we can check+ -- that the directory did indeed exist.+ -- We also follow this path when we get a permissions error, as+ -- trying to create "." when in the root directory on Windows+ -- fails with+ -- CreateDirectory ".": permission denied (Access is denied.)+ -- This caused GHCi to crash when loading a module in the root+ -- directory.+ | isAlreadyExistsError e+ || isPermissionError e -> do+ canIgnore <- pathIsDirectory dir+ `catchIOError` \ _ ->+ pure (isAlreadyExistsError e)+ unless canIgnore (ioError e)+ | otherwise -> ioError e+++{- | @'removeDirectory' dir@ removes an existing directory /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+for an implementation to partially remove a directory unless the+entire directory is removed. A conformant implementation need not+support directory removal in all situations (e.g. removal of the root+directory).++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+The operand is not a valid directory name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The directory does not exist.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY, ENOTEMPTY, EEXIST]@++* @UnsupportedOperation@+The implementation does not support removal in this situation.+@[EINVAL]@++* @InappropriateType@+The operand refers to an existing non-directory object.+@[ENOTDIR]@++-}++removeDirectory :: OsPath -> IO ()+removeDirectory = removePathInternal True++type Preremover = Maybe RawHandle -> OsPath -> Metadata -> IO ()++noPreremover :: Preremover+noPreremover _ _ _ = pure ()++forcePreremover :: Preremover+forcePreremover dir path metadata = do+ when (fileTypeIsDirectory (fileTypeFromMetadata metadata)+ || not filesAlwaysRemovable) $ do+ setModeAt dir path mode+ `catchIOError` \ _ -> pure ()+ where+ mode = setForceRemoveMode (modeFromMetadata metadata)++removeRecursivelyAt+ :: (IO () -> IO ())+ -> ([IO ()] -> IO ())+ -> Preremover+ -> Maybe RawHandle+ -> OsPath+ -> IO ()+removeRecursivelyAt catcher sequencer preremover dir name = catcher $ do+ metadata <- getMetadataAt NoFollow dir name+ preremover dir name metadata+ let+ fileType = fileTypeFromMetadata metadata+ subremovals = do+ when (fileType == Directory) $ do+ bracket (openRaw NoFollow dir name) closeRaw $ \ handle -> do+ -- dropSpecialDotDirs is extremely important! Otherwise it will+ -- recurse into the parent directory and wreak havoc.+ names <- dropSpecialDotDirs <$> readDirToEnd handle+ sequencer (recurse (Just handle) <$> names)+ sequencer [subremovals, removePathAt fileType dir name]+ where recurse = removeRecursivelyAt catcher sequencer preremover++-- | @'removeDirectoryRecursive' dir@ removes an existing directory /dir/+-- together with its contents and subdirectories. Within this directory,+-- symbolic links are removed without affecting their targets.+--+-- On Windows, the operation fails if /dir/ is a directory symbolic link.+--+-- This operation is reported to be flaky on Windows so retry logic may+-- be advisable. See: https://github.com/haskell/directory/pull/108+removeDirectoryRecursive :: OsPath -> IO ()+removeDirectoryRecursive path =+ (`ioeAddLocation` "removeDirectoryRecursive") `modifyIOError` do+ m <- getSymbolicLinkMetadata path+ case fileTypeFromMetadata m of+ Directory ->+ removeRecursivelyAt id sequenceA_ noPreremover Nothing path+ DirectoryLink ->+ ioError (err `ioeSetErrorString` "is a directory symbolic link")+ _ ->+ ioError (err `ioeSetErrorString` "not a directory")+ where err = mkIOError InappropriateType "" Nothing Nothing `ioeSetOsPath` path++-- | Removes a file or directory at /path/ together with its contents and+-- subdirectories. Symbolic links are removed without affecting their+-- targets. If the path does not exist, nothing happens.+--+-- Unlike other removal functions, this function will also attempt to delete+-- files marked as read-only or otherwise made unremovable due to permissions.+-- As a result, if the removal is incomplete, the permissions or attributes on+-- the remaining files may be altered. If there are hard links in the+-- directory, then permissions on all related hard links may be altered.+--+-- If an entry within the directory vanishes while @removePathForcibly@ is+-- running, it is silently ignored.+--+-- If an exception occurs while removing an entry, @removePathForcibly@ will+-- still try to remove as many entries as it can before failing with an+-- exception. The first exception that it encountered is re-thrown.+removePathForcibly :: OsPath -> IO ()+removePathForcibly path =+ (`ioeAddLocation` "removePathForcibly") `modifyIOError` do+ removeRecursivelyAt+ ignoreDoesNotExistError+ sequenceWithIOErrors_+ forcePreremover+ Nothing+ path++ where++ ignoreDoesNotExistError :: IO () -> IO ()+ ignoreDoesNotExistError action =+ () <$ tryIOErrorType isDoesNotExistError action++{- |'removeFile' /file/ removes the directory entry for an existing file+/file/, where /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+use by other processes).++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+The operand is not a valid file name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The file does not exist.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY]@++* @InappropriateType@+The operand refers to an existing directory.+@[EPERM, EINVAL]@++-}++removeFile :: OsPath -> IO ()+removeFile = removePathInternal False++{- |@'renameDirectory' old new@ changes the name of an existing+directory from /old/ to /new/. If the /new/ directory+already exists, it is atomically replaced by the /old/ directory.+If the /new/ directory is neither the /old/ directory nor an+alias of the /old/ directory, it is removed as if by+'removeDirectory'. A conformant implementation need not support+renaming directories in all situations (e.g. renaming to an existing+directory, or across different physical devices), but the constraints+must be documented.++On Win32 platforms, @renameDirectory@ fails if the /new/ directory already+exists.++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+Either operand is not a valid directory name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The original directory does not exist, or there is no path to the target.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* 'System.IO.isFullError'+Insufficient resources are available to perform the operation.+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY, ENOTEMPTY, EEXIST]@++* @UnsupportedOperation@+The implementation does not support renaming in this situation.+@[EINVAL, EXDEV]@++* @InappropriateType@+Either path refers to an existing non-directory object.+@[ENOTDIR, EISDIR]@++-}++renameDirectory :: OsPath -> OsPath -> IO ()+renameDirectory opath npath =+ (`ioeAddLocation` "renameDirectory") `modifyIOError` do+ -- XXX this test isn't performed atomically with the following rename+ isDir <- pathIsDirectory opath+ when (not isDir) . ioError $+ mkIOError InappropriateType "renameDirectory" Nothing Nothing+ `ioeSetErrorString` "not a directory"+ `ioeSetOsPath` opath+ renamePath opath npath++{- |@'renameFile' old new@ changes the name of an existing file system+object from /old/ to /new/. If the /new/ object already exists, it is+replaced by the /old/ object. Neither path may refer to an existing+directory.++A conformant implementation need not support renaming files in all situations+(e.g. renaming across different physical devices), but the constraints must be+documented. On Windows, this does not support renaming across different physical+devices; if you are looking to do so, consider using 'copyFileWithMetadata' and+'removeFile'.++On Windows, this calls @MoveFileEx@ with @MOVEFILE_REPLACE_EXISTING@ set,+which is not guaranteed to be atomic+(<https://github.com/haskell/directory/issues/109>).++On other platforms, this operation is atomic.++The operation may fail with:++* @HardwareFault@+A physical I\/O error has occurred.+@[EIO]@++* @InvalidArgument@+Either operand is not a valid file name.+@[ENAMETOOLONG, ELOOP]@++* 'isDoesNotExistError'+The original file does not exist, or there is no path to the target.+@[ENOENT, ENOTDIR]@++* 'isPermissionError'+The process has insufficient privileges to perform the operation.+@[EROFS, EACCES, EPERM]@++* 'System.IO.isFullError'+Insufficient resources are available to perform the operation.+@[EDQUOT, ENOSPC, ENOMEM, EMLINK]@++* @UnsatisfiedConstraints@+Implementation-dependent constraints are not satisfied.+@[EBUSY]@++* @UnsupportedOperation@+The implementation does not support renaming in this situation.+@[EXDEV]@++* @InappropriateType@+Either path refers to an existing directory.+@[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@++-}++renameFile :: OsPath -> OsPath -> IO ()+renameFile opath npath =+ (`ioeAddLocation` "renameFile") `modifyIOError` do+ -- XXX the tests are not performed atomically with the rename+ checkNotDir opath+ renamePath opath npath+ -- The underlying rename implementation can throw odd exceptions when the+ -- destination is a directory. For example, Windows typically throws a+ -- permission error, while POSIX systems may throw a resource busy error+ -- if one of the paths refers to the current directory. In these cases,+ -- we check if the destination is a directory and, if so, throw an+ -- InappropriateType error.+ `catchIOError` \ err -> do+ checkNotDir npath+ ioError err+ where checkNotDir path = do+ m <- tryIOError (getSymbolicLinkMetadata path)+ case fileTypeIsDirectory . fileTypeFromMetadata <$> m of+ Right True ->+ ioError $+ mkIOError InappropriateType "" Nothing Nothing+ `ioeSetErrorString` "is a directory"+ `ioeSetOsPath` path+ _ -> pure ()++-- | Rename a file or directory. If the destination path already exists, it+-- is replaced atomically. The destination path must not point to an existing+-- directory. A conformant implementation need not support renaming files in+-- all situations (e.g. renaming across different physical devices), but the+-- constraints must be documented.+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * @InvalidArgument@+-- Either operand is not a valid file name.+-- @[ENAMETOOLONG, ELOOP]@+--+-- * 'isDoesNotExistError'+-- The original file does not exist, or there is no path to the target.+-- @[ENOENT, ENOTDIR]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EROFS, EACCES, EPERM]@+--+-- * 'System.IO.isFullError'+-- Insufficient resources are available to perform the operation.+-- @[EDQUOT, ENOSPC, ENOMEM, EMLINK]@+--+-- * @UnsatisfiedConstraints@+-- Implementation-dependent constraints are not satisfied.+-- @[EBUSY]@+--+-- * @UnsupportedOperation@+-- The implementation does not support renaming in this situation.+-- @[EXDEV]@+--+-- * @InappropriateType@+-- Either the destination path refers to an existing directory, or one of the+-- parent segments in the destination path is not a directory.+-- @[ENOTDIR, EISDIR, EINVAL, EEXIST, ENOTEMPTY]@+renamePath :: OsPath -- ^ Old path+ -> OsPath -- ^ New path+ -> IO ()+renamePath opath npath =+ (`ioeAddLocation` "renamePath") `modifyIOError` do+ renamePathInternal opath npath++-- | Copy a file with its permissions. If the destination file already exists,+-- it is replaced atomically. Neither path may refer to an existing+-- directory. No exceptions are thrown if the permissions could not be+-- copied.+copyFile :: OsPath -- ^ Source filename+ -> OsPath -- ^ Destination filename+ -> IO ()+copyFile fromFPath toFPath =+ (`ioeAddLocation` "copyFile") `modifyIOError` do+ atomicCopyFileContents fromFPath toFPath+ (ignoreIOExceptions . copyPermissions fromFPath)++-- | Copy all data from a file to a handle.+copyFileToHandle :: OsPath -- ^ Source file+ -> Handle -- ^ Destination handle+ -> IO ()+copyFileToHandle fromFPath hTo =+ (`ioeAddLocation` "copyFileToHandle") `modifyIOError` do+ withBinaryFile fromFPath ReadMode $ \ hFrom ->+ copyHandleData hFrom hTo++-- | Copy the contents of a source file to a destination file, replacing the+-- destination file atomically via @withReplacementFile@, resetting the+-- attributes of the destination file to the defaults.+atomicCopyFileContents :: OsPath -- ^ Source filename+ -> OsPath -- ^ Destination filename+ -> (OsPath -> IO ()) -- ^ Post-action+ -> IO ()+atomicCopyFileContents fromFPath toFPath postAction =+ (`ioeAddLocation` "atomicCopyFileContents") `modifyIOError` do+ withReplacementFile toFPath postAction $ \ hTo -> do+ copyFileToHandle fromFPath hTo++-- | A helper function useful for replacing files in an atomic manner. The+-- function creates a temporary file in the directory of the destination file,+-- opens it, performs the main action with its handle, closes it, performs the+-- post-action with its path, and finally replaces the destination file with+-- the temporary file. If an error occurs during any step of this process,+-- the temporary file is removed and the destination file remains untouched.+withReplacementFile :: OsPath -- ^ Destination file+ -> (OsPath -> IO ()) -- ^ Post-action+ -> (Handle -> IO a) -- ^ Main action+ -> IO a+withReplacementFile path postAction action =+ (`ioeAddLocation` "withReplacementFile") `modifyIOError` do+ mask $ \ restore -> do+ let tmpPath = case encodeWith (mkUTF8 ErrorOnCodingFailure)+ (mkUTF16le ErrorOnCodingFailure)+ ".copyFile.tmp"+ of+ Left err ->+ error ("withReplacementFile: invalid encoding: " <> show err)+ Right p -> p+ let dir = takeDirectory path+ (tmpFPath, hTmp) <-+ openTempFile' "openTempFile'" dir tmpPath True 0o600 True+ (`onException` ignoreIOExceptions (removeFile tmpFPath)) $ do+ r <- (`onException` ignoreIOExceptions (hClose hTmp)) $ do+ restore (action hTmp)+ hClose hTmp+ restore (postAction tmpFPath)+ renameFile tmpFPath path+ pure r++-- | Copy a file with its associated metadata. If the destination file+-- already exists, it is overwritten. There is no guarantee of atomicity in+-- the replacement of the destination file. Neither path may refer to an+-- existing directory. If the source and/or destination are symbolic links,+-- the copy is performed on the targets of the links.+--+-- On Windows, it behaves like the Win32 function+-- <https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851.aspx CopyFile>,+-- which copies various kinds of metadata including file attributes and+-- security resource properties.+--+-- On Unix-like systems, permissions, access time, and modification time are+-- preserved. If possible, the owner and group are also preserved. Note that+-- the very act of copying can change the access time of the source file,+-- hence the access times of the two files may differ after the operation+-- completes.+copyFileWithMetadata :: OsPath -- ^ Source file+ -> OsPath -- ^ Destination file+ -> IO ()+copyFileWithMetadata src dst =+ (`ioeAddLocation` "copyFileWithMetadata") `modifyIOError`+ copyFileWithMetadataInternal copyPermissionsFromMetadata+ copyTimesFromMetadata+ src+ dst++copyTimesFromMetadata :: Metadata -> OsPath -> IO ()+copyTimesFromMetadata st dst = do+ let atime = accessTimeFromMetadata st+ let mtime = modificationTimeFromMetadata st+ setFileTimes dst (Just atime, Just mtime)++-- | Make a path absolute, normalize the path, and remove as many indirections+-- from it as possible. Any trailing path separators are discarded via+-- 'dropTrailingPathSeparator'. Additionally, on Windows the letter case of+-- the path is canonicalized.+--+-- __Note__: This function is a very big hammer. If you only need an absolute+-- path, 'makeAbsolute' is sufficient for removing dependence on the current+-- working directory.+--+-- Indirections include the two special directories @.@ and @..@, as well as+-- any symbolic links (and junction points on Windows). The input path need+-- not point to an existing file or directory. Canonicalization is performed+-- on the longest prefix of the path that points to an existing file or+-- directory. The remaining portion of the path that does not point to an+-- existing file or directory will still be normalized, but case+-- canonicalization and indirection removal are skipped as they are impossible+-- to do on a nonexistent path.+--+-- Most programs should not worry about the canonicity of a path. In+-- particular, despite the name, the function does not truly guarantee+-- canonicity of the returned path due to the presence of hard links, mount+-- points, etc.+--+-- If the path points to an existing file or directory, then the output path+-- shall also point to the same file or directory, subject to the condition+-- that the relevant parts of the file system do not change while the function+-- is still running. In other words, the function is definitively not atomic.+-- The results can be utterly wrong if the portions of the path change while+-- this function is running.+--+-- Since some indirections (symbolic links on all systems, @..@ on non-Windows+-- systems, and junction points on Windows) are dependent on the state of the+-- existing filesystem, the function can only make a conservative attempt by+-- removing such indirections from the longest prefix of the path that still+-- points to an existing file or directory.+--+-- Note that on Windows parent directories @..@ are always fully expanded+-- before the symbolic links, as consistent with the rest of the Windows API+-- (such as @GetFullPathName@). In contrast, on POSIX systems parent+-- directories @..@ are expanded alongside symbolic links from left to right.+-- To put this more concretely: if @L@ is a symbolic link for @R/P@, then on+-- Windows @L\\..@ refers to @.@, whereas on other operating systems @L/..@+-- refers to @R@.+--+-- Similar to 'System.FilePath.normalise', passing an empty path is equivalent+-- to passing the current directory.+--+-- @canonicalizePath@ can resolve at least 64 indirections in a single path,+-- more than what is supported by most operating systems. Therefore, it may+-- return the fully resolved path even though the operating system itself+-- would have long given up.+--+-- On Windows XP or earlier systems, junction expansion is not performed due+-- to their lack of @GetFinalPathNameByHandle@.+--+-- /Changes since 1.2.3.0:/ The function has been altered to be more robust+-- and has the same exception behavior as 'makeAbsolute'.+--+-- /Changes since 1.3.0.0:/ The function no longer preserves the trailing path+-- separator. File symbolic links that appear in the middle of a path are+-- properly dereferenced. Case canonicalization and symbolic link expansion+-- are now performed on Windows.+--+canonicalizePath :: OsPath -> IO OsPath+canonicalizePath = \ path ->+ ((`ioeAddLocation` "canonicalizePath") .+ (`ioeSetOsPath` path)) `modifyIOError` do+ -- simplify does more stuff, like upper-casing the drive letter+ dropTrailingPathSeparator . simplify <$>+ (attemptRealpath realPath =<< prependCurrentDirectory path)+ where++ -- allow up to 64 cycles before giving up+ attemptRealpath realpath =+ attemptRealpathWith (64 :: Int) Nothing realpath+ <=< canonicalizePathSimplify++ -- n is a counter to make sure we don't run into an infinite loop; we+ -- don't try to do any cycle detection here because an adversary could DoS+ -- any arbitrarily clever algorithm+ attemptRealpathWith n mFallback realpath path =+ case mFallback of+ -- too many indirections ... giving up.+ Just fallback | n <= 0 -> pure fallback+ -- either mFallback == Nothing (first attempt)+ -- or n > 0 (still have some attempts left)+ _ -> realpathPrefix (reverse (zip prefixes suffixes))++ where++ segments = splitDirectories path+ prefixes = scanl1 (</>) segments+ suffixes = NE.tail (NE.scanr (</>) mempty segments)++ -- try to call realpath on the largest possible prefix+ realpathPrefix candidates =+ case candidates of+ [] -> pure path+ (prefix, suffix) : rest -> do+ exist <- doesPathExist prefix+ if not exist+ -- never call realpath on an inaccessible path+ -- (to avoid bugs in system realpath implementations)+ -- try a smaller prefix instead+ then realpathPrefix rest+ else do+ mp <- tryIOError (realpath prefix)+ case mp of+ -- realpath failed: try a smaller prefix instead+ Left _ -> realpathPrefix rest+ -- realpath succeeded: fine-tune the result+ Right p -> realpathFurther (p </> suffix) p suffix++ -- by now we have a reasonable fallback value that we can use if we+ -- run into too many indirections; the fallback value is the same+ -- result that we have been returning in versions prior to 1.3.1.0+ -- (this is essentially the fix to #64)+ realpathFurther fallback p suffix =+ case splitDirectories suffix of+ [] -> pure fallback+ next : restSuffix -> do+ -- see if the 'next' segment is a symlink+ mTarget <- tryIOError (getSymbolicLinkTarget (p </> next))+ case mTarget of+ Left _ -> pure fallback+ Right target -> do+ -- if so, dereference it and restart the whole cycle+ let mFallback' = Just (fromMaybe fallback mFallback)+ path' <- canonicalizePathSimplify+ (p </> target </> joinPath restSuffix)+ attemptRealpathWith (n - 1) mFallback' realpath path'++-- | Convert a path into an absolute path. If the given path is relative, the+-- current directory is prepended and then the combined result is normalized.+-- If the path is already absolute, the path is simply normalized. The+-- function preserves the presence or absence of the trailing path separator+-- unless the path refers to the root directory @/@.+--+-- If the path is already absolute, the operation never fails. Otherwise, the+-- operation may fail with the same exceptions as 'getCurrentDirectory'.+--+makeAbsolute :: OsPath -> IO OsPath+makeAbsolute path =+ ((`ioeAddLocation` "makeAbsolute") .+ (`ioeSetOsPath` path)) `modifyIOError` do+ matchTrailingSeparator path . simplify <$> prependCurrentDirectory path++-- | Add or remove the trailing path separator in the second path so as to+-- match its presence in the first path.+--+-- (internal API)+matchTrailingSeparator :: OsPath -> OsPath -> OsPath+matchTrailingSeparator path+ | hasTrailingPathSeparator path = addTrailingPathSeparator+ | otherwise = dropTrailingPathSeparator++-- | Construct a path relative to the current directory, similar to+-- 'makeRelative'.+--+-- The operation may fail with the same exceptions as 'getCurrentDirectory'.+makeRelativeToCurrentDirectory :: OsPath -> IO OsPath+makeRelativeToCurrentDirectory x = do+ (`makeRelative` x) <$> getCurrentDirectory++-- | Given the name or path of an executable file, 'findExecutable' searches+-- for such a file in a list of system-defined locations, which generally+-- includes @PATH@ and possibly more. The full path to the executable is+-- returned if found. For example, @(findExecutable \"ghc\")@ would normally+-- give you the path to GHC.+--+-- The path returned by @'findExecutable' name@ corresponds to the program+-- that would be executed by+-- @<http://hackage.haskell.org/package/process/docs/System-Process.html#v:createProcess createProcess>@+-- when passed the same string (as a @RawCommand@, not a @ShellCommand@),+-- provided that @name@ is not a relative path with more than one segment.+--+-- On Windows, 'findExecutable' calls the Win32 function+-- @<https://msdn.microsoft.com/en-us/library/aa365527.aspx SearchPath>@,+-- which may search other places before checking the directories in the @PATH@+-- environment variable. Where it actually searches depends on registry+-- settings, but notably includes the directory containing the current+-- executable.+--+-- On non-Windows platforms, the behavior is equivalent to 'findFileWith'+-- using the search directories from the @PATH@ environment variable and+-- testing each file for executable permissions. Details can be found in the+-- documentation of 'findFileWith'.+findExecutable :: OsString -> IO (Maybe OsPath)+findExecutable binary =+ listTHead+ (findExecutablesLazyInternal findExecutablesInDirectoriesLazy binary)++-- | Search for executable files in a list of system-defined locations, which+-- generally includes @PATH@ and possibly more.+--+-- On Windows, this /only returns the first occurrence/, if any. Its behavior+-- is therefore equivalent to 'findExecutable'.+--+-- On non-Windows platforms, the behavior is equivalent to+-- 'findExecutablesInDirectories' using the search directories from the @PATH@+-- environment variable. Details can be found in the documentation of+-- 'findExecutablesInDirectories'.+findExecutables :: OsString -> IO [OsPath]+findExecutables binary =+ listTToList+ (findExecutablesLazyInternal findExecutablesInDirectoriesLazy binary)++-- | Given a name or path, 'findExecutable' appends the 'exeExtension' to the+-- query and searches for executable files in the list of given search+-- directories and returns all occurrences.+--+-- The behavior is equivalent to 'findFileWith' using the given search+-- directories and testing each file for executable permissions. Details can+-- be found in the documentation of 'findFileWith'.+--+-- Unlike other similarly named functions, 'findExecutablesInDirectories' does+-- not use @SearchPath@ from the Win32 API. The behavior of this function on+-- Windows is therefore equivalent to those on non-Windows platforms.+findExecutablesInDirectories :: [OsPath] -> OsString -> IO [OsPath]+findExecutablesInDirectories path binary =+ listTToList (findExecutablesInDirectoriesLazy path binary)++findExecutablesInDirectoriesLazy :: [OsPath] -> OsString -> ListT IO OsPath+findExecutablesInDirectoriesLazy path binary =+ findFilesWithLazy isExecutable path (binary <.> exeExtension)++-- | Test whether a file has executable permissions.+isExecutable :: OsPath -> IO Bool+isExecutable file = executable <$> getPermissions file++-- | Search through the given list of directories for the given file.+--+-- The behavior is equivalent to 'findFileWith', returning only the first+-- occurrence. Details can be found in the documentation of 'findFileWith'.+findFile :: [OsPath] -> OsString -> IO (Maybe OsPath)+findFile = findFileWith (\ _ -> pure True)++-- | Search through the given list of directories for the given file and+-- returns all paths where the given file exists.+--+-- The behavior is equivalent to 'findFilesWith'. Details can be found in the+-- documentation of 'findFilesWith'.+findFiles :: [OsPath] -> OsString -> IO [OsPath]+findFiles = findFilesWith (\ _ -> pure True)++-- | Search through a given list of directories for a file that has the given+-- name and satisfies the given predicate and return the path of the first+-- occurrence. The directories are checked in a left-to-right order.+--+-- This is essentially a more performant version of 'findFilesWith' that+-- always returns the first result, if any. Details can be found in the+-- documentation of 'findFilesWith'.+findFileWith :: (OsPath -> IO Bool) -> [OsPath] -> OsString -> IO (Maybe OsPath)+findFileWith f ds name = listTHead (findFilesWithLazy f ds name)++-- | @findFilesWith predicate dirs name@ searches through the list of+-- directories (@dirs@) for files that have the given @name@ and satisfy the+-- given @predicate@ and returns the paths of those files. The directories+-- are checked in a left-to-right order and the paths are returned in the same+-- order.+--+-- If the @name@ is a relative path, then for every search directory @dir@,+-- the function checks whether @dir '</>' name@ exists and satisfies the+-- predicate. If so, @dir '</>' name@ is returned as one of the results. In+-- other words, the returned paths can be either relative or absolute+-- depending on the search directories were used. If there are no search+-- directories, no results are ever returned.+--+-- If the @name@ is an absolute path, then the function will return a single+-- result if the file exists and satisfies the predicate and no results+-- otherwise. This is irrespective of what search directories were given.+findFilesWith :: (OsPath -> IO Bool) -> [OsPath] -> OsString -> IO [OsPath]+findFilesWith f ds name = listTToList (findFilesWithLazy f ds name)++findFilesWithLazy+ :: (OsPath -> IO Bool) -> [OsPath] -> OsString -> ListT IO OsPath+findFilesWithLazy f dirs path+ -- make sure absolute paths are handled properly irrespective of 'dirs'+ -- https://github.com/haskell/directory/issues/72+ | isAbsolute path = ListT (find [mempty])+ | otherwise = ListT (find dirs)++ where++ find [] = pure Nothing+ find (d : ds) = do+ let p = d </> path+ found <- doesFileExist p `andM` f p+ if found+ then pure (Just (p, ListT (find ds)))+ else find ds++-- | Filename extension for executable files (including the dot if any)+-- (usually @\"\"@ on POSIX systems and @\".exe\"@ on Windows or OS\/2).+exeExtension :: OsString+exeExtension = exeExtensionInternal++-- | Similar to 'listDirectory', but always includes the special entries (@.@+-- and @..@). (This applies to Windows as well.)+--+-- The operation may fail with the same exceptions as 'listDirectory'.+getDirectoryContents :: OsPath -> IO [OsPath]+getDirectoryContents path =+ ((`ioeSetOsPath` path) .+ (`ioeAddLocation` "getDirectoryContents")) `modifyIOError` do+ getDirectoryContentsInternal path++-- | @'listDirectory' dir@ returns a list of /all/ entries in /dir/ without+-- the special entries (@.@ and @..@).+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * @InvalidArgument@+-- The operand is not a valid directory name.+-- @[ENAMETOOLONG, ELOOP]@+--+-- * 'isDoesNotExistError'+-- The directory does not exist.+-- @[ENOENT, ENOTDIR]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EACCES]@+--+-- * 'System.IO.isFullError'+-- Insufficient resources are available to perform the operation.+-- @[EMFILE, ENFILE]@+--+-- * @InappropriateType@+-- The path refers to an existing non-directory object.+-- @[ENOTDIR]@+--+listDirectory :: OsPath -> IO [OsPath]+listDirectory path = dropSpecialDotDirs <$> getDirectoryContents path++-- | Obtain the current working directory as an absolute path.+--+-- In a multithreaded program, the current working directory is a global state+-- shared among all threads of the process. Therefore, when performing+-- filesystem operations from multiple threads, it is highly recommended to+-- use absolute rather than relative paths (see: 'makeAbsolute').+--+-- Note that 'getCurrentDirectory' is not guaranteed to return the same path+-- received by 'setCurrentDirectory'. On POSIX systems, the path returned will+-- always be fully dereferenced (not contain any symbolic links). For more+-- information, refer to the documentation of+-- <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html getcwd>.+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * 'isDoesNotExistError'+-- There is no path referring to the working directory.+-- @[EPERM, ENOENT, ESTALE...]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EACCES]@+--+-- * 'System.IO.isFullError'+-- Insufficient resources are available to perform the operation.+--+-- * @UnsupportedOperation@+-- The operating system has no notion of current working directory.+--+getCurrentDirectory :: IO OsPath+getCurrentDirectory =+ (`ioeAddLocation` "getCurrentDirectory") `modifyIOError` do+ specializeErrorString+ "Current working directory no longer exists"+ isDoesNotExistError+ getCurrentDirectoryInternal++-- | Change the working directory to the given path.+--+-- In a multithreaded program, the current working directory is a global state+-- shared among all threads of the process. Therefore, when performing+-- filesystem operations from multiple threads, it is highly recommended to+-- use absolute rather than relative paths (see: 'makeAbsolute').+--+-- The operation may fail with:+--+-- * @HardwareFault@+-- A physical I\/O error has occurred.+-- @[EIO]@+--+-- * @InvalidArgument@+-- The operand is not a valid directory name.+-- @[ENAMETOOLONG, ELOOP]@+--+-- * 'isDoesNotExistError'+-- The directory does not exist.+-- @[ENOENT, ENOTDIR]@+--+-- * 'isPermissionError'+-- The process has insufficient privileges to perform the operation.+-- @[EACCES]@+--+-- * @UnsupportedOperation@+-- The operating system has no notion of current working directory, or the+-- working directory cannot be dynamically changed.+--+-- * @InappropriateType@+-- The path refers to an existing non-directory object.+-- @[ENOTDIR]@+--+setCurrentDirectory :: OsPath -> IO ()+setCurrentDirectory = setCurrentDirectoryInternal++-- | Run an 'IO' action with the given working directory and restore the+-- original working directory afterwards, even if the given action fails due+-- to an exception.+--+-- The operation may fail with the same exceptions as 'getCurrentDirectory'+-- and 'setCurrentDirectory'.+--+withCurrentDirectory :: OsPath -- ^ Directory to execute in+ -> IO a -- ^ Action to be executed+ -> IO a+withCurrentDirectory dir action =+ bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do+ setCurrentDirectory dir+ action++-- | Obtain the size of a file in bytes.+getFileSize :: OsPath -> IO Integer+getFileSize path =+ (`ioeAddLocation` "getFileSize") `modifyIOError` do+ fileSizeFromMetadata <$> getFileMetadata path++-- | Test whether the given path points to an existing filesystem object. If+-- the user lacks necessary permissions to search the parent directories, this+-- function may return false even if the file does actually exist. This+-- operation traverses symbolic links, so it can return either True or False+-- for them.+doesPathExist :: OsPath -> IO Bool+doesPathExist path = do+ (True <$ getFileMetadata path)+ `catchIOError` \ _ ->+ pure False++-- | The operation 'doesDirectoryExist' returns 'True' if the argument file+-- exists and is either a directory or a symbolic link to a directory, and+-- 'False' otherwise. This operation traverses symbolic links, so it can+-- return either True or False for them.+doesDirectoryExist :: OsPath -> IO Bool+doesDirectoryExist path = do+ pathIsDirectory path+ `catchIOError` \ _ ->+ pure False++-- | The operation 'doesFileExist' returns 'True' if the argument file exists+-- and is not a directory, and 'False' otherwise. This operation traverses+-- symbolic links, so it can return either True or False for them.+doesFileExist :: OsPath -> IO Bool+doesFileExist path = do+ (not <$> pathIsDirectory path)+ `catchIOError` \ _ ->+ pure False++pathIsDirectory :: OsPath -> IO Bool+pathIsDirectory path =+ (`ioeAddLocation` "pathIsDirectory") `modifyIOError` do+ fileTypeIsDirectory . fileTypeFromMetadata <$> getFileMetadata path++-- | Create a /file/ symbolic link. The target path can be either absolute or+-- relative and need not refer to an existing file. The order of arguments+-- follows the POSIX convention.+--+-- To remove an existing file symbolic link, use 'removeFile'.+--+-- Although the distinction between /file/ symbolic links and /directory/+-- symbolic links does not exist on POSIX systems, on Windows this is an+-- intrinsic property of every symbolic link and cannot be changed without+-- recreating the link. A file symbolic link that actually points to a+-- directory will fail to dereference and vice versa. Moreover, creating+-- symbolic links on Windows may require privileges unavailable to users+-- outside the Administrators group. Portable programs that use symbolic+-- links should take both into consideration.+--+-- On Windows, the function is implemented using @CreateSymbolicLink@. Since+-- 1.3.3.0, the @SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE@ flag is included+-- if supported by the operating system. On POSIX, the function uses @symlink@+-- and is therefore atomic.+--+-- Windows-specific errors: This operation may fail with 'permissionErrorType'+-- if the user lacks the privileges to create symbolic links. It may also+-- fail with 'illegalOperationErrorType' if the file system does not support+-- symbolic links.+createFileLink+ :: OsPath -- ^ path to the target file+ -> OsPath -- ^ path of the link to be created+ -> IO ()+createFileLink target link =+ (`ioeAddLocation` "createFileLink") `modifyIOError` do+ createSymbolicLink False target link++-- | Create a /directory/ symbolic link. The target path can be either+-- absolute or relative and need not refer to an existing directory. The+-- order of arguments follows the POSIX convention.+--+-- To remove an existing directory symbolic link, use 'removeDirectoryLink'.+--+-- Although the distinction between /file/ symbolic links and /directory/+-- symbolic links does not exist on POSIX systems, on Windows this is an+-- intrinsic property of every symbolic link and cannot be changed without+-- recreating the link. A file symbolic link that actually points to a+-- directory will fail to dereference and vice versa. Moreover, creating+-- symbolic links on Windows may require privileges unavailable to users+-- outside the Administrators group. Portable programs that use symbolic+-- links should take both into consideration.+--+-- On Windows, the function is implemented using @CreateSymbolicLink@ with+-- @SYMBOLIC_LINK_FLAG_DIRECTORY@. Since 1.3.3.0, the+-- @SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE@ flag is also included if+-- supported by the operating system. On POSIX, this is an alias for+-- 'createFileLink' and is therefore atomic.+--+-- Windows-specific errors: This operation may fail with 'permissionErrorType'+-- if the user lacks the privileges to create symbolic links. It may also+-- fail with 'illegalOperationErrorType' if the file system does not support+-- symbolic links.+createDirectoryLink+ :: OsPath -- ^ path to the target directory+ -> OsPath -- ^ path of the link to be created+ -> IO ()+createDirectoryLink target link =+ (`ioeAddLocation` "createDirectoryLink") `modifyIOError` do+ createSymbolicLink True target link++-- | Remove an existing /directory/ symbolic link.+--+-- On Windows, this is an alias for 'removeDirectory'. On POSIX systems, this+-- is an alias for 'removeFile'.+--+-- See also: 'removeFile', which can remove an existing /file/ symbolic link.+removeDirectoryLink :: OsPath -> IO ()+removeDirectoryLink path =+ (`ioeAddLocation` "removeDirectoryLink") `modifyIOError` do+ removePathInternal linkToDirectoryIsDirectory path++-- | Check whether an existing @path@ is a symbolic link. If @path@ is a+-- regular file or directory, 'False' is returned. If @path@ does not exist+-- or is otherwise inaccessible, an exception is thrown (see below).+--+-- On Windows, this checks for @FILE_ATTRIBUTE_REPARSE_POINT@. In addition to+-- symbolic links, the function also returns true on junction points. On+-- POSIX systems, this checks for @S_IFLNK@.+--+-- The operation may fail with:+--+-- * 'isDoesNotExistError' if the symbolic link does not exist; or+--+-- * 'isPermissionError' if the user is not permitted to read the symbolic+-- link.+pathIsSymbolicLink :: OsPath -> IO Bool+pathIsSymbolicLink path =+ ((`ioeAddLocation` "pathIsSymbolicLink") .+ (`ioeSetOsPath` path)) `modifyIOError` do+ fileTypeIsLink . fileTypeFromMetadata <$> getSymbolicLinkMetadata path++-- | Retrieve the target path of either a file or directory symbolic link.+-- The returned path may not be absolute, may not exist, and may not even be a+-- valid path.+--+-- On Windows systems, this calls @DeviceIoControl@ with+-- @FSCTL_GET_REPARSE_POINT@. In addition to symbolic links, the function+-- also works on junction points. On POSIX systems, this calls @readlink@.+--+-- Windows-specific errors: This operation may fail with+-- 'illegalOperationErrorType' if the file system does not support symbolic+-- links.+getSymbolicLinkTarget :: OsPath -> IO OsPath+getSymbolicLinkTarget path =+ (`ioeAddLocation` "getSymbolicLinkTarget") `modifyIOError` do+ readSymbolicLink path++-- | Obtain the time at which the file or directory was last accessed.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to read+-- the access time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- Caveat for POSIX systems: This function returns a timestamp with sub-second+-- resolution only if this package is compiled against @unix-2.6.0.0@ or later+-- and the underlying filesystem supports them.+--+getAccessTime :: OsPath -> IO UTCTime+getAccessTime path =+ (`ioeAddLocation` "getAccessTime") `modifyIOError` do+ accessTimeFromMetadata <$> getFileMetadata (emptyToCurDir path)++-- | Obtain the time at which the file or directory was last modified.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to read+-- the modification time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- Caveat for POSIX systems: This function returns a timestamp with sub-second+-- resolution only if this package is compiled against @unix-2.6.0.0@ or later+-- and the underlying filesystem supports them.+--+getModificationTime :: OsPath -> IO UTCTime+getModificationTime path =+ (`ioeAddLocation` "getModificationTime") `modifyIOError` do+ modificationTimeFromMetadata <$> getFileMetadata (emptyToCurDir path)++-- | Change the time at which the file or directory was last accessed.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to alter the+-- access time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- Some caveats for POSIX systems:+--+-- * Not all systems support @utimensat@, in which case the function can only+-- emulate the behavior by reading the modification time and then setting+-- both the access and modification times together. On systems where+-- @utimensat@ is supported, the access time is set atomically with+-- nanosecond precision.+--+-- * If compiled against a version of @unix@ prior to @2.7.0.0@, the function+-- would not be able to set timestamps with sub-second resolution. In this+-- case, there would also be loss of precision in the modification time.+--+setAccessTime :: OsPath -> UTCTime -> IO ()+setAccessTime path atime =+ (`ioeAddLocation` "setAccessTime") `modifyIOError` do+ setFileTimes path (Just atime, Nothing)++-- | Change the time at which the file or directory was last modified.+--+-- The operation may fail with:+--+-- * 'isPermissionError' if the user is not permitted to alter the+-- modification time; or+--+-- * 'isDoesNotExistError' if the file or directory does not exist.+--+-- * 'InvalidArgument' on FAT32 file system if the time is before+-- DOS Epoch (1 January 1980).+--+-- Some caveats for POSIX systems:+--+-- * Not all systems support @utimensat@, in which case the function can only+-- emulate the behavior by reading the access time and then setting both the+-- access and modification times together. On systems where @utimensat@ is+-- supported, the modification time is set atomically with nanosecond+-- precision.+--+-- * If compiled against a version of @unix@ prior to @2.7.0.0@, the function+-- would not be able to set timestamps with sub-second resolution. In this+-- case, there would also be loss of precision in the access time.+--+setModificationTime :: OsPath -> UTCTime -> IO ()+setModificationTime path mtime =+ (`ioeAddLocation` "setModificationTime") `modifyIOError` do+ setFileTimes path (Nothing, Just mtime)++setFileTimes :: OsPath -> (Maybe UTCTime, Maybe UTCTime) -> IO ()+setFileTimes _ (Nothing, Nothing) = pure ()+setFileTimes path (atime, mtime) =+ ((`ioeAddLocation` "setFileTimes") .+ (`ioeSetOsPath` path)) `modifyIOError` do+ setTimes (emptyToCurDir path)+ (utcTimeToPOSIXSeconds <$> atime, utcTimeToPOSIXSeconds <$> mtime)++{- | Returns the current user's home directory.++The directory returned is expected to be writable by the current user,+but note that it isn't generally considered good practice to store+application-specific data here; use 'getXdgDirectory' or+'getAppUserDataDirectory' instead.++On Unix, 'getHomeDirectory' behaves as follows:++* Returns $HOME env variable if set (including to an empty string).+* Otherwise uses home directory returned by @getpwuid_r@ using the UID of the+ current process' user. This basically reads the @\/etc\/passwd@ file. An+ empty home directory field is considered valid.++On Windows, the system is queried for a suitable path; a typical path might be+@C:\/Users\//\<user\>/@.++The operation may fail with:++* @UnsupportedOperation@+The operating system has no notion of home directory.++* 'isDoesNotExistError'+The home directory for the current user does not exist, or+cannot be found.+-}+getHomeDirectory :: IO OsPath+getHomeDirectory =+ (`ioeAddLocation` "getHomeDirectory") `modifyIOError` do+ getHomeDirectoryInternal++-- | Obtain the paths to special directories for storing user-specific+-- application data, configuration, and cache files, conforming to the+-- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.+-- Compared with 'getAppUserDataDirectory', this function provides a more+-- fine-grained hierarchy as well as greater flexibility for the user.+--+-- On Windows, 'XdgData' and 'XdgConfig' usually map to the same directory+-- unless overridden.+--+-- Refer to the docs of 'XdgDirectory' for more details.+--+-- The second argument is usually the name of the application. Since it+-- will be integrated into the path, it must consist of valid path+-- characters. Note: if the second argument is an absolute path, it will+-- just return the second argument.+--+-- Note: The directory may not actually exist, in which case you would need+-- to create it with file mode @700@ (i.e. only accessible by the owner).+--+-- As of 1.3.5.0, the environment variable is ignored if set to a relative+-- path, per revised XDG Base Directory Specification. See+-- <https://github.com/haskell/directory/issues/100 #100>.+getXdgDirectory :: XdgDirectory -- ^ which special directory+ -> OsPath -- ^ a relative path that is appended+ -- to the path; if empty, the base+ -- path is returned+ -> IO OsPath+getXdgDirectory xdgDir suffix =+ (`ioeAddLocation` "getXdgDirectory") `modifyIOError` do+ simplify . (</> suffix) <$> do+ env <- lookupEnvOs $ case xdgDir of+ XdgData -> os "XDG_DATA_HOME"+ XdgConfig -> os "XDG_CONFIG_HOME"+ XdgCache -> os "XDG_CACHE_HOME"+ XdgState -> os "XDG_STATE_HOME"+ case env of+ Just path | isAbsolute path -> pure path+ _ -> getXdgDirectoryFallback getHomeDirectory xdgDir++-- | Similar to 'getXdgDirectory' but retrieves the entire list of XDG+-- directories.+--+-- On Windows, 'XdgDataDirs' and 'XdgConfigDirs' usually map to the same list+-- of directories unless overridden.+--+-- Refer to the docs of 'XdgDirectoryList' for more details.+getXdgDirectoryList :: XdgDirectoryList -- ^ which special directory list+ -> IO [OsPath]+getXdgDirectoryList xdgDirs =+ (`ioeAddLocation` "getXdgDirectoryList") `modifyIOError` do+ env <- lookupEnvOs $ case xdgDirs of+ XdgDataDirs -> os "XDG_DATA_DIRS"+ XdgConfigDirs -> os "XDG_CONFIG_DIRS"+ case env of+ Nothing -> getXdgDirectoryListFallback xdgDirs+ Just paths -> pure (splitSearchPath paths)++-- | Obtain the path to a special directory for storing user-specific+-- application data (traditional Unix location). Newer applications may+-- prefer the the XDG-conformant location provided by 'getXdgDirectory'+-- (<https://github.com/haskell/directory/issues/6#issuecomment-96521020 migration guide>).+--+-- The argument is usually the name of the application. Since it will be+-- integrated into the path, it must consist of valid path characters.+--+-- * On Unix-like systems, the path is @~\/./\<app\>/@.+-- * On Windows, the path is @%APPDATA%\//\<app\>/@+-- (e.g. @C:\/Users\//\<user\>/\/AppData\/Roaming\//\<app\>/@)+--+-- Note: the directory may not actually exist, in which case you would need+-- to create it. It is expected that the parent directory exists and is+-- writable.+--+-- The operation may fail with:+--+-- * @UnsupportedOperation@+-- The operating system has no notion of application-specific data+-- directory.+--+-- * 'isDoesNotExistError'+-- The home directory for the current user does not exist, or cannot be+-- found.+--+getAppUserDataDirectory :: OsPath -- ^ a relative path that is appended+ -- to the path+ -> IO OsPath+getAppUserDataDirectory appName = do+ (`ioeAddLocation` "getAppUserDataDirectory") `modifyIOError` do+ getAppUserDataDirectoryInternal appName++{- | Returns the current user's document directory.++The directory returned is expected to be writable by the current user,+but note that it isn't generally considered good practice to store+application-specific data here; use 'getXdgDirectory' or+'getAppUserDataDirectory' instead.++On Unix, 'getUserDocumentsDirectory' returns the value of the @HOME@+environment variable. On Windows, the system is queried for a+suitable path; a typical path might be @C:\/Users\//\<user\>/\/Documents@.++The operation may fail with:++* @UnsupportedOperation@+The operating system has no notion of document directory.++* 'isDoesNotExistError'+The document directory for the current user does not exist, or+cannot be found.+-}+getUserDocumentsDirectory :: IO OsPath+getUserDocumentsDirectory = do+ (`ioeAddLocation` "getUserDocumentsDirectory") `modifyIOError` do+ getUserDocumentsDirectoryInternal++{- | Returns the current directory for temporary files.++On Unix, 'getTemporaryDirectory' returns the value of the @TMPDIR@+environment variable or \"\/tmp\" if the variable isn\'t defined.+On Windows, the function checks for the existence of environment variables in+the following order and uses the first path found:++*+TMP environment variable.++*+TEMP environment variable.++*+USERPROFILE environment variable.++*+The Windows directory++The operation may fail with:++* @UnsupportedOperation@+The operating system has no notion of temporary directory.++The function doesn\'t verify whether the path exists.+-}+getTemporaryDirectory :: IO OsPath+getTemporaryDirectory = getTemporaryDirectoryInternal++-- | Get the contents of the @PATH@ environment variable.+getExecSearchPath :: IO [OsPath]+getExecSearchPath = getPath
changelog.md view
@@ -1,13 +1,259 @@ Changelog for the [`directory`][1] package ========================================== +## 1.3.11.0 (May 2026)++ * Cabal flag `os-string` was removed in favor of `impl(ghc >= 9.2)`.+ ([#176](https://github.com/haskell/directory/issues/176))+ * Enable close-on-exec flag when copying files and relax `file-io` version+ bounds to support 0.2.0. Note that close-on-exec when copying is only+ enabled on `file-io` 0.2.0 or later.+ ([#203](https://github.com/haskell/directory/issues/203))+ * Relax `time` version bounds to support 1.16.++## 1.3.10.1 (Jan 2026)++ * Make `findExecutable` return `Nothing` on absolute paths that aren't+ executable.+ ([#187](https://github.com/haskell/directory/issues/187))+ * Ensure `removePathForcibly` removes write-protected files on all+ platforms.+ ([#194](https://github.com/haskell/directory/issues/194))++## 1.3.10.0 (Dec 2025)++ * Add `getExecSearchPath` as replacement for+ `System.FilePath.getSearchPath`.+ ([#198](https://github.com/haskell/directory/pull/198))+ * The [extended-length prefix][extended-length prefix] (`\\?\`) is no longer+ implicitly prepended to Windows UNC paths to avoid triggering a Win32+ implementation bug. Clients using long UNC paths should find alternatives+ to [enable long paths][enable long paths].+ ([#206](https://github.com/haskell/directory/issues/206))++[extended-length prefix]: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation#:~:text=%5C%5C%3F%5C+[enable long paths]: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation#enable-long-paths-in-windows-10-version-1607-and-later++## 1.3.9.0 (Oct 2024)++ * Rely on `file-io` for file I/O.+ * Drop support for `base` older than 4.12.0.+ * Resolve TOCTOU issue with `removeDirectoryRecursive` and+ `removePathForcibly` on POSIX systems.+ (part of [#97](https://github.com/haskell/directory/issues/97))+ * `findExecutable ""` now returns `Nothing`, matching non-Windows systems+ ([#180](https://github.com/haskell/directory/issues/180))++## 1.3.8.5 (May 2024)++ * Fix regression that causes copying of nonexistent files to create empty+ files.+ ([#177](https://github.com/haskell/directory/issues/177))++## 1.3.8.4 (Apr 2024)++ * Relax `time` version bounds to support 1.14.+ ([#171](https://github.com/haskell/directory/issues/171))+ * Relax `base` version bounds to support 4.20.+ ([#173](https://github.com/haskell/directory/issues/173))+ * Relax `filepath` version bounds to support 1.4.300 when `os-string` is+ unavailable.+ ([#175](https://github.com/haskell/directory/issues/175))++## 1.3.8.3 (Jan 2024)++ * Relax `Win32` version bounds to support 2.14.0.0.+ ([#166](https://github.com/haskell/directory/issues/166))+ * Fix regression in `canonicalizePath` on Windows UNC paths.+ ([#170](https://github.com/haskell/directory/issues/170))++## 1.3.8.2 (Dec 2023)++ * Relax `base` version bounds to support 4.19.+ ([#157](https://github.com/haskell/directory/pull/157))+ * Support filepath >= 1.5.0.0 and os-string.+ ([#164](https://github.com/haskell/directory/issues/164))++## 1.3.8.1 (Feb 2023)++ * Use CApiFFI for utimensat.+ ([#145](https://github.com/haskell/directory/pull/145))+ * Relax `base` version bounds to support 4.18.+ ([#151](https://github.com/haskell/directory/pull/151))++## 1.3.8.0 (Sep 2022)++ * Drop support for `base` older than 4.11.0.+ * Drop support for `filepath` older than 1.4.100.+ * Drop support for `time` older than 1.8.0.+ * Drop support for `unix` older than 2.8.0.+ * Drop support for `Win32` older than 2.13.3.+ * Modules in `directory` are no longer considered+ [Safe](https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/safe_haskell.html)+ because the `System.OsPath` dependency is no longer Safe.+ * A new module, `System.Directory.OsPath`, has been introduced to support+ AFPP (`OsPath` and `OsString`) with an analogous API. The old module,+ `System.Directory`, shall be in maintenance mode as new features will no+ longer be accepted there.+ ([#136](https://github.com/haskell/directory/pull/136))+ * `removePathForcibly` no longer changes permissions of files on non-Windows+ systems. ([#135](https://github.com/haskell/directory/issues/135))++## 1.3.7.1 (Jul 2022)++ * Relax `time` version bounds to support 1.12.+ * Relax `Win32` version bounds to support 2.13.+ * Relax `base` version bounds to support 4.17.++## 1.3.7.0 (Sep 2021)++ * `getXdgDirectory` now supports `XdgState` (`XDG_STATE_HOME`).+ ([#121](https://github.com/haskell/directory/pull/121))++## 1.3.6.2 (May 2021)++ * Relax `Win32` version bounds to support 2.11.+ * Relax `time` version bounds to support 1.11.+ * Relax `base` version bounds to support 4.16.++## 1.3.6.1 (March 2020)++ * Relax `time` version bounds to support 1.10.++## 1.3.6.0 (January 2020)++ * On non-Windows platforms, `getHomeDirectory` will fall back to+ `getpwuid_r` if `HOME` is not set.+ ([#102](https://github.com/haskell/directory/issues/102))++## 1.3.5.0 (December 2019)++ * Revert change introduced in the version `1.3.3.2`: Non-absolute `XDG_*`+ environment variables are ignored. This behavior is according to+ [*XDG Base Directory Specification* version 0.7](https://specifications.freedesktop.org/basedir-spec/0.7/ar01s02.html)+ ([#100](https://github.com/haskell/directory/issues/100))++## 1.3.4.0 (July 2019)++ * `getXdgDirectory` and `getXdgDirectoryList` on Windows will now respect+ the XDG environment variables if present.+ ([#95](https://github.com/haskell/directory/issues/95))++## 1.3.3.2 (January 2019)++ * `getXdgDirectory` will no longer reject environment variables containing+ relative paths.+ ([#87](https://github.com/haskell/directory/issues/87))++## 1.3.3.1 (August 2018)++ * `doesDirectoryExist` and `doesPathExist` reject empty paths once again,+ reversing an undocumented change introduced in 1.3.1.1.+ ([#84](https://github.com/haskell/directory/issues/84))++## 1.3.3.0 (June 2018)++ * Relax `unix` version bounds to support 2.8.++ * Relax `Win32` version bounds to support 2.8.++ * Use `SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE` when creating symbolic+ links on Windows, if possible.+ ([#83](https://github.com/haskell/directory/issues/83))++## 1.3.2.2 (April 2018)++ * Relax `base` version bounds to support 4.12.++## 1.3.2.1 (March 2018)++ * Relax `Win32` version bounds to support 2.7.++## 1.3.2.0 (January 2018)++ * Relax `time` version bounds to support 1.9.++ * Implement `getXdgDirectoryList` and `XdgDirectoryList`.+ ([#78](https://github.com/haskell/directory/issues/78))++## 1.3.1.5 (October 2017)++ * Rename the internal header `windows.h` to avoid GHC#14312.+ ([#77](https://github.com/haskell/directory/issues/77))++## 1.3.1.4 (September 2017)++ * Fix `Win32` version 2.6 compatibility.+ ([#75](https://github.com/haskell/directory/pull/75))++## 1.3.1.3 (September 2017)++ * Relax `Win32` version bounds to support 2.6.++## 1.3.1.2 (September 2017)++ * Relax `base` version bounds to support 4.11.+ ([#74](https://github.com/haskell/directory/pull/74))++## 1.3.1.1 (March 2017)++ * Fix a bug where `createFileLink` and `createDirectoryLink` failed to+ handle `..` in absolute paths.++ * Improve support (partially) for paths longer than 260 characters on+ Windows. To achieve this, many functions will now automatically prepend+ `\\?\` before calling the Windows API. As a side effect, the `\\?\`+ prefix may show up in the error messages of the affected functions.++ * `makeAbsolute` can now handle drive-relative paths on Windows such as+ `C:foobar`++## 1.3.1.0 (March 2017)++ * `findFile` (and similar functions): when an absolute path is given, the+ list of search directories is now completely ignored. Previously, if the+ list was empty, `findFile` would always fail.+ ([#72](https://github.com/haskell/directory/issues/72))++ * For symbolic links on Windows, the following functions had previously+ interpreted paths as referring to the links themselves rather than their+ targets. This was inconsistent with other platforms and has been fixed.+ * `getFileSize`+ * `doesPathExist`+ * `doesDirectoryExist`+ * `doesFileExist`++ * Fix incorrect location info in errors from `pathIsSymbolicLink`.++ * Add functions for symbolic link manipulation:+ * `createFileLink`+ * `createDirectoryLink`+ * `removeDirectoryLink`+ * `getSymbolicLinkTarget`++ * `canonicalizePath` can now resolve broken symbolic links too.+ ([#64](https://github.com/haskell/directory/issues/64))++## 1.3.0.2 (February 2017)++ * [optimization] Increase internal buffer size of `copyFile`+ ([#69](https://github.com/haskell/directory/pull/69))++ * Relax `time` version bounds to support 1.8.++## 1.3.0.1 (January 2017)++ * Relax `Win32` version bounds to support 2.5.+ ([#67](https://github.com/haskell/directory/pull/67))+ ## 1.3.0.0 (December 2016) - * Drop trailing slashes in `canonicalizePath`+ * **[breaking]** Drop trailing slashes in `canonicalizePath` ([#63](https://github.com/haskell/directory/issues/63)) - * Rename `isSymbolicLink` to `pathIsSymbolicLink`. The old name will remain- available but may be removed in the next major release.+ * **[deprecation]** Rename `isSymbolicLink` to `pathIsSymbolicLink`. The+ old name will remain available but may be removed in the next major+ release. ([#52](https://github.com/haskell/directory/issues/52)) * Changed `canonicalizePath` to dereference symbolic links even if it points
configure view
@@ -1,4378 +1,4426 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles.-# Generated by GNU Autoconf 2.69 for Haskell directory package 1.0.-#-# Report bugs to <libraries@haskell.org>.-#-#-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.-#-#-# This configure script is free software; the Free Software Foundation-# gives unlimited permission to copy, distribute and modify it.-## -------------------- ##-## M4sh Initialization. ##-## -------------------- ##--# Be more Bourne compatible-DUALCASE=1; export DUALCASE # for MKS sh-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :- emulate sh- NULLCMD=:- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which- # is contrary to our usage. Disable this feature.- alias -g '${1+"$@"}'='"$@"'- setopt NO_GLOB_SUBST-else- case `(set -o) 2>/dev/null` in #(- *posix*) :- set -o posix ;; #(- *) :- ;;-esac-fi---as_nl='-'-export as_nl-# Printing a long string crashes Solaris 7 /usr/bin/printf.-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo-# Prefer a ksh shell builtin over an external printf program on Solaris,-# but without wasting forks for bash or zsh.-if test -z "$BASH_VERSION$ZSH_VERSION" \- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='print -r --'- as_echo_n='print -rn --'-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='printf %s\n'- as_echo_n='printf %s'-else- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'- as_echo_n='/usr/ucb/echo -n'- else- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'- as_echo_n_body='eval- arg=$1;- case $arg in #(- *"$as_nl"*)- expr "X$arg" : "X\\(.*\\)$as_nl";- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;- esac;- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"- '- export as_echo_n_body- as_echo_n='sh -c $as_echo_n_body as_echo'- fi- export as_echo_body- as_echo='sh -c $as_echo_body as_echo'-fi--# The user is always right.-if test "${PATH_SEPARATOR+set}" != set; then- PATH_SEPARATOR=:- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||- PATH_SEPARATOR=';'- }-fi---# IFS-# We need space, tab and new line, in precisely that order. Quoting is-# there to prevent editors from complaining about space-tab.-# (If _AS_PATH_WALK were called with IFS unset, it would disable word-# splitting by setting IFS to empty value.)-IFS=" "" $as_nl"--# Find who we are. Look in the path if we contain no directory separator.-as_myself=-case $0 in #((- *[\\/]* ) as_myself=$0 ;;- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break- done-IFS=$as_save_IFS-- ;;-esac-# We did not find ourselves, most probably we were run as `sh COMMAND'-# in which case we are not to be found in the path.-if test "x$as_myself" = x; then- as_myself=$0-fi-if test ! -f "$as_myself"; then- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2- exit 1-fi--# Unset variables that we do not need and which cause bugs (e.g. in-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"-# suppresses any "Segmentation fault" message there. '((' could-# trigger a bug in pdksh 5.2.14.-for as_var in BASH_ENV ENV MAIL MAILPATH-do eval test x\${$as_var+set} = xset \- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :-done-PS1='$ '-PS2='> '-PS4='+ '--# NLS nuisances.-LC_ALL=C-export LC_ALL-LANGUAGE=C-export LANGUAGE--# CDPATH.-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH--# Use a proper internal environment variable to ensure we don't fall- # into an infinite loop, continuously re-executing ourselves.- if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then- _as_can_reexec=no; export _as_can_reexec;- # We cannot yet assume a decent shell, so we have to provide a-# neutralization value for shells without unset; and this also-# works around shells that cannot unset nonexistent variables.-# Preserve -v and -x to the replacement shell.-BASH_ENV=/dev/null-ENV=/dev/null-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV-case $- in # ((((- *v*x* | *x*v* ) as_opts=-vx ;;- *v* ) as_opts=-v ;;- *x* ) as_opts=-x ;;- * ) as_opts= ;;-esac-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}-# Admittedly, this is quite paranoid, since all the known shells bail-# out after a failed `exec'.-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2-as_fn_exit 255- fi- # We don't want this to propagate to other subprocesses.- { _as_can_reexec=; unset _as_can_reexec;}-if test "x$CONFIG_SHELL" = x; then- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :- emulate sh- NULLCMD=:- # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which- # is contrary to our usage. Disable this feature.- alias -g '\${1+\"\$@\"}'='\"\$@\"'- setopt NO_GLOB_SUBST-else- case \`(set -o) 2>/dev/null\` in #(- *posix*) :- set -o posix ;; #(- *) :- ;;-esac-fi-"- as_required="as_fn_return () { (exit \$1); }-as_fn_success () { as_fn_return 0; }-as_fn_failure () { as_fn_return 1; }-as_fn_ret_success () { return 0; }-as_fn_ret_failure () { return 1; }--exitcode=0-as_fn_success || { exitcode=1; echo as_fn_success failed.; }-as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }-as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }-as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :--else- exitcode=1; echo positional parameters were not saved.-fi-test x\$exitcode = x0 || exit 1-test -x / || exit 1"- as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO- as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO- eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&- test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1-test \$(( 1 + 1 )) = 2 || exit 1"- if (eval "$as_required") 2>/dev/null; then :- as_have_required=yes-else- as_have_required=no-fi- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :--else- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-as_found=false-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- as_found=:- case $as_dir in #(- /*)- for as_base in sh bash ksh sh5; do- # Try only shells that exist, to save several forks.- as_shell=$as_dir/$as_base- if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :- CONFIG_SHELL=$as_shell as_have_required=yes- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :- break 2-fi-fi- done;;- esac- as_found=false-done-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :- CONFIG_SHELL=$SHELL as_have_required=yes-fi; }-IFS=$as_save_IFS--- if test "x$CONFIG_SHELL" != x; then :- export CONFIG_SHELL- # We cannot yet assume a decent shell, so we have to provide a-# neutralization value for shells without unset; and this also-# works around shells that cannot unset nonexistent variables.-# Preserve -v and -x to the replacement shell.-BASH_ENV=/dev/null-ENV=/dev/null-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV-case $- in # ((((- *v*x* | *x*v* ) as_opts=-vx ;;- *v* ) as_opts=-v ;;- *x* ) as_opts=-x ;;- * ) as_opts= ;;-esac-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}-# Admittedly, this is quite paranoid, since all the known shells bail-# out after a failed `exec'.-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2-exit 255-fi-- if test x$as_have_required = xno; then :- $as_echo "$0: This script requires a shell more modern than all"- $as_echo "$0: the shells that I found on your system."- if test x${ZSH_VERSION+set} = xset ; then- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"- $as_echo "$0: be upgraded to zsh 4.3.4 or later."- else- $as_echo "$0: Please tell bug-autoconf@gnu.org and-$0: libraries@haskell.org about your system, including any-$0: error possibly output before this message. Then install-$0: a modern shell, or manually run the script under such a-$0: shell if you do have one."- fi- exit 1-fi-fi-fi-SHELL=${CONFIG_SHELL-/bin/sh}-export SHELL-# Unset more variables known to interfere with behavior of common tools.-CLICOLOR_FORCE= GREP_OPTIONS=-unset CLICOLOR_FORCE GREP_OPTIONS--## --------------------- ##-## M4sh Shell Functions. ##-## --------------------- ##-# as_fn_unset VAR-# ----------------# Portably unset VAR.-as_fn_unset ()-{- { eval $1=; unset $1;}-}-as_unset=as_fn_unset--# as_fn_set_status STATUS-# ------------------------# Set $? to STATUS, without forking.-as_fn_set_status ()-{- return $1-} # as_fn_set_status--# as_fn_exit STATUS-# ------------------# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.-as_fn_exit ()-{- set +e- as_fn_set_status $1- exit $1-} # as_fn_exit--# as_fn_mkdir_p-# --------------# Create "$as_dir" as a directory, including parents if necessary.-as_fn_mkdir_p ()-{-- case $as_dir in #(- -*) as_dir=./$as_dir;;- esac- test -d "$as_dir" || eval $as_mkdir_p || {- as_dirs=- while :; do- case $as_dir in #(- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(- *) as_qdir=$as_dir;;- esac- as_dirs="'$as_qdir' $as_dirs"- as_dir=`$as_dirname -- "$as_dir" ||-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$as_dir" : 'X\(//\)[^/]' \| \- X"$as_dir" : 'X\(//\)$' \| \- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$as_dir" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- test -d "$as_dir" && break- done- test -z "$as_dirs" || eval "mkdir $as_dirs"- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"---} # as_fn_mkdir_p--# as_fn_executable_p FILE-# ------------------------# Test if FILE is an executable regular file.-as_fn_executable_p ()-{- test -f "$1" && test -x "$1"-} # as_fn_executable_p-# as_fn_append VAR VALUE-# -----------------------# Append the text in VALUE to the end of the definition contained in VAR. Take-# advantage of any shell optimizations that allow amortized linear growth over-# repeated appends, instead of the typical quadratic growth present in naive-# implementations.-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :- eval 'as_fn_append ()- {- eval $1+=\$2- }'-else- as_fn_append ()- {- eval $1=\$$1\$2- }-fi # as_fn_append--# as_fn_arith ARG...-# -------------------# Perform arithmetic evaluation on the ARGs, and store the result in the-# global $as_val. Take advantage of shells that can avoid forks. The arguments-# must be portable across $(()) and expr.-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :- eval 'as_fn_arith ()- {- as_val=$(( $* ))- }'-else- as_fn_arith ()- {- as_val=`expr "$@" || test $? -eq 1`- }-fi # as_fn_arith---# as_fn_error STATUS ERROR [LINENO LOG_FD]-# -----------------------------------------# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the-# script with STATUS, using 1 if that was 0.-as_fn_error ()-{- as_status=$1; test $as_status -eq 0 && as_status=1- if test "$4"; then- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4- fi- $as_echo "$as_me: error: $2" >&2- as_fn_exit $as_status-} # as_fn_error--if expr a : '\(a\)' >/dev/null 2>&1 &&- test "X`expr 00001 : '.*\(...\)'`" = X001; then- as_expr=expr-else- as_expr=false-fi--if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then- as_basename=basename-else- as_basename=false-fi--if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then- as_dirname=dirname-else- as_dirname=false-fi--as_me=`$as_basename -- "$0" ||-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \- X"$0" : 'X\(//\)$' \| \- X"$0" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X/"$0" |- sed '/^.*\/\([^/][^/]*\)\/*$/{- s//\1/- q- }- /^X\/\(\/\/\)$/{- s//\1/- q- }- /^X\/\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`--# Avoid depending upon Character Ranges.-as_cr_letters='abcdefghijklmnopqrstuvwxyz'-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'-as_cr_Letters=$as_cr_letters$as_cr_LETTERS-as_cr_digits='0123456789'-as_cr_alnum=$as_cr_Letters$as_cr_digits--- as_lineno_1=$LINENO as_lineno_1a=$LINENO- as_lineno_2=$LINENO as_lineno_2a=$LINENO- eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&- test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {- # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)- sed -n '- p- /[$]LINENO/=- ' <$as_myself |- sed '- s/[$]LINENO.*/&-/- t lineno- b- :lineno- N- :loop- s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/- t loop- s/-\n.*//- ' >$as_me.lineno &&- chmod +x "$as_me.lineno" ||- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }-- # If we had to re-execute with $CONFIG_SHELL, we're ensured to have- # already done that, so ensure we don't try to do so again and fall- # in an infinite loop. This has already happened in practice.- _as_can_reexec=no; export _as_can_reexec- # Don't try to exec as it changes $[0], causing all sort of problems- # (the dirname of $[0] is not the place where we might find the- # original and so on. Autoconf is especially sensitive to this).- . "./$as_me.lineno"- # Exit status is that of the last command.- exit-}--ECHO_C= ECHO_N= ECHO_T=-case `echo -n x` in #(((((--n*)- case `echo 'xy\c'` in- *c*) ECHO_T=' ';; # ECHO_T is single tab character.- xy) ECHO_C='\c';;- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null- ECHO_T=' ';;- esac;;-*)- ECHO_N='-n';;-esac--rm -f conf$$ conf$$.exe conf$$.file-if test -d conf$$.dir; then- rm -f conf$$.dir/conf$$.file-else- rm -f conf$$.dir- mkdir conf$$.dir 2>/dev/null-fi-if (echo >conf$$.file) 2>/dev/null; then- if ln -s conf$$.file conf$$ 2>/dev/null; then- as_ln_s='ln -s'- # ... but there are two gotchas:- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.- # In both cases, we have to default to `cp -pR'.- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||- as_ln_s='cp -pR'- elif ln conf$$.file conf$$ 2>/dev/null; then- as_ln_s=ln- else- as_ln_s='cp -pR'- fi-else- as_ln_s='cp -pR'-fi-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file-rmdir conf$$.dir 2>/dev/null--if mkdir -p . 2>/dev/null; then- as_mkdir_p='mkdir -p "$as_dir"'-else- test -d ./-p && rmdir ./-p- as_mkdir_p=false-fi--as_test_x='test -x'-as_executable_p=as_fn_executable_p--# Sed expression to map a string onto a valid CPP name.-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"--# Sed expression to map a string onto a valid variable name.-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"---test -n "$DJDIR" || exec 7<&0 </dev/null-exec 6>&1--# Name of the host.-# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,-# so uname gets run too.-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`--#-# Initializations.-#-ac_default_prefix=/usr/local-ac_clean_files=-ac_config_libobj_dir=.-LIBOBJS=-cross_compiling=no-subdirs=-MFLAGS=-MAKEFLAGS=--# Identity of this package.-PACKAGE_NAME='Haskell directory package'-PACKAGE_TARNAME='directory'-PACKAGE_VERSION='1.0'-PACKAGE_STRING='Haskell directory package 1.0'-PACKAGE_BUGREPORT='libraries@haskell.org'-PACKAGE_URL=''--ac_unique_file="System/Directory.hs"-# Factoring default headers for most tests.-ac_includes_default="\-#include <stdio.h>-#ifdef HAVE_SYS_TYPES_H-# include <sys/types.h>-#endif-#ifdef HAVE_SYS_STAT_H-# include <sys/stat.h>-#endif-#ifdef STDC_HEADERS-# include <stdlib.h>-# include <stddef.h>-#else-# ifdef HAVE_STDLIB_H-# include <stdlib.h>-# endif-#endif-#ifdef HAVE_STRING_H-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H-# include <memory.h>-# endif-# include <string.h>-#endif-#ifdef HAVE_STRINGS_H-# include <strings.h>-#endif-#ifdef HAVE_INTTYPES_H-# include <inttypes.h>-#endif-#ifdef HAVE_STDINT_H-# include <stdint.h>-#endif-#ifdef HAVE_UNISTD_H-# include <unistd.h>-#endif"--ac_subst_vars='LTLIBOBJS-LIBOBJS-EGREP-GREP-CPP-OBJEXT-EXEEXT-ac_ct_CC-CPPFLAGS-LDFLAGS-CFLAGS-CC-target_alias-host_alias-build_alias-LIBS-ECHO_T-ECHO_N-ECHO_C-DEFS-mandir-localedir-libdir-psdir-pdfdir-dvidir-htmldir-infodir-docdir-oldincludedir-includedir-localstatedir-sharedstatedir-sysconfdir-datadir-datarootdir-libexecdir-sbindir-bindir-program_transform_name-prefix-exec_prefix-PACKAGE_URL-PACKAGE_BUGREPORT-PACKAGE_STRING-PACKAGE_VERSION-PACKAGE_TARNAME-PACKAGE_NAME-PATH_SEPARATOR-SHELL'-ac_subst_files=''-ac_user_opts='-enable_option_checking-with_gcc-with_compiler-'- ac_precious_vars='build_alias-host_alias-target_alias-CC-CFLAGS-LDFLAGS-LIBS-CPPFLAGS-CPP'---# Initialize some variables set by options.-ac_init_help=-ac_init_version=false-ac_unrecognized_opts=-ac_unrecognized_sep=-# The variables have the same names as the options, with-# dashes changed to underlines.-cache_file=/dev/null-exec_prefix=NONE-no_create=-no_recursion=-prefix=NONE-program_prefix=NONE-program_suffix=NONE-program_transform_name=s,x,x,-silent=-site=-srcdir=-verbose=-x_includes=NONE-x_libraries=NONE--# Installation directory options.-# These are left unexpanded so users can "make install exec_prefix=/foo"-# and all the variables that are supposed to be based on exec_prefix-# by default will actually change.-# Use braces instead of parens because sh, perl, etc. also accept them.-# (The list follows the same order as the GNU Coding Standards.)-bindir='${exec_prefix}/bin'-sbindir='${exec_prefix}/sbin'-libexecdir='${exec_prefix}/libexec'-datarootdir='${prefix}/share'-datadir='${datarootdir}'-sysconfdir='${prefix}/etc'-sharedstatedir='${prefix}/com'-localstatedir='${prefix}/var'-includedir='${prefix}/include'-oldincludedir='/usr/include'-docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'-infodir='${datarootdir}/info'-htmldir='${docdir}'-dvidir='${docdir}'-pdfdir='${docdir}'-psdir='${docdir}'-libdir='${exec_prefix}/lib'-localedir='${datarootdir}/locale'-mandir='${datarootdir}/man'--ac_prev=-ac_dashdash=-for ac_option-do- # If the previous option needs an argument, assign it.- if test -n "$ac_prev"; then- eval $ac_prev=\$ac_option- ac_prev=- continue- fi-- case $ac_option in- *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;- *=) ac_optarg= ;;- *) ac_optarg=yes ;;- esac-- # Accept the important Cygnus configure options, so we can diagnose typos.-- case $ac_dashdash$ac_option in- --)- ac_dashdash=yes ;;-- -bindir | --bindir | --bindi | --bind | --bin | --bi)- ac_prev=bindir ;;- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)- bindir=$ac_optarg ;;-- -build | --build | --buil | --bui | --bu)- ac_prev=build_alias ;;- -build=* | --build=* | --buil=* | --bui=* | --bu=*)- build_alias=$ac_optarg ;;-- -cache-file | --cache-file | --cache-fil | --cache-fi \- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)- ac_prev=cache_file ;;- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)- cache_file=$ac_optarg ;;-- --config-cache | -C)- cache_file=config.cache ;;-- -datadir | --datadir | --datadi | --datad)- ac_prev=datadir ;;- -datadir=* | --datadir=* | --datadi=* | --datad=*)- datadir=$ac_optarg ;;-- -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \- | --dataroo | --dataro | --datar)- ac_prev=datarootdir ;;- -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \- | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)- datarootdir=$ac_optarg ;;-- -disable-* | --disable-*)- ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid feature name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"enable_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval enable_$ac_useropt=no ;;-- -docdir | --docdir | --docdi | --doc | --do)- ac_prev=docdir ;;- -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)- docdir=$ac_optarg ;;-- -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)- ac_prev=dvidir ;;- -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)- dvidir=$ac_optarg ;;-- -enable-* | --enable-*)- ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid feature name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"enable_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval enable_$ac_useropt=\$ac_optarg ;;-- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \- | --exec | --exe | --ex)- ac_prev=exec_prefix ;;- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \- | --exec=* | --exe=* | --ex=*)- exec_prefix=$ac_optarg ;;-- -gas | --gas | --ga | --g)- # Obsolete; use --with-gas.- with_gas=yes ;;-- -help | --help | --hel | --he | -h)- ac_init_help=long ;;- -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)- ac_init_help=recursive ;;- -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)- ac_init_help=short ;;-- -host | --host | --hos | --ho)- ac_prev=host_alias ;;- -host=* | --host=* | --hos=* | --ho=*)- host_alias=$ac_optarg ;;-- -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)- ac_prev=htmldir ;;- -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \- | --ht=*)- htmldir=$ac_optarg ;;-- -includedir | --includedir | --includedi | --included | --include \- | --includ | --inclu | --incl | --inc)- ac_prev=includedir ;;- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \- | --includ=* | --inclu=* | --incl=* | --inc=*)- includedir=$ac_optarg ;;-- -infodir | --infodir | --infodi | --infod | --info | --inf)- ac_prev=infodir ;;- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)- infodir=$ac_optarg ;;-- -libdir | --libdir | --libdi | --libd)- ac_prev=libdir ;;- -libdir=* | --libdir=* | --libdi=* | --libd=*)- libdir=$ac_optarg ;;-- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \- | --libexe | --libex | --libe)- ac_prev=libexecdir ;;- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \- | --libexe=* | --libex=* | --libe=*)- libexecdir=$ac_optarg ;;-- -localedir | --localedir | --localedi | --localed | --locale)- ac_prev=localedir ;;- -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)- localedir=$ac_optarg ;;-- -localstatedir | --localstatedir | --localstatedi | --localstated \- | --localstate | --localstat | --localsta | --localst | --locals)- ac_prev=localstatedir ;;- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \- | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)- localstatedir=$ac_optarg ;;-- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)- ac_prev=mandir ;;- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)- mandir=$ac_optarg ;;-- -nfp | --nfp | --nf)- # Obsolete; use --without-fp.- with_fp=no ;;-- -no-create | --no-create | --no-creat | --no-crea | --no-cre \- | --no-cr | --no-c | -n)- no_create=yes ;;-- -no-recursion | --no-recursion | --no-recursio | --no-recursi \- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)- no_recursion=yes ;;-- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \- | --oldin | --oldi | --old | --ol | --o)- ac_prev=oldincludedir ;;- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)- oldincludedir=$ac_optarg ;;-- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)- ac_prev=prefix ;;- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)- prefix=$ac_optarg ;;-- -program-prefix | --program-prefix | --program-prefi | --program-pref \- | --program-pre | --program-pr | --program-p)- ac_prev=program_prefix ;;- -program-prefix=* | --program-prefix=* | --program-prefi=* \- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)- program_prefix=$ac_optarg ;;-- -program-suffix | --program-suffix | --program-suffi | --program-suff \- | --program-suf | --program-su | --program-s)- ac_prev=program_suffix ;;- -program-suffix=* | --program-suffix=* | --program-suffi=* \- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)- program_suffix=$ac_optarg ;;-- -program-transform-name | --program-transform-name \- | --program-transform-nam | --program-transform-na \- | --program-transform-n | --program-transform- \- | --program-transform | --program-transfor \- | --program-transfo | --program-transf \- | --program-trans | --program-tran \- | --progr-tra | --program-tr | --program-t)- ac_prev=program_transform_name ;;- -program-transform-name=* | --program-transform-name=* \- | --program-transform-nam=* | --program-transform-na=* \- | --program-transform-n=* | --program-transform-=* \- | --program-transform=* | --program-transfor=* \- | --program-transfo=* | --program-transf=* \- | --program-trans=* | --program-tran=* \- | --progr-tra=* | --program-tr=* | --program-t=*)- program_transform_name=$ac_optarg ;;-- -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)- ac_prev=pdfdir ;;- -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)- pdfdir=$ac_optarg ;;-- -psdir | --psdir | --psdi | --psd | --ps)- ac_prev=psdir ;;- -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)- psdir=$ac_optarg ;;-- -q | -quiet | --quiet | --quie | --qui | --qu | --q \- | -silent | --silent | --silen | --sile | --sil)- silent=yes ;;-- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)- ac_prev=sbindir ;;- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \- | --sbi=* | --sb=*)- sbindir=$ac_optarg ;;-- -sharedstatedir | --sharedstatedir | --sharedstatedi \- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \- | --sharedst | --shareds | --shared | --share | --shar \- | --sha | --sh)- ac_prev=sharedstatedir ;;- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \- | --sha=* | --sh=*)- sharedstatedir=$ac_optarg ;;-- -site | --site | --sit)- ac_prev=site ;;- -site=* | --site=* | --sit=*)- site=$ac_optarg ;;-- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)- ac_prev=srcdir ;;- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)- srcdir=$ac_optarg ;;-- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \- | --syscon | --sysco | --sysc | --sys | --sy)- ac_prev=sysconfdir ;;- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)- sysconfdir=$ac_optarg ;;-- -target | --target | --targe | --targ | --tar | --ta | --t)- ac_prev=target_alias ;;- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)- target_alias=$ac_optarg ;;-- -v | -verbose | --verbose | --verbos | --verbo | --verb)- verbose=yes ;;-- -version | --version | --versio | --versi | --vers | -V)- ac_init_version=: ;;-- -with-* | --with-*)- ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid package name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"with_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval with_$ac_useropt=\$ac_optarg ;;-- -without-* | --without-*)- ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`- # Reject names that are not valid shell variable names.- expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&- as_fn_error $? "invalid package name: $ac_useropt"- ac_useropt_orig=$ac_useropt- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`- case $ac_user_opts in- *"-"with_$ac_useropt"-"*) ;;- *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"- ac_unrecognized_sep=', ';;- esac- eval with_$ac_useropt=no ;;-- --x)- # Obsolete; use --with-x.- with_x=yes ;;-- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \- | --x-incl | --x-inc | --x-in | --x-i)- ac_prev=x_includes ;;- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)- x_includes=$ac_optarg ;;-- -x-libraries | --x-libraries | --x-librarie | --x-librari \- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)- ac_prev=x_libraries ;;- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)- x_libraries=$ac_optarg ;;-- -*) as_fn_error $? "unrecognized option: \`$ac_option'-Try \`$0 --help' for more information"- ;;-- *=*)- ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`- # Reject names that are not valid shell variable names.- case $ac_envvar in #(- '' | [0-9]* | *[!_$as_cr_alnum]* )- as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;- esac- eval $ac_envvar=\$ac_optarg- export $ac_envvar ;;-- *)- # FIXME: should be removed in autoconf 3.0.- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2- expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2- : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"- ;;-- esac-done--if test -n "$ac_prev"; then- ac_option=--`echo $ac_prev | sed 's/_/-/g'`- as_fn_error $? "missing argument to $ac_option"-fi--if test -n "$ac_unrecognized_opts"; then- case $enable_option_checking in- no) ;;- fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;- esac-fi--# Check all directory arguments for consistency.-for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \- datadir sysconfdir sharedstatedir localstatedir includedir \- oldincludedir docdir infodir htmldir dvidir pdfdir psdir \- libdir localedir mandir-do- eval ac_val=\$$ac_var- # Remove trailing slashes.- case $ac_val in- */ )- ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`- eval $ac_var=\$ac_val;;- esac- # Be sure to have absolute directory names.- case $ac_val in- [\\/$]* | ?:[\\/]* ) continue;;- NONE | '' ) case $ac_var in *prefix ) continue;; esac;;- esac- as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"-done--# There might be people who depend on the old broken behavior: `$host'-# used to hold the argument of --host etc.-# FIXME: To remove some day.-build=$build_alias-host=$host_alias-target=$target_alias--# FIXME: To remove some day.-if test "x$host_alias" != x; then- if test "x$build_alias" = x; then- cross_compiling=maybe- elif test "x$build_alias" != "x$host_alias"; then- cross_compiling=yes- fi-fi--ac_tool_prefix=-test -n "$host_alias" && ac_tool_prefix=$host_alias---test "$silent" = yes && exec 6>/dev/null---ac_pwd=`pwd` && test -n "$ac_pwd" &&-ac_ls_di=`ls -di .` &&-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||- as_fn_error $? "working directory cannot be determined"-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||- as_fn_error $? "pwd does not report name of working directory"---# Find the source files, if location was not specified.-if test -z "$srcdir"; then- ac_srcdir_defaulted=yes- # Try the directory containing this script, then the parent directory.- ac_confdir=`$as_dirname -- "$as_myself" ||-$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$as_myself" : 'X\(//\)[^/]' \| \- X"$as_myself" : 'X\(//\)$' \| \- X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$as_myself" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- srcdir=$ac_confdir- if test ! -r "$srcdir/$ac_unique_file"; then- srcdir=..- fi-else- ac_srcdir_defaulted=no-fi-if test ! -r "$srcdir/$ac_unique_file"; then- test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."- as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"-fi-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"-ac_abs_confdir=`(- cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"- pwd)`-# When building in place, set srcdir=.-if test "$ac_abs_confdir" = "$ac_pwd"; then- srcdir=.-fi-# Remove unnecessary trailing slashes from srcdir.-# Double slashes in file names in object file debugging info-# mess up M-x gdb in Emacs.-case $srcdir in-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;-esac-for ac_var in $ac_precious_vars; do- eval ac_env_${ac_var}_set=\${${ac_var}+set}- eval ac_env_${ac_var}_value=\$${ac_var}- eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}- eval ac_cv_env_${ac_var}_value=\$${ac_var}-done--#-# Report the --help message.-#-if test "$ac_init_help" = "long"; then- # Omit some internal or obsolete options to make the list less imposing.- # This message is too long to be a string in the A/UX 3.1 sh.- cat <<_ACEOF-\`configure' configures Haskell directory package 1.0 to adapt to many kinds of systems.--Usage: $0 [OPTION]... [VAR=VALUE]...--To assign environment variables (e.g., CC, CFLAGS...), specify them as-VAR=VALUE. See below for descriptions of some of the useful variables.--Defaults for the options are specified in brackets.--Configuration:- -h, --help display this help and exit- --help=short display options specific to this package- --help=recursive display the short help of all the included packages- -V, --version display version information and exit- -q, --quiet, --silent do not print \`checking ...' messages- --cache-file=FILE cache test results in FILE [disabled]- -C, --config-cache alias for \`--cache-file=config.cache'- -n, --no-create do not create output files- --srcdir=DIR find the sources in DIR [configure dir or \`..']--Installation directories:- --prefix=PREFIX install architecture-independent files in PREFIX- [$ac_default_prefix]- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX- [PREFIX]--By default, \`make install' will install all the files in-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify-an installation prefix other than \`$ac_default_prefix' using \`--prefix',-for instance \`--prefix=\$HOME'.--For better control, use the options below.--Fine tuning of the installation directories:- --bindir=DIR user executables [EPREFIX/bin]- --sbindir=DIR system admin executables [EPREFIX/sbin]- --libexecdir=DIR program executables [EPREFIX/libexec]- --sysconfdir=DIR read-only single-machine data [PREFIX/etc]- --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]- --localstatedir=DIR modifiable single-machine data [PREFIX/var]- --libdir=DIR object code libraries [EPREFIX/lib]- --includedir=DIR C header files [PREFIX/include]- --oldincludedir=DIR C header files for non-gcc [/usr/include]- --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]- --datadir=DIR read-only architecture-independent data [DATAROOTDIR]- --infodir=DIR info documentation [DATAROOTDIR/info]- --localedir=DIR locale-dependent data [DATAROOTDIR/locale]- --mandir=DIR man documentation [DATAROOTDIR/man]- --docdir=DIR documentation root [DATAROOTDIR/doc/directory]- --htmldir=DIR html documentation [DOCDIR]- --dvidir=DIR dvi documentation [DOCDIR]- --pdfdir=DIR pdf documentation [DOCDIR]- --psdir=DIR ps documentation [DOCDIR]-_ACEOF-- cat <<\_ACEOF-_ACEOF-fi--if test -n "$ac_init_help"; then- case $ac_init_help in- short | recursive ) echo "Configuration of Haskell directory package 1.0:";;- esac- cat <<\_ACEOF--Optional Packages:- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)-C compiler-GHC compiler--Some influential environment variables:- CC C compiler command- CFLAGS C compiler flags- LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a- nonstandard directory <lib dir>- LIBS libraries to pass to the linker, e.g. -l<library>- CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if- you have headers in a nonstandard directory <include dir>- CPP C preprocessor--Use these variables to override the choices made by `configure' or to help-it to find libraries and programs with nonstandard names/locations.--Report bugs to <libraries@haskell.org>.-_ACEOF-ac_status=$?-fi--if test "$ac_init_help" = "recursive"; then- # If there are subdirs, report their specific --help.- for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue- test -d "$ac_dir" ||- { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||- continue- ac_builddir=.--case "$ac_dir" in-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;-*)- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`- # A ".." for each directory in $ac_dir_suffix.- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`- case $ac_top_builddir_sub in- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;- esac ;;-esac-ac_abs_top_builddir=$ac_pwd-ac_abs_builddir=$ac_pwd$ac_dir_suffix-# for backward compatibility:-ac_top_builddir=$ac_top_build_prefix--case $srcdir in- .) # We are building in place.- ac_srcdir=.- ac_top_srcdir=$ac_top_builddir_sub- ac_abs_top_srcdir=$ac_pwd ;;- [\\/]* | ?:[\\/]* ) # Absolute name.- ac_srcdir=$srcdir$ac_dir_suffix;- ac_top_srcdir=$srcdir- ac_abs_top_srcdir=$srcdir ;;- *) # Relative name.- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix- ac_top_srcdir=$ac_top_build_prefix$srcdir- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;-esac-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix-- cd "$ac_dir" || { ac_status=$?; continue; }- # Check for guested configure.- if test -f "$ac_srcdir/configure.gnu"; then- echo &&- $SHELL "$ac_srcdir/configure.gnu" --help=recursive- elif test -f "$ac_srcdir/configure"; then- echo &&- $SHELL "$ac_srcdir/configure" --help=recursive- else- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2- fi || ac_status=$?- cd "$ac_pwd" || { ac_status=$?; break; }- done-fi--test -n "$ac_init_help" && exit $ac_status-if $ac_init_version; then- cat <<\_ACEOF-Haskell directory package configure 1.0-generated by GNU Autoconf 2.69--Copyright (C) 2012 Free Software Foundation, Inc.-This configure script is free software; the Free Software Foundation-gives unlimited permission to copy, distribute and modify it.-_ACEOF- exit-fi--## ------------------------ ##-## Autoconf initialization. ##-## ------------------------ ##--# ac_fn_c_try_compile LINENO-# ---------------------------# Try to compile conftest.$ac_ext, and return whether this succeeded.-ac_fn_c_try_compile ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- rm -f conftest.$ac_objext- if { { ac_try="$ac_compile"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_compile") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- grep -v '^ *+' conftest.err >conftest.er1- cat conftest.er1 >&5- mv -f conftest.er1 conftest.err- fi- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } && {- test -z "$ac_c_werror_flag" ||- test ! -s conftest.err- } && test -s conftest.$ac_objext; then :- ac_retval=0-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=1-fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_compile--# ac_fn_c_try_cpp LINENO-# -----------------------# Try to preprocess conftest.$ac_ext, and return whether this succeeded.-ac_fn_c_try_cpp ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if { { ac_try="$ac_cpp conftest.$ac_ext"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- grep -v '^ *+' conftest.err >conftest.er1- cat conftest.er1 >&5- mv -f conftest.er1 conftest.err- fi- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } > conftest.i && {- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||- test ! -s conftest.err- }; then :- ac_retval=0-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=1-fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_cpp--# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES-# --------------------------------------------------------# Tests whether HEADER exists, giving a warning if it cannot be compiled using-# the include files in INCLUDES and setting the cache variable VAR-# accordingly.-ac_fn_c_check_header_mongrel ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if eval \${$3+:} false; then :- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }-else- # Is the header compilable?-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5-$as_echo_n "checking $2 usability... " >&6; }-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-#include <$2>-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_header_compiler=yes-else- ac_header_compiler=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5-$as_echo "$ac_header_compiler" >&6; }--# Is the header present?-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5-$as_echo_n "checking $2 presence... " >&6; }-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <$2>-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :- ac_header_preproc=yes-else- ac_header_preproc=no-fi-rm -f conftest.err conftest.i conftest.$ac_ext-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5-$as_echo "$ac_header_preproc" >&6; }--# So? What about this header?-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((- yes:no: )- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}- ;;- no:yes:* )- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}-( $as_echo "## ------------------------------------ ##-## Report this to libraries@haskell.org ##-## ------------------------------------ ##"- ) | sed "s/^/$as_me: WARNING: /" >&2- ;;-esac- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- eval "$3=\$ac_header_compiler"-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }-fi- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_header_mongrel--# ac_fn_c_try_run LINENO-# -----------------------# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes-# that executables *can* be run.-ac_fn_c_try_run ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- if { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'- { { case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_try") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; }; then :- ac_retval=0-else- $as_echo "$as_me: program exited with status $ac_status" >&5- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=$ac_status-fi- rm -rf conftest.dSYM conftest_ipa8_conftest.oo- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_run--# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES-# --------------------------------------------------------# Tests whether HEADER exists and can be compiled using the include files in-# INCLUDES, setting the cache variable VAR accordingly.-ac_fn_c_check_header_compile ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-$4-#include <$2>-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- eval "$3=yes"-else- eval "$3=no"-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_header_compile--# ac_fn_c_try_link LINENO-# ------------------------# Try to link conftest.$ac_ext, and return whether this succeeded.-ac_fn_c_try_link ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- rm -f conftest.$ac_objext conftest$ac_exeext- if { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- grep -v '^ *+' conftest.err >conftest.er1- cat conftest.er1 >&5- mv -f conftest.er1 conftest.err- fi- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; } && {- test -z "$ac_c_werror_flag" ||- test ! -s conftest.err- } && test -s conftest$ac_exeext && {- test "$cross_compiling" = yes ||- test -x conftest$ac_exeext- }; then :- ac_retval=0-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5-- ac_retval=1-fi- # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information- # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would- # interfere with the next link command; also delete a directory that is- # left behind by Apple's compiler. We do this before executing the actions.- rm -rf conftest.dSYM conftest_ipa8_conftest.oo- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno- as_fn_set_status $ac_retval--} # ac_fn_c_try_link--# ac_fn_c_check_func LINENO FUNC VAR-# -----------------------------------# Tests whether FUNC exists, setting the cache variable VAR accordingly-ac_fn_c_check_func ()-{- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5-$as_echo_n "checking for $2... " >&6; }-if eval \${$3+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.- For example, HP-UX 11i <limits.h> declares gettimeofday. */-#define $2 innocuous_$2--/* System header to define __stub macros and hopefully few prototypes,- which can conflict with char $2 (); below.- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since- <limits.h> exists even on freestanding compilers. */--#ifdef __STDC__-# include <limits.h>-#else-# include <assert.h>-#endif--#undef $2--/* Override any GCC internal prototype to avoid an error.- Use char because int might match the return type of a GCC- builtin and then its argument prototype would still apply. */-#ifdef __cplusplus-extern "C"-#endif-char $2 ();-/* The GNU C library defines this for functions which it implements- to always fail with ENOSYS. Some functions are actually named- something starting with __ and the normal name is an alias. */-#if defined __stub_$2 || defined __stub___$2-choke me-#endif--int-main ()-{-return $2 ();- ;- return 0;-}-_ACEOF-if ac_fn_c_try_link "$LINENO"; then :- eval "$3=yes"-else- eval "$3=no"-fi-rm -f core conftest.err conftest.$ac_objext \- conftest$ac_exeext conftest.$ac_ext-fi-eval ac_res=\$$3- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5-$as_echo "$ac_res" >&6; }- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno--} # ac_fn_c_check_func-cat >config.log <<_ACEOF-This file contains any messages produced by compilers while-running configure, to aid debugging if configure makes a mistake.--It was created by Haskell directory package $as_me 1.0, which was-generated by GNU Autoconf 2.69. Invocation command line was-- $ $0 $@--_ACEOF-exec 5>>config.log-{-cat <<_ASUNAME-## --------- ##-## Platform. ##-## --------- ##--hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`-uname -m = `(uname -m) 2>/dev/null || echo unknown`-uname -r = `(uname -r) 2>/dev/null || echo unknown`-uname -s = `(uname -s) 2>/dev/null || echo unknown`-uname -v = `(uname -v) 2>/dev/null || echo unknown`--/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`-/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`--/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`-/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`-/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`-/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`-/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`-/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`--_ASUNAME--as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- $as_echo "PATH: $as_dir"- done-IFS=$as_save_IFS--} >&5--cat >&5 <<_ACEOF---## ----------- ##-## Core tests. ##-## ----------- ##--_ACEOF---# Keep a trace of the command line.-# Strip out --no-create and --no-recursion so they do not pile up.-# Strip out --silent because we don't want to record it for future runs.-# Also quote any args containing shell meta-characters.-# Make two passes to allow for proper duplicate-argument suppression.-ac_configure_args=-ac_configure_args0=-ac_configure_args1=-ac_must_keep_next=false-for ac_pass in 1 2-do- for ac_arg- do- case $ac_arg in- -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;- -q | -quiet | --quiet | --quie | --qui | --qu | --q \- | -silent | --silent | --silen | --sile | --sil)- continue ;;- *\'*)- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;- esac- case $ac_pass in- 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;- 2)- as_fn_append ac_configure_args1 " '$ac_arg'"- if test $ac_must_keep_next = true; then- ac_must_keep_next=false # Got value, back to normal.- else- case $ac_arg in- *=* | --config-cache | -C | -disable-* | --disable-* \- | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \- | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \- | -with-* | --with-* | -without-* | --without-* | --x)- case "$ac_configure_args0 " in- "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;- esac- ;;- -* ) ac_must_keep_next=true ;;- esac- fi- as_fn_append ac_configure_args " '$ac_arg'"- ;;- esac- done-done-{ ac_configure_args0=; unset ac_configure_args0;}-{ ac_configure_args1=; unset ac_configure_args1;}--# When interrupted or exit'd, cleanup temporary files, and complete-# config.log. We remove comments because anyway the quotes in there-# would cause problems or look ugly.-# WARNING: Use '\'' to represent an apostrophe within the trap.-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.-trap 'exit_status=$?- # Save into config.log some information that might help in debugging.- {- echo-- $as_echo "## ---------------- ##-## Cache variables. ##-## ---------------- ##"- echo- # The following way of writing the cache mishandles newlines in values,-(- for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do- eval ac_val=\$$ac_var- case $ac_val in #(- *${as_nl}*)- case $ac_var in #(- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;- esac- case $ac_var in #(- _ | IFS | as_nl) ;; #(- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(- *) { eval $ac_var=; unset $ac_var;} ;;- esac ;;- esac- done- (set) 2>&1 |- case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(- *${as_nl}ac_space=\ *)- sed -n \- "s/'\''/'\''\\\\'\'''\''/g;- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"- ;; #(- *)- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"- ;;- esac |- sort-)- echo-- $as_echo "## ----------------- ##-## Output variables. ##-## ----------------- ##"- echo- for ac_var in $ac_subst_vars- do- eval ac_val=\$$ac_var- case $ac_val in- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;- esac- $as_echo "$ac_var='\''$ac_val'\''"- done | sort- echo-- if test -n "$ac_subst_files"; then- $as_echo "## ------------------- ##-## File substitutions. ##-## ------------------- ##"- echo- for ac_var in $ac_subst_files- do- eval ac_val=\$$ac_var- case $ac_val in- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;- esac- $as_echo "$ac_var='\''$ac_val'\''"- done | sort- echo- fi-- if test -s confdefs.h; then- $as_echo "## ----------- ##-## confdefs.h. ##-## ----------- ##"- echo- cat confdefs.h- echo- fi- test "$ac_signal" != 0 &&- $as_echo "$as_me: caught signal $ac_signal"- $as_echo "$as_me: exit $exit_status"- } >&5- rm -f core *.core core.conftest.* &&- rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&- exit $exit_status-' 0-for ac_signal in 1 2 13 15; do- trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal-done-ac_signal=0--# confdefs.h avoids OS command line length limits that DEFS can exceed.-rm -f -r conftest* confdefs.h--$as_echo "/* confdefs.h */" > confdefs.h--# Predefined preprocessor variables.--cat >>confdefs.h <<_ACEOF-#define PACKAGE_NAME "$PACKAGE_NAME"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_VERSION "$PACKAGE_VERSION"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_STRING "$PACKAGE_STRING"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"-_ACEOF--cat >>confdefs.h <<_ACEOF-#define PACKAGE_URL "$PACKAGE_URL"-_ACEOF---# Let the site file select an alternate cache file if it wants to.-# Prefer an explicitly selected file to automatically selected ones.-ac_site_file1=NONE-ac_site_file2=NONE-if test -n "$CONFIG_SITE"; then- # We do not want a PATH search for config.site.- case $CONFIG_SITE in #((- -*) ac_site_file1=./$CONFIG_SITE;;- */*) ac_site_file1=$CONFIG_SITE;;- *) ac_site_file1=./$CONFIG_SITE;;- esac-elif test "x$prefix" != xNONE; then- ac_site_file1=$prefix/share/config.site- ac_site_file2=$prefix/etc/config.site-else- ac_site_file1=$ac_default_prefix/share/config.site- ac_site_file2=$ac_default_prefix/etc/config.site-fi-for ac_site_file in "$ac_site_file1" "$ac_site_file2"-do- test "x$ac_site_file" = xNONE && continue- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5-$as_echo "$as_me: loading site script $ac_site_file" >&6;}- sed 's/^/| /' "$ac_site_file" >&5- . "$ac_site_file" \- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "failed to load site script $ac_site_file-See \`config.log' for more details" "$LINENO" 5; }- fi-done--if test -r "$cache_file"; then- # Some versions of bash will fail to source /dev/null (special files- # actually), so we avoid doing that. DJGPP emulates it as a regular file.- if test /dev/null != "$cache_file" && test -f "$cache_file"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5-$as_echo "$as_me: loading cache $cache_file" >&6;}- case $cache_file in- [\\/]* | ?:[\\/]* ) . "$cache_file";;- *) . "./$cache_file";;- esac- fi-else- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5-$as_echo "$as_me: creating cache $cache_file" >&6;}- >$cache_file-fi--# Check that the precious variables saved in the cache have kept the same-# value.-ac_cache_corrupted=false-for ac_var in $ac_precious_vars; do- eval ac_old_set=\$ac_cv_env_${ac_var}_set- eval ac_new_set=\$ac_env_${ac_var}_set- eval ac_old_val=\$ac_cv_env_${ac_var}_value- eval ac_new_val=\$ac_env_${ac_var}_value- case $ac_old_set,$ac_new_set in- set,)- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}- ac_cache_corrupted=: ;;- ,set)- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}- ac_cache_corrupted=: ;;- ,);;- *)- if test "x$ac_old_val" != "x$ac_new_val"; then- # differences in whitespace do not lead to failure.- ac_old_val_w=`echo x $ac_old_val`- ac_new_val_w=`echo x $ac_new_val`- if test "$ac_old_val_w" != "$ac_new_val_w"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}- ac_cache_corrupted=:- else- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}- eval $ac_var=\$ac_old_val- fi- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}- fi;;- esac- # Pass precious variables to config.status.- if test "$ac_new_set" = set; then- case $ac_new_val in- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;- *) ac_arg=$ac_var=$ac_new_val ;;- esac- case " $ac_configure_args " in- *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.- *) as_fn_append ac_configure_args " '$ac_arg'" ;;- esac- fi-done-if $ac_cache_corrupted; then- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5-fi-## -------------------- ##-## Main body of script. ##-## -------------------- ##--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu----# Safety check: Ensure that we are in the correct source directory.---ac_config_headers="$ac_config_headers HsDirectoryConfig.h"---# Autoconf chokes on spaces, but we may receive a path from Cabal containing-# spaces. In that case, we just ignore Cabal's suggestion.-set_with_gcc() {- case $withval in- *" "*)- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-gcc ignored due to presence of spaces" >&5-$as_echo "$as_me: WARNING: --with-gcc ignored due to presence of spaces" >&2;};;- *)- CC=$withval- esac-}--# Legacy support for setting the C compiler with Cabal<1.24-# Newer versions use Autoconf's native `CC=...` facility--# Check whether --with-gcc was given.-if test "${with_gcc+set}" = set; then :- withval=$with_gcc; set_with_gcc-fi--# avoid warnings when run via Cabal--# Check whether --with-compiler was given.-if test "${with_compiler+set}" = set; then :- withval=$with_compiler;-fi--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu-if test -n "$ac_tool_prefix"; then- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.-set dummy ${ac_tool_prefix}gcc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then- ac_cv_prog_CC="${ac_tool_prefix}gcc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi---fi-if test -z "$ac_cv_prog_CC"; then- ac_ct_CC=$CC- # Extract the first word of "gcc", so it can be a program name with args.-set dummy gcc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_ac_ct_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$ac_ct_CC"; then- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then- ac_cv_prog_ac_ct_CC="gcc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-ac_ct_CC=$ac_cv_prog_ac_ct_CC-if test -n "$ac_ct_CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5-$as_echo "$ac_ct_CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi-- if test "x$ac_ct_CC" = x; then- CC=""- else- case $cross_compiling:$ac_tool_warned in-yes:)-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}-ac_tool_warned=yes ;;-esac- CC=$ac_ct_CC- fi-else- CC="$ac_cv_prog_CC"-fi--if test -z "$CC"; then- if test -n "$ac_tool_prefix"; then- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.-set dummy ${ac_tool_prefix}cc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then- ac_cv_prog_CC="${ac_tool_prefix}cc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi--- fi-fi-if test -z "$CC"; then- # Extract the first word of "cc", so it can be a program name with args.-set dummy cc; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else- ac_prog_rejected=no-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then- ac_prog_rejected=yes- continue- fi- ac_cv_prog_CC="cc"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--if test $ac_prog_rejected = yes; then- # We found a bogon in the path, so make sure we never use it.- set dummy $ac_cv_prog_CC- shift- if test $# != 0; then- # We chose a different compiler from the bogus one.- # However, it has the same basename, so the bogon will be chosen- # first if we set CC to just the basename; use the full file name.- shift- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"- fi-fi-fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi---fi-if test -z "$CC"; then- if test -n "$ac_tool_prefix"; then- for ac_prog in cl.exe- do- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.-set dummy $ac_tool_prefix$ac_prog; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$CC"; then- ac_cv_prog_CC="$CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-CC=$ac_cv_prog_CC-if test -n "$CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5-$as_echo "$CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi--- test -n "$CC" && break- done-fi-if test -z "$CC"; then- ac_ct_CC=$CC- for ac_prog in cl.exe-do- # Extract the first word of "$ac_prog", so it can be a program name with args.-set dummy $ac_prog; ac_word=$2-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5-$as_echo_n "checking for $ac_word... " >&6; }-if ${ac_cv_prog_ac_ct_CC+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -n "$ac_ct_CC"; then- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.-else-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_exec_ext in '' $ac_executable_extensions; do- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then- ac_cv_prog_ac_ct_CC="$ac_prog"- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5- break 2- fi-done- done-IFS=$as_save_IFS--fi-fi-ac_ct_CC=$ac_cv_prog_ac_ct_CC-if test -n "$ac_ct_CC"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5-$as_echo "$ac_ct_CC" >&6; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-fi--- test -n "$ac_ct_CC" && break-done-- if test "x$ac_ct_CC" = x; then- CC=""- else- case $cross_compiling:$ac_tool_warned in-yes:)-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}-ac_tool_warned=yes ;;-esac- CC=$ac_ct_CC- fi-fi--fi---test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "no acceptable C compiler found in \$PATH-See \`config.log' for more details" "$LINENO" 5; }--# Provide some information about the compiler.-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5-set X $ac_compile-ac_compiler=$2-for ac_option in --version -v -V -qversion; do- { { ac_try="$ac_compiler $ac_option >&5"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_compiler $ac_option >&5") 2>conftest.err- ac_status=$?- if test -s conftest.err; then- sed '10a\-... rest of stderr output deleted ...- 10q' conftest.err >conftest.er1- cat conftest.er1 >&5- fi- rm -f conftest.er1 conftest.err- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }-done--cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-ac_clean_files_save=$ac_clean_files-ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"-# Try to create an executable without -o first, disregard a.out.-# It will help us diagnose broken compilers, and finding out an intuition-# of exeext.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5-$as_echo_n "checking whether the C compiler works... " >&6; }-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`--# The possible output files:-ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"--ac_rmfiles=-for ac_file in $ac_files-do- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;- * ) ac_rmfiles="$ac_rmfiles $ac_file";;- esac-done-rm -f $ac_rmfiles--if { { ac_try="$ac_link_default"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link_default") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; then :- # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'-# in a Makefile. We should not override ac_cv_exeext if it was cached,-# so that the user can short-circuit this test for compilers unknown to-# Autoconf.-for ac_file in $ac_files ''-do- test -f "$ac_file" || continue- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )- ;;- [ab].out )- # We found the default executable, but exeext='' is most- # certainly right.- break;;- *.* )- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;- then :; else- ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`- fi- # We set ac_cv_exeext here because the later test for it is not- # safe: cross compilers may not add the suffix if given an `-o'- # argument, so we may need to know it at that point already.- # Even if this section looks crufty: it has the advantage of- # actually working.- break;;- * )- break;;- esac-done-test "$ac_cv_exeext" = no && ac_cv_exeext=--else- ac_file=''-fi-if test -z "$ac_file"; then :- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5-$as_echo "no" >&6; }-$as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5--{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error 77 "C compiler cannot create executables-See \`config.log' for more details" "$LINENO" 5; }-else- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5-$as_echo "yes" >&6; }-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5-$as_echo_n "checking for C compiler default output file name... " >&6; }-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5-$as_echo "$ac_file" >&6; }-ac_exeext=$ac_cv_exeext--rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out-ac_clean_files=$ac_clean_files_save-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5-$as_echo_n "checking for suffix of executables... " >&6; }-if { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; then :- # If both `conftest.exe' and `conftest' are `present' (well, observable)-# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will-# work properly (i.e., refer to `conftest.exe'), while it won't with-# `rm'.-for ac_file in conftest.exe conftest conftest.*; do- test -f "$ac_file" || continue- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;- *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`- break;;- * ) break;;- esac-done-else- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "cannot compute suffix of executables: cannot compile and link-See \`config.log' for more details" "$LINENO" 5; }-fi-rm -f conftest conftest$ac_cv_exeext-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5-$as_echo "$ac_cv_exeext" >&6; }--rm -f conftest.$ac_ext-EXEEXT=$ac_cv_exeext-ac_exeext=$EXEEXT-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdio.h>-int-main ()-{-FILE *f = fopen ("conftest.out", "w");- return ferror (f) || fclose (f) != 0;-- ;- return 0;-}-_ACEOF-ac_clean_files="$ac_clean_files conftest.out"-# Check that the compiler produces executables we can run. If not, either-# the compiler is broken, or we cross compile.-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5-$as_echo_n "checking whether we are cross compiling... " >&6; }-if test "$cross_compiling" != yes; then- { { ac_try="$ac_link"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_link") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }- if { ac_try='./conftest$ac_cv_exeext'- { { case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_try") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; }; then- cross_compiling=no- else- if test "$cross_compiling" = maybe; then- cross_compiling=yes- else- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "cannot run C compiled programs.-If you meant to cross compile, use \`--host'.-See \`config.log' for more details" "$LINENO" 5; }- fi- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5-$as_echo "$cross_compiling" >&6; }--rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out-ac_clean_files=$ac_clean_files_save-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5-$as_echo_n "checking for suffix of object files... " >&6; }-if ${ac_cv_objext+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-rm -f conftest.o conftest.obj-if { { ac_try="$ac_compile"-case "(($ac_try" in- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;- *) ac_try_echo=$ac_try;;-esac-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""-$as_echo "$ac_try_echo"; } >&5- (eval "$ac_compile") 2>&5- ac_status=$?- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5- test $ac_status = 0; }; then :- for ac_file in conftest.o conftest.obj conftest.*; do- test -f "$ac_file" || continue;- case $ac_file in- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;- *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`- break;;- esac-done-else- $as_echo "$as_me: failed program was:" >&5-sed 's/^/| /' conftest.$ac_ext >&5--{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "cannot compute suffix of object files: cannot compile-See \`config.log' for more details" "$LINENO" 5; }-fi-rm -f conftest.$ac_cv_objext conftest.$ac_ext-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5-$as_echo "$ac_cv_objext" >&6; }-OBJEXT=$ac_cv_objext-ac_objext=$OBJEXT-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }-if ${ac_cv_c_compiler_gnu+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-#ifndef __GNUC__- choke me-#endif-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_compiler_gnu=yes-else- ac_compiler_gnu=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-ac_cv_c_compiler_gnu=$ac_compiler_gnu--fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5-$as_echo "$ac_cv_c_compiler_gnu" >&6; }-if test $ac_compiler_gnu = yes; then- GCC=yes-else- GCC=-fi-ac_test_CFLAGS=${CFLAGS+set}-ac_save_CFLAGS=$CFLAGS-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5-$as_echo_n "checking whether $CC accepts -g... " >&6; }-if ${ac_cv_prog_cc_g+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_save_c_werror_flag=$ac_c_werror_flag- ac_c_werror_flag=yes- ac_cv_prog_cc_g=no- CFLAGS="-g"- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_prog_cc_g=yes-else- CFLAGS=""- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :--else- ac_c_werror_flag=$ac_save_c_werror_flag- CFLAGS="-g"- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_prog_cc_g=yes-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext- ac_c_werror_flag=$ac_save_c_werror_flag-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5-$as_echo "$ac_cv_prog_cc_g" >&6; }-if test "$ac_test_CFLAGS" = set; then- CFLAGS=$ac_save_CFLAGS-elif test $ac_cv_prog_cc_g = yes; then- if test "$GCC" = yes; then- CFLAGS="-g -O2"- else- CFLAGS="-g"- fi-else- if test "$GCC" = yes; then- CFLAGS="-O2"- else- CFLAGS=- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }-if ${ac_cv_prog_cc_c89+:} false; then :- $as_echo_n "(cached) " >&6-else- ac_cv_prog_cc_c89=no-ac_save_CC=$CC-cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdarg.h>-#include <stdio.h>-struct stat;-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */-struct buf { int x; };-FILE * (*rcsopen) (struct buf *, struct stat *, int);-static char *e (p, i)- char **p;- int i;-{- return p[i];-}-static char *f (char * (*g) (char **, int), char **p, ...)-{- char *s;- va_list v;- va_start (v,p);- s = g (p, va_arg (v,int));- va_end (v);- return s;-}--/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has- function prototypes and stuff, but not '\xHH' hex character constants.- These don't provoke an error unfortunately, instead are silently treated- as 'x'. The following induces an error, until -std is added to get- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an- array size at least. It's necessary to write '\x00'==0 to get something- that's true only with -std. */-int osf4_cc_array ['\x00' == 0 ? 1 : -1];--/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters- inside strings and character constants. */-#define FOO(x) 'x'-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];--int test (int i, double x);-struct s1 {int (*f) (int a);};-struct s2 {int (*f) (double a);};-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);-int argc;-char **argv;-int-main ()-{-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];- ;- return 0;-}-_ACEOF-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"-do- CC="$ac_save_CC $ac_arg"- if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_prog_cc_c89=$ac_arg-fi-rm -f core conftest.err conftest.$ac_objext- test "x$ac_cv_prog_cc_c89" != "xno" && break-done-rm -f conftest.$ac_ext-CC=$ac_save_CC--fi-# AC_CACHE_VAL-case "x$ac_cv_prog_cc_c89" in- x)- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5-$as_echo "none needed" >&6; } ;;- xno)- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5-$as_echo "unsupported" >&6; } ;;- *)- CC="$CC $ac_cv_prog_cc_c89"- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;-esac-if test "x$ac_cv_prog_cc_c89" != xno; then :--fi--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu---# check for specific header (.h) files that we are interested in--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5-$as_echo_n "checking how to run the C preprocessor... " >&6; }-# On Suns, sometimes $CPP names a directory.-if test -n "$CPP" && test -d "$CPP"; then- CPP=-fi-if test -z "$CPP"; then- if ${ac_cv_prog_CPP+:} false; then :- $as_echo_n "(cached) " >&6-else- # Double quotes because CPP needs to be expanded- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"- do- ac_preproc_ok=false-for ac_c_preproc_warn_flag in '' yes-do- # Use a header file that comes with gcc, so configuring glibc- # with a fresh cross-compiler works.- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since- # <limits.h> exists even on freestanding compilers.- # On the NeXT, cc -E runs the code through the compiler's parser,- # not just through cpp. "Syntax error" is here to catch this case.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#ifdef __STDC__-# include <limits.h>-#else-# include <assert.h>-#endif- Syntax error-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :--else- # Broken: fails on valid input.-continue-fi-rm -f conftest.err conftest.i conftest.$ac_ext-- # OK, works on sane cases. Now check whether nonexistent headers- # can be detected and how.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ac_nonexistent.h>-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :- # Broken: success on invalid input.-continue-else- # Passes both tests.-ac_preproc_ok=:-break-fi-rm -f conftest.err conftest.i conftest.$ac_ext--done-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.-rm -f conftest.i conftest.err conftest.$ac_ext-if $ac_preproc_ok; then :- break-fi-- done- ac_cv_prog_CPP=$CPP--fi- CPP=$ac_cv_prog_CPP-else- ac_cv_prog_CPP=$CPP-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5-$as_echo "$CPP" >&6; }-ac_preproc_ok=false-for ac_c_preproc_warn_flag in '' yes-do- # Use a header file that comes with gcc, so configuring glibc- # with a fresh cross-compiler works.- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since- # <limits.h> exists even on freestanding compilers.- # On the NeXT, cc -E runs the code through the compiler's parser,- # not just through cpp. "Syntax error" is here to catch this case.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#ifdef __STDC__-# include <limits.h>-#else-# include <assert.h>-#endif- Syntax error-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :--else- # Broken: fails on valid input.-continue-fi-rm -f conftest.err conftest.i conftest.$ac_ext-- # OK, works on sane cases. Now check whether nonexistent headers- # can be detected and how.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ac_nonexistent.h>-_ACEOF-if ac_fn_c_try_cpp "$LINENO"; then :- # Broken: success on invalid input.-continue-else- # Passes both tests.-ac_preproc_ok=:-break-fi-rm -f conftest.err conftest.i conftest.$ac_ext--done-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.-rm -f conftest.i conftest.err conftest.$ac_ext-if $ac_preproc_ok; then :--else- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check-See \`config.log' for more details" "$LINENO" 5; }-fi--ac_ext=c-ac_cpp='$CPP $CPPFLAGS'-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'-ac_compiler_gnu=$ac_cv_c_compiler_gnu---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }-if ${ac_cv_path_GREP+:} false; then :- $as_echo_n "(cached) " >&6-else- if test -z "$GREP"; then- ac_path_GREP_found=false- # Loop through the user's path and test for each of PROGNAME-LIST- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_prog in grep ggrep; do- for ac_exec_ext in '' $ac_executable_extensions; do- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"- as_fn_executable_p "$ac_path_GREP" || continue-# Check for GNU ac_path_GREP and select it if it is found.- # Check for GNU $ac_path_GREP-case `"$ac_path_GREP" --version 2>&1` in-*GNU*)- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;-*)- ac_count=0- $as_echo_n 0123456789 >"conftest.in"- while :- do- cat "conftest.in" "conftest.in" >"conftest.tmp"- mv "conftest.tmp" "conftest.in"- cp "conftest.in" "conftest.nl"- $as_echo 'GREP' >> "conftest.nl"- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break- as_fn_arith $ac_count + 1 && ac_count=$as_val- if test $ac_count -gt ${ac_path_GREP_max-0}; then- # Best one so far, save it but keep looking for a better one- ac_cv_path_GREP="$ac_path_GREP"- ac_path_GREP_max=$ac_count- fi- # 10*(2^10) chars as input seems more than enough- test $ac_count -gt 10 && break- done- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;-esac-- $ac_path_GREP_found && break 3- done- done- done-IFS=$as_save_IFS- if test -z "$ac_cv_path_GREP"; then- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5- fi-else- ac_cv_path_GREP=$GREP-fi--fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5-$as_echo "$ac_cv_path_GREP" >&6; }- GREP="$ac_cv_path_GREP"---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5-$as_echo_n "checking for egrep... " >&6; }-if ${ac_cv_path_EGREP+:} false; then :- $as_echo_n "(cached) " >&6-else- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1- then ac_cv_path_EGREP="$GREP -E"- else- if test -z "$EGREP"; then- ac_path_EGREP_found=false- # Loop through the user's path and test for each of PROGNAME-LIST- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- for ac_prog in egrep; do- for ac_exec_ext in '' $ac_executable_extensions; do- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"- as_fn_executable_p "$ac_path_EGREP" || continue-# Check for GNU ac_path_EGREP and select it if it is found.- # Check for GNU $ac_path_EGREP-case `"$ac_path_EGREP" --version 2>&1` in-*GNU*)- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;-*)- ac_count=0- $as_echo_n 0123456789 >"conftest.in"- while :- do- cat "conftest.in" "conftest.in" >"conftest.tmp"- mv "conftest.tmp" "conftest.in"- cp "conftest.in" "conftest.nl"- $as_echo 'EGREP' >> "conftest.nl"- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break- as_fn_arith $ac_count + 1 && ac_count=$as_val- if test $ac_count -gt ${ac_path_EGREP_max-0}; then- # Best one so far, save it but keep looking for a better one- ac_cv_path_EGREP="$ac_path_EGREP"- ac_path_EGREP_max=$ac_count- fi- # 10*(2^10) chars as input seems more than enough- test $ac_count -gt 10 && break- done- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;-esac-- $ac_path_EGREP_found && break 3- done- done- done-IFS=$as_save_IFS- if test -z "$ac_cv_path_EGREP"; then- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5- fi-else- ac_cv_path_EGREP=$EGREP-fi-- fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5-$as_echo "$ac_cv_path_EGREP" >&6; }- EGREP="$ac_cv_path_EGREP"---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5-$as_echo_n "checking for ANSI C header files... " >&6; }-if ${ac_cv_header_stdc+:} false; then :- $as_echo_n "(cached) " >&6-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdlib.h>-#include <stdarg.h>-#include <string.h>-#include <float.h>--int-main ()-{-- ;- return 0;-}-_ACEOF-if ac_fn_c_try_compile "$LINENO"; then :- ac_cv_header_stdc=yes-else- ac_cv_header_stdc=no-fi-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext--if test $ac_cv_header_stdc = yes; then- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <string.h>--_ACEOF-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |- $EGREP "memchr" >/dev/null 2>&1; then :--else- ac_cv_header_stdc=no-fi-rm -f conftest*--fi--if test $ac_cv_header_stdc = yes; then- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <stdlib.h>--_ACEOF-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |- $EGREP "free" >/dev/null 2>&1; then :--else- ac_cv_header_stdc=no-fi-rm -f conftest*--fi--if test $ac_cv_header_stdc = yes; then- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.- if test "$cross_compiling" = yes; then :- :-else- cat confdefs.h - <<_ACEOF >conftest.$ac_ext-/* end confdefs.h. */-#include <ctype.h>-#include <stdlib.h>-#if ((' ' & 0x0FF) == 0x020)-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))-#else-# define ISLOWER(c) \- (('a' <= (c) && (c) <= 'i') \- || ('j' <= (c) && (c) <= 'r') \- || ('s' <= (c) && (c) <= 'z'))-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))-#endif--#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))-int-main ()-{- int i;- for (i = 0; i < 256; i++)- if (XOR (islower (i), ISLOWER (i))- || toupper (i) != TOUPPER (i))- return 2;- return 0;-}-_ACEOF-if ac_fn_c_try_run "$LINENO"; then :--else- ac_cv_header_stdc=no-fi-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \- conftest.$ac_objext conftest.beam conftest.$ac_ext-fi--fi-fi-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5-$as_echo "$ac_cv_header_stdc" >&6; }-if test $ac_cv_header_stdc = yes; then--$as_echo "#define STDC_HEADERS 1" >>confdefs.h--fi--# On IRIX 5.3, sys/types and inttypes.h are conflicting.-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \- inttypes.h stdint.h unistd.h-do :- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default-"-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1-_ACEOF--fi--done---for ac_header in fcntl.h limits.h sys/types.h sys/stat.h time.h-do :- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :- cat >>confdefs.h <<_ACEOF-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1-_ACEOF--fi--done---for ac_func in utimensat-do :- ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat"-if test "x$ac_cv_func_utimensat" = xyes; then :- cat >>confdefs.h <<_ACEOF-#define HAVE_UTIMENSAT 1-_ACEOF--fi-done--for ac_func in GetFinalPathNameByHandleW-do :- ac_fn_c_check_func "$LINENO" "GetFinalPathNameByHandleW" "ac_cv_func_GetFinalPathNameByHandleW"-if test "x$ac_cv_func_GetFinalPathNameByHandleW" = xyes; then :- cat >>confdefs.h <<_ACEOF-#define HAVE_GETFINALPATHNAMEBYHANDLEW 1-_ACEOF--fi-done---# EXTEXT is defined automatically by AC_PROG_CC;-# we just need to capture it in the header file--cat >>confdefs.h <<_ACEOF-#define EXE_EXTENSION "$EXEEXT"-_ACEOF---cat >confcache <<\_ACEOF-# This file is a shell script that caches the results of configure-# tests run on this system so they can be shared between configure-# scripts and configure runs, see configure's option --config-cache.-# It is not useful on other systems. If it contains results you don't-# want to keep, you may remove or edit it.-#-# config.status only pays attention to the cache file if you give it-# the --recheck option to rerun configure.-#-# `ac_cv_env_foo' variables (set or unset) will be overridden when-# loading this file, other *unset* `ac_cv_foo' will be assigned the-# following values.--_ACEOF--# The following way of writing the cache mishandles newlines in values,-# but we know of no workaround that is simple, portable, and efficient.-# So, we kill variables containing newlines.-# Ultrix sh set writes to stderr and can't be redirected directly,-# and sets the high bit in the cache file unless we assign to the vars.-(- for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do- eval ac_val=\$$ac_var- case $ac_val in #(- *${as_nl}*)- case $ac_var in #(- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;- esac- case $ac_var in #(- _ | IFS | as_nl) ;; #(- BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(- *) { eval $ac_var=; unset $ac_var;} ;;- esac ;;- esac- done-- (set) 2>&1 |- case $as_nl`(ac_space=' '; set) 2>&1` in #(- *${as_nl}ac_space=\ *)- # `set' does not quote correctly, so add quotes: double-quote- # substitution turns \\\\ into \\, and sed turns \\ into \.- sed -n \- "s/'/'\\\\''/g;- s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"- ;; #(- *)- # `set' quotes correctly as required by POSIX, so do not add quotes.- sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"- ;;- esac |- sort-) |- sed '- /^ac_cv_env_/b end- t clear- :clear- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/- t end- s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/- :end' >>confcache-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else- if test -w "$cache_file"; then- if test "x$cache_file" != "x/dev/null"; then- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5-$as_echo "$as_me: updating cache $cache_file" >&6;}- if test ! -f "$cache_file" || test -h "$cache_file"; then- cat confcache >"$cache_file"- else- case $cache_file in #(- */* | ?:*)- mv -f confcache "$cache_file"$$ &&- mv -f "$cache_file"$$ "$cache_file" ;; #(- *)- mv -f confcache "$cache_file" ;;- esac- fi- fi- else- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}- fi-fi-rm -f confcache--test "x$prefix" = xNONE && prefix=$ac_default_prefix-# Let make expand exec_prefix.-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'--DEFS=-DHAVE_CONFIG_H--ac_libobjs=-ac_ltlibobjs=-U=-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue- # 1. Remove the extension, and $U if already installed.- ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`- # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR- # will be set to the directory where LIBOBJS objects are built.- as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"- as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'-done-LIBOBJS=$ac_libobjs--LTLIBOBJS=$ac_ltlibobjs----: "${CONFIG_STATUS=./config.status}"-ac_write_fail=0-ac_clean_files_save=$ac_clean_files-ac_clean_files="$ac_clean_files $CONFIG_STATUS"-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}-as_write_fail=0-cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1-#! $SHELL-# Generated by $as_me.-# Run this file to recreate the current configuration.-# Compiler output produced by configure, useful for debugging-# configure, is in config.log if it exists.--debug=false-ac_cs_recheck=false-ac_cs_silent=false--SHELL=\${CONFIG_SHELL-$SHELL}-export SHELL-_ASEOF-cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1-## -------------------- ##-## M4sh Initialization. ##-## -------------------- ##--# Be more Bourne compatible-DUALCASE=1; export DUALCASE # for MKS sh-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :- emulate sh- NULLCMD=:- # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which- # is contrary to our usage. Disable this feature.- alias -g '${1+"$@"}'='"$@"'- setopt NO_GLOB_SUBST-else- case `(set -o) 2>/dev/null` in #(- *posix*) :- set -o posix ;; #(- *) :- ;;-esac-fi---as_nl='-'-export as_nl-# Printing a long string crashes Solaris 7 /usr/bin/printf.-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo-# Prefer a ksh shell builtin over an external printf program on Solaris,-# but without wasting forks for bash or zsh.-if test -z "$BASH_VERSION$ZSH_VERSION" \- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='print -r --'- as_echo_n='print -rn --'-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then- as_echo='printf %s\n'- as_echo_n='printf %s'-else- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'- as_echo_n='/usr/ucb/echo -n'- else- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'- as_echo_n_body='eval- arg=$1;- case $arg in #(- *"$as_nl"*)- expr "X$arg" : "X\\(.*\\)$as_nl";- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;- esac;- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"- '- export as_echo_n_body- as_echo_n='sh -c $as_echo_n_body as_echo'- fi- export as_echo_body- as_echo='sh -c $as_echo_body as_echo'-fi--# The user is always right.-if test "${PATH_SEPARATOR+set}" != set; then- PATH_SEPARATOR=:- (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {- (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||- PATH_SEPARATOR=';'- }-fi---# IFS-# We need space, tab and new line, in precisely that order. Quoting is-# there to prevent editors from complaining about space-tab.-# (If _AS_PATH_WALK were called with IFS unset, it would disable word-# splitting by setting IFS to empty value.)-IFS=" "" $as_nl"--# Find who we are. Look in the path if we contain no directory separator.-as_myself=-case $0 in #((- *[\\/]* ) as_myself=$0 ;;- *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR-for as_dir in $PATH-do- IFS=$as_save_IFS- test -z "$as_dir" && as_dir=.- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break- done-IFS=$as_save_IFS-- ;;-esac-# We did not find ourselves, most probably we were run as `sh COMMAND'-# in which case we are not to be found in the path.-if test "x$as_myself" = x; then- as_myself=$0-fi-if test ! -f "$as_myself"; then- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2- exit 1-fi--# Unset variables that we do not need and which cause bugs (e.g. in-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"-# suppresses any "Segmentation fault" message there. '((' could-# trigger a bug in pdksh 5.2.14.-for as_var in BASH_ENV ENV MAIL MAILPATH-do eval test x\${$as_var+set} = xset \- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :-done-PS1='$ '-PS2='> '-PS4='+ '--# NLS nuisances.-LC_ALL=C-export LC_ALL-LANGUAGE=C-export LANGUAGE--# CDPATH.-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH---# as_fn_error STATUS ERROR [LINENO LOG_FD]-# -----------------------------------------# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are-# provided, also output the error to LOG_FD, referencing LINENO. Then exit the-# script with STATUS, using 1 if that was 0.-as_fn_error ()-{- as_status=$1; test $as_status -eq 0 && as_status=1- if test "$4"; then- as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4- fi- $as_echo "$as_me: error: $2" >&2- as_fn_exit $as_status-} # as_fn_error---# as_fn_set_status STATUS-# ------------------------# Set $? to STATUS, without forking.-as_fn_set_status ()-{- return $1-} # as_fn_set_status--# as_fn_exit STATUS-# ------------------# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.-as_fn_exit ()-{- set +e- as_fn_set_status $1- exit $1-} # as_fn_exit--# as_fn_unset VAR-# ----------------# Portably unset VAR.-as_fn_unset ()-{- { eval $1=; unset $1;}-}-as_unset=as_fn_unset-# as_fn_append VAR VALUE-# -----------------------# Append the text in VALUE to the end of the definition contained in VAR. Take-# advantage of any shell optimizations that allow amortized linear growth over-# repeated appends, instead of the typical quadratic growth present in naive-# implementations.-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :- eval 'as_fn_append ()- {- eval $1+=\$2- }'-else- as_fn_append ()- {- eval $1=\$$1\$2- }-fi # as_fn_append--# as_fn_arith ARG...-# -------------------# Perform arithmetic evaluation on the ARGs, and store the result in the-# global $as_val. Take advantage of shells that can avoid forks. The arguments-# must be portable across $(()) and expr.-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :- eval 'as_fn_arith ()- {- as_val=$(( $* ))- }'-else- as_fn_arith ()- {- as_val=`expr "$@" || test $? -eq 1`- }-fi # as_fn_arith---if expr a : '\(a\)' >/dev/null 2>&1 &&- test "X`expr 00001 : '.*\(...\)'`" = X001; then- as_expr=expr-else- as_expr=false-fi--if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then- as_basename=basename-else- as_basename=false-fi--if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then- as_dirname=dirname-else- as_dirname=false-fi--as_me=`$as_basename -- "$0" ||-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \- X"$0" : 'X\(//\)$' \| \- X"$0" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X/"$0" |- sed '/^.*\/\([^/][^/]*\)\/*$/{- s//\1/- q- }- /^X\/\(\/\/\)$/{- s//\1/- q- }- /^X\/\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`--# Avoid depending upon Character Ranges.-as_cr_letters='abcdefghijklmnopqrstuvwxyz'-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'-as_cr_Letters=$as_cr_letters$as_cr_LETTERS-as_cr_digits='0123456789'-as_cr_alnum=$as_cr_Letters$as_cr_digits--ECHO_C= ECHO_N= ECHO_T=-case `echo -n x` in #(((((--n*)- case `echo 'xy\c'` in- *c*) ECHO_T=' ';; # ECHO_T is single tab character.- xy) ECHO_C='\c';;- *) echo `echo ksh88 bug on AIX 6.1` > /dev/null- ECHO_T=' ';;- esac;;-*)- ECHO_N='-n';;-esac--rm -f conf$$ conf$$.exe conf$$.file-if test -d conf$$.dir; then- rm -f conf$$.dir/conf$$.file-else- rm -f conf$$.dir- mkdir conf$$.dir 2>/dev/null-fi-if (echo >conf$$.file) 2>/dev/null; then- if ln -s conf$$.file conf$$ 2>/dev/null; then- as_ln_s='ln -s'- # ... but there are two gotchas:- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.- # In both cases, we have to default to `cp -pR'.- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||- as_ln_s='cp -pR'- elif ln conf$$.file conf$$ 2>/dev/null; then- as_ln_s=ln- else- as_ln_s='cp -pR'- fi-else- as_ln_s='cp -pR'-fi-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file-rmdir conf$$.dir 2>/dev/null---# as_fn_mkdir_p-# --------------# Create "$as_dir" as a directory, including parents if necessary.-as_fn_mkdir_p ()-{-- case $as_dir in #(- -*) as_dir=./$as_dir;;- esac- test -d "$as_dir" || eval $as_mkdir_p || {- as_dirs=- while :; do- case $as_dir in #(- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(- *) as_qdir=$as_dir;;- esac- as_dirs="'$as_qdir' $as_dirs"- as_dir=`$as_dirname -- "$as_dir" ||-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$as_dir" : 'X\(//\)[^/]' \| \- X"$as_dir" : 'X\(//\)$' \| \- X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$as_dir" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- test -d "$as_dir" && break- done- test -z "$as_dirs" || eval "mkdir $as_dirs"- } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"---} # as_fn_mkdir_p-if mkdir -p . 2>/dev/null; then- as_mkdir_p='mkdir -p "$as_dir"'-else- test -d ./-p && rmdir ./-p- as_mkdir_p=false-fi---# as_fn_executable_p FILE-# ------------------------# Test if FILE is an executable regular file.-as_fn_executable_p ()-{- test -f "$1" && test -x "$1"-} # as_fn_executable_p-as_test_x='test -x'-as_executable_p=as_fn_executable_p--# Sed expression to map a string onto a valid CPP name.-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"--# Sed expression to map a string onto a valid variable name.-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"---exec 6>&1-## ----------------------------------- ##-## Main body of $CONFIG_STATUS script. ##-## ----------------------------------- ##-_ASEOF-test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-# Save the log message, to keep $0 and so on meaningful, and to-# report actual input values of CONFIG_FILES etc. instead of their-# values after options handling.-ac_log="-This file was extended by Haskell directory package $as_me 1.0, which was-generated by GNU Autoconf 2.69. Invocation command line was-- CONFIG_FILES = $CONFIG_FILES- CONFIG_HEADERS = $CONFIG_HEADERS- CONFIG_LINKS = $CONFIG_LINKS- CONFIG_COMMANDS = $CONFIG_COMMANDS- $ $0 $@--on `(hostname || uname -n) 2>/dev/null | sed 1q`-"--_ACEOF---case $ac_config_headers in *"-"*) set x $ac_config_headers; shift; ac_config_headers=$*;;-esac---cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-# Files that config.status was made for.-config_headers="$ac_config_headers"--_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-ac_cs_usage="\-\`$as_me' instantiates files and other configuration actions-from templates according to the current configuration. Unless the files-and actions are specified as TAGs, all are instantiated by default.--Usage: $0 [OPTION]... [TAG]...-- -h, --help print this help, then exit- -V, --version print version number and configuration settings, then exit- --config print configuration, then exit- -q, --quiet, --silent- do not print progress messages- -d, --debug don't remove temporary files- --recheck update $as_me by reconfiguring in the same conditions- --header=FILE[:TEMPLATE]- instantiate the configuration header FILE--Configuration headers:-$config_headers--Report bugs to <libraries@haskell.org>."--_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"-ac_cs_version="\\-Haskell directory package config.status 1.0-configured by $0, generated by GNU Autoconf 2.69,- with options \\"\$ac_cs_config\\"--Copyright (C) 2012 Free Software Foundation, Inc.-This config.status script is free software; the Free Software Foundation-gives unlimited permission to copy, distribute and modify it."--ac_pwd='$ac_pwd'-srcdir='$srcdir'-test -n "\$AWK" || AWK=awk-_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-# The default lists apply if the user does not specify any file.-ac_need_defaults=:-while test $# != 0-do- case $1 in- --*=?*)- ac_option=`expr "X$1" : 'X\([^=]*\)='`- ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`- ac_shift=:- ;;- --*=)- ac_option=`expr "X$1" : 'X\([^=]*\)='`- ac_optarg=- ac_shift=:- ;;- *)- ac_option=$1- ac_optarg=$2- ac_shift=shift- ;;- esac-- case $ac_option in- # Handling of the options.- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)- ac_cs_recheck=: ;;- --version | --versio | --versi | --vers | --ver | --ve | --v | -V )- $as_echo "$ac_cs_version"; exit ;;- --config | --confi | --conf | --con | --co | --c )- $as_echo "$ac_cs_config"; exit ;;- --debug | --debu | --deb | --de | --d | -d )- debug=: ;;- --header | --heade | --head | --hea )- $ac_shift- case $ac_optarg in- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;- esac- as_fn_append CONFIG_HEADERS " '$ac_optarg'"- ac_need_defaults=false;;- --he | --h)- # Conflict between --help and --header- as_fn_error $? "ambiguous option: \`$1'-Try \`$0 --help' for more information.";;- --help | --hel | -h )- $as_echo "$ac_cs_usage"; exit ;;- -q | -quiet | --quiet | --quie | --qui | --qu | --q \- | -silent | --silent | --silen | --sile | --sil | --si | --s)- ac_cs_silent=: ;;-- # This is an error.- -*) as_fn_error $? "unrecognized option: \`$1'-Try \`$0 --help' for more information." ;;-- *) as_fn_append ac_config_targets " $1"- ac_need_defaults=false ;;-- esac- shift-done--ac_configure_extra_args=--if $ac_cs_silent; then- exec 6>/dev/null- ac_configure_extra_args="$ac_configure_extra_args --silent"-fi--_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-if \$ac_cs_recheck; then- set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion- shift- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6- CONFIG_SHELL='$SHELL'- export CONFIG_SHELL- exec "\$@"-fi--_ACEOF-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1-exec 5>>config.log-{- echo- sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX-## Running $as_me. ##-_ASBOX- $as_echo "$ac_log"-} >&5--_ACEOF-cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1-_ACEOF--cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1--# Handling of arguments.-for ac_config_target in $ac_config_targets-do- case $ac_config_target in- "HsDirectoryConfig.h") CONFIG_HEADERS="$CONFIG_HEADERS HsDirectoryConfig.h" ;;-- *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;- esac-done---# If the user did not use the arguments to specify the items to instantiate,-# then the envvar interface is used. Set only those that are not.-# We use the long form for the default assignment because of an extremely-# bizarre bug on SunOS 4.1.3.-if $ac_need_defaults; then- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers-fi--# Have a temporary directory for convenience. Make it in the build tree-# simply because there is no reason against having it here, and in addition,-# creating and moving files from /tmp can sometimes cause problems.-# Hook for its removal unless debugging.-# Note that there is a small window in which the directory will not be cleaned:-# after its creation but before its name has been assigned to `$tmp'.-$debug ||-{- tmp= ac_tmp=- trap 'exit_status=$?- : "${ac_tmp:=$tmp}"- { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status-' 0- trap 'as_fn_exit 1' 1 2 13 15-}-# Create a (secure) tmp directory for tmp files.--{- tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&- test -d "$tmp"-} ||-{- tmp=./conf$$-$RANDOM- (umask 077 && mkdir "$tmp")-} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5-ac_tmp=$tmp--# Set up the scripts for CONFIG_HEADERS section.-# No need to generate them if there are no CONFIG_HEADERS.-# This happens for instance with `./config.status Makefile'.-if test -n "$CONFIG_HEADERS"; then-cat >"$ac_tmp/defines.awk" <<\_ACAWK ||-BEGIN {-_ACEOF--# Transform confdefs.h into an awk script `defines.awk', embedded as-# here-document in config.status, that substitutes the proper values into-# config.h.in to produce config.h.--# Create a delimiter string that does not exist in confdefs.h, to ease-# handling of long lines.-ac_delim='%!_!# '-for ac_last_try in false false :; do- ac_tt=`sed -n "/$ac_delim/p" confdefs.h`- if test -z "$ac_tt"; then- break- elif $ac_last_try; then- as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5- else- ac_delim="$ac_delim!$ac_delim _$ac_delim!! "- fi-done--# For the awk script, D is an array of macro values keyed by name,-# likewise P contains macro parameters if any. Preserve backslash-# newline sequences.--ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*-sed -n '-s/.\{148\}/&'"$ac_delim"'/g-t rset-:rset-s/^[ ]*#[ ]*define[ ][ ]*/ /-t def-d-:def-s/\\$//-t bsnl-s/["\\]/\\&/g-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\-D["\1"]=" \3"/p-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p-d-:bsnl-s/["\\]/\\&/g-s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\-D["\1"]=" \3\\\\\\n"\\/p-t cont-s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p-t cont-d-:cont-n-s/.\{148\}/&'"$ac_delim"'/g-t clear-:clear-s/\\$//-t bsnlc-s/["\\]/\\&/g; s/^/"/; s/$/"/p-d-:bsnlc-s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p-b cont-' <confdefs.h | sed '-s/'"$ac_delim"'/"\\\-"/g' >>$CONFIG_STATUS || ac_write_fail=1--cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1- for (key in D) D_is_set[key] = 1- FS = ""-}-/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {- line = \$ 0- split(line, arg, " ")- if (arg[1] == "#") {- defundef = arg[2]- mac1 = arg[3]- } else {- defundef = substr(arg[1], 2)- mac1 = arg[2]- }- split(mac1, mac2, "(") #)- macro = mac2[1]- prefix = substr(line, 1, index(line, defundef) - 1)- if (D_is_set[macro]) {- # Preserve the white space surrounding the "#".- print prefix "define", macro P[macro] D[macro]- next- } else {- # Replace #undef with comments. This is necessary, for example,- # in the case of _POSIX_SOURCE, which is predefined and required- # on some systems where configure will not decide to define it.- if (defundef == "undef") {- print "/*", prefix defundef, macro, "*/"- next- }- }-}-{ print }-_ACAWK-_ACEOF-cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1- as_fn_error $? "could not setup config headers machinery" "$LINENO" 5-fi # test -n "$CONFIG_HEADERS"---eval set X " :H $CONFIG_HEADERS "-shift-for ac_tag-do- case $ac_tag in- :[FHLC]) ac_mode=$ac_tag; continue;;- esac- case $ac_mode$ac_tag in- :[FHL]*:*);;- :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;- :[FH]-) ac_tag=-:-;;- :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;- esac- ac_save_IFS=$IFS- IFS=:- set x $ac_tag- IFS=$ac_save_IFS- shift- ac_file=$1- shift-- case $ac_mode in- :L) ac_source=$1;;- :[FH])- ac_file_inputs=- for ac_f- do- case $ac_f in- -) ac_f="$ac_tmp/stdin";;- *) # Look for the file first in the build tree, then in the source tree- # (if the path is not absolute). The absolute path cannot be DOS-style,- # because $ac_f cannot contain `:'.- test -f "$ac_f" ||- case $ac_f in- [\\/$]*) false;;- *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;- esac ||- as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;- esac- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac- as_fn_append ac_file_inputs " '$ac_f'"- done-- # Let's still pretend it is `configure' which instantiates (i.e., don't- # use $as_me), people would be surprised to read:- # /* config.h. Generated by config.status. */- configure_input='Generated from '`- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'- `' by configure.'- if test x"$ac_file" != x-; then- configure_input="$ac_file. $configure_input"- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5-$as_echo "$as_me: creating $ac_file" >&6;}- fi- # Neutralize special characters interpreted by sed in replacement strings.- case $configure_input in #(- *\&* | *\|* | *\\* )- ac_sed_conf_input=`$as_echo "$configure_input" |- sed 's/[\\\\&|]/\\\\&/g'`;; #(- *) ac_sed_conf_input=$configure_input;;- esac-- case $ac_tag in- *:-:* | *:-) cat >"$ac_tmp/stdin" \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;- esac- ;;- esac-- ac_dir=`$as_dirname -- "$ac_file" ||-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \- X"$ac_file" : 'X\(//\)[^/]' \| \- X"$ac_file" : 'X\(//\)$' \| \- X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||-$as_echo X"$ac_file" |- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{- s//\1/- q- }- /^X\(\/\/\)[^/].*/{- s//\1/- q- }- /^X\(\/\/\)$/{- s//\1/- q- }- /^X\(\/\).*/{- s//\1/- q- }- s/.*/./; q'`- as_dir="$ac_dir"; as_fn_mkdir_p- ac_builddir=.--case "$ac_dir" in-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;-*)- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`- # A ".." for each directory in $ac_dir_suffix.- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`- case $ac_top_builddir_sub in- "") ac_top_builddir_sub=. ac_top_build_prefix= ;;- *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;- esac ;;-esac-ac_abs_top_builddir=$ac_pwd-ac_abs_builddir=$ac_pwd$ac_dir_suffix-# for backward compatibility:-ac_top_builddir=$ac_top_build_prefix--case $srcdir in- .) # We are building in place.- ac_srcdir=.- ac_top_srcdir=$ac_top_builddir_sub- ac_abs_top_srcdir=$ac_pwd ;;- [\\/]* | ?:[\\/]* ) # Absolute name.- ac_srcdir=$srcdir$ac_dir_suffix;- ac_top_srcdir=$srcdir- ac_abs_top_srcdir=$srcdir ;;- *) # Relative name.- ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix- ac_top_srcdir=$ac_top_build_prefix$srcdir- ac_abs_top_srcdir=$ac_pwd/$srcdir ;;-esac-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix--- case $ac_mode in-- :H)- #- # CONFIG_HEADER- #- if test x"$ac_file" != x-; then- {- $as_echo "/* $configure_input */" \- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"- } >"$ac_tmp/config.h" \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5- if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5-$as_echo "$as_me: $ac_file is unchanged" >&6;}- else- rm -f "$ac_file"- mv "$ac_tmp/config.h" "$ac_file" \- || as_fn_error $? "could not create $ac_file" "$LINENO" 5- fi- else- $as_echo "/* $configure_input */" \- && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \- || as_fn_error $? "could not create -" "$LINENO" 5- fi- ;;--- esac--done # for ac_tag---as_fn_exit 0-_ACEOF-ac_clean_files=$ac_clean_files_save--test $ac_write_fail = 0 ||- as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5---# configure is writing to config.log, and then calls config.status.-# config.status does its own redirection, appending to config.log.-# Unfortunately, on DOS this fails, as config.log is still kept open-# by configure, so config.status won't be able to write to it; its-# output is simply discarded. So we exec the FD to /dev/null,-# effectively closing config.log, so it can be properly (re)opened and-# appended to by config.status. When coming back to configure, we-# need to make the FD available again.-if test "$no_create" != yes; then- ac_cs_success=:- ac_config_status_args=- test "$silent" = yes &&- ac_config_status_args="$ac_config_status_args --quiet"- exec 5>/dev/null- $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false- exec 5>>config.log- # Use ||, not &&, to avoid exiting from the if with $? = 1, which- # would make configure fail if this is the last instruction.- $ac_cs_success || as_fn_exit 1-fi-if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}-fi+# Generated by GNU Autoconf 2.71 for Haskell directory package 1.0.+#+# Report bugs to <libraries@haskell.org>.+#+#+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,+# Inc.+#+#+# This configure script is free software; the Free Software Foundation+# gives unlimited permission to copy, distribute and modify it.+## -------------------- ##+## M4sh Initialization. ##+## -------------------- ##++# Be more Bourne compatible+DUALCASE=1; export DUALCASE # for MKS sh+as_nop=:+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1+then :+ emulate sh+ NULLCMD=:+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which+ # is contrary to our usage. Disable this feature.+ alias -g '${1+"$@"}'='"$@"'+ setopt NO_GLOB_SUBST+else $as_nop+ case `(set -o) 2>/dev/null` in #(+ *posix*) :+ set -o posix ;; #(+ *) :+ ;;+esac+fi++++# Reset variables that may have inherited troublesome values from+# the environment.++# IFS needs to be set, to space, tab, and newline, in precisely that order.+# (If _AS_PATH_WALK were called with IFS unset, it would have the+# side effect of setting IFS to empty, thus disabling word splitting.)+# Quoting is to prevent editors from complaining about space-tab.+as_nl='+'+export as_nl+IFS=" "" $as_nl"++PS1='$ '+PS2='> '+PS4='+ '++# Ensure predictable behavior from utilities with locale-dependent output.+LC_ALL=C+export LC_ALL+LANGUAGE=C+export LANGUAGE++# We cannot yet rely on "unset" to work, but we need these variables+# to be unset--not just set to an empty or harmless value--now, to+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct+# also avoids known problems related to "unset" and subshell syntax+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH+do eval test \${$as_var+y} \+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :+done++# Ensure that fds 0, 1, and 2 are open.+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi++# The user is always right.+if ${PATH_SEPARATOR+false} :; then+ PATH_SEPARATOR=:+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||+ PATH_SEPARATOR=';'+ }+fi+++# Find who we are. Look in the path if we contain no directory separator.+as_myself=+case $0 in #((+ *[\\/]* ) as_myself=$0 ;;+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break+ done+IFS=$as_save_IFS++ ;;+esac+# We did not find ourselves, most probably we were run as `sh COMMAND'+# in which case we are not to be found in the path.+if test "x$as_myself" = x; then+ as_myself=$0+fi+if test ! -f "$as_myself"; then+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2+ exit 1+fi+++# Use a proper internal environment variable to ensure we don't fall+ # into an infinite loop, continuously re-executing ourselves.+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then+ _as_can_reexec=no; export _as_can_reexec;+ # We cannot yet assume a decent shell, so we have to provide a+# neutralization value for shells without unset; and this also+# works around shells that cannot unset nonexistent variables.+# Preserve -v and -x to the replacement shell.+BASH_ENV=/dev/null+ENV=/dev/null+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV+case $- in # ((((+ *v*x* | *x*v* ) as_opts=-vx ;;+ *v* ) as_opts=-v ;;+ *x* ) as_opts=-x ;;+ * ) as_opts= ;;+esac+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}+# Admittedly, this is quite paranoid, since all the known shells bail+# out after a failed `exec'.+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2+exit 255+ fi+ # We don't want this to propagate to other subprocesses.+ { _as_can_reexec=; unset _as_can_reexec;}+if test "x$CONFIG_SHELL" = x; then+ as_bourne_compatible="as_nop=:+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1+then :+ emulate sh+ NULLCMD=:+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which+ # is contrary to our usage. Disable this feature.+ alias -g '\${1+\"\$@\"}'='\"\$@\"'+ setopt NO_GLOB_SUBST+else \$as_nop+ case \`(set -o) 2>/dev/null\` in #(+ *posix*) :+ set -o posix ;; #(+ *) :+ ;;+esac+fi+"+ as_required="as_fn_return () { (exit \$1); }+as_fn_success () { as_fn_return 0; }+as_fn_failure () { as_fn_return 1; }+as_fn_ret_success () { return 0; }+as_fn_ret_failure () { return 1; }++exitcode=0+as_fn_success || { exitcode=1; echo as_fn_success failed.; }+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }+if ( set x; as_fn_ret_success y && test x = \"\$1\" )+then :++else \$as_nop+ exitcode=1; echo positional parameters were not saved.+fi+test x\$exitcode = x0 || exit 1+blah=\$(echo \$(echo blah))+test x\"\$blah\" = xblah || exit 1+test -x / || exit 1"+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1"+ if (eval "$as_required") 2>/dev/null+then :+ as_have_required=yes+else $as_nop+ as_have_required=no+fi+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null+then :++else $as_nop+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+as_found=false+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ as_found=:+ case $as_dir in #(+ /*)+ for as_base in sh bash ksh sh5; do+ # Try only shells that exist, to save several forks.+ as_shell=$as_dir$as_base+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null+then :+ CONFIG_SHELL=$as_shell as_have_required=yes+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null+then :+ break 2+fi+fi+ done;;+ esac+ as_found=false+done+IFS=$as_save_IFS+if $as_found+then :++else $as_nop+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null+then :+ CONFIG_SHELL=$SHELL as_have_required=yes+fi+fi+++ if test "x$CONFIG_SHELL" != x+then :+ export CONFIG_SHELL+ # We cannot yet assume a decent shell, so we have to provide a+# neutralization value for shells without unset; and this also+# works around shells that cannot unset nonexistent variables.+# Preserve -v and -x to the replacement shell.+BASH_ENV=/dev/null+ENV=/dev/null+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV+case $- in # ((((+ *v*x* | *x*v* ) as_opts=-vx ;;+ *v* ) as_opts=-v ;;+ *x* ) as_opts=-x ;;+ * ) as_opts= ;;+esac+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}+# Admittedly, this is quite paranoid, since all the known shells bail+# out after a failed `exec'.+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2+exit 255+fi++ if test x$as_have_required = xno+then :+ printf "%s\n" "$0: This script requires a shell more modern than all"+ printf "%s\n" "$0: the shells that I found on your system."+ if test ${ZSH_VERSION+y} ; then+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."+ else+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and+$0: libraries@haskell.org about your system, including any+$0: error possibly output before this message. Then install+$0: a modern shell, or manually run the script under such a+$0: shell if you do have one."+ fi+ exit 1+fi+fi+fi+SHELL=${CONFIG_SHELL-/bin/sh}+export SHELL+# Unset more variables known to interfere with behavior of common tools.+CLICOLOR_FORCE= GREP_OPTIONS=+unset CLICOLOR_FORCE GREP_OPTIONS++## --------------------- ##+## M4sh Shell Functions. ##+## --------------------- ##+# as_fn_unset VAR+# ---------------+# Portably unset VAR.+as_fn_unset ()+{+ { eval $1=; unset $1;}+}+as_unset=as_fn_unset+++# as_fn_set_status STATUS+# -----------------------+# Set $? to STATUS, without forking.+as_fn_set_status ()+{+ return $1+} # as_fn_set_status++# as_fn_exit STATUS+# -----------------+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.+as_fn_exit ()+{+ set +e+ as_fn_set_status $1+ exit $1+} # as_fn_exit+# as_fn_nop+# ---------+# Do nothing but, unlike ":", preserve the value of $?.+as_fn_nop ()+{+ return $?+}+as_nop=as_fn_nop++# as_fn_mkdir_p+# -------------+# Create "$as_dir" as a directory, including parents if necessary.+as_fn_mkdir_p ()+{++ case $as_dir in #(+ -*) as_dir=./$as_dir;;+ esac+ test -d "$as_dir" || eval $as_mkdir_p || {+ as_dirs=+ while :; do+ case $as_dir in #(+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(+ *) as_qdir=$as_dir;;+ esac+ as_dirs="'$as_qdir' $as_dirs"+ as_dir=`$as_dirname -- "$as_dir" ||+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+ X"$as_dir" : 'X\(//\)[^/]' \| \+ X"$as_dir" : 'X\(//\)$' \| \+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||+printf "%s\n" X"$as_dir" |+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+ s//\1/+ q+ }+ /^X\(\/\/\)[^/].*/{+ s//\1/+ q+ }+ /^X\(\/\/\)$/{+ s//\1/+ q+ }+ /^X\(\/\).*/{+ s//\1/+ q+ }+ s/.*/./; q'`+ test -d "$as_dir" && break+ done+ test -z "$as_dirs" || eval "mkdir $as_dirs"+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"+++} # as_fn_mkdir_p++# as_fn_executable_p FILE+# -----------------------+# Test if FILE is an executable regular file.+as_fn_executable_p ()+{+ test -f "$1" && test -x "$1"+} # as_fn_executable_p+# as_fn_append VAR VALUE+# ----------------------+# Append the text in VALUE to the end of the definition contained in VAR. Take+# advantage of any shell optimizations that allow amortized linear growth over+# repeated appends, instead of the typical quadratic growth present in naive+# implementations.+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null+then :+ eval 'as_fn_append ()+ {+ eval $1+=\$2+ }'+else $as_nop+ as_fn_append ()+ {+ eval $1=\$$1\$2+ }+fi # as_fn_append++# as_fn_arith ARG...+# ------------------+# Perform arithmetic evaluation on the ARGs, and store the result in the+# global $as_val. Take advantage of shells that can avoid forks. The arguments+# must be portable across $(()) and expr.+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null+then :+ eval 'as_fn_arith ()+ {+ as_val=$(( $* ))+ }'+else $as_nop+ as_fn_arith ()+ {+ as_val=`expr "$@" || test $? -eq 1`+ }+fi # as_fn_arith++# as_fn_nop+# ---------+# Do nothing but, unlike ":", preserve the value of $?.+as_fn_nop ()+{+ return $?+}+as_nop=as_fn_nop++# as_fn_error STATUS ERROR [LINENO LOG_FD]+# ----------------------------------------+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the+# script with STATUS, using 1 if that was 0.+as_fn_error ()+{+ as_status=$1; test $as_status -eq 0 && as_status=1+ if test "$4"; then+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4+ fi+ printf "%s\n" "$as_me: error: $2" >&2+ as_fn_exit $as_status+} # as_fn_error++if expr a : '\(a\)' >/dev/null 2>&1 &&+ test "X`expr 00001 : '.*\(...\)'`" = X001; then+ as_expr=expr+else+ as_expr=false+fi++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then+ as_basename=basename+else+ as_basename=false+fi++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then+ as_dirname=dirname+else+ as_dirname=false+fi++as_me=`$as_basename -- "$0" ||+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \+ X"$0" : 'X\(//\)$' \| \+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||+printf "%s\n" X/"$0" |+ sed '/^.*\/\([^/][^/]*\)\/*$/{+ s//\1/+ q+ }+ /^X\/\(\/\/\)$/{+ s//\1/+ q+ }+ /^X\/\(\/\).*/{+ s//\1/+ q+ }+ s/.*/./; q'`++# Avoid depending upon Character Ranges.+as_cr_letters='abcdefghijklmnopqrstuvwxyz'+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'+as_cr_Letters=$as_cr_letters$as_cr_LETTERS+as_cr_digits='0123456789'+as_cr_alnum=$as_cr_Letters$as_cr_digits+++ as_lineno_1=$LINENO as_lineno_1a=$LINENO+ as_lineno_2=$LINENO as_lineno_2a=$LINENO+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)+ sed -n '+ p+ /[$]LINENO/=+ ' <$as_myself |+ sed '+ s/[$]LINENO.*/&-/+ t lineno+ b+ :lineno+ N+ :loop+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/+ t loop+ s/-\n.*//+ ' >$as_me.lineno &&+ chmod +x "$as_me.lineno" ||+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }++ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have+ # already done that, so ensure we don't try to do so again and fall+ # in an infinite loop. This has already happened in practice.+ _as_can_reexec=no; export _as_can_reexec+ # Don't try to exec as it changes $[0], causing all sort of problems+ # (the dirname of $[0] is not the place where we might find the+ # original and so on. Autoconf is especially sensitive to this).+ . "./$as_me.lineno"+ # Exit status is that of the last command.+ exit+}+++# Determine whether it's possible to make 'echo' print without a newline.+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed+# for compatibility with existing Makefiles.+ECHO_C= ECHO_N= ECHO_T=+case `echo -n x` in #(((((+-n*)+ case `echo 'xy\c'` in+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.+ xy) ECHO_C='\c';;+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null+ ECHO_T=' ';;+ esac;;+*)+ ECHO_N='-n';;+esac++# For backward compatibility with old third-party macros, we provide+# the shell variables $as_echo and $as_echo_n. New code should use+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.+as_echo='printf %s\n'+as_echo_n='printf %s'+++rm -f conf$$ conf$$.exe conf$$.file+if test -d conf$$.dir; then+ rm -f conf$$.dir/conf$$.file+else+ rm -f conf$$.dir+ mkdir conf$$.dir 2>/dev/null+fi+if (echo >conf$$.file) 2>/dev/null; then+ if ln -s conf$$.file conf$$ 2>/dev/null; then+ as_ln_s='ln -s'+ # ... but there are two gotchas:+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.+ # In both cases, we have to default to `cp -pR'.+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||+ as_ln_s='cp -pR'+ elif ln conf$$.file conf$$ 2>/dev/null; then+ as_ln_s=ln+ else+ as_ln_s='cp -pR'+ fi+else+ as_ln_s='cp -pR'+fi+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file+rmdir conf$$.dir 2>/dev/null++if mkdir -p . 2>/dev/null; then+ as_mkdir_p='mkdir -p "$as_dir"'+else+ test -d ./-p && rmdir ./-p+ as_mkdir_p=false+fi++as_test_x='test -x'+as_executable_p=as_fn_executable_p++# Sed expression to map a string onto a valid CPP name.+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"++# Sed expression to map a string onto a valid variable name.+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"+++test -n "$DJDIR" || exec 7<&0 </dev/null+exec 6>&1++# Name of the host.+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,+# so uname gets run too.+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`++#+# Initializations.+#+ac_default_prefix=/usr/local+ac_clean_files=+ac_config_libobj_dir=.+LIBOBJS=+cross_compiling=no+subdirs=+MFLAGS=+MAKEFLAGS=++# Identity of this package.+PACKAGE_NAME='Haskell directory package'+PACKAGE_TARNAME='directory'+PACKAGE_VERSION='1.0'+PACKAGE_STRING='Haskell directory package 1.0'+PACKAGE_BUGREPORT='libraries@haskell.org'+PACKAGE_URL=''++ac_unique_file="System/Directory.hs"+# Factoring default headers for most tests.+ac_includes_default="\+#include <stddef.h>+#ifdef HAVE_STDIO_H+# include <stdio.h>+#endif+#ifdef HAVE_STDLIB_H+# include <stdlib.h>+#endif+#ifdef HAVE_STRING_H+# include <string.h>+#endif+#ifdef HAVE_INTTYPES_H+# include <inttypes.h>+#endif+#ifdef HAVE_STDINT_H+# include <stdint.h>+#endif+#ifdef HAVE_STRINGS_H+# include <strings.h>+#endif+#ifdef HAVE_SYS_TYPES_H+# include <sys/types.h>+#endif+#ifdef HAVE_SYS_STAT_H+# include <sys/stat.h>+#endif+#ifdef HAVE_UNISTD_H+# include <unistd.h>+#endif"++ac_header_c_list=+ac_subst_vars='LTLIBOBJS+LIBOBJS+OBJEXT+EXEEXT+ac_ct_CC+CPPFLAGS+LDFLAGS+CFLAGS+CC+target_alias+host_alias+build_alias+LIBS+ECHO_T+ECHO_N+ECHO_C+DEFS+mandir+localedir+libdir+psdir+pdfdir+dvidir+htmldir+infodir+docdir+oldincludedir+includedir+runstatedir+localstatedir+sharedstatedir+sysconfdir+datadir+datarootdir+libexecdir+sbindir+bindir+program_transform_name+prefix+exec_prefix+PACKAGE_URL+PACKAGE_BUGREPORT+PACKAGE_STRING+PACKAGE_VERSION+PACKAGE_TARNAME+PACKAGE_NAME+PATH_SEPARATOR+SHELL'+ac_subst_files=''+ac_user_opts='+enable_option_checking+with_gcc+with_compiler+'+ ac_precious_vars='build_alias+host_alias+target_alias+CC+CFLAGS+LDFLAGS+LIBS+CPPFLAGS'+++# Initialize some variables set by options.+ac_init_help=+ac_init_version=false+ac_unrecognized_opts=+ac_unrecognized_sep=+# The variables have the same names as the options, with+# dashes changed to underlines.+cache_file=/dev/null+exec_prefix=NONE+no_create=+no_recursion=+prefix=NONE+program_prefix=NONE+program_suffix=NONE+program_transform_name=s,x,x,+silent=+site=+srcdir=+verbose=+x_includes=NONE+x_libraries=NONE++# Installation directory options.+# These are left unexpanded so users can "make install exec_prefix=/foo"+# and all the variables that are supposed to be based on exec_prefix+# by default will actually change.+# Use braces instead of parens because sh, perl, etc. also accept them.+# (The list follows the same order as the GNU Coding Standards.)+bindir='${exec_prefix}/bin'+sbindir='${exec_prefix}/sbin'+libexecdir='${exec_prefix}/libexec'+datarootdir='${prefix}/share'+datadir='${datarootdir}'+sysconfdir='${prefix}/etc'+sharedstatedir='${prefix}/com'+localstatedir='${prefix}/var'+runstatedir='${localstatedir}/run'+includedir='${prefix}/include'+oldincludedir='/usr/include'+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'+infodir='${datarootdir}/info'+htmldir='${docdir}'+dvidir='${docdir}'+pdfdir='${docdir}'+psdir='${docdir}'+libdir='${exec_prefix}/lib'+localedir='${datarootdir}/locale'+mandir='${datarootdir}/man'++ac_prev=+ac_dashdash=+for ac_option+do+ # If the previous option needs an argument, assign it.+ if test -n "$ac_prev"; then+ eval $ac_prev=\$ac_option+ ac_prev=+ continue+ fi++ case $ac_option in+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;+ *=) ac_optarg= ;;+ *) ac_optarg=yes ;;+ esac++ case $ac_dashdash$ac_option in+ --)+ ac_dashdash=yes ;;++ -bindir | --bindir | --bindi | --bind | --bin | --bi)+ ac_prev=bindir ;;+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)+ bindir=$ac_optarg ;;++ -build | --build | --buil | --bui | --bu)+ ac_prev=build_alias ;;+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)+ build_alias=$ac_optarg ;;++ -cache-file | --cache-file | --cache-fil | --cache-fi \+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)+ ac_prev=cache_file ;;+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)+ cache_file=$ac_optarg ;;++ --config-cache | -C)+ cache_file=config.cache ;;++ -datadir | --datadir | --datadi | --datad)+ ac_prev=datadir ;;+ -datadir=* | --datadir=* | --datadi=* | --datad=*)+ datadir=$ac_optarg ;;++ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \+ | --dataroo | --dataro | --datar)+ ac_prev=datarootdir ;;+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)+ datarootdir=$ac_optarg ;;++ -disable-* | --disable-*)+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`+ # Reject names that are not valid shell variable names.+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&+ as_fn_error $? "invalid feature name: \`$ac_useropt'"+ ac_useropt_orig=$ac_useropt+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`+ case $ac_user_opts in+ *"+"enable_$ac_useropt"+"*) ;;+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"+ ac_unrecognized_sep=', ';;+ esac+ eval enable_$ac_useropt=no ;;++ -docdir | --docdir | --docdi | --doc | --do)+ ac_prev=docdir ;;+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)+ docdir=$ac_optarg ;;++ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)+ ac_prev=dvidir ;;+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)+ dvidir=$ac_optarg ;;++ -enable-* | --enable-*)+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`+ # Reject names that are not valid shell variable names.+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&+ as_fn_error $? "invalid feature name: \`$ac_useropt'"+ ac_useropt_orig=$ac_useropt+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`+ case $ac_user_opts in+ *"+"enable_$ac_useropt"+"*) ;;+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"+ ac_unrecognized_sep=', ';;+ esac+ eval enable_$ac_useropt=\$ac_optarg ;;++ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \+ | --exec | --exe | --ex)+ ac_prev=exec_prefix ;;+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \+ | --exec=* | --exe=* | --ex=*)+ exec_prefix=$ac_optarg ;;++ -gas | --gas | --ga | --g)+ # Obsolete; use --with-gas.+ with_gas=yes ;;++ -help | --help | --hel | --he | -h)+ ac_init_help=long ;;+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)+ ac_init_help=recursive ;;+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)+ ac_init_help=short ;;++ -host | --host | --hos | --ho)+ ac_prev=host_alias ;;+ -host=* | --host=* | --hos=* | --ho=*)+ host_alias=$ac_optarg ;;++ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)+ ac_prev=htmldir ;;+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \+ | --ht=*)+ htmldir=$ac_optarg ;;++ -includedir | --includedir | --includedi | --included | --include \+ | --includ | --inclu | --incl | --inc)+ ac_prev=includedir ;;+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \+ | --includ=* | --inclu=* | --incl=* | --inc=*)+ includedir=$ac_optarg ;;++ -infodir | --infodir | --infodi | --infod | --info | --inf)+ ac_prev=infodir ;;+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)+ infodir=$ac_optarg ;;++ -libdir | --libdir | --libdi | --libd)+ ac_prev=libdir ;;+ -libdir=* | --libdir=* | --libdi=* | --libd=*)+ libdir=$ac_optarg ;;++ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \+ | --libexe | --libex | --libe)+ ac_prev=libexecdir ;;+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \+ | --libexe=* | --libex=* | --libe=*)+ libexecdir=$ac_optarg ;;++ -localedir | --localedir | --localedi | --localed | --locale)+ ac_prev=localedir ;;+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)+ localedir=$ac_optarg ;;++ -localstatedir | --localstatedir | --localstatedi | --localstated \+ | --localstate | --localstat | --localsta | --localst | --locals)+ ac_prev=localstatedir ;;+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)+ localstatedir=$ac_optarg ;;++ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)+ ac_prev=mandir ;;+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)+ mandir=$ac_optarg ;;++ -nfp | --nfp | --nf)+ # Obsolete; use --without-fp.+ with_fp=no ;;++ -no-create | --no-create | --no-creat | --no-crea | --no-cre \+ | --no-cr | --no-c | -n)+ no_create=yes ;;++ -no-recursion | --no-recursion | --no-recursio | --no-recursi \+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)+ no_recursion=yes ;;++ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \+ | --oldin | --oldi | --old | --ol | --o)+ ac_prev=oldincludedir ;;+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)+ oldincludedir=$ac_optarg ;;++ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)+ ac_prev=prefix ;;+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)+ prefix=$ac_optarg ;;++ -program-prefix | --program-prefix | --program-prefi | --program-pref \+ | --program-pre | --program-pr | --program-p)+ ac_prev=program_prefix ;;+ -program-prefix=* | --program-prefix=* | --program-prefi=* \+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)+ program_prefix=$ac_optarg ;;++ -program-suffix | --program-suffix | --program-suffi | --program-suff \+ | --program-suf | --program-su | --program-s)+ ac_prev=program_suffix ;;+ -program-suffix=* | --program-suffix=* | --program-suffi=* \+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)+ program_suffix=$ac_optarg ;;++ -program-transform-name | --program-transform-name \+ | --program-transform-nam | --program-transform-na \+ | --program-transform-n | --program-transform- \+ | --program-transform | --program-transfor \+ | --program-transfo | --program-transf \+ | --program-trans | --program-tran \+ | --progr-tra | --program-tr | --program-t)+ ac_prev=program_transform_name ;;+ -program-transform-name=* | --program-transform-name=* \+ | --program-transform-nam=* | --program-transform-na=* \+ | --program-transform-n=* | --program-transform-=* \+ | --program-transform=* | --program-transfor=* \+ | --program-transfo=* | --program-transf=* \+ | --program-trans=* | --program-tran=* \+ | --progr-tra=* | --program-tr=* | --program-t=*)+ program_transform_name=$ac_optarg ;;++ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)+ ac_prev=pdfdir ;;+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)+ pdfdir=$ac_optarg ;;++ -psdir | --psdir | --psdi | --psd | --ps)+ ac_prev=psdir ;;+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)+ psdir=$ac_optarg ;;++ -q | -quiet | --quiet | --quie | --qui | --qu | --q \+ | -silent | --silent | --silen | --sile | --sil)+ silent=yes ;;++ -runstatedir | --runstatedir | --runstatedi | --runstated \+ | --runstate | --runstat | --runsta | --runst | --runs \+ | --run | --ru | --r)+ ac_prev=runstatedir ;;+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \+ | --run=* | --ru=* | --r=*)+ runstatedir=$ac_optarg ;;++ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)+ ac_prev=sbindir ;;+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \+ | --sbi=* | --sb=*)+ sbindir=$ac_optarg ;;++ -sharedstatedir | --sharedstatedir | --sharedstatedi \+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \+ | --sharedst | --shareds | --shared | --share | --shar \+ | --sha | --sh)+ ac_prev=sharedstatedir ;;+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \+ | --sha=* | --sh=*)+ sharedstatedir=$ac_optarg ;;++ -site | --site | --sit)+ ac_prev=site ;;+ -site=* | --site=* | --sit=*)+ site=$ac_optarg ;;++ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)+ ac_prev=srcdir ;;+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)+ srcdir=$ac_optarg ;;++ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \+ | --syscon | --sysco | --sysc | --sys | --sy)+ ac_prev=sysconfdir ;;+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)+ sysconfdir=$ac_optarg ;;++ -target | --target | --targe | --targ | --tar | --ta | --t)+ ac_prev=target_alias ;;+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)+ target_alias=$ac_optarg ;;++ -v | -verbose | --verbose | --verbos | --verbo | --verb)+ verbose=yes ;;++ -version | --version | --versio | --versi | --vers | -V)+ ac_init_version=: ;;++ -with-* | --with-*)+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`+ # Reject names that are not valid shell variable names.+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&+ as_fn_error $? "invalid package name: \`$ac_useropt'"+ ac_useropt_orig=$ac_useropt+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`+ case $ac_user_opts in+ *"+"with_$ac_useropt"+"*) ;;+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"+ ac_unrecognized_sep=', ';;+ esac+ eval with_$ac_useropt=\$ac_optarg ;;++ -without-* | --without-*)+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`+ # Reject names that are not valid shell variable names.+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&+ as_fn_error $? "invalid package name: \`$ac_useropt'"+ ac_useropt_orig=$ac_useropt+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`+ case $ac_user_opts in+ *"+"with_$ac_useropt"+"*) ;;+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"+ ac_unrecognized_sep=', ';;+ esac+ eval with_$ac_useropt=no ;;++ --x)+ # Obsolete; use --with-x.+ with_x=yes ;;++ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \+ | --x-incl | --x-inc | --x-in | --x-i)+ ac_prev=x_includes ;;+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)+ x_includes=$ac_optarg ;;++ -x-libraries | --x-libraries | --x-librarie | --x-librari \+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)+ ac_prev=x_libraries ;;+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)+ x_libraries=$ac_optarg ;;++ -*) as_fn_error $? "unrecognized option: \`$ac_option'+Try \`$0 --help' for more information"+ ;;++ *=*)+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`+ # Reject names that are not valid shell variable names.+ case $ac_envvar in #(+ '' | [0-9]* | *[!_$as_cr_alnum]* )+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;+ esac+ eval $ac_envvar=\$ac_optarg+ export $ac_envvar ;;++ *)+ # FIXME: should be removed in autoconf 3.0.+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"+ ;;++ esac+done++if test -n "$ac_prev"; then+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`+ as_fn_error $? "missing argument to $ac_option"+fi++if test -n "$ac_unrecognized_opts"; then+ case $enable_option_checking in+ no) ;;+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;+ esac+fi++# Check all directory arguments for consistency.+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \+ datadir sysconfdir sharedstatedir localstatedir includedir \+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \+ libdir localedir mandir runstatedir+do+ eval ac_val=\$$ac_var+ # Remove trailing slashes.+ case $ac_val in+ */ )+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`+ eval $ac_var=\$ac_val;;+ esac+ # Be sure to have absolute directory names.+ case $ac_val in+ [\\/$]* | ?:[\\/]* ) continue;;+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;+ esac+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"+done++# There might be people who depend on the old broken behavior: `$host'+# used to hold the argument of --host etc.+# FIXME: To remove some day.+build=$build_alias+host=$host_alias+target=$target_alias++# FIXME: To remove some day.+if test "x$host_alias" != x; then+ if test "x$build_alias" = x; then+ cross_compiling=maybe+ elif test "x$build_alias" != "x$host_alias"; then+ cross_compiling=yes+ fi+fi++ac_tool_prefix=+test -n "$host_alias" && ac_tool_prefix=$host_alias-++test "$silent" = yes && exec 6>/dev/null+++ac_pwd=`pwd` && test -n "$ac_pwd" &&+ac_ls_di=`ls -di .` &&+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||+ as_fn_error $? "working directory cannot be determined"+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||+ as_fn_error $? "pwd does not report name of working directory"+++# Find the source files, if location was not specified.+if test -z "$srcdir"; then+ ac_srcdir_defaulted=yes+ # Try the directory containing this script, then the parent directory.+ ac_confdir=`$as_dirname -- "$as_myself" ||+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+ X"$as_myself" : 'X\(//\)[^/]' \| \+ X"$as_myself" : 'X\(//\)$' \| \+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||+printf "%s\n" X"$as_myself" |+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+ s//\1/+ q+ }+ /^X\(\/\/\)[^/].*/{+ s//\1/+ q+ }+ /^X\(\/\/\)$/{+ s//\1/+ q+ }+ /^X\(\/\).*/{+ s//\1/+ q+ }+ s/.*/./; q'`+ srcdir=$ac_confdir+ if test ! -r "$srcdir/$ac_unique_file"; then+ srcdir=..+ fi+else+ ac_srcdir_defaulted=no+fi+if test ! -r "$srcdir/$ac_unique_file"; then+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"+fi+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"+ac_abs_confdir=`(+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"+ pwd)`+# When building in place, set srcdir=.+if test "$ac_abs_confdir" = "$ac_pwd"; then+ srcdir=.+fi+# Remove unnecessary trailing slashes from srcdir.+# Double slashes in file names in object file debugging info+# mess up M-x gdb in Emacs.+case $srcdir in+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;+esac+for ac_var in $ac_precious_vars; do+ eval ac_env_${ac_var}_set=\${${ac_var}+set}+ eval ac_env_${ac_var}_value=\$${ac_var}+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}+ eval ac_cv_env_${ac_var}_value=\$${ac_var}+done++#+# Report the --help message.+#+if test "$ac_init_help" = "long"; then+ # Omit some internal or obsolete options to make the list less imposing.+ # This message is too long to be a string in the A/UX 3.1 sh.+ cat <<_ACEOF+\`configure' configures Haskell directory package 1.0 to adapt to many kinds of systems.++Usage: $0 [OPTION]... [VAR=VALUE]...++To assign environment variables (e.g., CC, CFLAGS...), specify them as+VAR=VALUE. See below for descriptions of some of the useful variables.++Defaults for the options are specified in brackets.++Configuration:+ -h, --help display this help and exit+ --help=short display options specific to this package+ --help=recursive display the short help of all the included packages+ -V, --version display version information and exit+ -q, --quiet, --silent do not print \`checking ...' messages+ --cache-file=FILE cache test results in FILE [disabled]+ -C, --config-cache alias for \`--cache-file=config.cache'+ -n, --no-create do not create output files+ --srcdir=DIR find the sources in DIR [configure dir or \`..']++Installation directories:+ --prefix=PREFIX install architecture-independent files in PREFIX+ [$ac_default_prefix]+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX+ [PREFIX]++By default, \`make install' will install all the files in+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify+an installation prefix other than \`$ac_default_prefix' using \`--prefix',+for instance \`--prefix=\$HOME'.++For better control, use the options below.++Fine tuning of the installation directories:+ --bindir=DIR user executables [EPREFIX/bin]+ --sbindir=DIR system admin executables [EPREFIX/sbin]+ --libexecdir=DIR program executables [EPREFIX/libexec]+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]+ --libdir=DIR object code libraries [EPREFIX/lib]+ --includedir=DIR C header files [PREFIX/include]+ --oldincludedir=DIR C header files for non-gcc [/usr/include]+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]+ --infodir=DIR info documentation [DATAROOTDIR/info]+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]+ --mandir=DIR man documentation [DATAROOTDIR/man]+ --docdir=DIR documentation root [DATAROOTDIR/doc/directory]+ --htmldir=DIR html documentation [DOCDIR]+ --dvidir=DIR dvi documentation [DOCDIR]+ --pdfdir=DIR pdf documentation [DOCDIR]+ --psdir=DIR ps documentation [DOCDIR]+_ACEOF++ cat <<\_ACEOF+_ACEOF+fi++if test -n "$ac_init_help"; then+ case $ac_init_help in+ short | recursive ) echo "Configuration of Haskell directory package 1.0:";;+ esac+ cat <<\_ACEOF++Optional Packages:+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)+C compiler+GHC compiler++Some influential environment variables:+ CC C compiler command+ CFLAGS C compiler flags+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a+ nonstandard directory <lib dir>+ LIBS libraries to pass to the linker, e.g. -l<library>+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if+ you have headers in a nonstandard directory <include dir>++Use these variables to override the choices made by `configure' or to help+it to find libraries and programs with nonstandard names/locations.++Report bugs to <libraries@haskell.org>.+_ACEOF+ac_status=$?+fi++if test "$ac_init_help" = "recursive"; then+ # If there are subdirs, report their specific --help.+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue+ test -d "$ac_dir" ||+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||+ continue+ ac_builddir=.++case "$ac_dir" in+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;+*)+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`+ # A ".." for each directory in $ac_dir_suffix.+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`+ case $ac_top_builddir_sub in+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;+ esac ;;+esac+ac_abs_top_builddir=$ac_pwd+ac_abs_builddir=$ac_pwd$ac_dir_suffix+# for backward compatibility:+ac_top_builddir=$ac_top_build_prefix++case $srcdir in+ .) # We are building in place.+ ac_srcdir=.+ ac_top_srcdir=$ac_top_builddir_sub+ ac_abs_top_srcdir=$ac_pwd ;;+ [\\/]* | ?:[\\/]* ) # Absolute name.+ ac_srcdir=$srcdir$ac_dir_suffix;+ ac_top_srcdir=$srcdir+ ac_abs_top_srcdir=$srcdir ;;+ *) # Relative name.+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix+ ac_top_srcdir=$ac_top_build_prefix$srcdir+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;+esac+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix++ cd "$ac_dir" || { ac_status=$?; continue; }+ # Check for configure.gnu first; this name is used for a wrapper for+ # Metaconfig's "Configure" on case-insensitive file systems.+ if test -f "$ac_srcdir/configure.gnu"; then+ echo &&+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive+ elif test -f "$ac_srcdir/configure"; then+ echo &&+ $SHELL "$ac_srcdir/configure" --help=recursive+ else+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2+ fi || ac_status=$?+ cd "$ac_pwd" || { ac_status=$?; break; }+ done+fi++test -n "$ac_init_help" && exit $ac_status+if $ac_init_version; then+ cat <<\_ACEOF+Haskell directory package configure 1.0+generated by GNU Autoconf 2.71++Copyright (C) 2021 Free Software Foundation, Inc.+This configure script is free software; the Free Software Foundation+gives unlimited permission to copy, distribute and modify it.+_ACEOF+ exit+fi++## ------------------------ ##+## Autoconf initialization. ##+## ------------------------ ##++# ac_fn_c_try_compile LINENO+# --------------------------+# Try to compile conftest.$ac_ext, and return whether this succeeded.+ac_fn_c_try_compile ()+{+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack+ rm -f conftest.$ac_objext conftest.beam+ if { { ac_try="$ac_compile"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_compile") 2>conftest.err+ ac_status=$?+ if test -s conftest.err; then+ grep -v '^ *+' conftest.err >conftest.er1+ cat conftest.er1 >&5+ mv -f conftest.er1 conftest.err+ fi+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; } && {+ test -z "$ac_c_werror_flag" ||+ test ! -s conftest.err+ } && test -s conftest.$ac_objext+then :+ ac_retval=0+else $as_nop+ printf "%s\n" "$as_me: failed program was:" >&5+sed 's/^/| /' conftest.$ac_ext >&5++ ac_retval=1+fi+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno+ as_fn_set_status $ac_retval++} # ac_fn_c_try_compile++# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES+# -------------------------------------------------------+# Tests whether HEADER exists and can be compiled using the include files in+# INCLUDES, setting the cache variable VAR accordingly.+ac_fn_c_check_header_compile ()+{+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5+printf %s "checking for $2... " >&6; }+if eval test \${$3+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */+$4+#include <$2>+_ACEOF+if ac_fn_c_try_compile "$LINENO"+then :+ eval "$3=yes"+else $as_nop+ eval "$3=no"+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext+fi+eval ac_res=\$$3+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5+printf "%s\n" "$ac_res" >&6; }+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno++} # ac_fn_c_check_header_compile++# ac_fn_c_try_link LINENO+# -----------------------+# Try to link conftest.$ac_ext, and return whether this succeeded.+ac_fn_c_try_link ()+{+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext+ if { { ac_try="$ac_link"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_link") 2>conftest.err+ ac_status=$?+ if test -s conftest.err; then+ grep -v '^ *+' conftest.err >conftest.er1+ cat conftest.er1 >&5+ mv -f conftest.er1 conftest.err+ fi+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; } && {+ test -z "$ac_c_werror_flag" ||+ test ! -s conftest.err+ } && test -s conftest$ac_exeext && {+ test "$cross_compiling" = yes ||+ test -x conftest$ac_exeext+ }+then :+ ac_retval=0+else $as_nop+ printf "%s\n" "$as_me: failed program was:" >&5+sed 's/^/| /' conftest.$ac_ext >&5++ ac_retval=1+fi+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would+ # interfere with the next link command; also delete a directory that is+ # left behind by Apple's compiler. We do this before executing the actions.+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno+ as_fn_set_status $ac_retval++} # ac_fn_c_try_link++# ac_fn_c_check_func LINENO FUNC VAR+# ----------------------------------+# Tests whether FUNC exists, setting the cache variable VAR accordingly+ac_fn_c_check_func ()+{+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5+printf %s "checking for $2... " >&6; }+if eval test \${$3+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.+ For example, HP-UX 11i <limits.h> declares gettimeofday. */+#define $2 innocuous_$2++/* System header to define __stub macros and hopefully few prototypes,+ which can conflict with char $2 (); below. */++#include <limits.h>+#undef $2++/* Override any GCC internal prototype to avoid an error.+ Use char because int might match the return type of a GCC+ builtin and then its argument prototype would still apply. */+#ifdef __cplusplus+extern "C"+#endif+char $2 ();+/* The GNU C library defines this for functions which it implements+ to always fail with ENOSYS. Some functions are actually named+ something starting with __ and the normal name is an alias. */+#if defined __stub_$2 || defined __stub___$2+choke me+#endif++int+main (void)+{+return $2 ();+ ;+ return 0;+}+_ACEOF+if ac_fn_c_try_link "$LINENO"+then :+ eval "$3=yes"+else $as_nop+ eval "$3=no"+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam \+ conftest$ac_exeext conftest.$ac_ext+fi+eval ac_res=\$$3+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5+printf "%s\n" "$ac_res" >&6; }+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno++} # ac_fn_c_check_func+ac_configure_args_raw=+for ac_arg+do+ case $ac_arg in+ *\'*)+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;+ esac+ as_fn_append ac_configure_args_raw " '$ac_arg'"+done++case $ac_configure_args_raw in+ *$as_nl*)+ ac_safe_unquote= ;;+ *)+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.+ ac_unsafe_a="$ac_unsafe_z#~"+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;+esac++cat >config.log <<_ACEOF+This file contains any messages produced by compilers while+running configure, to aid debugging if configure makes a mistake.++It was created by Haskell directory package $as_me 1.0, which was+generated by GNU Autoconf 2.71. Invocation command line was++ $ $0$ac_configure_args_raw++_ACEOF+exec 5>>config.log+{+cat <<_ASUNAME+## --------- ##+## Platform. ##+## --------- ##++hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`+uname -m = `(uname -m) 2>/dev/null || echo unknown`+uname -r = `(uname -r) 2>/dev/null || echo unknown`+uname -s = `(uname -s) 2>/dev/null || echo unknown`+uname -v = `(uname -v) 2>/dev/null || echo unknown`++/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`++/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`++_ASUNAME++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ printf "%s\n" "PATH: $as_dir"+ done+IFS=$as_save_IFS++} >&5++cat >&5 <<_ACEOF+++## ----------- ##+## Core tests. ##+## ----------- ##++_ACEOF+++# Keep a trace of the command line.+# Strip out --no-create and --no-recursion so they do not pile up.+# Strip out --silent because we don't want to record it for future runs.+# Also quote any args containing shell meta-characters.+# Make two passes to allow for proper duplicate-argument suppression.+ac_configure_args=+ac_configure_args0=+ac_configure_args1=+ac_must_keep_next=false+for ac_pass in 1 2+do+ for ac_arg+ do+ case $ac_arg in+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \+ | -silent | --silent | --silen | --sile | --sil)+ continue ;;+ *\'*)+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;+ esac+ case $ac_pass in+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;+ 2)+ as_fn_append ac_configure_args1 " '$ac_arg'"+ if test $ac_must_keep_next = true; then+ ac_must_keep_next=false # Got value, back to normal.+ else+ case $ac_arg in+ *=* | --config-cache | -C | -disable-* | --disable-* \+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \+ | -with-* | --with-* | -without-* | --without-* | --x)+ case "$ac_configure_args0 " in+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;+ esac+ ;;+ -* ) ac_must_keep_next=true ;;+ esac+ fi+ as_fn_append ac_configure_args " '$ac_arg'"+ ;;+ esac+ done+done+{ ac_configure_args0=; unset ac_configure_args0;}+{ ac_configure_args1=; unset ac_configure_args1;}++# When interrupted or exit'd, cleanup temporary files, and complete+# config.log. We remove comments because anyway the quotes in there+# would cause problems or look ugly.+# WARNING: Use '\'' to represent an apostrophe within the trap.+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.+trap 'exit_status=$?+ # Sanitize IFS.+ IFS=" "" $as_nl"+ # Save into config.log some information that might help in debugging.+ {+ echo++ printf "%s\n" "## ---------------- ##+## Cache variables. ##+## ---------------- ##"+ echo+ # The following way of writing the cache mishandles newlines in values,+(+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do+ eval ac_val=\$$ac_var+ case $ac_val in #(+ *${as_nl}*)+ case $ac_var in #(+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;+ esac+ case $ac_var in #(+ _ | IFS | as_nl) ;; #(+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(+ *) { eval $ac_var=; unset $ac_var;} ;;+ esac ;;+ esac+ done+ (set) 2>&1 |+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(+ *${as_nl}ac_space=\ *)+ sed -n \+ "s/'\''/'\''\\\\'\'''\''/g;+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"+ ;; #(+ *)+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"+ ;;+ esac |+ sort+)+ echo++ printf "%s\n" "## ----------------- ##+## Output variables. ##+## ----------------- ##"+ echo+ for ac_var in $ac_subst_vars+ do+ eval ac_val=\$$ac_var+ case $ac_val in+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;+ esac+ printf "%s\n" "$ac_var='\''$ac_val'\''"+ done | sort+ echo++ if test -n "$ac_subst_files"; then+ printf "%s\n" "## ------------------- ##+## File substitutions. ##+## ------------------- ##"+ echo+ for ac_var in $ac_subst_files+ do+ eval ac_val=\$$ac_var+ case $ac_val in+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;+ esac+ printf "%s\n" "$ac_var='\''$ac_val'\''"+ done | sort+ echo+ fi++ if test -s confdefs.h; then+ printf "%s\n" "## ----------- ##+## confdefs.h. ##+## ----------- ##"+ echo+ cat confdefs.h+ echo+ fi+ test "$ac_signal" != 0 &&+ printf "%s\n" "$as_me: caught signal $ac_signal"+ printf "%s\n" "$as_me: exit $exit_status"+ } >&5+ rm -f core *.core core.conftest.* &&+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&+ exit $exit_status+' 0+for ac_signal in 1 2 13 15; do+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal+done+ac_signal=0++# confdefs.h avoids OS command line length limits that DEFS can exceed.+rm -f -r conftest* confdefs.h++printf "%s\n" "/* confdefs.h */" > confdefs.h++# Predefined preprocessor variables.++printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h++printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h++printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h++printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h++printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h++printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h+++# Let the site file select an alternate cache file if it wants to.+# Prefer an explicitly selected file to automatically selected ones.+if test -n "$CONFIG_SITE"; then+ ac_site_files="$CONFIG_SITE"+elif test "x$prefix" != xNONE; then+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"+else+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"+fi++for ac_site_file in $ac_site_files+do+ case $ac_site_file in #(+ */*) :+ ;; #(+ *) :+ ac_site_file=./$ac_site_file ;;+esac+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}+ sed 's/^/| /' "$ac_site_file" >&5+ . "$ac_site_file" \+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+as_fn_error $? "failed to load site script $ac_site_file+See \`config.log' for more details" "$LINENO" 5; }+ fi+done++if test -r "$cache_file"; then+ # Some versions of bash will fail to source /dev/null (special files+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}+ case $cache_file in+ [\\/]* | ?:[\\/]* ) . "$cache_file";;+ *) . "./$cache_file";;+ esac+ fi+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}+ >$cache_file+fi++# Test code for whether the C compiler supports C89 (global declarations)+ac_c_conftest_c89_globals='+/* Does the compiler advertise C89 conformance?+ Do not test the value of __STDC__, because some compilers set it to 0+ while being otherwise adequately conformant. */+#if !defined __STDC__+# error "Compiler does not advertise C89 conformance"+#endif++#include <stddef.h>+#include <stdarg.h>+struct stat;+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */+struct buf { int x; };+struct buf * (*rcsopen) (struct buf *, struct stat *, int);+static char *e (p, i)+ char **p;+ int i;+{+ return p[i];+}+static char *f (char * (*g) (char **, int), char **p, ...)+{+ char *s;+ va_list v;+ va_start (v,p);+ s = g (p, va_arg (v,int));+ va_end (v);+ return s;+}++/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has+ function prototypes and stuff, but not \xHH hex character constants.+ These do not provoke an error unfortunately, instead are silently treated+ as an "x". The following induces an error, until -std is added to get+ proper ANSI mode. Curiously \x00 != x always comes out true, for an+ array size at least. It is necessary to write \x00 == 0 to get something+ that is true only with -std. */+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];++/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters+ inside strings and character constants. */+#define FOO(x) '\''x'\''+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];++int test (int i, double x);+struct s1 {int (*f) (int a);};+struct s2 {int (*f) (double a);};+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),+ int, int);'++# Test code for whether the C compiler supports C89 (body of main).+ac_c_conftest_c89_main='+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);+'++# Test code for whether the C compiler supports C99 (global declarations)+ac_c_conftest_c99_globals='+// Does the compiler advertise C99 conformance?+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L+# error "Compiler does not advertise C99 conformance"+#endif++#include <stdbool.h>+extern int puts (const char *);+extern int printf (const char *, ...);+extern int dprintf (int, const char *, ...);+extern void *malloc (size_t);++// Check varargs macros. These examples are taken from C99 6.10.3.5.+// dprintf is used instead of fprintf to avoid needing to declare+// FILE and stderr.+#define debug(...) dprintf (2, __VA_ARGS__)+#define showlist(...) puts (#__VA_ARGS__)+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))+static void+test_varargs_macros (void)+{+ int x = 1234;+ int y = 5678;+ debug ("Flag");+ debug ("X = %d\n", x);+ showlist (The first, second, and third items.);+ report (x>y, "x is %d but y is %d", x, y);+}++// Check long long types.+#define BIG64 18446744073709551615ull+#define BIG32 4294967295ul+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)+#if !BIG_OK+ #error "your preprocessor is broken"+#endif+#if BIG_OK+#else+ #error "your preprocessor is broken"+#endif+static long long int bignum = -9223372036854775807LL;+static unsigned long long int ubignum = BIG64;++struct incomplete_array+{+ int datasize;+ double data[];+};++struct named_init {+ int number;+ const wchar_t *name;+ double average;+};++typedef const char *ccp;++static inline int+test_restrict (ccp restrict text)+{+ // See if C++-style comments work.+ // Iterate through items via the restricted pointer.+ // Also check for declarations in for loops.+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)+ continue;+ return 0;+}++// Check varargs and va_copy.+static bool+test_varargs (const char *format, ...)+{+ va_list args;+ va_start (args, format);+ va_list args_copy;+ va_copy (args_copy, args);++ const char *str = "";+ int number = 0;+ float fnumber = 0;++ while (*format)+ {+ switch (*format++)+ {+ case '\''s'\'': // string+ str = va_arg (args_copy, const char *);+ break;+ case '\''d'\'': // int+ number = va_arg (args_copy, int);+ break;+ case '\''f'\'': // float+ fnumber = va_arg (args_copy, double);+ break;+ default:+ break;+ }+ }+ va_end (args_copy);+ va_end (args);++ return *str && number && fnumber;+}+'++# Test code for whether the C compiler supports C99 (body of main).+ac_c_conftest_c99_main='+ // Check bool.+ _Bool success = false;+ success |= (argc != 0);++ // Check restrict.+ if (test_restrict ("String literal") == 0)+ success = true;+ char *restrict newvar = "Another string";++ // Check varargs.+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);+ test_varargs_macros ();++ // Check flexible array members.+ struct incomplete_array *ia =+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));+ ia->datasize = 10;+ for (int i = 0; i < ia->datasize; ++i)+ ia->data[i] = i * 1.234;++ // Check named initializers.+ struct named_init ni = {+ .number = 34,+ .name = L"Test wide string",+ .average = 543.34343,+ };++ ni.number = 58;++ int dynamic_array[ni.number];+ dynamic_array[0] = argv[0][0];+ dynamic_array[ni.number - 1] = 543;++ // work around unused variable warnings+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''+ || dynamic_array[ni.number - 1] != 543);+'++# Test code for whether the C compiler supports C11 (global declarations)+ac_c_conftest_c11_globals='+// Does the compiler advertise C11 conformance?+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L+# error "Compiler does not advertise C11 conformance"+#endif++// Check _Alignas.+char _Alignas (double) aligned_as_double;+char _Alignas (0) no_special_alignment;+extern char aligned_as_int;+char _Alignas (0) _Alignas (int) aligned_as_int;++// Check _Alignof.+enum+{+ int_alignment = _Alignof (int),+ int_array_alignment = _Alignof (int[100]),+ char_alignment = _Alignof (char)+};+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");++// Check _Noreturn.+int _Noreturn does_not_return (void) { for (;;) continue; }++// Check _Static_assert.+struct test_static_assert+{+ int x;+ _Static_assert (sizeof (int) <= sizeof (long int),+ "_Static_assert does not work in struct");+ long int y;+};++// Check UTF-8 literals.+#define u8 syntax error!+char const utf8_literal[] = u8"happens to be ASCII" "another string";++// Check duplicate typedefs.+typedef long *long_ptr;+typedef long int *long_ptr;+typedef long_ptr long_ptr;++// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.+struct anonymous+{+ union {+ struct { int i; int j; };+ struct { int k; long int l; } w;+ };+ int m;+} v1;+'++# Test code for whether the C compiler supports C11 (body of main).+ac_c_conftest_c11_main='+ _Static_assert ((offsetof (struct anonymous, i)+ == offsetof (struct anonymous, w.k)),+ "Anonymous union alignment botch");+ v1.i = 2;+ v1.w.k = 5;+ ok |= v1.i != 5;+'++# Test code for whether the C compiler supports C11 (complete).+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}+${ac_c_conftest_c99_globals}+${ac_c_conftest_c11_globals}++int+main (int argc, char **argv)+{+ int ok = 0;+ ${ac_c_conftest_c89_main}+ ${ac_c_conftest_c99_main}+ ${ac_c_conftest_c11_main}+ return ok;+}+"++# Test code for whether the C compiler supports C99 (complete).+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}+${ac_c_conftest_c99_globals}++int+main (int argc, char **argv)+{+ int ok = 0;+ ${ac_c_conftest_c89_main}+ ${ac_c_conftest_c99_main}+ return ok;+}+"++# Test code for whether the C compiler supports C89 (complete).+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}++int+main (int argc, char **argv)+{+ int ok = 0;+ ${ac_c_conftest_c89_main}+ return ok;+}+"++as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"+# Check that the precious variables saved in the cache have kept the same+# value.+ac_cache_corrupted=false+for ac_var in $ac_precious_vars; do+ eval ac_old_set=\$ac_cv_env_${ac_var}_set+ eval ac_new_set=\$ac_env_${ac_var}_set+ eval ac_old_val=\$ac_cv_env_${ac_var}_value+ eval ac_new_val=\$ac_env_${ac_var}_value+ case $ac_old_set,$ac_new_set in+ set,)+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}+ ac_cache_corrupted=: ;;+ ,set)+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}+ ac_cache_corrupted=: ;;+ ,);;+ *)+ if test "x$ac_old_val" != "x$ac_new_val"; then+ # differences in whitespace do not lead to failure.+ ac_old_val_w=`echo x $ac_old_val`+ ac_new_val_w=`echo x $ac_new_val`+ if test "$ac_old_val_w" != "$ac_new_val_w"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}+ ac_cache_corrupted=:+ else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}+ eval $ac_var=\$ac_old_val+ fi+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}+ fi;;+ esac+ # Pass precious variables to config.status.+ if test "$ac_new_set" = set; then+ case $ac_new_val in+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;+ *) ac_arg=$ac_var=$ac_new_val ;;+ esac+ case " $ac_configure_args " in+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;+ esac+ fi+done+if $ac_cache_corrupted; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'+ and start over" "$LINENO" 5+fi+## -------------------- ##+## Main body of script. ##+## -------------------- ##++ac_ext=c+ac_cpp='$CPP $CPPFLAGS'+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'+ac_compiler_gnu=$ac_cv_c_compiler_gnu++++# Safety check: Ensure that we are in the correct source directory.+++ac_config_headers="$ac_config_headers HsDirectoryConfig.h"+++# Autoconf chokes on spaces, but we may receive a path from Cabal containing+# spaces. In that case, we just ignore Cabal's suggestion.+set_with_gcc() {+ case $withval in+ *" "*)+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-gcc ignored due to presence of spaces" >&5+printf "%s\n" "$as_me: WARNING: --with-gcc ignored due to presence of spaces" >&2;};;+ *)+ CC=$withval+ esac+}++# Legacy support for setting the C compiler with Cabal<1.24+# Newer versions use Autoconf's native `CC=...` facility++# Check whether --with-gcc was given.+if test ${with_gcc+y}+then :+ withval=$with_gcc; set_with_gcc+fi++# avoid warnings when run via Cabal++# Check whether --with-compiler was given.+if test ${with_compiler+y}+then :+ withval=$with_compiler;+fi+++++++++++ac_ext=c+ac_cpp='$CPP $CPPFLAGS'+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'+ac_compiler_gnu=$ac_cv_c_compiler_gnu+if test -n "$ac_tool_prefix"; then+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.+set dummy ${ac_tool_prefix}gcc; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$CC"; then+ ac_cv_prog_CC="$CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_CC="${ac_tool_prefix}gcc"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+CC=$ac_cv_prog_CC+if test -n "$CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5+printf "%s\n" "$CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi+++fi+if test -z "$ac_cv_prog_CC"; then+ ac_ct_CC=$CC+ # Extract the first word of "gcc", so it can be a program name with args.+set dummy gcc; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_ac_ct_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$ac_ct_CC"; then+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_ac_ct_CC="gcc"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+ac_ct_CC=$ac_cv_prog_ac_ct_CC+if test -n "$ac_ct_CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5+printf "%s\n" "$ac_ct_CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi++ if test "x$ac_ct_CC" = x; then+ CC=""+ else+ case $cross_compiling:$ac_tool_warned in+yes:)+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}+ac_tool_warned=yes ;;+esac+ CC=$ac_ct_CC+ fi+else+ CC="$ac_cv_prog_CC"+fi++if test -z "$CC"; then+ if test -n "$ac_tool_prefix"; then+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.+set dummy ${ac_tool_prefix}cc; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$CC"; then+ ac_cv_prog_CC="$CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_CC="${ac_tool_prefix}cc"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+CC=$ac_cv_prog_CC+if test -n "$CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5+printf "%s\n" "$CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi+++ fi+fi+if test -z "$CC"; then+ # Extract the first word of "cc", so it can be a program name with args.+set dummy cc; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$CC"; then+ ac_cv_prog_CC="$CC" # Let the user override the test.+else+ ac_prog_rejected=no+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then+ ac_prog_rejected=yes+ continue+ fi+ ac_cv_prog_CC="cc"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++if test $ac_prog_rejected = yes; then+ # We found a bogon in the path, so make sure we never use it.+ set dummy $ac_cv_prog_CC+ shift+ if test $# != 0; then+ # We chose a different compiler from the bogus one.+ # However, it has the same basename, so the bogon will be chosen+ # first if we set CC to just the basename; use the full file name.+ shift+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"+ fi+fi+fi+fi+CC=$ac_cv_prog_CC+if test -n "$CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5+printf "%s\n" "$CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi+++fi+if test -z "$CC"; then+ if test -n "$ac_tool_prefix"; then+ for ac_prog in cl.exe+ do+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.+set dummy $ac_tool_prefix$ac_prog; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$CC"; then+ ac_cv_prog_CC="$CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+CC=$ac_cv_prog_CC+if test -n "$CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5+printf "%s\n" "$CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi+++ test -n "$CC" && break+ done+fi+if test -z "$CC"; then+ ac_ct_CC=$CC+ for ac_prog in cl.exe+do+ # Extract the first word of "$ac_prog", so it can be a program name with args.+set dummy $ac_prog; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_ac_ct_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$ac_ct_CC"; then+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_ac_ct_CC="$ac_prog"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+ac_ct_CC=$ac_cv_prog_ac_ct_CC+if test -n "$ac_ct_CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5+printf "%s\n" "$ac_ct_CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi+++ test -n "$ac_ct_CC" && break+done++ if test "x$ac_ct_CC" = x; then+ CC=""+ else+ case $cross_compiling:$ac_tool_warned in+yes:)+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}+ac_tool_warned=yes ;;+esac+ CC=$ac_ct_CC+ fi+fi++fi+if test -z "$CC"; then+ if test -n "$ac_tool_prefix"; then+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.+set dummy ${ac_tool_prefix}clang; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$CC"; then+ ac_cv_prog_CC="$CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_CC="${ac_tool_prefix}clang"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+CC=$ac_cv_prog_CC+if test -n "$CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5+printf "%s\n" "$CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi+++fi+if test -z "$ac_cv_prog_CC"; then+ ac_ct_CC=$CC+ # Extract the first word of "clang", so it can be a program name with args.+set dummy clang; ac_word=$2+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5+printf %s "checking for $ac_word... " >&6; }+if test ${ac_cv_prog_ac_ct_CC+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ if test -n "$ac_ct_CC"; then+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.+else+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ for ac_exec_ext in '' $ac_executable_extensions; do+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then+ ac_cv_prog_ac_ct_CC="clang"+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5+ break 2+ fi+done+ done+IFS=$as_save_IFS++fi+fi+ac_ct_CC=$ac_cv_prog_ac_ct_CC+if test -n "$ac_ct_CC"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5+printf "%s\n" "$ac_ct_CC" >&6; }+else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+fi++ if test "x$ac_ct_CC" = x; then+ CC=""+ else+ case $cross_compiling:$ac_tool_warned in+yes:)+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}+ac_tool_warned=yes ;;+esac+ CC=$ac_ct_CC+ fi+else+ CC="$ac_cv_prog_CC"+fi++fi+++test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+as_fn_error $? "no acceptable C compiler found in \$PATH+See \`config.log' for more details" "$LINENO" 5; }++# Provide some information about the compiler.+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5+set X $ac_compile+ac_compiler=$2+for ac_option in --version -v -V -qversion -version; do+ { { ac_try="$ac_compiler $ac_option >&5"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err+ ac_status=$?+ if test -s conftest.err; then+ sed '10a\+... rest of stderr output deleted ...+ 10q' conftest.err >conftest.er1+ cat conftest.er1 >&5+ fi+ rm -f conftest.er1 conftest.err+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; }+done++cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */++int+main (void)+{++ ;+ return 0;+}+_ACEOF+ac_clean_files_save=$ac_clean_files+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"+# Try to create an executable without -o first, disregard a.out.+# It will help us diagnose broken compilers, and finding out an intuition+# of exeext.+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5+printf %s "checking whether the C compiler works... " >&6; }+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`++# The possible output files:+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"++ac_rmfiles=+for ac_file in $ac_files+do+ case $ac_file in+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;+ esac+done+rm -f $ac_rmfiles++if { { ac_try="$ac_link_default"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_link_default") 2>&5+ ac_status=$?+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; }+then :+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'+# in a Makefile. We should not override ac_cv_exeext if it was cached,+# so that the user can short-circuit this test for compilers unknown to+# Autoconf.+for ac_file in $ac_files ''+do+ test -f "$ac_file" || continue+ case $ac_file in+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )+ ;;+ [ab].out )+ # We found the default executable, but exeext='' is most+ # certainly right.+ break;;+ *.* )+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;+ then :; else+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`+ fi+ # We set ac_cv_exeext here because the later test for it is not+ # safe: cross compilers may not add the suffix if given an `-o'+ # argument, so we may need to know it at that point already.+ # Even if this section looks crufty: it has the advantage of+ # actually working.+ break;;+ * )+ break;;+ esac+done+test "$ac_cv_exeext" = no && ac_cv_exeext=++else $as_nop+ ac_file=''+fi+if test -z "$ac_file"+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5+printf "%s\n" "no" >&6; }+printf "%s\n" "$as_me: failed program was:" >&5+sed 's/^/| /' conftest.$ac_ext >&5++{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+as_fn_error 77 "C compiler cannot create executables+See \`config.log' for more details" "$LINENO" 5; }+else $as_nop+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5+printf "%s\n" "yes" >&6; }+fi+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5+printf %s "checking for C compiler default output file name... " >&6; }+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5+printf "%s\n" "$ac_file" >&6; }+ac_exeext=$ac_cv_exeext++rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out+ac_clean_files=$ac_clean_files_save+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5+printf %s "checking for suffix of executables... " >&6; }+if { { ac_try="$ac_link"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_link") 2>&5+ ac_status=$?+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; }+then :+ # If both `conftest.exe' and `conftest' are `present' (well, observable)+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will+# work properly (i.e., refer to `conftest.exe'), while it won't with+# `rm'.+for ac_file in conftest.exe conftest conftest.*; do+ test -f "$ac_file" || continue+ case $ac_file in+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`+ break;;+ * ) break;;+ esac+done+else $as_nop+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+as_fn_error $? "cannot compute suffix of executables: cannot compile and link+See \`config.log' for more details" "$LINENO" 5; }+fi+rm -f conftest conftest$ac_cv_exeext+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5+printf "%s\n" "$ac_cv_exeext" >&6; }++rm -f conftest.$ac_ext+EXEEXT=$ac_cv_exeext+ac_exeext=$EXEEXT+cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */+#include <stdio.h>+int+main (void)+{+FILE *f = fopen ("conftest.out", "w");+ return ferror (f) || fclose (f) != 0;++ ;+ return 0;+}+_ACEOF+ac_clean_files="$ac_clean_files conftest.out"+# Check that the compiler produces executables we can run. If not, either+# the compiler is broken, or we cross compile.+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5+printf %s "checking whether we are cross compiling... " >&6; }+if test "$cross_compiling" != yes; then+ { { ac_try="$ac_link"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_link") 2>&5+ ac_status=$?+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; }+ if { ac_try='./conftest$ac_cv_exeext'+ { { case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_try") 2>&5+ ac_status=$?+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; }; }; then+ cross_compiling=no+ else+ if test "$cross_compiling" = maybe; then+ cross_compiling=yes+ else+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+as_fn_error 77 "cannot run C compiled programs.+If you meant to cross compile, use \`--host'.+See \`config.log' for more details" "$LINENO" 5; }+ fi+ fi+fi+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5+printf "%s\n" "$cross_compiling" >&6; }++rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out+ac_clean_files=$ac_clean_files_save+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5+printf %s "checking for suffix of object files... " >&6; }+if test ${ac_cv_objext+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */++int+main (void)+{++ ;+ return 0;+}+_ACEOF+rm -f conftest.o conftest.obj+if { { ac_try="$ac_compile"+case "(($ac_try" in+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;+ *) ac_try_echo=$ac_try;;+esac+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""+printf "%s\n" "$ac_try_echo"; } >&5+ (eval "$ac_compile") 2>&5+ ac_status=$?+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5+ test $ac_status = 0; }+then :+ for ac_file in conftest.o conftest.obj conftest.*; do+ test -f "$ac_file" || continue;+ case $ac_file in+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`+ break;;+ esac+done+else $as_nop+ printf "%s\n" "$as_me: failed program was:" >&5+sed 's/^/| /' conftest.$ac_ext >&5++{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}+as_fn_error $? "cannot compute suffix of object files: cannot compile+See \`config.log' for more details" "$LINENO" 5; }+fi+rm -f conftest.$ac_cv_objext conftest.$ac_ext+fi+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5+printf "%s\n" "$ac_cv_objext" >&6; }+OBJEXT=$ac_cv_objext+ac_objext=$OBJEXT+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5+printf %s "checking whether the compiler supports GNU C... " >&6; }+if test ${ac_cv_c_compiler_gnu+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */++int+main (void)+{+#ifndef __GNUC__+ choke me+#endif++ ;+ return 0;+}+_ACEOF+if ac_fn_c_try_compile "$LINENO"+then :+ ac_compiler_gnu=yes+else $as_nop+ ac_compiler_gnu=no+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext+ac_cv_c_compiler_gnu=$ac_compiler_gnu++fi+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }+ac_compiler_gnu=$ac_cv_c_compiler_gnu++if test $ac_compiler_gnu = yes; then+ GCC=yes+else+ GCC=+fi+ac_test_CFLAGS=${CFLAGS+y}+ac_save_CFLAGS=$CFLAGS+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5+printf %s "checking whether $CC accepts -g... " >&6; }+if test ${ac_cv_prog_cc_g+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ ac_save_c_werror_flag=$ac_c_werror_flag+ ac_c_werror_flag=yes+ ac_cv_prog_cc_g=no+ CFLAGS="-g"+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */++int+main (void)+{++ ;+ return 0;+}+_ACEOF+if ac_fn_c_try_compile "$LINENO"+then :+ ac_cv_prog_cc_g=yes+else $as_nop+ CFLAGS=""+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */++int+main (void)+{++ ;+ return 0;+}+_ACEOF+if ac_fn_c_try_compile "$LINENO"+then :++else $as_nop+ ac_c_werror_flag=$ac_save_c_werror_flag+ CFLAGS="-g"+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */++int+main (void)+{++ ;+ return 0;+}+_ACEOF+if ac_fn_c_try_compile "$LINENO"+then :+ ac_cv_prog_cc_g=yes+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext+ ac_c_werror_flag=$ac_save_c_werror_flag+fi+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }+if test $ac_test_CFLAGS; then+ CFLAGS=$ac_save_CFLAGS+elif test $ac_cv_prog_cc_g = yes; then+ if test "$GCC" = yes; then+ CFLAGS="-g -O2"+ else+ CFLAGS="-g"+ fi+else+ if test "$GCC" = yes; then+ CFLAGS="-O2"+ else+ CFLAGS=+ fi+fi+ac_prog_cc_stdc=no+if test x$ac_prog_cc_stdc = xno+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5+printf %s "checking for $CC option to enable C11 features... " >&6; }+if test ${ac_cv_prog_cc_c11+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ ac_cv_prog_cc_c11=no+ac_save_CC=$CC+cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */+$ac_c_conftest_c11_program+_ACEOF+for ac_arg in '' -std=gnu11+do+ CC="$ac_save_CC $ac_arg"+ if ac_fn_c_try_compile "$LINENO"+then :+ ac_cv_prog_cc_c11=$ac_arg+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam+ test "x$ac_cv_prog_cc_c11" != "xno" && break+done+rm -f conftest.$ac_ext+CC=$ac_save_CC+fi++if test "x$ac_cv_prog_cc_c11" = xno+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5+printf "%s\n" "unsupported" >&6; }+else $as_nop+ if test "x$ac_cv_prog_cc_c11" = x+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5+printf "%s\n" "none needed" >&6; }+else $as_nop+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }+ CC="$CC $ac_cv_prog_cc_c11"+fi+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11+ ac_prog_cc_stdc=c11+fi+fi+if test x$ac_prog_cc_stdc = xno+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5+printf %s "checking for $CC option to enable C99 features... " >&6; }+if test ${ac_cv_prog_cc_c99+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ ac_cv_prog_cc_c99=no+ac_save_CC=$CC+cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */+$ac_c_conftest_c99_program+_ACEOF+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=+do+ CC="$ac_save_CC $ac_arg"+ if ac_fn_c_try_compile "$LINENO"+then :+ ac_cv_prog_cc_c99=$ac_arg+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam+ test "x$ac_cv_prog_cc_c99" != "xno" && break+done+rm -f conftest.$ac_ext+CC=$ac_save_CC+fi++if test "x$ac_cv_prog_cc_c99" = xno+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5+printf "%s\n" "unsupported" >&6; }+else $as_nop+ if test "x$ac_cv_prog_cc_c99" = x+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5+printf "%s\n" "none needed" >&6; }+else $as_nop+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }+ CC="$CC $ac_cv_prog_cc_c99"+fi+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99+ ac_prog_cc_stdc=c99+fi+fi+if test x$ac_prog_cc_stdc = xno+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5+printf %s "checking for $CC option to enable C89 features... " >&6; }+if test ${ac_cv_prog_cc_c89+y}+then :+ printf %s "(cached) " >&6+else $as_nop+ ac_cv_prog_cc_c89=no+ac_save_CC=$CC+cat confdefs.h - <<_ACEOF >conftest.$ac_ext+/* end confdefs.h. */+$ac_c_conftest_c89_program+_ACEOF+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"+do+ CC="$ac_save_CC $ac_arg"+ if ac_fn_c_try_compile "$LINENO"+then :+ ac_cv_prog_cc_c89=$ac_arg+fi+rm -f core conftest.err conftest.$ac_objext conftest.beam+ test "x$ac_cv_prog_cc_c89" != "xno" && break+done+rm -f conftest.$ac_ext+CC=$ac_save_CC+fi++if test "x$ac_cv_prog_cc_c89" = xno+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5+printf "%s\n" "unsupported" >&6; }+else $as_nop+ if test "x$ac_cv_prog_cc_c89" = x+then :+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5+printf "%s\n" "none needed" >&6; }+else $as_nop+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }+ CC="$CC $ac_cv_prog_cc_c89"+fi+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89+ ac_prog_cc_stdc=c89+fi+fi++ac_ext=c+ac_cpp='$CPP $CPPFLAGS'+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'+ac_compiler_gnu=$ac_cv_c_compiler_gnu+++# check for specific header (.h) files that we are interested in++ac_header= ac_cache=+for ac_item in $ac_header_c_list+do+ if test $ac_cache; then+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then+ printf "%s\n" "#define $ac_item 1" >> confdefs.h+ fi+ ac_header= ac_cache=+ elif test $ac_header; then+ ac_cache=$ac_item+ else+ ac_header=$ac_item+ fi+done+++++++++if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes+then :++printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h++fi+ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"+if test "x$ac_cv_header_fcntl_h" = xyes+then :+ printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h++fi+ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default"+if test "x$ac_cv_header_limits_h" = xyes+then :+ printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h++fi+ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default"+if test "x$ac_cv_header_sys_types_h" = xyes+then :+ printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h++fi+ac_fn_c_check_header_compile "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default"+if test "x$ac_cv_header_sys_stat_h" = xyes+then :+ printf "%s\n" "#define HAVE_SYS_STAT_H 1" >>confdefs.h++fi+ac_fn_c_check_header_compile "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default"+if test "x$ac_cv_header_time_h" = xyes+then :+ printf "%s\n" "#define HAVE_TIME_H 1" >>confdefs.h++fi+++ac_fn_c_check_func "$LINENO" "realpath" "ac_cv_func_realpath"+if test "x$ac_cv_func_realpath" = xyes+then :+ printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h++fi++ac_fn_c_check_func "$LINENO" "utimensat" "ac_cv_func_utimensat"+if test "x$ac_cv_func_utimensat" = xyes+then :+ printf "%s\n" "#define HAVE_UTIMENSAT 1" >>confdefs.h++fi++ac_fn_c_check_func "$LINENO" "CreateSymbolicLinkW" "ac_cv_func_CreateSymbolicLinkW"+if test "x$ac_cv_func_CreateSymbolicLinkW" = xyes+then :+ printf "%s\n" "#define HAVE_CREATESYMBOLICLINKW 1" >>confdefs.h++fi++ac_fn_c_check_func "$LINENO" "GetFinalPathNameByHandleW" "ac_cv_func_GetFinalPathNameByHandleW"+if test "x$ac_cv_func_GetFinalPathNameByHandleW" = xyes+then :+ printf "%s\n" "#define HAVE_GETFINALPATHNAMEBYHANDLEW 1" >>confdefs.h++fi+++# EXTEXT is defined automatically by AC_PROG_CC;+# we just need to capture it in the header file++printf "%s\n" "#define EXE_EXTENSION \"$EXEEXT\"" >>confdefs.h+++cat >confcache <<\_ACEOF+# This file is a shell script that caches the results of configure+# tests run on this system so they can be shared between configure+# scripts and configure runs, see configure's option --config-cache.+# It is not useful on other systems. If it contains results you don't+# want to keep, you may remove or edit it.+#+# config.status only pays attention to the cache file if you give it+# the --recheck option to rerun configure.+#+# `ac_cv_env_foo' variables (set or unset) will be overridden when+# loading this file, other *unset* `ac_cv_foo' will be assigned the+# following values.++_ACEOF++# The following way of writing the cache mishandles newlines in values,+# but we know of no workaround that is simple, portable, and efficient.+# So, we kill variables containing newlines.+# Ultrix sh set writes to stderr and can't be redirected directly,+# and sets the high bit in the cache file unless we assign to the vars.+(+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do+ eval ac_val=\$$ac_var+ case $ac_val in #(+ *${as_nl}*)+ case $ac_var in #(+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;+ esac+ case $ac_var in #(+ _ | IFS | as_nl) ;; #(+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(+ *) { eval $ac_var=; unset $ac_var;} ;;+ esac ;;+ esac+ done++ (set) 2>&1 |+ case $as_nl`(ac_space=' '; set) 2>&1` in #(+ *${as_nl}ac_space=\ *)+ # `set' does not quote correctly, so add quotes: double-quote+ # substitution turns \\\\ into \\, and sed turns \\ into \.+ sed -n \+ "s/'/'\\\\''/g;+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"+ ;; #(+ *)+ # `set' quotes correctly as required by POSIX, so do not add quotes.+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"+ ;;+ esac |+ sort+) |+ sed '+ /^ac_cv_env_/b end+ t clear+ :clear+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/+ t end+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/+ :end' >>confcache+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else+ if test -w "$cache_file"; then+ if test "x$cache_file" != "x/dev/null"; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}+ if test ! -f "$cache_file" || test -h "$cache_file"; then+ cat confcache >"$cache_file"+ else+ case $cache_file in #(+ */* | ?:*)+ mv -f confcache "$cache_file"$$ &&+ mv -f "$cache_file"$$ "$cache_file" ;; #(+ *)+ mv -f confcache "$cache_file" ;;+ esac+ fi+ fi+ else+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}+ fi+fi+rm -f confcache++test "x$prefix" = xNONE && prefix=$ac_default_prefix+# Let make expand exec_prefix.+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'++DEFS=-DHAVE_CONFIG_H++ac_libobjs=+ac_ltlibobjs=+U=+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue+ # 1. Remove the extension, and $U if already installed.+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR+ # will be set to the directory where LIBOBJS objects are built.+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'+done+LIBOBJS=$ac_libobjs++LTLIBOBJS=$ac_ltlibobjs++++: "${CONFIG_STATUS=./config.status}"+ac_write_fail=0+ac_clean_files_save=$ac_clean_files+ac_clean_files="$ac_clean_files $CONFIG_STATUS"+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}+as_write_fail=0+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1+#! $SHELL+# Generated by $as_me.+# Run this file to recreate the current configuration.+# Compiler output produced by configure, useful for debugging+# configure, is in config.log if it exists.++debug=false+ac_cs_recheck=false+ac_cs_silent=false++SHELL=\${CONFIG_SHELL-$SHELL}+export SHELL+_ASEOF+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1+## -------------------- ##+## M4sh Initialization. ##+## -------------------- ##++# Be more Bourne compatible+DUALCASE=1; export DUALCASE # for MKS sh+as_nop=:+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1+then :+ emulate sh+ NULLCMD=:+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which+ # is contrary to our usage. Disable this feature.+ alias -g '${1+"$@"}'='"$@"'+ setopt NO_GLOB_SUBST+else $as_nop+ case `(set -o) 2>/dev/null` in #(+ *posix*) :+ set -o posix ;; #(+ *) :+ ;;+esac+fi++++# Reset variables that may have inherited troublesome values from+# the environment.++# IFS needs to be set, to space, tab, and newline, in precisely that order.+# (If _AS_PATH_WALK were called with IFS unset, it would have the+# side effect of setting IFS to empty, thus disabling word splitting.)+# Quoting is to prevent editors from complaining about space-tab.+as_nl='+'+export as_nl+IFS=" "" $as_nl"++PS1='$ '+PS2='> '+PS4='+ '++# Ensure predictable behavior from utilities with locale-dependent output.+LC_ALL=C+export LC_ALL+LANGUAGE=C+export LANGUAGE++# We cannot yet rely on "unset" to work, but we need these variables+# to be unset--not just set to an empty or harmless value--now, to+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct+# also avoids known problems related to "unset" and subshell syntax+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH+do eval test \${$as_var+y} \+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :+done++# Ensure that fds 0, 1, and 2 are open.+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi++# The user is always right.+if ${PATH_SEPARATOR+false} :; then+ PATH_SEPARATOR=:+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||+ PATH_SEPARATOR=';'+ }+fi+++# Find who we are. Look in the path if we contain no directory separator.+as_myself=+case $0 in #((+ *[\\/]* ) as_myself=$0 ;;+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+ IFS=$as_save_IFS+ case $as_dir in #(((+ '') as_dir=./ ;;+ */) ;;+ *) as_dir=$as_dir/ ;;+ esac+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break+ done+IFS=$as_save_IFS++ ;;+esac+# We did not find ourselves, most probably we were run as `sh COMMAND'+# in which case we are not to be found in the path.+if test "x$as_myself" = x; then+ as_myself=$0+fi+if test ! -f "$as_myself"; then+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2+ exit 1+fi++++# as_fn_error STATUS ERROR [LINENO LOG_FD]+# ----------------------------------------+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the+# script with STATUS, using 1 if that was 0.+as_fn_error ()+{+ as_status=$1; test $as_status -eq 0 && as_status=1+ if test "$4"; then+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4+ fi+ printf "%s\n" "$as_me: error: $2" >&2+ as_fn_exit $as_status+} # as_fn_error++++# as_fn_set_status STATUS+# -----------------------+# Set $? to STATUS, without forking.+as_fn_set_status ()+{+ return $1+} # as_fn_set_status++# as_fn_exit STATUS+# -----------------+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.+as_fn_exit ()+{+ set +e+ as_fn_set_status $1+ exit $1+} # as_fn_exit++# as_fn_unset VAR+# ---------------+# Portably unset VAR.+as_fn_unset ()+{+ { eval $1=; unset $1;}+}+as_unset=as_fn_unset++# as_fn_append VAR VALUE+# ----------------------+# Append the text in VALUE to the end of the definition contained in VAR. Take+# advantage of any shell optimizations that allow amortized linear growth over+# repeated appends, instead of the typical quadratic growth present in naive+# implementations.+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null+then :+ eval 'as_fn_append ()+ {+ eval $1+=\$2+ }'+else $as_nop+ as_fn_append ()+ {+ eval $1=\$$1\$2+ }+fi # as_fn_append++# as_fn_arith ARG...+# ------------------+# Perform arithmetic evaluation on the ARGs, and store the result in the+# global $as_val. Take advantage of shells that can avoid forks. The arguments+# must be portable across $(()) and expr.+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null+then :+ eval 'as_fn_arith ()+ {+ as_val=$(( $* ))+ }'+else $as_nop+ as_fn_arith ()+ {+ as_val=`expr "$@" || test $? -eq 1`+ }+fi # as_fn_arith+++if expr a : '\(a\)' >/dev/null 2>&1 &&+ test "X`expr 00001 : '.*\(...\)'`" = X001; then+ as_expr=expr+else+ as_expr=false+fi++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then+ as_basename=basename+else+ as_basename=false+fi++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then+ as_dirname=dirname+else+ as_dirname=false+fi++as_me=`$as_basename -- "$0" ||+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \+ X"$0" : 'X\(//\)$' \| \+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||+printf "%s\n" X/"$0" |+ sed '/^.*\/\([^/][^/]*\)\/*$/{+ s//\1/+ q+ }+ /^X\/\(\/\/\)$/{+ s//\1/+ q+ }+ /^X\/\(\/\).*/{+ s//\1/+ q+ }+ s/.*/./; q'`++# Avoid depending upon Character Ranges.+as_cr_letters='abcdefghijklmnopqrstuvwxyz'+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'+as_cr_Letters=$as_cr_letters$as_cr_LETTERS+as_cr_digits='0123456789'+as_cr_alnum=$as_cr_Letters$as_cr_digits+++# Determine whether it's possible to make 'echo' print without a newline.+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed+# for compatibility with existing Makefiles.+ECHO_C= ECHO_N= ECHO_T=+case `echo -n x` in #(((((+-n*)+ case `echo 'xy\c'` in+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.+ xy) ECHO_C='\c';;+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null+ ECHO_T=' ';;+ esac;;+*)+ ECHO_N='-n';;+esac++# For backward compatibility with old third-party macros, we provide+# the shell variables $as_echo and $as_echo_n. New code should use+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.+as_echo='printf %s\n'+as_echo_n='printf %s'++rm -f conf$$ conf$$.exe conf$$.file+if test -d conf$$.dir; then+ rm -f conf$$.dir/conf$$.file+else+ rm -f conf$$.dir+ mkdir conf$$.dir 2>/dev/null+fi+if (echo >conf$$.file) 2>/dev/null; then+ if ln -s conf$$.file conf$$ 2>/dev/null; then+ as_ln_s='ln -s'+ # ... but there are two gotchas:+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.+ # In both cases, we have to default to `cp -pR'.+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||+ as_ln_s='cp -pR'+ elif ln conf$$.file conf$$ 2>/dev/null; then+ as_ln_s=ln+ else+ as_ln_s='cp -pR'+ fi+else+ as_ln_s='cp -pR'+fi+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file+rmdir conf$$.dir 2>/dev/null+++# as_fn_mkdir_p+# -------------+# Create "$as_dir" as a directory, including parents if necessary.+as_fn_mkdir_p ()+{++ case $as_dir in #(+ -*) as_dir=./$as_dir;;+ esac+ test -d "$as_dir" || eval $as_mkdir_p || {+ as_dirs=+ while :; do+ case $as_dir in #(+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(+ *) as_qdir=$as_dir;;+ esac+ as_dirs="'$as_qdir' $as_dirs"+ as_dir=`$as_dirname -- "$as_dir" ||+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+ X"$as_dir" : 'X\(//\)[^/]' \| \+ X"$as_dir" : 'X\(//\)$' \| \+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||+printf "%s\n" X"$as_dir" |+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+ s//\1/+ q+ }+ /^X\(\/\/\)[^/].*/{+ s//\1/+ q+ }+ /^X\(\/\/\)$/{+ s//\1/+ q+ }+ /^X\(\/\).*/{+ s//\1/+ q+ }+ s/.*/./; q'`+ test -d "$as_dir" && break+ done+ test -z "$as_dirs" || eval "mkdir $as_dirs"+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"+++} # as_fn_mkdir_p+if mkdir -p . 2>/dev/null; then+ as_mkdir_p='mkdir -p "$as_dir"'+else+ test -d ./-p && rmdir ./-p+ as_mkdir_p=false+fi+++# as_fn_executable_p FILE+# -----------------------+# Test if FILE is an executable regular file.+as_fn_executable_p ()+{+ test -f "$1" && test -x "$1"+} # as_fn_executable_p+as_test_x='test -x'+as_executable_p=as_fn_executable_p++# Sed expression to map a string onto a valid CPP name.+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"++# Sed expression to map a string onto a valid variable name.+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"+++exec 6>&1+## ----------------------------------- ##+## Main body of $CONFIG_STATUS script. ##+## ----------------------------------- ##+_ASEOF+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1+# Save the log message, to keep $0 and so on meaningful, and to+# report actual input values of CONFIG_FILES etc. instead of their+# values after options handling.+ac_log="+This file was extended by Haskell directory package $as_me 1.0, which was+generated by GNU Autoconf 2.71. Invocation command line was++ CONFIG_FILES = $CONFIG_FILES+ CONFIG_HEADERS = $CONFIG_HEADERS+ CONFIG_LINKS = $CONFIG_LINKS+ CONFIG_COMMANDS = $CONFIG_COMMANDS+ $ $0 $@++on `(hostname || uname -n) 2>/dev/null | sed 1q`+"++_ACEOF+++case $ac_config_headers in *"+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;+esac+++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1+# Files that config.status was made for.+config_headers="$ac_config_headers"++_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1+ac_cs_usage="\+\`$as_me' instantiates files and other configuration actions+from templates according to the current configuration. Unless the files+and actions are specified as TAGs, all are instantiated by default.++Usage: $0 [OPTION]... [TAG]...++ -h, --help print this help, then exit+ -V, --version print version number and configuration settings, then exit+ --config print configuration, then exit+ -q, --quiet, --silent+ do not print progress messages+ -d, --debug don't remove temporary files+ --recheck update $as_me by reconfiguring in the same conditions+ --header=FILE[:TEMPLATE]+ instantiate the configuration header FILE++Configuration headers:+$config_headers++Report bugs to <libraries@haskell.org>."++_ACEOF+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1+ac_cs_config='$ac_cs_config_escaped'+ac_cs_version="\\+Haskell directory package config.status 1.0+configured by $0, generated by GNU Autoconf 2.71,+ with options \\"\$ac_cs_config\\"++Copyright (C) 2021 Free Software Foundation, Inc.+This config.status script is free software; the Free Software Foundation+gives unlimited permission to copy, distribute and modify it."++ac_pwd='$ac_pwd'+srcdir='$srcdir'+test -n "\$AWK" || AWK=awk+_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1+# The default lists apply if the user does not specify any file.+ac_need_defaults=:+while test $# != 0+do+ case $1 in+ --*=?*)+ ac_option=`expr "X$1" : 'X\([^=]*\)='`+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`+ ac_shift=:+ ;;+ --*=)+ ac_option=`expr "X$1" : 'X\([^=]*\)='`+ ac_optarg=+ ac_shift=:+ ;;+ *)+ ac_option=$1+ ac_optarg=$2+ ac_shift=shift+ ;;+ esac++ case $ac_option in+ # Handling of the options.+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)+ ac_cs_recheck=: ;;+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )+ printf "%s\n" "$ac_cs_version"; exit ;;+ --config | --confi | --conf | --con | --co | --c )+ printf "%s\n" "$ac_cs_config"; exit ;;+ --debug | --debu | --deb | --de | --d | -d )+ debug=: ;;+ --header | --heade | --head | --hea )+ $ac_shift+ case $ac_optarg in+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;+ esac+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"+ ac_need_defaults=false;;+ --he | --h)+ # Conflict between --help and --header+ as_fn_error $? "ambiguous option: \`$1'+Try \`$0 --help' for more information.";;+ --help | --hel | -h )+ printf "%s\n" "$ac_cs_usage"; exit ;;+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \+ | -silent | --silent | --silen | --sile | --sil | --si | --s)+ ac_cs_silent=: ;;++ # This is an error.+ -*) as_fn_error $? "unrecognized option: \`$1'+Try \`$0 --help' for more information." ;;++ *) as_fn_append ac_config_targets " $1"+ ac_need_defaults=false ;;++ esac+ shift+done++ac_configure_extra_args=++if $ac_cs_silent; then+ exec 6>/dev/null+ ac_configure_extra_args="$ac_configure_extra_args --silent"+fi++_ACEOF+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1+if \$ac_cs_recheck; then+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion+ shift+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6+ CONFIG_SHELL='$SHELL'+ export CONFIG_SHELL+ exec "\$@"+fi++_ACEOF+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1+exec 5>>config.log+{+ echo+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX+## Running $as_me. ##+_ASBOX+ printf "%s\n" "$ac_log"+} >&5++_ACEOF+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1+_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1++# Handling of arguments.+for ac_config_target in $ac_config_targets+do+ case $ac_config_target in+ "HsDirectoryConfig.h") CONFIG_HEADERS="$CONFIG_HEADERS HsDirectoryConfig.h" ;;++ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;+ esac+done+++# If the user did not use the arguments to specify the items to instantiate,+# then the envvar interface is used. Set only those that are not.+# We use the long form for the default assignment because of an extremely+# bizarre bug on SunOS 4.1.3.+if $ac_need_defaults; then+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers+fi++# Have a temporary directory for convenience. Make it in the build tree+# simply because there is no reason against having it here, and in addition,+# creating and moving files from /tmp can sometimes cause problems.+# Hook for its removal unless debugging.+# Note that there is a small window in which the directory will not be cleaned:+# after its creation but before its name has been assigned to `$tmp'.+$debug ||+{+ tmp= ac_tmp=+ trap 'exit_status=$?+ : "${ac_tmp:=$tmp}"+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status+' 0+ trap 'as_fn_exit 1' 1 2 13 15+}+# Create a (secure) tmp directory for tmp files.++{+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&+ test -d "$tmp"+} ||+{+ tmp=./conf$$-$RANDOM+ (umask 077 && mkdir "$tmp")+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5+ac_tmp=$tmp++# Set up the scripts for CONFIG_HEADERS section.+# No need to generate them if there are no CONFIG_HEADERS.+# This happens for instance with `./config.status Makefile'.+if test -n "$CONFIG_HEADERS"; then+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||+BEGIN {+_ACEOF++# Transform confdefs.h into an awk script `defines.awk', embedded as+# here-document in config.status, that substitutes the proper values into+# config.h.in to produce config.h.++# Create a delimiter string that does not exist in confdefs.h, to ease+# handling of long lines.+ac_delim='%!_!# '+for ac_last_try in false false :; do+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`+ if test -z "$ac_tt"; then+ break+ elif $ac_last_try; then+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5+ else+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "+ fi+done++# For the awk script, D is an array of macro values keyed by name,+# likewise P contains macro parameters if any. Preserve backslash+# newline sequences.++ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*+sed -n '+s/.\{148\}/&'"$ac_delim"'/g+t rset+:rset+s/^[ ]*#[ ]*define[ ][ ]*/ /+t def+d+:def+s/\\$//+t bsnl+s/["\\]/\\&/g+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\+D["\1"]=" \3"/p+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p+d+:bsnl+s/["\\]/\\&/g+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\+D["\1"]=" \3\\\\\\n"\\/p+t cont+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p+t cont+d+:cont+n+s/.\{148\}/&'"$ac_delim"'/g+t clear+:clear+s/\\$//+t bsnlc+s/["\\]/\\&/g; s/^/"/; s/$/"/p+d+:bsnlc+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p+b cont+' <confdefs.h | sed '+s/'"$ac_delim"'/"\\\+"/g' >>$CONFIG_STATUS || ac_write_fail=1++cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1+ for (key in D) D_is_set[key] = 1+ FS = ""+}+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {+ line = \$ 0+ split(line, arg, " ")+ if (arg[1] == "#") {+ defundef = arg[2]+ mac1 = arg[3]+ } else {+ defundef = substr(arg[1], 2)+ mac1 = arg[2]+ }+ split(mac1, mac2, "(") #)+ macro = mac2[1]+ prefix = substr(line, 1, index(line, defundef) - 1)+ if (D_is_set[macro]) {+ # Preserve the white space surrounding the "#".+ print prefix "define", macro P[macro] D[macro]+ next+ } else {+ # Replace #undef with comments. This is necessary, for example,+ # in the case of _POSIX_SOURCE, which is predefined and required+ # on some systems where configure will not decide to define it.+ if (defundef == "undef") {+ print "/*", prefix defundef, macro, "*/"+ next+ }+ }+}+{ print }+_ACAWK+_ACEOF+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5+fi # test -n "$CONFIG_HEADERS"+++eval set X " :H $CONFIG_HEADERS "+shift+for ac_tag+do+ case $ac_tag in+ :[FHLC]) ac_mode=$ac_tag; continue;;+ esac+ case $ac_mode$ac_tag in+ :[FHL]*:*);;+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;+ :[FH]-) ac_tag=-:-;;+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;+ esac+ ac_save_IFS=$IFS+ IFS=:+ set x $ac_tag+ IFS=$ac_save_IFS+ shift+ ac_file=$1+ shift++ case $ac_mode in+ :L) ac_source=$1;;+ :[FH])+ ac_file_inputs=+ for ac_f+ do+ case $ac_f in+ -) ac_f="$ac_tmp/stdin";;+ *) # Look for the file first in the build tree, then in the source tree+ # (if the path is not absolute). The absolute path cannot be DOS-style,+ # because $ac_f cannot contain `:'.+ test -f "$ac_f" ||+ case $ac_f in+ [\\/$]*) false;;+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;+ esac ||+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;+ esac+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac+ as_fn_append ac_file_inputs " '$ac_f'"+ done++ # Let's still pretend it is `configure' which instantiates (i.e., don't+ # use $as_me), people would be surprised to read:+ # /* config.h. Generated by config.status. */+ configure_input='Generated from '`+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'+ `' by configure.'+ if test x"$ac_file" != x-; then+ configure_input="$ac_file. $configure_input"+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5+printf "%s\n" "$as_me: creating $ac_file" >&6;}+ fi+ # Neutralize special characters interpreted by sed in replacement strings.+ case $configure_input in #(+ *\&* | *\|* | *\\* )+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |+ sed 's/[\\\\&|]/\\\\&/g'`;; #(+ *) ac_sed_conf_input=$configure_input;;+ esac++ case $ac_tag in+ *:-:* | *:-) cat >"$ac_tmp/stdin" \+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;+ esac+ ;;+ esac++ ac_dir=`$as_dirname -- "$ac_file" ||+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+ X"$ac_file" : 'X\(//\)[^/]' \| \+ X"$ac_file" : 'X\(//\)$' \| \+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||+printf "%s\n" X"$ac_file" |+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+ s//\1/+ q+ }+ /^X\(\/\/\)[^/].*/{+ s//\1/+ q+ }+ /^X\(\/\/\)$/{+ s//\1/+ q+ }+ /^X\(\/\).*/{+ s//\1/+ q+ }+ s/.*/./; q'`+ as_dir="$ac_dir"; as_fn_mkdir_p+ ac_builddir=.++case "$ac_dir" in+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;+*)+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`+ # A ".." for each directory in $ac_dir_suffix.+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`+ case $ac_top_builddir_sub in+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;+ esac ;;+esac+ac_abs_top_builddir=$ac_pwd+ac_abs_builddir=$ac_pwd$ac_dir_suffix+# for backward compatibility:+ac_top_builddir=$ac_top_build_prefix++case $srcdir in+ .) # We are building in place.+ ac_srcdir=.+ ac_top_srcdir=$ac_top_builddir_sub+ ac_abs_top_srcdir=$ac_pwd ;;+ [\\/]* | ?:[\\/]* ) # Absolute name.+ ac_srcdir=$srcdir$ac_dir_suffix;+ ac_top_srcdir=$srcdir+ ac_abs_top_srcdir=$srcdir ;;+ *) # Relative name.+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix+ ac_top_srcdir=$ac_top_build_prefix$srcdir+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;+esac+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix+++ case $ac_mode in++ :H)+ #+ # CONFIG_HEADER+ #+ if test x"$ac_file" != x-; then+ {+ printf "%s\n" "/* $configure_input */" >&1 \+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"+ } >"$ac_tmp/config.h" \+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}+ else+ rm -f "$ac_file"+ mv "$ac_tmp/config.h" "$ac_file" \+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5+ fi+ else+ printf "%s\n" "/* $configure_input */" >&1 \+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \+ || as_fn_error $? "could not create -" "$LINENO" 5+ fi+ ;;+++ esac++done # for ac_tag+++as_fn_exit 0+_ACEOF+ac_clean_files=$ac_clean_files_save++test $ac_write_fail = 0 ||+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5+++# configure is writing to config.log, and then calls config.status.+# config.status does its own redirection, appending to config.log.+# Unfortunately, on DOS this fails, as config.log is still kept open+# by configure, so config.status won't be able to write to it; its+# output is simply discarded. So we exec the FD to /dev/null,+# effectively closing config.log, so it can be properly (re)opened and+# appended to by config.status. When coming back to configure, we+# need to make the FD available again.+if test "$no_create" != yes; then+ ac_cs_success=:+ ac_config_status_args=+ test "$silent" = yes &&+ ac_config_status_args="$ac_config_status_args --quiet"+ exec 5>/dev/null+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false+ exec 5>>config.log+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which+ # would make configure fail if this is the last instruction.+ $ac_cs_success || as_fn_exit 1+fi+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}+fi+
configure.ac view
@@ -30,7 +30,9 @@ # check for specific header (.h) files that we are interested in AC_CHECK_HEADERS([fcntl.h limits.h sys/types.h sys/stat.h time.h]) +AC_CHECK_FUNCS([realpath]) AC_CHECK_FUNCS([utimensat])+AC_CHECK_FUNCS([CreateSymbolicLinkW]) AC_CHECK_FUNCS([GetFinalPathNameByHandleW]) # EXTEXT is defined automatically by AC_PROG_CC;
− directory.buildinfo
@@ -1,1 +0,0 @@-install-includes: HsDirectoryConfig.h
directory.cabal view
@@ -1,7 +1,7 @@+cabal-version: 2.2 name: directory-version: 1.3.0.0--- NOTE: Don't forget to update ./changelog.md-license: BSD3+version: 1.3.11.0+license: BSD-3-Clause license-file: LICENSE maintainer: libraries@haskell.org bug-reports: https://github.com/haskell/directory/issues@@ -11,8 +11,7 @@ directories in a portable way. category: System build-type: Configure-cabal-version: >= 1.10-tested-with: GHC>=7.4.1+tested-with: GHC == 8.10.7 || == 9.0.2 || == 9.2.4 || == 9.4.3 extra-tmp-files: autom4te.cache@@ -20,16 +19,16 @@ config.status HsDirectoryConfig.h +extra-doc-files:+ README.md+ changelog.md+ extra-source-files: HsDirectoryConfig.h.in- README.md System/Directory/Internal/*.h- changelog.md configure configure.ac- directory.buildinfo tests/*.hs- tests/util.inl source-repository head type: git@@ -37,36 +36,43 @@ Library default-language: Haskell2010- other-extensions:- CPP- Trustworthy+ other-extensions: CApiFFI, CPP exposed-modules: System.Directory+ System.Directory.OsPath System.Directory.Internal System.Directory.Internal.Prelude other-modules:- System.Directory.Internal.Config System.Directory.Internal.C_utimensat+ System.Directory.Internal.Common+ System.Directory.Internal.Config System.Directory.Internal.Posix System.Directory.Internal.Windows include-dirs: . build-depends:- base >= 4.5 && < 4.11,- time >= 1.4 && < 1.8,- filepath >= 1.3 && < 1.5+ base >= 4.13.0 && < 4.23,+ file-io >= 0.1.4 && < 0.3,+ time >= 1.8.0 && < 1.17, if os(windows)- build-depends: Win32 >= 2.2.2 && < 2.5+ build-depends: Win32 >= 2.14.1.0 && < 2.15 else- build-depends: unix >= 2.5.1 && < 2.8+ build-depends: unix >= 2.8.0 && < 2.9 + if impl(ghc >= 9.2)+ build-depends: filepath >= 1.5.0 && < 1.6,+ os-string >= 2.0.0 && < 2.1,+ else+ build-depends: filepath >= 1.4.100 && < 1.5+ ghc-options: -Wall test-suite test default-language: Haskell2010 other-extensions: BangPatterns, CPP+ default-extensions: OverloadedStrings ghc-options: -Wall hs-source-dirs: tests main-is: Main.hs@@ -91,20 +97,25 @@ DoesDirectoryExist001 DoesPathExist FileTime+ FindExecutable FindFile001 GetDirContents001 GetDirContents002 GetFileSize GetHomeDirectory001+ GetHomeDirectory002 GetPermissions001+ LongPaths MakeAbsolute+ MinimizeNameConflicts PathIsSymbolicLink RemoveDirectoryRecursive001 RemovePathForcibly RenameDirectory RenameFile001 RenamePath- Safe+ Simplify T8482 WithCurrentDirectory+ Xdg -- test-modules-end
tests/CanonicalizePath.hs view
@@ -1,13 +1,14 @@ {-# LANGUAGE CPP #-} module CanonicalizePath where-#include "util.inl"-import System.FilePath ((</>), dropFileName, dropTrailingPathSeparator,- normalise, takeFileName)+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath import TestUtils-#ifdef mingw32_HOST_OS-import System.Directory.Internal (win32_getFinalPathNameByHandle)-import qualified System.Win32 as Win32-#endif+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>), dropFileName, dropTrailingPathSeparator,+ normalise, takeFileName) main :: TestEnv -> IO () main _t = do@@ -15,10 +16,10 @@ dot2 <- canonicalizePath "." dot3 <- canonicalizePath "./" dot4 <- canonicalizePath "./."- T(expectEq) () dot (dropTrailingPathSeparator dot)- T(expectEq) () dot dot2- T(expectEq) () dot dot3- T(expectEq) () dot dot4+ T.expectEq _t () dot (dropTrailingPathSeparator dot)+ T.expectEq _t () dot dot2+ T.expectEq _t () dot dot3+ T.expectEq _t () dot dot4 writeFile "bar" "" bar <- canonicalizePath "bar"@@ -28,13 +29,13 @@ bar5 <- canonicalizePath "./bar" bar6 <- canonicalizePath "./bar/" bar7 <- canonicalizePath "./bar/."- T(expectEq) () bar (normalise (dot </> "bar"))- T(expectEq) () bar bar2- T(expectEq) () bar bar3- T(expectEq) () bar bar4- T(expectEq) () bar bar5- T(expectEq) () bar bar6- T(expectEq) () bar bar7+ T.expectEq _t () bar (normalise (dot </> "bar"))+ T.expectEq _t () bar bar2+ T.expectEq _t () bar bar3+ T.expectEq _t () bar bar4+ T.expectEq _t () bar bar5+ T.expectEq _t () bar bar6+ T.expectEq _t () bar bar7 createDirectory "foo" foo <- canonicalizePath "foo"@@ -43,12 +44,12 @@ foo4 <- canonicalizePath "foo/./" foo5 <- canonicalizePath "./foo" foo6 <- canonicalizePath "./foo/"- T(expectEq) () foo (normalise (dot </> "foo"))- T(expectEq) () foo foo2- T(expectEq) () foo foo3- T(expectEq) () foo foo4- T(expectEq) () foo foo5- T(expectEq) () foo foo6+ T.expectEq _t () foo (normalise (dot </> "foo"))+ T.expectEq _t () foo foo2+ T.expectEq _t () foo foo3+ T.expectEq _t () foo foo4+ T.expectEq _t () foo foo5+ T.expectEq _t () foo foo6 -- should not fail for non-existent paths fooNon <- canonicalizePath "foo/non-existent"@@ -59,57 +60,63 @@ fooNon6 <- canonicalizePath "./foo/non-existent/" fooNon7 <- canonicalizePath "./foo/./non-existent" fooNon8 <- canonicalizePath "./foo/./non-existent/"- T(expectEq) () fooNon (normalise (foo </> "non-existent"))- T(expectEq) () fooNon fooNon2- T(expectEq) () fooNon fooNon3- T(expectEq) () fooNon fooNon4- T(expectEq) () fooNon fooNon5- T(expectEq) () fooNon fooNon6- T(expectEq) () fooNon fooNon7- T(expectEq) () fooNon fooNon8-- supportsSymbolicLinks <- do-#ifdef mingw32_HOST_OS- hasSymbolicLinkPrivileges <-- (True <$ createSymbolicLink "_symlinktest_src" "_symlinktest_dst")- -- only test if symbolic links can be created- -- (usually disabled on Windows by group policy)- `catchIOError` \ e ->- if isPermissionError e- then pure False- else ioError e-- supportsGetFinalPathNameByHandle <-- (True <$ win32_getFinalPathNameByHandle Win32.nullHANDLE 0)- `catchIOError` \ e ->- case ioeGetErrorType e of- UnsupportedOperation -> pure False- _ -> pure True+ T.expectEq _t () fooNon (normalise (foo </> "non-existent"))+ T.expectEq _t () fooNon fooNon2+ T.expectEq _t () fooNon fooNon3+ T.expectEq _t () fooNon fooNon4+ T.expectEq _t () fooNon fooNon5+ T.expectEq _t () fooNon fooNon6+ T.expectEq _t () fooNon fooNon7+ T.expectEq _t () fooNon fooNon8 - pure (hasSymbolicLinkPrivileges && supportsGetFinalPathNameByHandle)-#else- pure True-#endif+ -- make sure ".." gets expanded properly by 'toExtendedLengthPath'+ -- (turns out this test won't detect the problem because GetFullPathName+ -- would expand them for us if we don't, but leaving it here anyway)+ T.expectEq _t () foo =<< canonicalizePath (foo </> ".." </> "foo") + supportsSymbolicLinks <- supportsSymlinks when supportsSymbolicLinks $ do let barQux = dot </> "bar" </> "qux" - createSymbolicLink "../bar" "foo/bar"- T(expectEq) () bar =<< canonicalizePath "foo/bar"- T(expectEq) () barQux =<< canonicalizePath "foo/bar/qux"+ -- note: this also checks that "../bar" gets normalized to "..\\bar"+ -- since Windows does not like "/" in symbolic links targets+ createFileLink "../bar" "foo/bar"+ T.expectEq _t () bar =<< canonicalizePath "foo/bar"+ T.expectEq _t () barQux =<< canonicalizePath "foo/bar/qux" - createSymbolicLink "foo" "lfoo"- T(expectEq) () foo =<< canonicalizePath "lfoo"- T(expectEq) () foo =<< canonicalizePath "lfoo/"- T(expectEq) () bar =<< canonicalizePath "lfoo/bar"- T(expectEq) () barQux =<< canonicalizePath "lfoo/bar/qux"+ createDirectoryLink "foo" "lfoo"+ T.expectEq _t () foo =<< canonicalizePath "lfoo"+ T.expectEq _t () foo =<< canonicalizePath "lfoo/"+ T.expectEq _t () bar =<< canonicalizePath "lfoo/bar"+ T.expectEq _t () barQux =<< canonicalizePath "lfoo/bar/qux" - -- FIXME: uncomment this test once #64 is fixed- -- createSymbolicLink "../foo/non-existent" "foo/qux"- -- qux <- canonicalizePath "foo/qux"- -- T(expectEq) () qux (dot </> "../foo/non-existent")+ -- create a haphazard chain of links+ createDirectoryLink "./../foo/../foo/." "./foo/./somelink3"+ createDirectoryLink ".././foo/somelink3" "foo/somelink2"+ createDirectoryLink "./foo/somelink2" "somelink"+ T.expectEq _t () foo =<< canonicalizePath "somelink" + -- regression test for #64+ createFileLink "../foo/non-existent" "foo/qux"+ removeDirectoryLink "foo/somelink3" -- break the chain made earlier+ qux <- canonicalizePath "foo/qux"+ T.expectEq _t () qux =<< canonicalizePath "foo/non-existent"+ T.expectEq _t () (foo </> "somelink3") =<< canonicalizePath "somelink"++ -- make sure it can handle loops+ createFileLink "loop1" "loop2"+ createFileLink "loop2" "loop1"+ loop1 <- canonicalizePath "loop1"+ loop2 <- canonicalizePath "loop2"+ T.expectEq _t () loop1 (normalise (dot </> "loop1"))+ T.expectEq _t () loop2 (normalise (dot </> "loop2"))++ -- make sure ".." gets expanded properly by 'toExtendedLengthPath'+ createDirectoryLink (foo </> ".." </> "foo") "foolink"+ _ <- listDirectory "foolink" -- make sure directory is accessible+ T.expectEq _t () foo =<< canonicalizePath "foolink"+ caseInsensitive <- (False <$ createDirectory "FOO") `catch` \ e ->@@ -121,8 +128,8 @@ when caseInsensitive $ do foo7 <- canonicalizePath "FOO" foo8 <- canonicalizePath "FOO/"- T(expectEq) () foo foo7- T(expectEq) () foo foo8+ T.expectEq _t () foo foo7+ T.expectEq _t () foo foo8 fooNon9 <- canonicalizePath "FOO/non-existent" fooNon10 <- canonicalizePath "fOo/non-existent/"@@ -132,28 +139,35 @@ fooNon14 <- canonicalizePath "./FOo/non-existent/" cfooNon15 <- canonicalizePath "./FOO/./NON-EXISTENT" cfooNon16 <- canonicalizePath "./FOO/./NON-EXISTENT/"- T(expectEq) () fooNon fooNon9- T(expectEq) () fooNon fooNon10- T(expectEq) () fooNon fooNon11- T(expectEq) () fooNon fooNon12- T(expectEq) () fooNon fooNon13- T(expectEq) () fooNon fooNon14- T(expectEq) () fooNon (dropFileName cfooNon15 <>- (toLower <$> takeFileName cfooNon15))- T(expectEq) () fooNon (dropFileName cfooNon16 <>- (toLower <$> takeFileName cfooNon16))- T(expectNe) () fooNon cfooNon15- T(expectNe) () fooNon cfooNon16+ T.expectEq _t () fooNon fooNon9+ T.expectEq _t () fooNon fooNon10+ T.expectEq _t () fooNon fooNon11+ T.expectEq _t () fooNon fooNon12+ T.expectEq _t () fooNon fooNon13+ T.expectEq _t () fooNon fooNon14+ T.expectEq _t () fooNon+ (dropFileName cfooNon15 <> os (toLower <$> so (takeFileName cfooNon15)))+ T.expectEq _t () fooNon+ (dropFileName cfooNon16 <> os (toLower <$> so (takeFileName cfooNon16)))+ T.expectNe _t () fooNon cfooNon15+ T.expectNe _t () fooNon cfooNon16 setCurrentDirectory "foo" foo9 <- canonicalizePath "../FOO" foo10 <- canonicalizePath "../FOO/"- T(expectEq) () foo foo9- T(expectEq) () foo foo10+ T.expectEq _t () foo foo9+ T.expectEq _t () foo foo10 - -- Make sure long file names can be canonicalized too- -- (i.e. GetLongPathName by itself won't work)- createDirectory "verylongdirectoryname"- vldn <- canonicalizePath "verylongdirectoryname"- vldn2 <- canonicalizePath "VERYLONGDIRECTORYNAME"- T(expectEq) () vldn vldn2+ let isWindows =+#if defined(mingw32_HOST_OS)+ True+#else+ False+#endif++ when isWindows $ do+ -- https://github.com/haskell/directory/issues/170+ T.expectEq _t () "\\\\localhost" =<< canonicalizePath "\\\\localhost"+ -- https://github.com/haskell/directory/issues/206+ T.expectEq _t () "\\\\localhost\\C$" =<<+ canonicalizePath "\\\\localhost\\C$\\.."
tests/CopyFile001.hs view
@@ -1,17 +1,29 @@-{-# LANGUAGE CPP #-} module CopyFile001 where-#include "util.inl"-import System.FilePath ((</>))+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>)) import qualified Data.List as List main :: TestEnv -> IO () main _t = do createDirectory dir- writeFile (dir </> from) contents- T(expectEq) () [from] . List.sort =<< listDirectory dir+ writeFile (so (dir </> from)) contents+ T.expectEq _t () [from] . List.sort =<< listDirectory dir copyFile (dir </> from) (dir </> to)- T(expectEq) () [from, to] . List.sort =<< listDirectory dir- T(expectEq) () contents =<< readFile (dir </> to)+ T.expectEq _t () [from, to] . List.sort =<< listDirectory dir+ T.expectEq _t () contents =<< readFile (so (dir </> to))++ -- Regression test for https://github.com/haskell/directory/issues/177+ createDirectory "issue177"+ T.expectIOErrorType _t () isDoesNotExistError+ (copyFile "issue177/nonexistentSrc" "issue177/dst")+ T.expectEq _t () [] =<< listDirectory "issue177"+ where contents = "This is the data\n" from = "source"
tests/CopyFile002.hs view
@@ -1,17 +1,22 @@-{-# LANGUAGE CPP #-} module CopyFile002 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T import qualified Data.List as List main :: TestEnv -> IO () main _t = do -- Similar to CopyFile001 but moves a file in the current directory -- (Bug #1652 on GHC Trac)- writeFile from contents- T(expectEq) () [from] . List.sort =<< listDirectory "."+ writeFile (so from) contents+ T.expectEq _t () [from] . List.sort =<< listDirectory "." copyFile from to- T(expectEq) () [from, to] . List.sort =<< listDirectory "."- T(expectEq) () contents =<< readFile to+ T.expectEq _t () [from, to] . List.sort =<< listDirectory "."+ T.expectEq _t () contents =<< readFile (so to) where contents = "This is the data\n" from = "source"
tests/CopyFileWithMetadata.hs view
@@ -1,6 +1,11 @@-{-# LANGUAGE CPP #-} module CopyFileWithMetadata where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T import qualified Data.List as List main :: TestEnv -> IO ()@@ -14,28 +19,28 @@ perm <- getPermissions "a" -- sanity check- T(expectEq) () ["a", "b"] . List.sort =<< listDirectory "."+ T.expectEq _t () ["a", "b"] . List.sort =<< listDirectory "." -- copy file copyFileWithMetadata "a" "b" copyFileWithMetadata "a" "c" -- make sure we got the right results- T(expectEq) () ["a", "b", "c"] . List.sort =<< listDirectory "."+ T.expectEq _t () ["a", "b", "c"] . List.sort =<< listDirectory "." for_ ["b", "c"] $ \ f -> do- T(expectEq) f perm =<< getPermissions f- T(expectEq) f mtime =<< getModificationTime f- T(expectEq) f contents =<< readFile f+ T.expectEq _t f perm =<< getPermissions f+ T.expectEq _t f mtime =<< getModificationTime f+ T.expectEq _t f contents =<< readFile (so f) where contents = "This is the data\n"- mtime = read "2000-01-01 00:00:00"+ mtime = read "2000-01-01 00:00:00Z" cleanup = do -- needed to ensure the test runner can clean up our mess- modifyWritable True "a" `catchIOError` \ _ -> return ()- modifyWritable True "b" `catchIOError` \ _ -> return ()- modifyWritable True "c" `catchIOError` \ _ -> return ()+ modifyWritable True "a" `catchIOError` \ _ -> pure ()+ modifyWritable True "b" `catchIOError` \ _ -> pure ()+ modifyWritable True "c" `catchIOError` \ _ -> pure () modifyWritable b f = do perm <- getPermissions f
tests/CreateDirectory001.hs view
@@ -1,9 +1,13 @@-{-# LANGUAGE CPP #-} module CreateDirectory001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do createDirectory testdir- T(expectIOErrorType) () isAlreadyExistsError (createDirectory testdir)+ T.expectIOErrorType _t () isAlreadyExistsError (createDirectory testdir) where testdir = "dir"
tests/CreateDirectoryIfMissing001.hs view
@@ -1,7 +1,14 @@ {-# LANGUAGE CPP #-} module CreateDirectoryIfMissing001 where-#include "util.inl"-import System.FilePath ((</>), addTrailingPathSeparator)+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import Data.Either (lefts)+import System.OsPath ((</>), addTrailingPathSeparator) main :: TestEnv -> IO () main _t = do@@ -9,7 +16,7 @@ createDirectoryIfMissing False testdir cleanup - T(expectIOErrorType) () isDoesNotExistError $+ T.expectIOErrorType _t () isDoesNotExistError $ createDirectoryIfMissing False testdir_a createDirectoryIfMissing True testdir_a@@ -19,21 +26,21 @@ createDirectoryIfMissing True (addTrailingPathSeparator testdir_a) - T(inform) "testing for race conditions ..."+ T.inform _t "testing for race conditions ..." raceCheck1- T(inform) "testing for race conditions ..."+ T.inform _t "testing for race conditions ..." raceCheck2- T(inform) "done."+ T.inform _t "done." cleanup - writeFile testdir testdir- T(expectIOErrorType) () isAlreadyExistsError $+ writeFile (so testdir) (so testdir)+ T.expectIOErrorType _t () isAlreadyExistsError $ createDirectoryIfMissing False testdir removeFile testdir cleanup - writeFile testdir testdir- T(expectIOErrorType) () isNotADirectoryError $+ writeFile (so testdir) (so testdir)+ T.expectIOErrorType _t () isNotADirectoryError $ createDirectoryIfMissing True testdir_a removeFile testdir cleanup@@ -42,34 +49,35 @@ testname = "CreateDirectoryIfMissing001" - testdir = testname <> ".d"+ testdir = os (testname <> ".d") testdir_a = testdir </> "a" - numRepeats = T.readArg _t testname "num-repeats" 10000+ numRepeats = T.readArg _t testname "num-repeats" 10 numThreads = T.readArg _t testname "num-threads" 4 + forkPut mvar action = () <$ forkFinally action (putMVar mvar)+ -- Look for race conditions (bug #2808 on GHC Trac). This fails with -- +RTS -N2 and directory 1.0.0.2. raceCheck1 = do m <- newEmptyMVar- _ <- forkIO $ do+ forkPut m $ do replicateM_ numRepeats create- putMVar m ()- _ <- forkIO $ do+ forkPut m $ do replicateM_ numRepeats cleanup- putMVar m ()- replicateM_ 2 (takeMVar m)+ results <- replicateM 2 (takeMVar m)+ T.expectEq _t () [] (show <$> lefts results) -- This test fails on Windows (see bug #2924 on GHC Trac): raceCheck2 = do m <- newEmptyMVar- replicateM_ numThreads $- forkIO $ do+ replicateM_ numThreads $ do+ forkPut m $ do replicateM_ numRepeats $ do create cleanup- putMVar m ()- replicateM_ numThreads (takeMVar m)+ results <- replicateM numThreads (takeMVar m)+ T.expectEq _t () [] (show <$> lefts results) -- createDirectoryIfMissing is allowed to fail with isDoesNotExistError if -- another process/thread removes one of the directories during the process@@ -79,16 +87,19 @@ -- (see bug #2924 on GHC Trac) create = createDirectoryIfMissing True testdir_a `catch` \ e ->- if isDoesNotExistError e || isPermissionError e || isInappropriateTypeError e- then return ()+ if isDoesNotExistError e+ || isPermissionError e+ || isInappropriateTypeError e+ || ioeGetErrorType e == InvalidArgument+ then pure () else ioError e - cleanup = removeDirectoryRecursive testdir `catchAny` \ _ -> return ()+ cleanup = removeDirectoryRecursive testdir `catchAny` \ _ -> pure () catchAny :: IO a -> (SomeException -> IO a) -> IO a catchAny = catch -#ifdef mingw32_HOST_OS+#if defined(mingw32_HOST_OS) isNotADirectoryError = isAlreadyExistsError #else isNotADirectoryError = isInappropriateTypeError
tests/CurrentDirectory001.hs view
@@ -1,6 +1,10 @@-{-# LANGUAGE CPP #-} module CurrentDirectory001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T import qualified Data.List as List main :: TestEnv -> IO ()@@ -8,6 +12,6 @@ prevDir <- getCurrentDirectory createDirectory "dir" setCurrentDirectory "dir"- T(expectEq) () [".", ".."] . List.sort =<< getDirectoryContents "."+ T.expectEq _t () [".", ".."] . List.sort =<< getDirectoryContents "." setCurrentDirectory prevDir removeDirectory "dir"
tests/Directory001.hs view
@@ -1,6 +1,10 @@-{-# LANGUAGE CPP #-} module Directory001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do@@ -10,7 +14,7 @@ renameFile "foo/bar" "foo/baz" renameDirectory "foo" "bar" str' <- readFile "bar/baz"- T(expectEq) () str' str+ T.expectEq _t () str' str removeFile "bar/baz" removeDirectory "bar"
tests/DoesDirectoryExist001.hs view
@@ -1,23 +1,30 @@ {-# LANGUAGE CPP #-} module DoesDirectoryExist001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do -- [regression test] "/" was not recognised as a directory prior to GHC 6.1- T(expect) () =<< doesDirectoryExist rootDir+ T.expect _t () =<< doesDirectoryExist rootDir createDirectory "somedir" - T(expect) () . not =<< doesDirectoryExist "nonexistent"- T(expect) () =<< doesDirectoryExist "somedir"-#ifdef mingw32_HOST_OS- T(expect) () =<< doesDirectoryExist "SoMeDiR"+ T.expect _t () . not =<< doesDirectoryExist ""+ T.expect _t () . not =<< doesDirectoryExist "nonexistent"+ T.expect _t () =<< doesDirectoryExist "."+ T.expect _t () =<< doesDirectoryExist "somedir"+#if defined(mingw32_HOST_OS)+ T.expect _t () =<< doesDirectoryExist "SoMeDiR" #endif where-#ifdef mingw32_HOST_OS+#if defined(mingw32_HOST_OS) rootDir = "C:\\" #else rootDir = "/"
tests/DoesPathExist.hs view
@@ -1,28 +1,49 @@ {-# LANGUAGE CPP #-} module DoesPathExist where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils (supportsSymlinks)+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do - T(expect) () =<< doesPathExist rootDir+ T.expect _t () =<< doesPathExist rootDir createDirectory "somedir" writeFile "somefile" "somedata" writeFile "\x3c0\x42f\x97f3\xe6\x221e" "somedata" - T(expect) () . not =<< doesPathExist "nonexistent"- T(expect) () =<< doesPathExist "somedir"- T(expect) () =<< doesPathExist "somefile"- T(expect) () =<< doesPathExist "./somefile"-#ifdef mingw32_HOST_OS- T(expect) () =<< doesPathExist "SoMeDiR"- T(expect) () =<< doesPathExist "sOmEfIlE"+ T.expect _t () . not =<< doesPathExist ""+ T.expect _t () . not =<< doesPathExist "nonexistent"+ T.expect _t () =<< doesPathExist "."+ T.expect _t () =<< doesPathExist "somedir"+ T.expect _t () =<< doesPathExist "somefile"+ T.expect _t () =<< doesPathExist "./somefile"+#if defined(mingw32_HOST_OS)+ T.expect _t () =<< doesPathExist "SoMeDiR"+ T.expect _t () =<< doesPathExist "sOmEfIlE" #endif- T(expect) () =<< doesPathExist "\x3c0\x42f\x97f3\xe6\x221e"+ T.expect _t () =<< doesPathExist "\x3c0\x42f\x97f3\xe6\x221e" + supportsSymbolicLinks <- supportsSymlinks+ when supportsSymbolicLinks $ do++ createDirectoryLink "somedir" "somedirlink"+ createFileLink "somefile" "somefilelink"+ createFileLink "nonexistent" "nonexistentlink"++ T.expect _t () =<< doesFileExist "somefilelink"+ T.expect _t () . not =<< doesDirectoryExist "somefilelink"+ T.expect _t () =<< doesDirectoryExist "somedirlink"+ T.expect _t () . not =<< doesFileExist "somedirlink"+ T.expect _t () . not =<< doesDirectoryExist "nonexistentlink"+ T.expect _t () . not =<< doesFileExist "nonexistentlink"+ where-#ifdef mingw32_HOST_OS+#if defined(mingw32_HOST_OS) rootDir = "C:\\" #else rootDir = "/"
tests/FileTime.hs view
@@ -1,6 +1,10 @@-{-# LANGUAGE CPP #-} module FileTime where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T import Data.Time.Clock (addUTCTime, getCurrentTime) main :: TestEnv -> IO ()@@ -9,13 +13,13 @@ let someTimeAgo = addUTCTime (-3600) now someTimeAgo' = addUTCTime (-7200) now - T(expectIOErrorType) () isDoesNotExistError $+ T.expectIOErrorType _t () isDoesNotExistError $ getAccessTime "nonexistent-file"- T(expectIOErrorType) () isDoesNotExistError $+ T.expectIOErrorType _t () isDoesNotExistError $ setAccessTime "nonexistent-file" someTimeAgo- T(expectIOErrorType) () isDoesNotExistError $+ T.expectIOErrorType _t () isDoesNotExistError $ getModificationTime "nonexistent-file"- T(expectIOErrorType) () isDoesNotExistError $+ T.expectIOErrorType _t () isDoesNotExistError $ setModificationTime "nonexistent-file" someTimeAgo writeFile "foo" ""@@ -31,20 +35,27 @@ mtime2 <- getModificationTime file -- modification time should be set with at worst 1 sec resolution- T(expectNearTime) file mtime mtime2 1+ T.expectNearTime _t file mtime mtime2 1 -- access time should not change, although it may lose some precision -- on POSIX systems without 'utimensat'- T(expectNearTime) file atime1 atime2 1+ T.expectNearTime _t file atime1 atime2 1 setAccessTime file atime atime3 <- getAccessTime file mtime3 <- getModificationTime file - -- access time should be set with at worst 1 sec resolution- T(expectNearTime) file atime atime3 1+ when setAtime $ do+ -- access time should be set with at worst 1 sec resolution+ T.expectNearTime _t file atime atime3 1 -- modification time should not change, although it may lose some precision -- on POSIX systems without 'utimensat'- T(expectNearTime) file mtime2 mtime3 1+ T.expectNearTime _t file mtime2 mtime3 1++ where++ testname = "FileTime"++ setAtime = T.readArg _t testname "set-atime" True
+ tests/FindExecutable.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE CPP #-}+module FindExecutable where+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T++main :: TestEnv -> IO ()+main _t = do++ -- 'find' expected to exist on both Windows and POSIX,+ -- though we have no idea if it's writable+ Just _ <- findExecutable "find"++ T.expectEq _t () Nothing =<<+ findExecutable "__nonexistent_binary_gbowyxcejjawf7r6__"++ -- https://github.com/haskell/directory/issues/187+ T.expectEq _t () Nothing =<< findExecutable "/"+ T.expectEq _t () Nothing =<< findExecutable "//"+#if !defined(mingw32_HOST_OS)+ T.expectEq _t () Nothing =<< findExecutable "\\"+ T.expectEq _t () Nothing =<< findExecutable "\\\\"+ T.expectEq _t () Nothing =<< findExecutable "\\\\localhost\\c$"+#endif
tests/FindFile001.hs view
@@ -1,10 +1,58 @@-{-# LANGUAGE CPP #-} module FindFile001 where-#include "util.inl"-import System.FilePath ((</>))+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import qualified Data.List as List+import System.OsPath ((</>)) main :: TestEnv -> IO () main _t = do++ createDirectory "bar"+ createDirectory "qux" writeFile "foo" ""- found <- findFile ("." : undefined) "foo"- T(expectEq) () found (Just ("." </> "foo"))+ writeFile (so ("bar" </> "foo")) ""+ writeFile (so ("qux" </> "foo")) ":3"++ -- make sure findFile is lazy enough+ T.expectEq _t () (Just ("." </> "foo")) =<< findFile ("." : undefined) "foo"++ -- make sure relative paths work+ T.expectEq _t () (Just ("." </> "bar" </> "foo")) =<<+ findFile ["."] ("bar" </> "foo")++ T.expectEq _t () (Just ("." </> "foo")) =<< findFile [".", "bar"] "foo"+ T.expectEq _t () (Just ("bar" </> "foo")) =<< findFile ["bar", "."] "foo"++ let f fn = (== ":3") <$> readFile (so fn)+ for_ (List.permutations ["qux", "bar", "."]) $ \ ds -> do++ let (match, noMatch) = List.partition (== "qux") ds+ match0 : _ <- pure match+ noMatch0 : _ <- pure noMatch++ T.expectEq _t ds (Just (match0 </> "foo")) =<<+ findFileWith f ds "foo"++ T.expectEq _t ds ((</> "foo") <$> match) =<< findFilesWith f ds "foo"++ T.expectEq _t ds (Just (noMatch0 </> "foo")) =<<+ findFileWith ((not <$>) . f) ds "foo"++ T.expectEq _t ds ((</> "foo") <$> noMatch) =<<+ findFilesWith ((not <$>) . f) ds "foo"++ T.expectEq _t ds Nothing =<< findFileWith (\ _ -> pure False) ds "foo"++ T.expectEq _t ds [] =<< findFilesWith (\ _ -> pure False) ds "foo"++ -- make sure absolute paths are handled properly irrespective of 'dirs'+ -- https://github.com/haskell/directory/issues/72+ absPath <- makeAbsolute ("bar" </> "foo")+ absPath2 <- makeAbsolute ("bar" </> "nonexistent")+ T.expectEq _t () (Just absPath) =<< findFile [] absPath+ T.expectEq _t () Nothing =<< findFile [] absPath2
tests/GetDirContents001.hs view
@@ -1,23 +1,28 @@-{-# LANGUAGE CPP #-} module GetDirContents001 where-#include "util.inl"-import System.FilePath ((</>))+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>)) import qualified Data.List as List main :: TestEnv -> IO () main _t = do createDirectory dir- T(expectEq) () specials . List.sort =<<+ T.expectEq _t () specials . List.sort =<< getDirectoryContents dir- T(expectEq) () [] . List.sort =<<+ T.expectEq _t () [] . List.sort =<< listDirectory dir names <- for [1 .. 100 :: Int] $ \ i -> do- let name = 'f' : show i- writeFile (dir </> name) ""- return name- T(expectEq) () (List.sort (specials <> names)) . List.sort =<<+ let name = "f" <> os (show i)+ writeFile (so (dir </> name)) ""+ pure name+ T.expectEq _t () (List.sort (specials <> names)) . List.sort =<< getDirectoryContents dir- T(expectEq) () (List.sort names) . List.sort =<<+ T.expectEq _t () (List.sort names) . List.sort =<< listDirectory dir where dir = "dir" specials = [".", ".."]
tests/GetDirContents002.hs view
@@ -1,8 +1,12 @@-{-# LANGUAGE CPP #-} module GetDirContents002 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do- T(expectIOErrorType) () isDoesNotExistError $+ T.expectIOErrorType _t () isDoesNotExistError $ getDirectoryContents "nonexistent"
tests/GetFileSize.hs view
@@ -1,17 +1,19 @@-{-# LANGUAGE CPP #-} module GetFileSize where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do - withBinaryFile "emptyfile" WriteMode $ \ _ -> do- return ()- withBinaryFile "testfile" WriteMode $ \ h -> do- hPutStr h string+ writeFile "emptyfile" ""+ writeFile "testfile" string - T(expectEq) () 0 =<< getFileSize "emptyfile"- T(expectEq) () (fromIntegral (length string)) =<< getFileSize "testfile"+ T.expectEq _t () 0 =<< getFileSize "emptyfile"+ T.expectEq _t () (fromIntegral (length string)) =<< getFileSize "testfile" where string = "The quick brown fox jumps over the lazy dog."
tests/GetHomeDirectory001.hs view
@@ -1,15 +1,20 @@-{-# LANGUAGE CPP #-} module GetHomeDirectory001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do homeDir <- getHomeDirectory- T(expect) () (homeDir /= "") -- sanity check+ T.expect _t () (homeDir /= mempty) -- sanity check _ <- getAppUserDataDirectory "test" _ <- getXdgDirectory XdgCache "test" _ <- getXdgDirectory XdgConfig "test" _ <- getXdgDirectory XdgData "test"+ _ <- getXdgDirectory XdgState "test" _ <- getUserDocumentsDirectory _ <- getTemporaryDirectory- return ()+ pure ()
+ tests/GetHomeDirectory002.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE CPP #-}+module GetHomeDirectory002 where++#if !defined(mingw32_HOST_OS)+import System.Posix.Env+#endif+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T++-- Test that the getpwuid_r fallback works.+-- This is only relevant on unix.+main :: TestEnv -> IO ()+main _t = do+#if !defined(mingw32_HOST_OS)+ unsetEnv "HOME"+#endif+ _ <- getHomeDirectory+ T.expect _t () True -- avoid warnings about redundant imports
tests/GetPermissions001.hs view
@@ -1,6 +1,10 @@-{-# LANGUAGE CPP #-} module GetPermissions001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do@@ -10,37 +14,54 @@ checkOrdinary checkTrailingSlash + -- 'writable' is the only permission that can be changed on Windows+ writeFile "foo.txt" ""+ foo <- makeAbsolute "foo.txt"+ modifyPermissions "foo.txt" (\ p -> p { writable = False })+ T.expect _t () =<< not . writable <$> getPermissions "foo.txt"+ modifyPermissions "foo.txt" (\ p -> p { writable = True })+ T.expect _t () =<< writable <$> getPermissions "foo.txt"+ modifyPermissions "foo.txt" (\ p -> p { writable = False })+ T.expect _t () =<< not . writable <$> getPermissions "foo.txt"+ modifyPermissions foo (\ p -> p { writable = True })+ T.expect _t () =<< writable <$> getPermissions foo+ modifyPermissions foo (\ p -> p { writable = False })+ T.expect _t () =<< not . writable <$> getPermissions foo++ -- test empty path+ modifyPermissions "" id+ where checkCurrentDir = do -- since the current directory is created by the test runner, -- it should be readable, writable, and searchable p <- getPermissions "."- T(expect) () (readable p)- T(expect) () (writable p)- T(expect) () (not (executable p))- T(expect) () (searchable p)+ T.expect _t () (readable p)+ T.expect _t () (writable p)+ T.expect _t () (not (executable p))+ T.expect _t () (searchable p) checkExecutable = do -- 'find' expected to exist on both Windows and POSIX, -- though we have no idea if it's writable Just f <- findExecutable "find" p <- getPermissions f- T(expect) () (readable p)- T(expect) () (executable p)- T(expect) () (not (searchable p))+ T.expect _t () (readable p)+ T.expect _t () (executable p)+ T.expect _t () (not (searchable p)) checkOrdinary = do writeFile "foo" "" p <- getPermissions "foo"- T(expect) () (readable p)- T(expect) () (writable p)- T(expect) () (not (executable p))- T(expect) () (not (searchable p))+ T.expect _t () (readable p)+ T.expect _t () (writable p)+ T.expect _t () (not (executable p))+ T.expect _t () (not (searchable p)) -- [regression test] (issue #9) -- Windows doesn't like trailing path separators checkTrailingSlash = do createDirectory "bar" _ <- getPermissions "bar/"- return ()+ pure ()
+ tests/LongPaths.hs view
@@ -0,0 +1,65 @@+module LongPaths where+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>))++main :: TestEnv -> IO ()+main _t = do+ let longName = mconcat (replicate 10 "its_very_long")+ longDir <- makeAbsolute (longName </> longName)++ supportsLongPaths <- do+ -- create 2 dirs because 1 path segment by itself can't exceed MAX_PATH+ -- tests: [createDirectory]+ createDirectory =<< makeAbsolute longName+ createDirectory longDir+ pure True+ `catchIOError` \ _ ->+ pure False++ -- skip tests on file systems that do not support long paths+ when supportsLongPaths $ do++ -- test relative paths+ let relDir = longName </> mconcat (replicate 8 "yeah_its_long")+ createDirectory relDir+ T.expect _t () =<< doesDirectoryExist relDir+ T.expectEq _t () [] =<< listDirectory relDir+ setPermissions relDir emptyPermissions+ T.expectEq _t () False =<< writable <$> getPermissions relDir++ writeFile "foobar.txt" "^.^" -- writeFile does not support long paths yet++ -- tests: [renamePath], [copyFileWithMetadata]+ renamePath "foobar.txt" (longDir </> "foobar_tmp.txt")+ renamePath (longDir </> "foobar_tmp.txt") (longDir </> "foobar.txt")+ copyFileWithMetadata (longDir </> "foobar.txt")+ (longDir </> "foobar_copy.txt")++ -- tests: [doesDirectoryExist], [doesFileExist], [doesPathExist]+ T.expect _t () =<< doesDirectoryExist longDir+ T.expect _t () =<< doesFileExist (longDir </> "foobar.txt")+ T.expect _t () =<< doesPathExist longDir+ T.expect _t () =<< doesPathExist (longDir </> "foobar.txt")++ -- tests: [getFileSize], [getModificationTime]+ T.expectEq _t () 3 =<< getFileSize (longDir </> "foobar.txt")+ _ <- getModificationTime (longDir </> "foobar.txt")++ supportsSymbolicLinks <- supportsSymlinks+ when supportsSymbolicLinks $ do++ -- tests: [createDirectoryLink], [getSymbolicLinkTarget], [listDirectory]+ -- also tests expansion of "." and ".."+ createDirectoryLink "." (longDir </> "link")+ _ <- listDirectory (longDir </> ".." </> longName </> "link")+ T.expectEq _t () "." =<<+ getSymbolicLinkTarget (longDir </> "." </> "link")++ pure ()++ -- [removeFile], [removeDirectory] are automatically tested by the cleanup
tests/Main.hs view
@@ -11,22 +11,27 @@ import qualified DoesDirectoryExist001 import qualified DoesPathExist import qualified FileTime+import qualified FindExecutable import qualified FindFile001 import qualified GetDirContents001 import qualified GetDirContents002 import qualified GetFileSize import qualified GetHomeDirectory001+import qualified GetHomeDirectory002 import qualified GetPermissions001+import qualified LongPaths import qualified MakeAbsolute+import qualified MinimizeNameConflicts import qualified PathIsSymbolicLink import qualified RemoveDirectoryRecursive001 import qualified RemovePathForcibly import qualified RenameDirectory import qualified RenameFile001 import qualified RenamePath-import qualified Safe+import qualified Simplify import qualified T8482 import qualified WithCurrentDirectory+import qualified Xdg main :: IO () main = T.testMain $ \ _t -> do@@ -41,19 +46,24 @@ T.isolatedRun _t "DoesDirectoryExist001" DoesDirectoryExist001.main T.isolatedRun _t "DoesPathExist" DoesPathExist.main T.isolatedRun _t "FileTime" FileTime.main+ T.isolatedRun _t "FindExecutable" FindExecutable.main T.isolatedRun _t "FindFile001" FindFile001.main T.isolatedRun _t "GetDirContents001" GetDirContents001.main T.isolatedRun _t "GetDirContents002" GetDirContents002.main T.isolatedRun _t "GetFileSize" GetFileSize.main T.isolatedRun _t "GetHomeDirectory001" GetHomeDirectory001.main+ T.isolatedRun _t "GetHomeDirectory002" GetHomeDirectory002.main T.isolatedRun _t "GetPermissions001" GetPermissions001.main+ T.isolatedRun _t "LongPaths" LongPaths.main T.isolatedRun _t "MakeAbsolute" MakeAbsolute.main+ T.isolatedRun _t "MinimizeNameConflicts" MinimizeNameConflicts.main T.isolatedRun _t "PathIsSymbolicLink" PathIsSymbolicLink.main T.isolatedRun _t "RemoveDirectoryRecursive001" RemoveDirectoryRecursive001.main T.isolatedRun _t "RemovePathForcibly" RemovePathForcibly.main T.isolatedRun _t "RenameDirectory" RenameDirectory.main T.isolatedRun _t "RenameFile001" RenameFile001.main T.isolatedRun _t "RenamePath" RenamePath.main- T.isolatedRun _t "Safe" Safe.main+ T.isolatedRun _t "Simplify" Simplify.main T.isolatedRun _t "T8482" T8482.main T.isolatedRun _t "WithCurrentDirectory" WithCurrentDirectory.main+ T.isolatedRun _t "Xdg" Xdg.main
tests/MakeAbsolute.hs view
@@ -1,33 +1,53 @@ {-# LANGUAGE CPP #-} module MakeAbsolute where-#include "util.inl"-import System.FilePath ((</>), addTrailingPathSeparator,- dropTrailingPathSeparator, normalise)+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>), addTrailingPathSeparator,+ dropTrailingPathSeparator, normalise)+#if defined(mingw32_HOST_OS)+import System.Directory.Internal+import System.OsPath (takeDrive, toChar, unpack)+#endif main :: TestEnv -> IO () main _t = do dot <- makeAbsolute "" dot2 <- makeAbsolute "." dot3 <- makeAbsolute "./."- T(expectEq) () dot (dropTrailingPathSeparator dot)- T(expectEq) () dot dot2- T(expectEq) () dot dot3+ T.expectEq _t () dot (dropTrailingPathSeparator dot)+ T.expectEq _t () dot dot2+ T.expectEq _t () dot dot3 sdot <- makeAbsolute "./" sdot2 <- makeAbsolute "././"- T(expectEq) () sdot (addTrailingPathSeparator sdot)- T(expectEq) () sdot sdot2+ T.expectEq _t () sdot (addTrailingPathSeparator sdot)+ T.expectEq _t () sdot sdot2 foo <- makeAbsolute "foo" foo2 <- makeAbsolute "foo/." foo3 <- makeAbsolute "./foo"- T(expectEq) () foo (normalise (dot </> "foo"))- T(expectEq) () foo foo2- T(expectEq) () foo foo3+ T.expectEq _t () foo (normalise (dot </> "foo"))+ T.expectEq _t () foo foo2+ T.expectEq _t () foo foo3 sfoo <- makeAbsolute "foo/" sfoo2 <- makeAbsolute "foo/./" sfoo3 <- makeAbsolute "./foo/"- T(expectEq) () sfoo (normalise (dot </> "foo/"))- T(expectEq) () sfoo sfoo2- T(expectEq) () sfoo sfoo3+ T.expectEq _t () sfoo (normalise (dot </> "foo/"))+ T.expectEq _t () sfoo sfoo2+ T.expectEq _t () sfoo sfoo3++#if defined(mingw32_HOST_OS)+ cwd <- getCurrentDirectory+ cwdDriveLetter : _ <- pure (unpack (takeDrive cwd))+ let driveLetter = toUpper (toChar cwdDriveLetter)+ let driveLetter' = if driveLetter == 'Z' then 'A' else succ driveLetter+ drp1 <- makeAbsolute (os (driveLetter : ":foobar"))+ drp2 <- makeAbsolute (os (driveLetter' : ":foobar"))+ T.expectEq _t () drp1 =<< makeAbsolute "foobar"+ T.expectEq _t () drp2 (os (driveLetter' : ":\\foobar"))+#endif
+ tests/MinimizeNameConflicts.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE CPP #-}+module MinimizeNameConflicts+ ( main+ , module System.Directory.OsPath+#if defined(mingw32_HOST_OS)+ , module System.Win32+#else+ , module System.Posix+#endif+ ) where+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+#if defined(mingw32_HOST_OS)+import System.Win32 hiding+ ( copyFile+ , createDirectory+ , getCurrentDirectory+ , getTemporaryDirectory+ , removeDirectory+ , setCurrentDirectory+ )+#else+import System.Posix hiding+ ( createDirectory+ , isSymbolicLink+ , removeDirectory+ )+#endif++-- This is just a compile-test to check for name conflicts between directory+-- and other boot libraries. See for example:+-- https://github.com/haskell/directory/issues/52+main :: TestEnv -> IO ()+main _t = do+ T.expect _t ("no-op" :: String) True
tests/PathIsSymbolicLink.hs view
@@ -1,18 +1,36 @@-{-# LANGUAGE CPP #-} module PathIsSymbolicLink where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath import TestUtils+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do- success <- (createSymbolicLink "x" "y" >> return True)-#ifdef mingw32_HOST_OS- -- only test if symbolic links can be created- -- (usually disabled on Windows by group policy)- `catchIOError` \ e ->- if isPermissionError e- then return False- else ioError e-#endif- when success $- T(expect) () =<< pathIsSymbolicLink "y"+ supportsSymbolicLinks <- supportsSymlinks+ when supportsSymbolicLinks $ do++ createFileLink "x" "y"+ createDirectoryLink "a" "b"++ T.expect _t () =<< pathIsSymbolicLink "y"+ T.expect _t () =<< pathIsSymbolicLink "b"+ T.expectEq _t () "x" =<< getSymbolicLinkTarget "y"+ T.expectEq _t () "a" =<< getSymbolicLinkTarget "b"+ T.expectEq _t () False =<< doesFileExist "y"+ T.expectEq _t () False =<< doesDirectoryExist "b"++ writeFile "x" ""+ createDirectory "a"++ T.expect _t () =<< doesFileExist "y"+ T.expect _t () =<< doesDirectoryExist "b"++ removeFile "y"+ removeDirectoryLink "b"++ T.expectIOErrorType _t () isDoesNotExistError (pathIsSymbolicLink "y")+ T.expectIOErrorType _t () isDoesNotExistError (pathIsSymbolicLink "b")+ T.expectEq _t () False =<< doesFileExist "y"+ T.expectEq _t () False =<< doesDirectoryExist "b"
tests/RemoveDirectoryRecursive001.hs view
@@ -1,9 +1,14 @@ {-# LANGUAGE CPP #-} module RemoveDirectoryRecursive001 where-#include "util.inl"-import System.FilePath ((</>), normalise)+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils (modifyPermissions, symlinkOrCopy)+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>), normalise) import qualified Data.List as List-import TestUtils main :: TestEnv -> IO () main _t = do@@ -12,9 +17,9 @@ -- clean up junk from previous invocations modifyPermissions (tmp "c") (\ p -> p { writable = True })- `catchIOError` \ _ -> return ()+ `catchIOError` \ _ -> pure () removeDirectoryRecursive tmpD- `catchIOError` \ _ -> return ()+ `catchIOError` \ _ -> pure () ------------------------------------------------------------ -- set up@@ -24,40 +29,40 @@ createDirectoryIfMissing True (tmp "a/z") createDirectoryIfMissing True (tmp "b") createDirectoryIfMissing True (tmp "c")- writeFile (tmp "a/x/w/u") "foo"- writeFile (tmp "a/t") "bar"- tryCreateSymbolicLink (normalise "../a") (tmp "b/g")- tryCreateSymbolicLink (normalise "../b") (tmp "c/h")- tryCreateSymbolicLink (normalise "a") (tmp "d")+ writeFile (so (tmp "a/x/w/u")) "foo"+ writeFile (so (tmp "a/t")) "bar"+ symlinkOrCopy (normalise "../a") (tmp "b/g")+ symlinkOrCopy (normalise "../b") (tmp "c/h")+ symlinkOrCopy (normalise "a") (tmp "d") modifyPermissions (tmp "c") (\ p -> p { writable = False }) ------------------------------------------------------------ -- tests - T(expectEq) () [".", "..", "a", "b", "c", "d"] . List.sort =<<+ T.expectEq _t () [".", "..", "a", "b", "c", "d"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a")- T(expectEq) () [".", "..", "g"] . List.sort =<<+ T.expectEq _t () [".", "..", "g"] . List.sort =<< getDirectoryContents (tmp "b")- T(expectEq) () [".", "..", "h"] . List.sort =<<+ T.expectEq _t () [".", "..", "h"] . List.sort =<< getDirectoryContents (tmp "c")- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "d") removeDirectoryRecursive (tmp "d") `catchIOError` \ _ -> removeFile (tmp "d")-#ifdef mingw32_HOST_OS+#if defined(mingw32_HOST_OS) `catchIOError` \ _ -> removeDirectory (tmp "d") #endif - T(expectEq) () [".", "..", "a", "b", "c"] . List.sort =<<+ T.expectEq _t () [".", "..", "a", "b", "c"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a")- T(expectEq) () [".", "..", "g"] . List.sort =<<+ T.expectEq _t () [".", "..", "g"] . List.sort =<< getDirectoryContents (tmp "b")- T(expectEq) () [".", "..", "h"] . List.sort =<<+ T.expectEq _t () [".", "..", "h"] . List.sort =<< getDirectoryContents (tmp "c") removeDirectoryRecursive (tmp "c")@@ -65,25 +70,25 @@ modifyPermissions (tmp "c") (\ p -> p { writable = True }) removeDirectoryRecursive (tmp "c") - T(expectEq) () [".", "..", "a", "b"] . List.sort =<<+ T.expectEq _t () [".", "..", "a", "b"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a")- T(expectEq) () [".", "..", "g"] . List.sort =<<+ T.expectEq _t () [".", "..", "g"] . List.sort =<< getDirectoryContents (tmp "b") removeDirectoryRecursive (tmp "b") - T(expectEq) () [".", "..", "a"] . List.sort =<<+ T.expectEq _t () [".", "..", "a"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a") removeDirectoryRecursive (tmp "a") - T(expectEq) () [".", ".."] . List.sort =<<+ T.expectEq _t () [".", ".."] . List.sort =<< getDirectoryContents tmpD where testName = "removeDirectoryRecursive001"- tmpD = testName ++ ".tmp"+ tmpD = testName <> ".tmp" tmp s = tmpD </> normalise s
tests/RemovePathForcibly.hs view
@@ -1,9 +1,13 @@-{-# LANGUAGE CPP #-} module RemovePathForcibly where-#include "util.inl"-import System.FilePath ((</>), normalise)+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils (hardLinkOrCopy, modifyPermissions, symlinkOrCopy)+import Util (TestEnv)+import qualified Util as T+import System.Directory.Internal+import System.OsPath ((</>), normalise) import qualified Data.List as List-import TestUtils main :: TestEnv -> IO () main _t = do@@ -12,9 +16,9 @@ -- clean up junk from previous invocations modifyPermissions (tmp "c") (\ p -> p { writable = True })- `catchIOError` \ _ -> return ()+ `catchIOError` \ _ -> pure () removePathForcibly tmpD- `catchIOError` \ _ -> return ()+ `catchIOError` \ _ -> pure () ------------------------------------------------------------ -- set up@@ -25,12 +29,12 @@ createDirectoryIfMissing True (tmp "b") createDirectoryIfMissing True (tmp "c") createDirectoryIfMissing True (tmp "f")- writeFile (tmp "a/x/w/u") "foo"- writeFile (tmp "a/t") "bar"- writeFile (tmp "f/s") "qux"- tryCreateSymbolicLink (normalise "../a") (tmp "b/g")- tryCreateSymbolicLink (normalise "../b") (tmp "c/h")- tryCreateSymbolicLink (normalise "a") (tmp "d")+ writeFile (so (tmp "a/x/w/u")) "foo"+ writeFile (so (tmp "a/t")) "bar"+ writeFile (so (tmp "f/s")) "qux"+ symlinkOrCopy (normalise "../a") (tmp "b/g")+ symlinkOrCopy (normalise "../b") (tmp "c/h")+ symlinkOrCopy (normalise "a") (tmp "d") setPermissions (tmp "f/s") emptyPermissions setPermissions (tmp "f") emptyPermissions @@ -40,49 +44,59 @@ removePathForcibly (tmp "f") removePathForcibly (tmp "e") -- intentionally non-existent - T(expectEq) () [".", "..", "a", "b", "c", "d"] . List.sort =<<+ T.expectEq _t () [".", "..", "a", "b", "c", "d"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a")- T(expectEq) () [".", "..", "g"] . List.sort =<<+ T.expectEq _t () [".", "..", "g"] . List.sort =<< getDirectoryContents (tmp "b")- T(expectEq) () [".", "..", "h"] . List.sort =<<+ T.expectEq _t () [".", "..", "h"] . List.sort =<< getDirectoryContents (tmp "c")- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "d") removePathForcibly (tmp "d") - T(expectEq) () [".", "..", "a", "b", "c"] . List.sort =<<+ T.expectEq _t () [".", "..", "a", "b", "c"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a")- T(expectEq) () [".", "..", "g"] . List.sort =<<+ T.expectEq _t () [".", "..", "g"] . List.sort =<< getDirectoryContents (tmp "b")- T(expectEq) () [".", "..", "h"] . List.sort =<<+ T.expectEq _t () [".", "..", "h"] . List.sort =<< getDirectoryContents (tmp "c") removePathForcibly (tmp "c") - T(expectEq) () [".", "..", "a", "b"] . List.sort =<<+ T.expectEq _t () [".", "..", "a", "b"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a")- T(expectEq) () [".", "..", "g"] . List.sort =<<+ T.expectEq _t () [".", "..", "g"] . List.sort =<< getDirectoryContents (tmp "b") removePathForcibly (tmp "b") - T(expectEq) () [".", "..", "a"] . List.sort =<<+ T.expectEq _t () [".", "..", "a"] . List.sort =<< getDirectoryContents tmpD- T(expectEq) () [".", "..", "t", "x", "y", "z"] . List.sort =<<+ T.expectEq _t () [".", "..", "t", "x", "y", "z"] . List.sort =<< getDirectoryContents (tmp "a") removePathForcibly (tmp "a") - T(expectEq) () [".", ".."] . List.sort =<<+ T.expectEq _t () [".", ".."] . List.sort =<< getDirectoryContents tmpD + ----------------------------------------------------------------------+ -- regression test for https://github.com/haskell/directory/issues/135+ + writeFile "hl1" "hardlinked"+ setPermissions "hl1" emptyPermissions+ origPermissions <- getPermissions "hl1"+ hardLinkOrCopy "hl1" "hl2"+ removePathForcibly "hl2"+ T.expectEq _t () origPermissions =<< getPermissions "hl1"+ where testName = "removePathForcibly"- tmpD = testName ++ ".tmp"+ tmpD = testName <> ".tmp" tmp s = tmpD </> normalise s
tests/RenameDirectory.hs view
@@ -1,10 +1,14 @@-{-# LANGUAGE CPP #-} module RenameDirectory where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do createDirectory "a"- T(expectEq) () ["a"] =<< listDirectory "."+ T.expectEq _t () ["a"] =<< listDirectory "." renameDirectory "a" "b"- T(expectEq) () ["b"] =<< listDirectory "."+ T.expectEq _t () ["b"] =<< listDirectory "."
tests/RenameFile001.hs view
@@ -1,15 +1,20 @@-{-# LANGUAGE CPP #-} module RenameFile001 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do writeFile tmp1 contents1- renameFile tmp1 tmp2- T(expectEq) () contents1 =<< readFile tmp2+ renameFile (os tmp1) (os tmp2)+ T.expectEq _t () contents1 =<< readFile tmp2 writeFile tmp1 contents2- renameFile tmp2 tmp1- T(expectEq) () contents1 =<< readFile tmp1+ renameFile (os tmp2) (os tmp1)+ T.expectEq _t () contents1 =<< readFile tmp1 where tmp1 = "tmp1" tmp2 = "tmp2"
tests/RenamePath.hs view
@@ -1,21 +1,26 @@-{-# LANGUAGE CPP #-} module RenamePath where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T main :: TestEnv -> IO () main _t = do createDirectory "a"- T(expectEq) () ["a"] =<< listDirectory "."+ T.expectEq _t () ["a"] =<< listDirectory "." renamePath "a" "b"- T(expectEq) () ["b"] =<< listDirectory "."+ T.expectEq _t () ["b"] =<< listDirectory "." writeFile tmp1 contents1- renamePath tmp1 tmp2- T(expectEq) () contents1 =<< readFile tmp2+ renamePath (os tmp1) (os tmp2)+ T.expectEq _t () contents1 =<< readFile tmp2 writeFile tmp1 contents2- renamePath tmp2 tmp1- T(expectEq) () contents1 =<< readFile tmp1+ renamePath (os tmp2) (os tmp1)+ T.expectEq _t () contents1 =<< readFile tmp1 where tmp1 = "tmp1"
− tests/Safe.hs
@@ -1,7 +0,0 @@--- Verify that System.Directory is indeed Safe (regression test for issue #30)-{-# LANGUAGE Safe #-}-module Safe where-import System.Directory ()--main :: a -> IO ()-main _ = return ()
+ tests/Simplify.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE CPP #-}+module Simplify where+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal (simplifyWindows)+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import System.OsPath (normalise)++main :: TestEnv -> IO ()+main _t = do+ T.expectIOErrorType _t () (const True) (setCurrentDirectory "")+ T.expectEq _t () (simplifyWindows "") ""+ T.expectEq _t () (simplifyWindows ".") "."+ T.expectEq _t () (simplifyWindows "a///b") (normalise "a/b")+ T.expectEq _t () (simplifyWindows "./a//b") (normalise "a/b")+ T.expectEq _t () (simplifyWindows "a/../../../b/.") (normalise "../../b")+ T.expectEq _t () (simplifyWindows "a/.././b/./") (normalise "b/")+ T.expectEq _t () (simplifyWindows "C:/a/../b") (normalise "C:/b")+ T.expectEq _t () (simplifyWindows "\\\\?\\./a\\../b") "\\\\?\\./a\\../b"+ T.expectEq _t () (simplifyWindows "C:/a") (normalise "C:/a")+ T.expectEq _t () (simplifyWindows "/a") (normalise "/a")+#ifdef mingw32_HOST_OS+ T.expectEq _t () (simplifyWindows "C:") "C:"+ T.expectEq _t () (simplifyWindows "c:\\\\") "C:\\"+ T.expectEq _t () (simplifyWindows "C:.") "C:"+ T.expectEq _t () (simplifyWindows "C:.\\\\") "C:.\\"+ T.expectEq _t () (simplifyWindows "C:..") "C:.."+ T.expectEq _t () (simplifyWindows "C:..\\") "C:..\\"+ T.expectEq _t () (simplifyWindows "C:\\.\\") "C:\\"+ T.expectEq _t () (simplifyWindows "C:\\a") "C:\\a"+ T.expectEq _t () (simplifyWindows "C:\\a\\\\b\\") "C:\\a\\b\\"+ T.expectEq _t () (simplifyWindows "\\\\a\\b") "\\\\a\\b"+ T.expectEq _t () (simplifyWindows "//a\\b/c/./d") "\\\\a\\b/c/./d"+ T.expectEq _t () (simplifyWindows "/.") "\\"+ T.expectEq _t () (simplifyWindows "/./") "\\"+ T.expectEq _t () (simplifyWindows "/../") "\\"+ T.expectEq _t () (simplifyWindows "\\a\\.") "\\a"+ T.expectEq _t () (simplifyWindows "//?") "\\\\?"+ T.expectEq _t () (simplifyWindows "//?\\") "\\\\?\\"+ T.expectEq _t () (simplifyWindows "//?/a/b") "\\\\?\\a/b"+#endif
tests/T8482.hs view
@@ -1,18 +1,23 @@-{-# LANGUAGE CPP #-} module T8482 where-#include "util.inl"+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T -tmp1 :: FilePath+tmp1 :: OsPath tmp1 = "T8482.tmp1" -testdir :: FilePath+testdir :: OsPath testdir = "T8482.dir" main :: TestEnv -> IO () main _t = do- writeFile tmp1 "hello"+ writeFile (so tmp1) "hello" createDirectory testdir- T(expectIOErrorType) () (is InappropriateType) (renameFile testdir tmp1)- T(expectIOErrorType) () (is InappropriateType) (renameFile tmp1 testdir)- T(expectIOErrorType) () (is InappropriateType) (renameFile tmp1 ".")+ T.expectIOErrorType _t () (is InappropriateType) (renameFile testdir tmp1)+ T.expectIOErrorType _t () (is InappropriateType) (renameFile tmp1 testdir)+ T.expectIOErrorType _t () (is InappropriateType) (renameFile tmp1 ".") where is t = (== t) . ioeGetErrorType
tests/TestUtils.hs view
@@ -1,38 +1,28 @@-{-# LANGUAGE CPP, ForeignFunctionInterface #-}+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wno-orphans #-}+-- | Utility functions specific to 'directory' tests module TestUtils ( copyPathRecursive- , createSymbolicLink+ , hardLinkOrCopy , modifyPermissions- , tryCreateSymbolicLink+ , symlinkOrCopy+ , supportsSymlinks ) where import Prelude () import System.Directory.Internal.Prelude-import System.Directory-import System.FilePath ((</>))-#ifdef mingw32_HOST_OS-import System.FilePath (takeDirectory)+import System.Directory.Internal+import System.Directory.OsPath+import Data.String (IsString(fromString))+import System.OsPath ((</>), normalise, takeDirectory)+#if defined(mingw32_HOST_OS) import qualified System.Win32 as Win32-#else-import System.Posix (createSymbolicLink) #endif -#ifdef mingw32_HOST_OS-# if defined i386_HOST_ARCH-# define WINAPI stdcall-# elif defined x86_64_HOST_ARCH-# define WINAPI ccall-# else-# error unknown architecture-# endif-foreign import WINAPI unsafe "windows.h CreateSymbolicLinkW"- c_CreateSymbolicLink :: Ptr CWchar -> Ptr CWchar -> CULong -> IO CUChar-#endif- -- | @'copyPathRecursive' path@ copies an existing file or directory at -- /path/ together with its contents and subdirectories. -- -- Warning: mostly untested and might not handle symlinks correctly.-copyPathRecursive :: FilePath -> FilePath -> IO ()+copyPathRecursive :: OsPath -> OsPath -> IO () copyPathRecursive source dest = (`ioeSetLocation` "copyPathRecursive") `modifyIOError` do dirExists <- doesDirectoryExist source@@ -44,42 +34,77 @@ [(source </> x, dest </> x) | x <- contents] else copyFile source dest -modifyPermissions :: FilePath -> (Permissions -> Permissions) -> IO ()+modifyPermissions :: OsPath -> (Permissions -> Permissions) -> IO () modifyPermissions path modify = do permissions <- getPermissions path setPermissions path (modify permissions) -#ifdef mingw32_HOST_OS-createSymbolicLink :: String -> String -> IO ()-createSymbolicLink target link =- (`ioeSetLocation` "createSymbolicLink") `modifyIOError` do- isDir <- (fromIntegral . fromEnum) `fmap`- doesDirectoryExist (takeDirectory link </> target)- let target' = fixSlash <$> target- withCWString target' $ \ pTarget ->- withCWString link $ \ pLink -> do- status <- c_CreateSymbolicLink pLink pTarget isDir- if status == 0- then do- errCode <- Win32.getLastError- if errCode == c_ERROR_PRIVILEGE_NOT_HELD- then ioError . (`ioeSetErrorString` permissionErrorMsg) $- mkIOError permissionErrorType "" Nothing (Just link)- else Win32.failWith "createSymbolicLink" errCode- else return ()- where c_ERROR_PRIVILEGE_NOT_HELD = 0x522- permissionErrorMsg = "no permission to create symbolic links"- fixSlash '/' = '\\'- fixSlash c = c+-- | On Windows, the handler is called if symbolic links are unsupported or+-- the user lacks the necessary privileges to create them. On other+-- platforms, the handler is never run.+handleSymlinkUnavail+ :: IO a -- ^ handler+ -> IO a -- ^ arbitrary action+ -> IO a+handleSymlinkUnavail _handler action = action+#if defined(mingw32_HOST_OS)+ `catchIOError` \ e ->+ case ioeGetErrorType e of+ UnsupportedOperation -> _handler+ _ | isIllegalOperation e || isPermissionError e -> _handler+ _ -> ioError e #endif --- | Attempt to create a symbolic link. On Windows, this falls back to--- copying if forbidden due to Group Policies.-tryCreateSymbolicLink :: FilePath -> FilePath -> IO ()-tryCreateSymbolicLink target link = createSymbolicLink target link-#ifdef mingw32_HOST_OS+-- | Create a hard link on Posix. On Windows, it just copies.+hardLinkOrCopy :: OsPath -> OsPath -> IO ()+#if defined(mingw32_HOST_OS)+hardLinkOrCopy = copyPathRecursive+#else+hardLinkOrCopy = createHardLink+#endif++-- | Create a symbolic link. On Windows, this falls back to copying if+-- forbidden by Group Policy or is not supported. On other platforms, there+-- is no fallback. Also, automatically detect if the source is a file or a+-- directory and create the appropriate type of link.+symlinkOrCopy :: OsPath -> OsPath -> IO ()+symlinkOrCopy target link = do+ let fullTarget = takeDirectory link </> target+ handleSymlinkUnavail (copyPathRecursive fullTarget link) $ do+ isDir <- doesDirectoryExist fullTarget+ (if isDir then createDirectoryLink else createFileLink)+ (normalise target)+ link++supportsSymlinks :: IO Bool+supportsSymlinks = do+ canCreate <- supportsLinkCreation+ canDeref <- supportsLinkDeref+ pure (canCreate && canDeref)++-- | On Windows, test if symbolic link creation is supported and the user has+-- the necessary privileges to create them. On other platforms, this always+-- returns 'True'.+supportsLinkCreation :: IO Bool+supportsLinkCreation = do+ let path = os "_symlink_test.tmp"+ isSupported <- handleSymlinkUnavail (pure False) $ do+ True <$ createFileLink path path+ when isSupported $ do+ removeFile path+ pure isSupported++supportsLinkDeref :: IO Bool+supportsLinkDeref = do+#if defined(mingw32_HOST_OS)+ True <$ win32_getFinalPathNameByHandle Win32.nullHANDLE 0 `catchIOError` \ e ->- if isPermissionError e- then copyPathRecursive (takeDirectory link </> target) link- else ioError e+ case ioeGetErrorType e of+ UnsupportedOperation -> pure False+ _ -> pure True+#else+ pure True #endif++instance IsString OsString where+ fromString = os
tests/Util.hs view
@@ -1,10 +1,15 @@ {-# LANGUAGE BangPatterns #-}+-- | A rudimentary testing framework module Util where import Prelude () import System.Directory.Internal.Prelude-import System.Directory+import System.Directory.Internal+import System.Directory.OsPath import Data.Time.Clock (NominalDiffTime, UTCTime, diffUTCTime)-import System.FilePath ((</>), normalise)+import GHC.Stack (CallStack, HasCallStack, callStack, getCallStack, srcLocFile,+ srcLocStartLine)+import System.Environment (getEnvironment, setEnv, unsetEnv)+import System.OsPath ((</>), decodeFS, encodeFS, normalise) import qualified Data.List as List modifyIORef' :: IORef a -> (a -> a) -> IO ()@@ -24,7 +29,7 @@ result <- timeout (round (1000000 * time)) action case result of Nothing -> throwIO (userError "timed out")- Just x -> return x+ Just x -> pure x data TestEnv = TestEnv@@ -35,7 +40,7 @@ } printInfo :: TestEnv -> [String] -> IO ()-printInfo TestEnv{testSilent = True} _ = return ()+printInfo TestEnv{testSilent = True} _ = pure () printInfo TestEnv{testSilent = False} msg = do putStrLn (List.intercalate ": " msg) hFlush stdout@@ -58,69 +63,72 @@ checkEither t prefix (Right msg) = printInfo t (prefix <> msg) checkEither t prefix (Left msg) = printFailure t (prefix <> msg) -showContext :: Show a => String -> Integer -> a -> String-showContext file line context =- file <> ":" <> show line <>+showContext :: Show a => CallStack -> a -> String+showContext stack context =+ case getCallStack stack of+ (_, l) : _ -> srcLocFile l <> ":" <> show (srcLocStartLine l)+ [] -> "<unknown caller>"+ <> case show context of "()" -> "" s -> ":" <> s -inform :: TestEnv -> String -> Integer -> String -> IO ()-inform t file line msg =- printInfo t [showContext file line (), msg]+inform :: HasCallStack => TestEnv -> String -> IO ()+inform t msg =+ printInfo t [showContext callStack (), msg] -expect :: Show a => TestEnv -> String -> Integer -> a -> Bool -> IO ()-expect t file line context x =++expect :: (HasCallStack, Show a) => TestEnv -> a -> Bool -> IO ()+expect t context x = check t x- [showContext file line context]+ [showContext callStack context] ["True"] ["False, but True was expected"] -expectEq :: (Eq a, Show a, Show b) =>- TestEnv -> String -> Integer -> b -> a -> a -> IO ()-expectEq t file line context x y =+expectEq :: (HasCallStack, Eq a, Show a, Show b) =>+ TestEnv -> b -> a -> a -> IO ()+expectEq t context x y = check t (x == y)- [showContext file line context]+ [showContext callStack context] [show x <> " equals " <> show y] [show x <> " is not equal to " <> show y] -expectNe :: (Eq a, Show a, Show b) =>- TestEnv -> String -> Integer -> b -> a -> a -> IO ()-expectNe t file line context x y =+expectNe :: (HasCallStack, Eq a, Show a, Show b) =>+ TestEnv -> b -> a -> a -> IO ()+expectNe t context x y = check t (x /= y)- [showContext file line context]+ [showContext callStack context] [show x <> " is not equal to " <> show y] [show x <> " equals " <> show y] -expectNear :: (Num a, Ord a, Show a, Show b) =>- TestEnv -> String -> Integer -> b -> a -> a -> a -> IO ()-expectNear t file line context x y diff =+expectNear :: (HasCallStack, Num a, Ord a, Show a, Show b) =>+ TestEnv -> b -> a -> a -> a -> IO ()+expectNear t context x y diff = check t (abs (x - y) <= diff)- [showContext file line context]+ [showContext callStack context] [show x <> " is near " <> show y] [show x <> " is not near " <> show y] -expectNearTime :: Show a =>- TestEnv -> String -> Integer -> a ->+expectNearTime :: (HasCallStack, Show a) =>+ TestEnv -> a -> UTCTime -> UTCTime -> NominalDiffTime -> IO ()-expectNearTime t file line context x y diff =+expectNearTime t context x y diff = check t (abs (diffUTCTime x y) <= diff)- [showContext file line context]+ [showContext callStack context] [show x <> " is near " <> show y] [show x <> " is not near " <> show y] -expectIOErrorType :: Show a =>- TestEnv -> String -> Integer -> a- -> (IOError -> Bool) -> IO b -> IO ()-expectIOErrorType t file line context which action = do+expectIOErrorType :: (HasCallStack, Show a) =>+ TestEnv -> a -> (IOError -> Bool) -> IO b -> IO ()+expectIOErrorType t context which action = do result <- try action- checkEither t [showContext file line context] $ case result of+ checkEither t [showContext callStack context] $ case result of Left e | which e -> Right ["got expected exception (" <> show e <> ")"] | otherwise -> Left ["got wrong exception: ", show e] Right _ -> Left ["did not throw an exception"] -- | Traverse the directory tree in preorder.-preprocessPathRecursive :: (FilePath -> IO ()) -> FilePath -> IO ()+preprocessPathRecursive :: (OsPath -> IO ()) -> OsPath -> IO () preprocessPathRecursive f path = do dirExists <- doesDirectoryExist path if dirExists@@ -129,26 +137,76 @@ f path when (not isLink) $ do names <- listDirectory path- traverse_ (preprocessPathRecursive f) ((path </>) <$> names)+ for_ ((path </>) <$> names) (preprocessPathRecursive f) else do f path -withNewDirectory :: Bool -> FilePath -> IO a -> IO a+withNewDirectory :: Bool -> OsPath -> IO a -> IO a withNewDirectory keep dir action = do dir' <- makeAbsolute dir bracket_ (createDirectoryIfMissing True dir') (cleanup dir') action- where cleanup dir' | keep = return ()+ where cleanup dir' | keep = pure () | otherwise = removePathForcibly dir' -isolateWorkingDirectory :: Bool -> FilePath -> IO a -> IO a+diffAsc' :: (j -> k -> Ordering)+ -> (u -> v -> Bool)+ -> [(j, u)]+ -> [(k, v)]+ -> ([(j, u)], [(k, v)])+diffAsc' cmp eq = go id id+ where+ go a b [] [] = (a [], b [])+ go a b jus [] = go (a . (jus <>)) b [] []+ go a b [] kvs = go a (b . (kvs <>)) [] []+ go a b jus@((j, u) : jus') kvs@((k, v) : kvs') =+ case cmp j k of+ LT -> go (a . ((j, u) :)) b jus' kvs+ GT -> go a (b . ((k, v) :)) jus kvs'+ EQ | eq u v -> go a b jus' kvs'+ | otherwise -> go (a . ((j, u) :)) (b . ((k, v) :)) jus' kvs'++diffAsc :: (Ord k, Eq v) => [(k, v)] -> [(k, v)] -> ([(k, v)], [(k, v)])+diffAsc = diffAsc' compare (==)++-- Environment variables may be sensitive, so don't log their values.+scrubEnv :: (String, String) -> (String, String)+scrubEnv (k, v)+ -- Allowlist for nonsensitive variables.+ | k `elem` ["XDG_CONFIG_HOME"] = (k, v)+ | otherwise = (k, "<" <> show (length v) <> " chars>")++isolateEnvironment :: IO a -> IO a+isolateEnvironment = bracket getEnvs setEnvs . const+ where+ -- Duplicate environment variables will cause problems for this code.+ -- https://github.com/haskell/cabal/issues/10718+ getEnvs = List.sort . filter (\(k, _) -> not (null k)) <$> getEnvironment+ setEnvs target = do+ current <- getEnvs+ let (deletions, insertions) = diffAsc current target+ updateEnvs deletions insertions+ new <- getEnvs+ when (target /= new) $ do+ let (missing, extraneous) = diffAsc target new+ throwIO (userError ("isolateEnvironment.setEnvs failed:" <>+ " deletions=" <> show (scrubEnv <$> deletions) <>+ " insertions=" <> show (scrubEnv <$> insertions) <>+ " missing=" <> show (scrubEnv <$> missing) <>+ " extraneous=" <> show (scrubEnv <$> extraneous)))+ updateEnvs deletions insertions = do+ for_ deletions (unsetEnv . fst)+ for_ insertions (uncurry setEnv)++isolateWorkingDirectory :: Bool -> OsPath -> IO a -> IO a isolateWorkingDirectory keep dir action = do- when (normalise dir `List.elem` [".", "./"]) $+ normalisedDir <- decodeFS (normalise dir)+ when (normalisedDir `List.elem` [".", "./"]) $ throwIO (userError ("isolateWorkingDirectory cannot be used " <> "with current directory")) dir' <- makeAbsolute dir removePathForcibly dir'- withNewDirectory keep dir' $- withCurrentDirectory dir' $+ withNewDirectory keep dir' $ do+ withCurrentDirectory dir' $ do action run :: TestEnv -> String -> (TestEnv -> IO ()) -> IO ()@@ -156,12 +214,14 @@ result <- tryAny (action t) case result of Left e -> check t False [name] [] ["exception", show e]- Right () -> return ()+ Right () -> pure () isolatedRun :: TestEnv -> String -> (TestEnv -> IO ()) -> IO ()-isolatedRun t@TestEnv{testKeepDirs = keep} name =- run t name .- (isolateWorkingDirectory keep ("dist/test-" <> name <> ".tmp") .)+isolatedRun t@TestEnv{testKeepDirs = keep} name action = do+ workDir <- encodeFS ("dist-newstyle/tmp/test-" <> name <> ".tmp")+ run t name (isolate workDir . action)+ where+ isolate workDir = isolateEnvironment . isolateWorkingDirectory keep workDir tryRead :: Read a => String -> Maybe a tryRead s =@@ -199,7 +259,7 @@ , testArgs = args } action t- n <- readIORef (counter)+ n <- readIORef counter unless (n == 0) $ do putStrLn ("[" <> show n <> " failures]") hFlush stdout
tests/WithCurrentDirectory.hs view
@@ -1,22 +1,27 @@-{-# LANGUAGE CPP #-} module WithCurrentDirectory where-#include "util.inl"-import System.FilePath ((</>))+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.Internal+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import System.OsPath ((</>)) import qualified Data.List as List main :: TestEnv -> IO () main _t = do createDirectory dir -- Make sure we're starting empty- T(expectEq) () [] . List.sort =<< listDirectory dir+ T.expectEq _t () [] . List.sort =<< listDirectory dir cwd <- getCurrentDirectory- withCurrentDirectory dir (writeFile testfile contents)+ withCurrentDirectory dir (writeFile (so testfile) contents) -- Are we still in original directory?- T(expectEq) () cwd =<< getCurrentDirectory+ T.expectEq _t () cwd =<< getCurrentDirectory -- Did the test file get created?- T(expectEq) () [testfile] . List.sort =<< listDirectory dir+ T.expectEq _t () [testfile] . List.sort =<< listDirectory dir -- Does the file contain what we expected to write?- T(expectEq) () contents =<< readFile (dir </> testfile)+ T.expectEq _t () contents =<< readFile (so (dir </> testfile)) where testfile = "testfile" contents = "some data\n"
+ tests/Xdg.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE CPP #-}+module Xdg where+import Prelude ()+import System.Directory.Internal.Prelude+import System.Directory.OsPath+import TestUtils ()+import Util (TestEnv)+import qualified Util as T+import qualified Data.List as List+import System.Environment (setEnv, unsetEnv)+import System.FilePath (searchPathSeparator)+#if !defined(mingw32_HOST_OS)+import System.OsPath ((</>))+#endif++main :: TestEnv -> IO ()+main _t = do++ -- smoke tests+ _ <- getXdgDirectoryList XdgDataDirs+ _ <- getXdgDirectoryList XdgConfigDirs++ T.expect _t () True -- avoid warnings about redundant imports++ -- setEnv, unsetEnv require base 4.7.0.0++#if !defined(mingw32_HOST_OS)+ unsetEnv "XDG_CONFIG_HOME"+ home <- getHomeDirectory+ T.expectEq _t () (home </> ".config/mow") =<< getXdgDirectory XdgConfig "mow"+#endif++ -- unset variables, so env doesn't affect test running+ unsetEnv "XDG_DATA_HOME"+ unsetEnv "XDG_CONFIG_HOME"+ unsetEnv "XDG_CACHE_HOME"+ unsetEnv "XDG_STATE_HOME"+ xdgData <- getXdgDirectory XdgData "ff"+ xdgConfig <- getXdgDirectory XdgConfig "oo"+ xdgCache <- getXdgDirectory XdgCache "rk"+ xdgState <- getXdgDirectory XdgState "aa"++ -- non-absolute paths are ignored, and the fallback is used+ setEnv "XDG_DATA_HOME" "ar"+ setEnv "XDG_CONFIG_HOME" "aw"+ setEnv "XDG_CACHE_HOME" "ba"+ setEnv "XDG_STATE_HOME" "uw"+ T.expectEq _t () xdgData =<< getXdgDirectory XdgData "ff"+ T.expectEq _t () xdgConfig =<< getXdgDirectory XdgConfig "oo"+ T.expectEq _t () xdgCache =<< getXdgDirectory XdgCache "rk"+ T.expectEq _t () xdgState =<< getXdgDirectory XdgState "aa"++ unsetEnv "XDG_CONFIG_DIRS"+ unsetEnv "XDG_DATA_DIRS"+ _xdgConfigDirs <- getXdgDirectoryList XdgConfigDirs+ _xdgDataDirs <- getXdgDirectoryList XdgDataDirs++#if !defined(mingw32_HOST_OS)+ T.expectEq _t () ["/etc/xdg"] _xdgConfigDirs+ T.expectEq _t () ["/usr/local/share/", "/usr/share/"] _xdgDataDirs+#endif++ setEnv "XDG_DATA_DIRS" (List.intercalate [searchPathSeparator] ["/a", "/b"])+ setEnv "XDG_CONFIG_DIRS" (List.intercalate [searchPathSeparator] ["/c", "/d"])+ T.expectEq _t () ["/a", "/b"] =<< getXdgDirectoryList XdgDataDirs+ T.expectEq _t () ["/c", "/d"] =<< getXdgDirectoryList XdgConfigDirs
− tests/util.inl
@@ -1,7 +0,0 @@-#define T(f) (T.f _t __FILE__ __LINE__)--import Prelude ()-import System.Directory.Internal.Prelude-import System.Directory-import Util (TestEnv)-import qualified Util as T