{- Copyright 2015 Markus Ongyerth, Stephan Guenther This file is part of Monky. Monky is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Monky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Monky. If not, see <http://www.gnu.org/licenses/>. -} {-# LANGUAGE ExistentialQuantification #-} {-# LANGUAGE CPP #-} {-| Module : Monky.Disk.Common Description : Provides the common disk interfaces Maintainer : moepi Stability : experimental Portability : Linux This provides the class used by file system specific implementations -} module Monky.Disk.Common ( FSI(FSI) , FsInfo(..) , fsToFSI , blBasePath , devToMapper , mapperToDev ) where import Monky.Utility import System.Directory (doesDirectoryExist) import Data.List (nub, sort) #if MIN_VERSION_base(4,8,0) #else import Control.Applicative ((<$>)) #endif {-| Type class that should be instanciated by file system handlers The Monky.Disk module is designed to work with different handlers specialized for different file systems and a generic block device handler. This typeclass gives the interface a file system handler has to implement to be usable. -} class FsInfo a where -- |Get the bytes free on the file system getFsFree :: a -> IO Int getFsFree h = do s <- getFsSize h u <- getFsUsed h return (s - u) -- |Get the total size of the file system getFsSize :: a -> IO Int getFsSize h = do u <- getFsUsed h f <- getFsFree h return (u + f) -- |Get the bytes used by the file system getFsUsed :: a -> IO Int getFsUsed h = do s <- getFsSize h f <- getFsFree h return (s - f) -- |Get all data, might be more efficient -- (Size, Free, Used) getFsAll :: a -> IO (Int, Int, Int) getFsAll h = do s <- getFsSize h f <- getFsFree h u <- getFsUsed h return (s, f, u) -- |Existential datatype to wrap 'FsInfo' instances data FSI = forall a. FsInfo a => FSI a -- |Wrap a 'FsInfo' into an 'FSI' fsToFSI :: FsInfo a => a -> FSI fsToFSI = FSI -- |The base path of block devices on the system blBasePath :: String blBasePath = "/sys/class/block/" -- |Get the physical block devices supporting some device mapperToDev :: String -> IO [String] mapperToDev x = sort . nub <$> do let path = blBasePath ++ x ++ "/slaves/" e <- doesDirectoryExist path if e then do rec <- mapM mapperToDev =<< listDirectory path return $ concat rec else return [x] -- |Get the "top most" virtual device(s) based on the physical device devToMapper :: String -> IO [String] devToMapper x = sort . nub <$> do let path = blBasePath ++ x ++ "/holders/" holders <- listDirectory path if null holders then return [x] else do rec <- mapM devToMapper holders return $ concat rec