packages feed

Network-NineP 0.3.0 → 0.4.0

raw patch · 9 files changed

+86/−65 lines, 9 filesdep +exceptionsdep +monad-peelPVP ok

version bump matches the API change (PVP)

Dependencies added: exceptions, monad-peel

API changes (from Hackage documentation)

- Network.NineP.Error: instance Control.Monad.Trans.Error.Error Network.NineP.Error.NineError
+ Network.NineP.Error: EInval :: NineError
+ Network.NineP.Error: instance GHC.Exception.Exception Network.NineP.Error.NineError
- Network.NineP.File: simpleDirectory :: (Monad m, EmbedIO m) => String -> (String -> ErrorT NineError m (NineFile m)) -> (String -> ErrorT NineError m (NineFile m)) -> IO (NineFile m)
+ Network.NineP.File: simpleDirectory :: (Monad m, EmbedIO m) => String -> (String -> m (NineFile m)) -> (String -> m (NineFile m)) -> IO (NineFile m, IORef [(String, NineFile m)])
- Network.NineP.Server: Directory :: m [NineFile m] -> m (Maybe (NineFile m)) -> (String -> ErrorT NineError m (NineFile m)) -> (String -> Word32 -> ErrorT NineError m (NineFile m)) -> m () -> m Stat -> (Stat -> m ()) -> m Word32 -> NineFile m
+ Network.NineP.Server: Directory :: m [NineFile m] -> m (Maybe (NineFile m)) -> (String -> m (NineFile m)) -> (String -> Word32 -> m (NineFile m)) -> m () -> m Stat -> (Stat -> m ()) -> m Word32 -> NineFile m
- Network.NineP.Server: RegularFile :: (Word64 -> Word32 -> ErrorT NineError m (ByteString)) -> (Word64 -> ByteString -> ErrorT NineError m (Word32)) -> m () -> m Stat -> (Stat -> m ()) -> m Word32 -> NineFile m
+ Network.NineP.Server: RegularFile :: (Word64 -> Word32 -> m (ByteString)) -> (Word64 -> ByteString -> m (Word32)) -> m () -> m Stat -> (Stat -> m ()) -> m Word32 -> NineFile m
- Network.NineP.Server: [create] :: NineFile m -> String -> Word32 -> ErrorT NineError m (NineFile m)
+ Network.NineP.Server: [create] :: NineFile m -> String -> Word32 -> m (NineFile m)
- Network.NineP.Server: [descend] :: NineFile m -> String -> ErrorT NineError m (NineFile m)
+ Network.NineP.Server: [descend] :: NineFile m -> String -> m (NineFile m)
- Network.NineP.Server: [read] :: NineFile m -> Word64 -> Word32 -> ErrorT NineError m (ByteString)
+ Network.NineP.Server: [read] :: NineFile m -> Word64 -> Word32 -> m (ByteString)
- Network.NineP.Server: [write] :: NineFile m -> Word64 -> ByteString -> ErrorT NineError m (Word32)
+ Network.NineP.Server: [write] :: NineFile m -> Word64 -> ByteString -> m (Word32)

Files

