mirror of https://github.com/voidlizard/hbs2
114 lines
4.3 KiB
Haskell
114 lines
4.3 KiB
Haskell
module Main where
|
|
|
|
import qualified Data.ByteString.Char8 as B
|
|
import Foreign.C.Error
|
|
import System.Posix.Types
|
|
import System.Posix.Files
|
|
import System.Posix.IO
|
|
|
|
import System.Fuse
|
|
|
|
type HT = ()
|
|
|
|
main :: IO ()
|
|
main = fuseMain helloFSOps defaultExceptionHandler
|
|
|
|
helloFSOps :: FuseOperations HT
|
|
helloFSOps = defaultFuseOps { fuseGetFileStat = helloGetFileStat
|
|
, fuseOpen = helloOpen
|
|
, fuseRead = helloRead
|
|
, fuseOpenDirectory = helloOpenDirectory
|
|
, fuseReadDirectory = helloReadDirectory
|
|
, fuseGetFileSystemStats = helloGetFileSystemStats
|
|
}
|
|
helloString :: B.ByteString
|
|
helloString = B.pack "Hello World, HFuse!\n"
|
|
|
|
helloPath :: FilePath
|
|
helloPath = "/hello"
|
|
dirStat ctx = FileStat { statEntryType = Directory
|
|
, statFileMode = foldr1 unionFileModes
|
|
[ ownerReadMode
|
|
, ownerExecuteMode
|
|
, groupReadMode
|
|
, groupExecuteMode
|
|
, otherReadMode
|
|
, otherExecuteMode
|
|
]
|
|
, statLinkCount = 2
|
|
, statFileOwner = fuseCtxUserID ctx
|
|
, statFileGroup = fuseCtxGroupID ctx
|
|
, statSpecialDeviceID = 0
|
|
, statFileSize = 4096
|
|
, statBlocks = 1
|
|
, statAccessTime = 0
|
|
, statModificationTime = 0
|
|
, statStatusChangeTime = 0
|
|
}
|
|
|
|
fileStat ctx = FileStat { statEntryType = RegularFile
|
|
, statFileMode = foldr1 unionFileModes
|
|
[ ownerReadMode
|
|
, groupReadMode
|
|
, otherReadMode
|
|
]
|
|
, statLinkCount = 1
|
|
, statFileOwner = fuseCtxUserID ctx
|
|
, statFileGroup = fuseCtxGroupID ctx
|
|
, statSpecialDeviceID = 0
|
|
, statFileSize = fromIntegral $ B.length helloString
|
|
, statBlocks = 1
|
|
, statAccessTime = 0
|
|
, statModificationTime = 0
|
|
, statStatusChangeTime = 0
|
|
}
|
|
|
|
helloGetFileStat :: FilePath -> IO (Either Errno FileStat)
|
|
helloGetFileStat "/" = do
|
|
ctx <- getFuseContext
|
|
return $ Right $ dirStat ctx
|
|
helloGetFileStat path | path == helloPath = do
|
|
ctx <- getFuseContext
|
|
return $ Right $ fileStat ctx
|
|
helloGetFileStat _ =
|
|
return $ Left eNOENT
|
|
|
|
helloOpenDirectory "/" = return eOK
|
|
helloOpenDirectory _ = return eNOENT
|
|
|
|
helloReadDirectory :: FilePath -> IO (Either Errno [(FilePath, FileStat)])
|
|
helloReadDirectory "/" = do
|
|
ctx <- getFuseContext
|
|
return $ Right [(".", dirStat ctx)
|
|
,("..", dirStat ctx)
|
|
,(helloName, fileStat ctx)
|
|
]
|
|
where (_:helloName) = helloPath
|
|
helloReadDirectory _ = return (Left (eNOENT))
|
|
|
|
helloOpen :: FilePath -> OpenMode -> OpenFileFlags -> IO (Either Errno HT)
|
|
helloOpen path mode flags
|
|
| path == helloPath = case mode of
|
|
ReadOnly -> return (Right ())
|
|
_ -> return (Left eACCES)
|
|
| otherwise = return (Left eNOENT)
|
|
|
|
|
|
helloRead :: FilePath -> HT -> ByteCount -> FileOffset -> IO (Either Errno B.ByteString)
|
|
helloRead path _ byteCount offset
|
|
| path == helloPath =
|
|
return $ Right $ B.take (fromIntegral byteCount) $ B.drop (fromIntegral offset) helloString
|
|
| otherwise = return $ Left eNOENT
|
|
|
|
helloGetFileSystemStats :: String -> IO (Either Errno FileSystemStats)
|
|
helloGetFileSystemStats str =
|
|
return $ Right $ FileSystemStats
|
|
{ fsStatBlockSize = 512
|
|
, fsStatBlockCount = 1
|
|
, fsStatBlocksFree = 1
|
|
, fsStatBlocksAvailable = 1
|
|
, fsStatFileCount = 5
|
|
, fsStatFilesFree = 10
|
|
, fsStatMaxNameLength = 255
|
|
}
|