1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
--- Library for accessing the directory structure of the
--- underlying operating system.
---
--- @author Michael Hanus
--- @version January 2013
--- @category general

module Directory
  ( doesFileExist, doesDirectoryExist, fileSize, getModificationTime
  , getCurrentDirectory, setCurrentDirectory
  , getDirectoryContents, createDirectory, createDirectoryIfMissing
  , removeDirectory, renameDirectory
  , getHomeDirectory, getTemporaryDirectory
  , getAbsolutePath
  , removeFile, renameFile, copyFile
  ) where

import FilePath (FilePath, (</>), splitDirectories, isAbsolute, normalise)
import List     (isPrefixOf, scanl1, last)
import System   (getEnviron, isWindows)
import Time     (ClockTime)


--- Returns true if the argument is the name of an existing file.
doesFileExist :: FilePath -> IO Bool
doesFileExist fname = prim_doesFileExist $## fname

prim_doesFileExist :: FilePath -> IO Bool
prim_doesFileExist external

--- Returns true if the argument is the name of an existing directory.
doesDirectoryExist :: FilePath -> IO Bool
doesDirectoryExist dir = prim_doesDirectoryExist $## dir

prim_doesDirectoryExist :: FilePath -> IO Bool
prim_doesDirectoryExist external

--- Returns the size of the file.
fileSize :: FilePath -> IO Int
fileSize fname = prim_fileSize $## fname

prim_fileSize :: FilePath -> IO Int
prim_fileSize external

--- Returns the modification time of the file.
getModificationTime :: FilePath -> IO ClockTime
getModificationTime fname = prim_getModificationTime $## fname

prim_getModificationTime :: FilePath -> IO ClockTime
prim_getModificationTime external

--- Returns the current working directory.
getCurrentDirectory :: IO FilePath
getCurrentDirectory external

--- Sets the current working directory.
setCurrentDirectory :: FilePath -> IO ()
setCurrentDirectory dir = prim_setCurrentDirectory $## dir

prim_setCurrentDirectory :: FilePath -> IO ()
prim_setCurrentDirectory external

--- Returns the list of all entries in a directory.
getDirectoryContents :: FilePath -> IO [FilePath]
getDirectoryContents dir = prim_getDirectoryContents $## dir

prim_getDirectoryContents :: FilePath -> IO [FilePath]
prim_getDirectoryContents external

--- Creates a new directory with the given name.
createDirectory :: FilePath -> IO ()
createDirectory dir = prim_createDirectory $## dir

prim_createDirectory :: FilePath -> IO ()
prim_createDirectory external

--- Creates a new directory with the given name if it does not already exist.
--- If the first parameter is `True` it will also create all missing
--- parent directories.
createDirectoryIfMissing :: Bool -> FilePath -> IO ()
createDirectoryIfMissing createParents path
  = if createParents then createDirs parents
                     else createDirs [last parents]
 where
  parents = scanl1 (</>) $ splitDirectories $ path

  createDirs []     = done
  createDirs (d:ds) = do
    exists <- doesDirectoryExist d
    if exists then done else createDirectory d
    createDirs ds

--- Deletes a directory from the file system.
removeDirectory :: FilePath -> IO ()
removeDirectory dir = prim_removeDirectory $## dir

prim_removeDirectory :: FilePath -> IO ()
prim_removeDirectory external

--- Renames a directory.
renameDirectory :: FilePath -> FilePath -> IO ()
renameDirectory dir1 dir2 = (prim_renameDirectory $## dir1) $## dir2

prim_renameDirectory :: FilePath -> FilePath -> IO ()
prim_renameDirectory external

--- Returns the home directory of the current user.
getHomeDirectory :: IO FilePath
getHomeDirectory = if isWindows
                     then getEnviron "USERPROFILE"
                     else getEnviron "HOME"

--- Returns the temporary directory of the operating system.
getTemporaryDirectory :: IO FilePath
getTemporaryDirectory = if isWindows then getEnviron "TMP" else return "/tmp"

--- Convert a path name into an absolute one.
--- For instance, a leading `~` is replaced by the current home directory.
getAbsolutePath :: FilePath -> IO FilePath
getAbsolutePath path
  | isAbsolute path        = return (normalise path)
  | path == "~"            = getHomeDirectory
  | "~/" `isPrefixOf` path = do homedir <- getHomeDirectory
                                return (normalise (homedir </> drop 2 path))
  | otherwise              = do curdir <- getCurrentDirectory
                                return (normalise (curdir </> path))

--- Deletes a file from the file system.
removeFile :: FilePath -> IO ()
removeFile file = prim_removeFile $## file

prim_removeFile :: FilePath -> IO ()
prim_removeFile external

--- Renames a file.
renameFile :: FilePath -> FilePath -> IO ()
renameFile file1 file2 = (prim_renameFile $## file1) $## file2

prim_renameFile :: FilePath -> FilePath -> IO ()
prim_renameFile external

--- Copy the contents from one file to another file
copyFile :: FilePath -> FilePath -> IO ()
copyFile src dest = readFile src >>= writeFile dest