{-# LINE 1 "System/Posix/StatVFS.hsc" #-}
{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, ForeignFunctionInterface, CApiFFI #-}
{-# LINE 2 "System/Posix/StatVFS.hsc" #-}

#include "StatVFSConfig.h"

{-# LINE 5 "System/Posix/StatVFS.hsc" #-}

{-# LINE 6 "System/Posix/StatVFS.hsc" #-}
-- | Get information about a mounted filesystem.
-- A minimal example of usage is:
--
-- @
-- import System.Posix.StatVFS (statVFS, statVFS_bfree)
--
-- main = do
--     stat <- statVFS "/"
--     putStrLn $ (show (statVFS_bfree stat)) ++ " free blocks on /"
-- @

module System.Posix.StatVFS where

import Control.Applicative
import Foreign
import Foreign.C.Error (throwErrnoIfMinus1_)
import Foreign.C.Types (CInt(..), CULong(..))
import Foreign.C.String (CString, withCString)
import System.Posix.Types
import Unsafe.Coerce (unsafeCoerce)

newtype CFSBlkCnt = CFSBlkCnt HTYPE_FSBLKCNT_T deriving (Bounded, Enum, Eq, Integral, Num, Ord, Real, Storable)
newtype CFSFilCnt = CFSFilCnt HTYPE_FSFILCNT_T deriving (Bounded, Enum, Eq, Integral, Num, Ord, Real, Storable)

instance Read CFSBlkCnt where
  readsPrec            = unsafeCoerce (readsPrec :: Int -> ReadS HTYPE_FSBLKCNT_T)
  readList             = unsafeCoerce (readList  :: ReadS [HTYPE_FSBLKCNT_T])

instance Show CFSBlkCnt where
   showsPrec            = unsafeCoerce (showsPrec :: Int -> HTYPE_FSBLKCNT_T -> ShowS)
   show                 = unsafeCoerce (show :: HTYPE_FSBLKCNT_T -> String)
   showList             = unsafeCoerce (showList :: [HTYPE_FSBLKCNT_T] -> ShowS)

instance Read CFSFilCnt where
  readsPrec            = unsafeCoerce (readsPrec :: Int -> ReadS HTYPE_FSFILCNT_T)
  readList             = unsafeCoerce (readList  :: ReadS [HTYPE_FSFILCNT_T])

instance Show CFSFilCnt where
   showsPrec            = unsafeCoerce (showsPrec :: Int -> HTYPE_FSFILCNT_T -> ShowS)
   show                 = unsafeCoerce (show :: HTYPE_FSFILCNT_T -> String)
   showList             = unsafeCoerce (showList :: [HTYPE_FSFILCNT_T] -> ShowS)

type CStatVFS = ()

foreign import capi unsafe "sys/statvfs.h fstatvfs"
  c_fstatvfs :: CInt -> Ptr CStatVFS -> IO CInt

foreign import capi unsafe "sys/statvfs.h statvfs"
  c_statvfs :: CString -> Ptr CStatVFS -> IO CInt
-- | File system information record, reflects data mentioned in the statvfs(3) manual
data StatVFS = StatVFS { -- | Filesystem block size
                         statVFS_bsize :: CULong
                         -- | Fragment size
                       , statVFS_frsize :: CULong
                         -- | Size of fs in f_frsize units
                       , statVFS_blocks :: CFSBlkCnt
                         -- | Free blocks
                       , statVFS_bfree :: CFSBlkCnt
                         -- | Free blocks for unprivileged users
                       , statVFS_bavail :: CFSBlkCnt
                         -- | Inodes
                       , statVFS_files :: CFSFilCnt
                         -- | Free inodes
                       , statVFS_ffree :: CFSFilCnt
                         -- | Free inodes for unprivileged users
                       , statVFS_favail :: CFSFilCnt
                         -- | Filesystem ID
                       , statVFS_fsid :: CULong
                         -- | Mount flags
                       , statVFS_flag :: CULong
                         -- | Maximum filename length
                       , statVFS_namemax :: CULong
                       } deriving Show

statVFS_st_rdonly :: CULong
statVFS_st_rdonly = (1)
{-# LINE 82 "System/Posix/StatVFS.hsc" #-}

statVFS_st_nosuid :: CULong
statVFS_st_nosuid = (2)
{-# LINE 85 "System/Posix/StatVFS.hsc" #-}

toStatVFS :: Ptr CStatVFS -> IO StatVFS
toStatVFS p = StatVFS
              <$> ((\hsc_ptr -> peekByteOff hsc_ptr 0)) p
{-# LINE 89 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 8)) p
{-# LINE 90 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 16)) p
{-# LINE 91 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 24)) p
{-# LINE 92 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 32)) p
{-# LINE 93 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 40)) p
{-# LINE 94 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 48)) p
{-# LINE 95 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 56)) p
{-# LINE 96 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 64)) p
{-# LINE 97 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 72)) p
{-# LINE 98 "System/Posix/StatVFS.hsc" #-}
              <*> ((\hsc_ptr -> peekByteOff hsc_ptr 80)) p
{-# LINE 99 "System/Posix/StatVFS.hsc" #-}

fStatVFS :: Fd -> IO StatVFS
fStatVFS (Fd fd) = do
  fp <- mallocForeignPtrBytes (112)
{-# LINE 103 "System/Posix/StatVFS.hsc" #-}
  withForeignPtr fp $ \p -> do
    throwErrnoIfMinus1_ "fStatVFS" $ c_fstatvfs fd p
    toStatVFS p

statVFS :: FilePath -> IO StatVFS
statVFS path = do
  withCString path $ \c_path -> do
    fp <- mallocForeignPtrBytes (112)
{-# LINE 111 "System/Posix/StatVFS.hsc" #-}
    withForeignPtr fp $ \p -> do
      throwErrnoIfMinus1_ "statVFS" $ c_statvfs c_path p
      toStatVFS p