module Halfs.Directory (Directory(..), getChildrenInodeNums, addChild,
removeChild, getChildWithName, getChildrenNames,
filePathsNoDots, hasChild, DirectoryMap,
dirInodeNum,
DirectoryCache(..), emptyDirectoryCache,
addDirectoryToCache, getDirectoryFromCache,
directoryCacheToList, dirCacheDirty,
markDirectoryCacheClean, rmDirectoryFromCache)
where
import Halfs.Inode(Inode(..), InodeMetadata(..), inodeAddLink)
import Halfs.FileHandle (FileHandle, fhInodeNum)
import Data.Integral (INInt)
--base
import Data.Map(Map)
import qualified Data.Map as Map
import Control.Exception(assert)
type DirectoryMap = Map String INInt
data Directory = Directory {dirFile :: FileHandle
,dirContents :: DirectoryMap
,dirDirty :: Bool
}
dirInodeNum :: Directory -> INInt
dirInodeNum d = fhInodeNum $ dirFile d
addChild :: Directory
-> Inode
-> String
-> Maybe (Directory, Inode)
addChild (Directory dirFH theContents _) inode name =
case Map.lookup name theContents of
Just _ -> Nothing
Nothing -> Just ((Directory dirFH (Map.insert name
(assert (inodeNum > 0) inodeNum)
theContents)
True
,inodeAddLink inode))
where inodeNum = inode_num $ metaData inode
hasChild :: Directory -> String -> Bool
hasChild Directory{dirContents=theMap} s
= Map.member s theMap
removeChild :: Directory -> String -> Directory
removeChild (Directory f c _) k
= Directory f (Map.delete k c) True
getChildrenInodeNums :: Directory -> [INInt]
getChildrenInodeNums = Map.elems . dirContents
getChildrenNames :: Directory -> [String]
getChildrenNames = Map.keys . dirContents
getChildWithName :: Directory -> String -> Maybe INInt
getChildWithName dir str
= let e = Map.lookup str (dirContents dir)
in assert (notLEZ e) e
where notLEZ Nothing = True
notLEZ (Just n) = n > 0
filePathsNoDots :: [FilePath] -> [FilePath]
filePathsNoDots = filter (\x -> (x /= ".") && (x /= ".."))
data DirectoryCache = DirectoryCache { dirCacheDirty :: Bool
, _dirCache :: Map INInt Directory}
emptyDirectoryCache :: DirectoryCache
emptyDirectoryCache = DirectoryCache False Map.empty
directoryCacheToList :: DirectoryCache -> [Directory]
directoryCacheToList (DirectoryCache _ c) = Map.elems c
addDirectoryToCache :: DirectoryCache -> Directory -> DirectoryCache
addDirectoryToCache (DirectoryCache cacheDirty c) d
= DirectoryCache (if dirDirty d
then True
else cacheDirty)
(Map.insert (dirInodeNum d) d c)
markDirectoryCacheClean :: DirectoryCache -> DirectoryCache
markDirectoryCacheClean (DirectoryCache _ c)
= DirectoryCache False c
getDirectoryFromCache :: DirectoryCache -> INInt -> Maybe Directory
getDirectoryFromCache (DirectoryCache _ c) i
= Map.lookup i c
rmDirectoryFromCache :: DirectoryCache -> INInt -> DirectoryCache
rmDirectoryFromCache (DirectoryCache _ c) i
= DirectoryCache False (Map.delete i c)