2012-07-19 16:51:55 +00:00
|
|
|
{- Interface to mtab (and fstab)
|
|
|
|
-
|
|
|
|
- Derived from hsshellscript, originally written by
|
|
|
|
- Volker Wysk <hsss@volker-wysk.de>
|
2012-07-20 00:38:58 +00:00
|
|
|
-
|
2013-05-04 20:04:17 +00:00
|
|
|
- Modified to support BSD, Mac OS X, and Android by
|
2015-01-21 16:50:09 +00:00
|
|
|
- Joey Hess <id@joeyh.name>
|
2012-07-19 16:51:55 +00:00
|
|
|
-
|
|
|
|
- Licensed under the GNU LGPL version 2.1 or higher.
|
|
|
|
-}
|
|
|
|
|
|
|
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
|
|
|
|
|
|
|
module Utility.Mounts (
|
|
|
|
Mntent(..),
|
2012-07-20 00:38:58 +00:00
|
|
|
getMounts
|
2012-07-19 16:51:55 +00:00
|
|
|
) where
|
|
|
|
|
2013-05-04 20:04:17 +00:00
|
|
|
#ifndef __ANDROID__
|
2012-07-19 16:51:55 +00:00
|
|
|
import Control.Monad
|
|
|
|
import Foreign
|
|
|
|
import Foreign.C
|
2012-07-20 00:38:58 +00:00
|
|
|
#include "libmounts.h"
|
2013-05-04 20:04:17 +00:00
|
|
|
#else
|
|
|
|
import Utility.Exception
|
|
|
|
import Data.Maybe
|
|
|
|
import Control.Applicative
|
|
|
|
#endif
|
2015-05-10 20:19:56 +00:00
|
|
|
import Prelude
|
2012-07-19 16:51:55 +00:00
|
|
|
|
2012-07-20 00:38:58 +00:00
|
|
|
{- This is a stripped down mntent, containing only
|
|
|
|
- fields available everywhere. -}
|
2012-07-19 16:51:55 +00:00
|
|
|
data Mntent = Mntent
|
|
|
|
{ mnt_fsname :: String
|
2012-08-04 22:17:16 +00:00
|
|
|
, mnt_dir :: FilePath
|
2012-07-19 16:51:55 +00:00
|
|
|
, mnt_type :: String
|
2012-07-20 01:25:26 +00:00
|
|
|
} deriving (Read, Show, Eq, Ord)
|
2012-07-19 16:51:55 +00:00
|
|
|
|
2013-05-04 20:04:17 +00:00
|
|
|
#ifndef __ANDROID__
|
|
|
|
|
2012-07-20 00:38:58 +00:00
|
|
|
getMounts :: IO [Mntent]
|
|
|
|
getMounts = do
|
|
|
|
h <- c_mounts_start
|
2012-07-19 16:51:55 +00:00
|
|
|
when (h == nullPtr) $
|
2012-07-20 00:38:58 +00:00
|
|
|
throwErrno "getMounts"
|
2012-07-19 16:51:55 +00:00
|
|
|
mntent <- getmntent h []
|
2012-07-20 00:38:58 +00:00
|
|
|
_ <- c_mounts_end h
|
2012-07-19 16:51:55 +00:00
|
|
|
return mntent
|
|
|
|
|
2012-12-13 04:24:19 +00:00
|
|
|
where
|
|
|
|
getmntent h c = do
|
|
|
|
ptr <- c_mounts_next h
|
|
|
|
if (ptr == nullPtr)
|
|
|
|
then return $ reverse c
|
|
|
|
else do
|
|
|
|
mnt_fsname_str <- #{peek struct mntent, mnt_fsname} ptr >>= peekCString
|
|
|
|
mnt_dir_str <- #{peek struct mntent, mnt_dir} ptr >>= peekCString
|
|
|
|
mnt_type_str <- #{peek struct mntent, mnt_type} ptr >>= peekCString
|
|
|
|
let ent = Mntent
|
|
|
|
{ mnt_fsname = mnt_fsname_str
|
|
|
|
, mnt_dir = mnt_dir_str
|
|
|
|
, mnt_type = mnt_type_str
|
|
|
|
}
|
|
|
|
getmntent h (ent:c)
|
2012-07-19 16:51:55 +00:00
|
|
|
|
2012-07-20 19:07:48 +00:00
|
|
|
{- Using unsafe imports because the C functions are belived to never block.
|
|
|
|
- Note that getmntinfo is called with MNT_NOWAIT to avoid possibly blocking;
|
|
|
|
- while getmntent only accesses a file in /etc (or /proc) that should not
|
|
|
|
- block. -}
|
2012-07-20 00:38:58 +00:00
|
|
|
foreign import ccall unsafe "libmounts.h mounts_start" c_mounts_start
|
|
|
|
:: IO (Ptr ())
|
|
|
|
foreign import ccall unsafe "libmounts.h mounts_next" c_mounts_next
|
|
|
|
:: Ptr () -> IO (Ptr ())
|
|
|
|
foreign import ccall unsafe "libmounts.h mounts_end" c_mounts_end
|
|
|
|
:: Ptr () -> IO CInt
|
2013-05-04 20:04:17 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
{- Android does not support getmntent (well, it's a no-op stub in Bionic).
|
|
|
|
-
|
|
|
|
- But, the linux kernel's /proc/mounts is available to be parsed.
|
|
|
|
-}
|
|
|
|
getMounts :: IO [Mntent]
|
|
|
|
getMounts = catchDefaultIO [] $
|
|
|
|
mapMaybe (parse . words) . lines <$> readFile "/proc/mounts"
|
|
|
|
where
|
|
|
|
parse (device:mountpoint:fstype:_rest) = Just $ Mntent
|
|
|
|
{ mnt_fsname = device
|
|
|
|
, mnt_dir = mountpoint
|
|
|
|
, mnt_type = fstype
|
|
|
|
}
|
|
|
|
parse _ = Nothing
|
|
|
|
|
|
|
|
#endif
|