Network-NineP.cabal view
@@ -1,5 +1,5 @@ Name:                Network-NineP-Version:             0.3.0+Version:             0.4.0 Description:         A library providing one with a somewhat higher level interface to 9P2000 protocol than existing implementations. Designed to facilitate rapid development of synthetic filesystems. Synopsis:            High-level abstraction over 9P protocol Maintainer:          Sergey Alirzaev <zl29ah@gmail.com>@@ -9,7 +9,7 @@ Build-Type:          Simple Cabal-Version:       >= 1.6 Stability:           Experimental-Tested-With:         GHC == 7.8.4+Tested-With:         GHC == 7.10.1  Source-repository head   type:              git@@ -18,7 +18,7 @@ Source-repository this   type:              git   location:          https://github.com/l29ah/Network-NineP.git-  tag:               0.3.0+  tag:               0.4.0  Library   Build-Depends:@@ -34,7 +34,9 @@     mstate >= 0.2.4 && < 0.3,     transformers >= 0.3.0.0 && < 0.5,     stateref >= 0.3 && < 0.4,-    convertible >= 1.0.11.1 && < 1.2+    convertible >= 1.0.11.1 && < 1.2,+    exceptions >= 0.8.0.2 && < 0.9,+    monad-peel >= 0.1.1 && < 0.3   Exposed-modules:     Control.Monad.EmbedIO     Network.NineP@@ -46,6 +48,8 @@     Network.NineP.Internal.File     Network.NineP.Internal.Msg     Network.NineP.Internal.State- +  ghc-options: -fno-warn-tabs+ Executable test   Main-is: Test.hs+  ghc-options: -fno-warn-tabs
Network/NineP/Error.hs view
@@ -1,17 +1,17 @@ -- | -- Stability   :  Ultra-Violence -- Portability :  I'm too young to die+-- The exceptions one would want to throw to be understood by the existing 9P clients.  module Network.NineP.Error 	( NineError(..)-	, module Control.Monad.Error 	) where -import Control.Monad.Error+import Control.Exception+import Data.Typeable import Data.Word --- |Throwable errors-data NineError = +data NineError = 	ENotImplemented String | 	ENotADir | 	EDir |@@ -19,13 +19,12 @@ 	ENoFid Word32 | 	ENoAuthRequired | 	EPermissionDenied |-	OtherError String+	EInval |+	OtherError String deriving (Typeable) -instance Error NineError where-	noMsg = undefined-	strMsg = OtherError+instance Exception NineError --- |See also: @linux/net/9p/error.c@+-- |See also: @linux\/net\/9p\/error.c@ instance Show NineError where 	show (ENotImplemented s) = s ++ " is not implemented" 	show ENotADir = "not a directory"@@ -34,4 +33,5 @@ 	show (ENoFid i) = "fid " ++ show i ++ " is not registered on the server" 	show ENoAuthRequired = "the server doesn't require any kind of authentication" 	show EPermissionDenied = "permission denied"+	show EInval = "Invalid argument" 	show (OtherError s) = s
Network/NineP/File.hs view
@@ -17,7 +17,9 @@  import Control.Concurrent.Chan import Control.Exception+import Control.Monad import Control.Monad.EmbedIO+import Control.Monad.Trans import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as B import Data.Bits@@ -35,19 +37,17 @@ 	-> Bool isDir perms = testBit perms 31 -simpleRead :: (Monad m, EmbedIO m) => m ByteString -> Word64 -> Word32 -> ErrorT NineError m ByteString+simpleRead :: (Monad m, EmbedIO m) => m ByteString -> Word64 -> Word32 -> m ByteString simpleRead get offset count = do-		r <- lift $ tryE $ get-		either (throwError . OtherError . (show :: SomeException -> String))-				(return . B.take (fromIntegral count) . B.drop (fromIntegral offset)) r+		r <- get+		(return . B.take (fromIntegral count) . B.drop (fromIntegral offset)) r  -- TODO make it offset-aware-simpleWrite :: (Monad m, EmbedIO m) => (ByteString -> m ()) -> Word64 -> ByteString -> ErrorT NineError m Word32+simpleWrite :: (Monad m, EmbedIO m) => (ByteString -> m ()) -> Word64 -> ByteString -> m Word32 simpleWrite put offset d = case offset of 	_ -> do-		r <- lift $ tryE $ put d-		either (throwError . OtherError . (show :: SomeException -> String))-				(const $ return $ fromIntegral $ B.length d) r+		r <- put d+		(const $ return $ fromIntegral $ B.length d) r 	--_ -> throwError $ OtherError "can't write at offset"  @@ -99,12 +99,12 @@ -- |A directory that stores its contents in the form of 'IORef [(String, NineFile m)]' simpleDirectory :: forall m. (Monad m, EmbedIO m) 			=> String	-- ^File name-			-> (String -> ErrorT NineError m (NineFile m))	-- ^A function for creating new files-			-> (String -> ErrorT NineError m (NineFile m))	-- ^A function for creating new directories-			-> IO (NineFile m)+			-> (String -> m (NineFile m))	-- ^A function for creating new files+			-> (String -> m (NineFile m))	-- ^A function for creating new directories+			-> IO (NineFile m, IORef [(String, NineFile m)]) simpleDirectory name newfile newdir = do 	files <- newIORef [] :: IO (IORef [(String, NineFile m)])-	return (boringDir name [] :: NineFile m) {+	return $ (\f -> (f, files)) $ (boringDir name [] :: NineFile m) { 		create = \name perms -> do 			nf <- (if isDir perms then newdir else newfile) name 			let nelem = (name, nf)@@ -113,11 +113,11 @@ 		getFiles = liftIO $ liftM (map snd) $ readIORef files, 		descend = \name -> do 			d <- liftIO $ readIORef files-			maybe (throwError $ ENoFile name) (return) $ lookup name d+			maybe (throw $ ENoFile name) (return) $ lookup name d 	}  -- |A composition of a 'simpleDirectory' and a 'memoryFile' memoryDirectory :: forall m. (Monad m, EmbedIO m) 			=> String	-- ^File name 			-> IO (NineFile m)-memoryDirectory name = simpleDirectory name (liftIO . memoryFile) (liftIO . memoryDirectory)+memoryDirectory name = liftM fst $ simpleDirectory name (liftIO . memoryFile) (liftIO . memoryDirectory)
Network/NineP/File/Instances.hs view
@@ -3,7 +3,7 @@ -- Portability :  I'm too young to die -- Instances for dealing with the usual data. -{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, OverloadedStrings, OverlappingInstances, ViewPatterns #-}+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, OverloadedStrings, ViewPatterns #-}  module Network.NineP.File.Instances 	( Convertible
Network/NineP/Internal/File.hs view
@@ -6,6 +6,7 @@ 	, boringDir 	) where +import Control.Exception import Control.Monad.EmbedIO import qualified Data.ByteString.Lazy.Char8 as B import qualified Data.Map as M@@ -18,10 +19,10 @@ 	RegularFile {         	read :: Word64	-- Offset 			-> Word32 -- Length-			-> ErrorT NineError m (B.ByteString),	-- Resulting data+			-> m (B.ByteString),	-- Resulting data         	write :: Word64	-- Offset 			-> B.ByteString	-- The written data-			-> ErrorT NineError m (Word32),	-- Number of bytes written successfully. Should return @0@ in case of an error.+			-> m (Word32),	-- Number of bytes written successfully. Should return @0@ in case of an error. 		remove :: m (), 		stat :: m Stat, 		wstat :: Stat -> m (),@@ -31,9 +32,9 @@ 		getFiles :: m [NineFile m], 		parent :: m (Maybe (NineFile m)), 		-- |A callback to address a specific file by its name. @.@ and @..@ are handled in the library.-		descend :: String -> ErrorT NineError m (NineFile m),+		descend :: String -> m (NineFile m), 		-- |Create a file under this directory.-		create :: String -> Word32 -> ErrorT NineError m (NineFile m),+		create :: String -> Word32 -> m (NineFile m), 		remove :: m (), 		-- |The directory stat must return only stat for @.@. 		stat :: m Stat,@@ -59,7 +60,7 @@ boringDir name contents = let m = M.fromList contents in Directory { 	getFiles = (return $ map snd $ contents), 	descend = (\x -> case M.lookup x m of-		Nothing -> throwError $ ENoFile x+		Nothing -> throw $ ENoFile x 		Just f -> return f), 	create = (\name perms -> return $ boringFile name), 	remove = (return ()),
Network/NineP/Internal/Msg.hs view
@@ -18,6 +18,7 @@ 	) where  import Control.Concurrent.MState hiding (put)+import Control.Exception import Control.Monad.EmbedIO import Control.Monad.Reader import Data.Binary.Put@@ -41,14 +42,14 @@ checkPerms' :: (Monad m, EmbedIO m) => Word32 -> Word8 -> Nine m () checkPerms' have want = do 	-- TODO stop presuming we are owners-	let checkRead = unless (testBit have 2) $ throwError EPermissionDenied-	let checkWrite = unless (testBit have 1) $ throwError EPermissionDenied-	let checkExec = unless (testBit have 0) $ throwError EPermissionDenied+	let checkRead = unless (testBit have 2) $ throw EPermissionDenied+	let checkWrite = unless (testBit have 1) $ throw EPermissionDenied+	let checkExec = unless (testBit have 0) $ throw EPermissionDenied 	when (testBit want 4) $ do 		checkWrite-		throwError $ ENotImplemented "OTRUNC"+		throw $ ENotImplemented "OTRUNC" 	when (testBit want 6) $ do-		throwError $ ENotImplemented "ORCLOSE"+		throw $ ENotImplemented "ORCLOSE" 	case want of 		0 -> checkRead 		1 -> checkWrite@@ -66,7 +67,7 @@ rversion :: Msg -> Nine m [Msg] rversion (Msg _ t (Tversion s v)) = do 	let ver = readVersion v-	lift $ modifyM_ (\st -> st { msize = s, protoVersion = ver })+	modifyM_ (\st -> st { msize = s, protoVersion = ver }) 	return $ return $ Msg TRversion t $ Rversion s $ show ver  rattach (Msg _ t (Tattach fid _ _ _)) = do@@ -75,9 +76,9 @@ 	q <- makeQid root 	return $ return $ Msg TRattach t $ Rattach q  -desc :: (Monad m, EmbedIO m) => NineFile m -> String -> ErrorT NineError m (NineFile m)+desc :: (Monad m, EmbedIO m) => NineFile m -> String -> m (NineFile m) desc f ".." = do-	mp <- lift $ parent f+	mp <- parent f 	return $ case mp of 		Just p -> p 		Nothing -> f@@ -85,9 +86,9 @@  walk :: (Monad m, EmbedIO m) => [Qid] -> [String] -> NineFile m -> Nine m (NineFile m, [Qid]) walk qs [] f = return (f, qs)-walk qs (x:xs) (RegularFile {}) = throwError ENotADir+walk qs (x:xs) (RegularFile {}) = throw ENotADir walk qs (x:xs) d@(Directory {}) = do-	f <- mapErrorT call $ desc d x+	f <- call $ desc d x 	q <- makeQid f 	walk (q:qs) xs f @@ -106,7 +107,7 @@ 				(RegularFile {}) -> flip clearBit 31 				(Directory {}) -> flip setBit 31 			)-	s <- lift $ call $ stat f+	s <- call $ stat f 	return s { st_mode = fixDirBit $ st_mode s, 		st_qid = (st_qid s) { qid_typ = getQidTyp s } } 	@@ -125,7 +126,7 @@ 	return $ return $ Msg TRclunk t $ Rclunk  rauth (Msg {}) = do-	throwError ENoAuthRequired+	throw ENoAuthRequired  open :: (Monad m, EmbedIO m) => NineFile m -> Nine m Qid open f = do@@ -142,9 +143,9 @@ 	f <- lookup fid 	-- TODO check permissions to create 	case f of-		RegularFile {} -> throwError ENotADir+		RegularFile {} -> throw ENotADir 		Directory {} -> do-			nf <- mapErrorT call $ (create f) name perm+			nf <- call $ (create f) name perm 			insert fid nf 			qid <- open f 			iou <- iounit@@ -160,10 +161,10 @@ 			let (a, b) = B.splitAt s d in a : splitMsg' b s 	case f of 		RegularFile {} -> do-			d <- mapErrorT call $ (read f) offset count+			d <- call $ (read f) offset count 			mapM (return . Msg TRread t . Rread) $ splitMsg d $ fromIntegral u 		Directory {} -> do-			contents <- lift $ call $ getFiles f+			contents <- call $ getFiles f 			s <- mapM getStat $ contents 			let d = runPut $ mapM_ put s 			mapM (return . Msg TRread t . Rread) $ splitMsg (B.drop (fromIntegral offset) d) $ fromIntegral u@@ -173,9 +174,9 @@ 	f <- lookup fid 	checkPerms f 1 	case f of-		Directory {} -> throwError EDir+		Directory {} -> throw EDir 		RegularFile {} -> do-			c <- mapErrorT call $ (write f) offset d+			c <- call $ (write f) offset d 			return $ return $ Msg TRwrite t $ Rwrite c  rwstat (Msg _ t (Twstat fid stat)) = do@@ -187,6 +188,6 @@ rremove (Msg _ t (Tremove fid)) = do 	-- TODO check perms 	f <- lookup fid-	throwError $ ENotImplemented "remove"+	throw $ ENotImplemented "remove"  rflush _ = return []
Network/NineP/Internal/State.hs view
@@ -15,7 +15,11 @@ 	) where  import Control.Concurrent.MState+import Control.Exception (throw)+import Control.Exception.Peel as P+import Control.Monad.Catch import Control.Monad.EmbedIO+import Control.Monad.IO.Peel import Control.Monad.Reader import Control.Monad.State.Class import Data.List (isPrefixOf)@@ -60,8 +64,13 @@ 	mState = m } -type Nine m x = ErrorT NineError (MState (NineState m) (ReaderT (Config m) IO)) x+type Nine m x = MState (NineState m) (ReaderT (Config m) IO) x +instance MonadThrow m => MonadThrow (MState s m) where+	throwM e = lift $ throwM e+instance (MonadCatch m, MonadPeelIO m) => MonadCatch (MState s m) where+	catch = P.catch+ call :: (EmbedIO m) => m a -> MState (NineState m) (ReaderT (Config m) IO) a call x = do 	s <- (return . mState) =<< get@@ -71,17 +80,17 @@ lookup fid = do 	m <- (return . fidMap) =<< get  	case M.lookup fid m of-		Nothing -> throwError $ ENoFid fid+		Nothing -> throw $ ENoFid fid 		Just f -> return f  insert :: Word32 -> NineFile m -> Nine m () insert fid f = do 	m <- (return . fidMap) =<< get -	lift $ modifyM_ (\s -> s { fidMap = M.insert fid f $ fidMap s })+	modifyM_ (\s -> s { fidMap = M.insert fid f $ fidMap s })  delete :: Word32 -> Nine m () delete fid = do-	lift $ modifyM_ (\s -> s { fidMap = M.delete fid $ fidMap s })+	modifyM_ (\s -> s { fidMap = M.delete fid $ fidMap s })  iounit :: Nine m Word32 iounit = do
Network/NineP/Server.hs view
@@ -12,8 +12,9 @@  import Control.Concurrent import Control.Concurrent.MState hiding (get, put)-import Control.Exception+import Control.Exception (assert) import Control.Monad+import Control.Monad.Catch import Control.Monad.EmbedIO import Control.Monad.Loops import Control.Monad.Reader@@ -118,7 +119,7 @@ handleMsg :: (EmbedIO m) => (Msg -> IO ()) -> Msg -> MState (NineState m) (ReaderT (Config m) IO) () handleMsg say p = do 	let Msg typ t m = p-	r <- runErrorT (case typ of+	r <- try (case typ of 			TTversion -> rversion p 			TTattach -> rattach p 			TTwalk -> rwalk p@@ -135,4 +136,5 @@ 		) 	case r of 		(Right response) -> liftIO $ mapM_ say $ response-		(Left fail) -> liftIO $ say $ Msg TRerror t $ Rerror $ show $ fail+		-- FIXME which exceptions should i catch?+		(Left fail) -> liftIO $ say $ Msg TRerror t $ Rerror $ show $ (fail :: SomeException)
Test.hs view
@@ -1,18 +1,18 @@ {-# LANGUAGE OverloadedStrings #-} -import Control.Monad.Error+import Control.Exception import Control.Monad.Trans import qualified Data.ByteString.Lazy.Char8 as B import Data.Word -import Network.NineP+import Network.NineP as N import Network.NineP.Error import Network.NineP.File  --cfg = Config $ boringDir "/" [("boring", boringFile "boring"),("nyak", boringFile "nyak")]-spamwr :: Word64 -> B.ByteString -> ErrorT NineError IO (Word32)+spamwr :: Word64 -> B.ByteString -> IO Word32 spamwr _ d = do-	lift $ B.putStr d+	B.putStr d 	return $ fromIntegral $ B.length d  boringwr _ c = return $ B.take (fromIntegral c) "i am so very boring"@@ -20,7 +20,11 @@ main = do 	memd <- memoryDirectory "/" :: IO (NineFile IO) 	run9PServer $ Config {-			root = boringDir "/" [("lol", (boringFile "lol") { write = spamwr }), ("memd", memd)],+			-- TODO Data.Default?+			root = boringDir "/" [+				("lol", (boringFile "lol") { write = spamwr }),+				("memd", memd),+				("exception", (boringFile "exception") { N.read = \_ _ -> throw $ AssertionFailed "lol" })], 			addr = "unix!/tmp/h9pt", 			monadState = undefined 		}