X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=System%2FDirectory.hs;h=78dd94ccc0b42f988b69f12267484f05a081c9cb;hb=3cc1f5d185caf783013bbfe4858a1ed09b3329e0;hp=39ca47f271efb1f523363c5d23a2a20e723183f0;hpb=cabbe6e5fc458473162345543f55bad0d9faa892;p=haskell-directory.git diff --git a/System/Directory.hs b/System/Directory.hs index 39ca47f..78dd94c 100644 --- a/System/Directory.hs +++ b/System/Directory.hs @@ -25,10 +25,17 @@ module System.Directory , getCurrentDirectory -- :: IO FilePath , setCurrentDirectory -- :: FilePath -> IO () + -- * Pre-defined directories + , getHomeDirectory + , getAppUserDataDirectory + , getUserDocumentsDirectory + -- * Actions on files , removeFile -- :: FilePath -> IO () , renameFile -- :: FilePath -> FilePath -> IO () +#ifdef __GLASGOW_HASKELL__ , copyFile -- :: FilePath -> FilePath -> IO () +#endif -- * Existence tests , doesFileExist -- :: FilePath -> IO Bool @@ -56,6 +63,13 @@ module System.Directory #ifdef __NHC__ import Directory +getHomeDirectory :: IO FilePath +getHomeDirectory = getEnv "HOME" +getAppUserDataDirectory :: String -> IO FilePath +getAppUserDataDirectory appName = do path <- getEnv "HOME" + return (path++'/':'.':appName) +getUserDocumentsDirectory :: IO FilePath +getUserDocumentsDirectory= getEnv "HOME" #elif defined(__HUGS__) import Hugs.Directory #else @@ -76,6 +90,10 @@ import Foreign.C import GHC.IOBase ( IOException(..), IOErrorType(..), ioException ) #endif +#ifndef mingw32_TARGET_OS +import System.Environment +#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 @@ -435,7 +453,7 @@ If the /new/ file already exists, it is atomically replaced by the /old/ file. Neither path may refer to an existing directory. -} copyFile :: FilePath -> FilePath -> IO () -copyFile fromFPath toFPath = handle (changeFunName) $ +copyFile fromFPath toFPath = (bracket (openBinaryFile fromFPath ReadMode) hClose $ \hFrom -> bracket (openBinaryFile toFPath WriteMode) hClose $ \hTo -> allocaBytes bufferSize $ \buffer -> @@ -444,7 +462,6 @@ copyFile fromFPath toFPath = handle (changeFunName) $ bufferSize = 1024 changeFunName (IOError h iot fun str mb_fp) = IOError h iot "copyFile" str mb_fp - changeFunName e = e copyContents hFrom hTo buffer = do count <- hGetBuf hFrom buffer bufferSize @@ -601,6 +618,124 @@ setCurrentDirectory path = do throwErrnoIfMinus1Retry_ "setCurrentDirectory" (c_chdir s) -- ToDo: add path to error +{- | 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 '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:/Documents And Settings/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 = +#ifdef mingw32_TARGET_OS + allocaBytes long_path_size $ \pPath -> do + r <- c_SHGetFolderPath nullPtr csidl_PROFILE nullPtr 0 pPath + if (r < 0) + then c_SHGetFolderPath nullPtr csidl_WINDOWS nullPtr 0 pPath + else return 0 + peekCString pPath +#else + getEnv "HOME" +#endif + +{- | Returns the pathname of a directory in which application-specific +data for the current user can be stored. The result of +'getAppUserDataDirectory' for a given application is specific to +the current user. + +The argument should be the name of the application, which will be used +to construct the pathname (so avoid using unusual characters that +might result in an invalid pathname). + +Note: the directory may not actually exist, and may need to be created +first. It is expected that the parent directory exists and is +writable. + +On Unix, this function returns @$HOME\/.appName@. On Windows, a +typical path might be + +> C:/Documents And Settings/user/Application Data/appName + +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 :: String -> IO FilePath +getAppUserDataDirectory appName = do +#ifdef mingw32_TARGET_OS + allocaBytes long_path_size $ \pPath -> do + r <- c_SHGetFolderPath nullPtr csidl_APPDATA nullPtr 0 pPath + s <- peekCString pPath + 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 '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:/Documents and Settings/user/My 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 +#ifdef mingw32_TARGET_OS + allocaBytes long_path_size $ \pPath -> do + r <- c_SHGetFolderPath nullPtr csidl_PERSONAL nullPtr 0 pPath + peekCString pPath +#else + getEnv "HOME" +#endif + +#ifdef mingw32_TARGET_OS +foreign import stdcall unsafe "SHGetFolderPath" + c_SHGetFolderPath :: Ptr () + -> CInt + -> Ptr () + -> CInt + -> CString + -> IO CInt +foreign import ccall unsafe "__hscore_CSIDL_PROFILE" csidl_PROFILE :: CInt +foreign import ccall unsafe "__hscore_CSIDL_APPDATA" csidl_APPDATA :: CInt +foreign import ccall unsafe "__hscore_CSIDL_WINDOWS" csidl_WINDOWS :: CInt +foreign import ccall unsafe "__hscore_CSIDL_PERSONAL" csidl_PERSONAL :: CInt +#endif + {- |The operation 'doesDirectoryExist' returns 'True' if the argument file exists and is a directory, and 'False' otherwise. -}