packages feed

Network-NineP 0.2.0 → 0.3.0

raw patch · 6 files changed

+101/−46 lines, 6 filesdep ~mtldep ~networkdep ~transformersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: mtl, network, transformers

API changes (from Hackage documentation)

- Control.Monad.EmbedIO: instance EmbedIO IO
- Network.NineP.Error: instance Error NineError
- Network.NineP.Error: instance Show NineError
- Network.NineP.File.Instances: instance [overlap ok] (Read a, Num a, Typeable a) => Convertible ByteString a
- Network.NineP.File.Instances: instance [overlap ok] (Show a, Num a) => Convertible a ByteString
- Network.NineP.File.Instances: instance [overlap ok] Convertible () ByteString
- Network.NineP.File.Instances: instance [overlap ok] Convertible Bool ByteString
- Network.NineP.File.Instances: instance [overlap ok] Convertible ByteString ()
- Network.NineP.File.Instances: instance [overlap ok] Convertible ByteString Bool
- Network.NineP.File.Instances: instance [overlap ok] Convertible ByteString ByteString
- Network.NineP.File.Instances: instance [overlap ok] Monad m => WriteRef () m ByteString
- Network.NineP.File.Instances: instance [overlap ok] MonadIO m => ReadRef (Chan a) m a
- Network.NineP.File.Instances: instance [overlap ok] MonadIO m => WriteRef (Chan a) m a
- Network.NineP.File.Instances: instance [overlap ok] ReadRef () m ByteString
- Network.NineP.Server: addr :: Config m -> String
- Network.NineP.Server: descend :: NineFile m -> String -> ErrorT NineError m (NineFile m)
- Network.NineP.Server: getFiles :: NineFile m -> m [NineFile m]
- Network.NineP.Server: monadState :: Config m -> Content m
- Network.NineP.Server: parent :: NineFile m -> m (Maybe (NineFile m))
- Network.NineP.Server: read :: NineFile m -> Word64 -> Word32 -> ErrorT NineError m (ByteString)
- Network.NineP.Server: remove :: NineFile m -> m ()
- Network.NineP.Server: root :: Config m -> NineFile m
- Network.NineP.Server: stat :: NineFile m -> m Stat
- Network.NineP.Server: version :: NineFile m -> m Word32
- Network.NineP.Server: write :: NineFile m -> Word64 -> ByteString -> ErrorT NineError m (Word32)
- Network.NineP.Server: wstat :: NineFile m -> Stat -> m ()
+ Control.Monad.EmbedIO: instance Control.Monad.EmbedIO.EmbedIO GHC.Types.IO
+ Network.NineP.Error: instance Control.Monad.Trans.Error.Error Network.NineP.Error.NineError
+ Network.NineP.Error: instance GHC.Show.Show Network.NineP.Error.NineError
+ Network.NineP.File: isDir :: Word32 -> Bool
+ Network.NineP.File: memoryDirectory :: (Monad m, EmbedIO m) => String -> IO (NineFile m)
+ Network.NineP.File: memoryFile :: (Monad m, EmbedIO m) => String -> IO (NineFile m)
+ 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.Instances: instance (GHC.Read.Read a, GHC.Num.Num a, Data.Typeable.Internal.Typeable a) => Data.Convertible.Base.Convertible Data.ByteString.Lazy.Internal.ByteString a
+ Network.NineP.File.Instances: instance (GHC.Show.Show a, GHC.Num.Num a) => Data.Convertible.Base.Convertible a Data.ByteString.Lazy.Internal.ByteString
+ Network.NineP.File.Instances: instance Control.Monad.IO.Class.MonadIO m => Data.StateRef.Types.ReadRef (Control.Concurrent.Chan.Chan a) m a
+ Network.NineP.File.Instances: instance Control.Monad.IO.Class.MonadIO m => Data.StateRef.Types.WriteRef (Control.Concurrent.Chan.Chan a) m a
+ Network.NineP.File.Instances: instance Data.Convertible.Base.Convertible () Data.ByteString.Lazy.Internal.ByteString
+ Network.NineP.File.Instances: instance Data.Convertible.Base.Convertible Data.ByteString.Lazy.Internal.ByteString ()
+ Network.NineP.File.Instances: instance Data.Convertible.Base.Convertible Data.ByteString.Lazy.Internal.ByteString Data.ByteString.Lazy.Internal.ByteString
+ Network.NineP.File.Instances: instance Data.Convertible.Base.Convertible Data.ByteString.Lazy.Internal.ByteString GHC.Types.Bool
+ Network.NineP.File.Instances: instance Data.Convertible.Base.Convertible GHC.Types.Bool Data.ByteString.Lazy.Internal.ByteString
+ Network.NineP.File.Instances: instance Data.StateRef.Types.ReadRef () m Data.ByteString.Lazy.Internal.ByteString
+ Network.NineP.File.Instances: instance GHC.Base.Monad m => Data.StateRef.Types.WriteRef () m Data.ByteString.Lazy.Internal.ByteString
+ Network.NineP.Server: [addr] :: Config m -> String
+ Network.NineP.Server: [create] :: NineFile m -> String -> Word32 -> ErrorT NineError m (NineFile m)
+ Network.NineP.Server: [descend] :: NineFile m -> String -> ErrorT NineError m (NineFile m)
+ Network.NineP.Server: [getFiles] :: NineFile m -> m [NineFile m]
+ Network.NineP.Server: [monadState] :: Config m -> Content m
+ Network.NineP.Server: [parent] :: NineFile m -> m (Maybe (NineFile m))
+ Network.NineP.Server: [read] :: NineFile m -> Word64 -> Word32 -> ErrorT NineError m (ByteString)
+ Network.NineP.Server: [remove] :: NineFile m -> m ()
+ Network.NineP.Server: [root] :: Config m -> NineFile m
+ Network.NineP.Server: [stat] :: NineFile m -> m Stat
+ Network.NineP.Server: [version] :: NineFile m -> m Word32
+ Network.NineP.Server: [write] :: NineFile m -> Word64 -> ByteString -> ErrorT NineError m (Word32)
+ Network.NineP.Server: [wstat] :: NineFile m -> Stat -> m ()
- Control.Monad.EmbedIO: class MonadIO o => EmbedIO o where type family Content o
+ Control.Monad.EmbedIO: class (MonadIO o) => EmbedIO o where type family Content o
- Network.NineP.File: rwFile :: EmbedIO m => String -> Maybe (m ByteString) -> Maybe (ByteString -> m ()) -> NineFile m
+ Network.NineP.File: rwFile :: (EmbedIO m) => String -> Maybe (m ByteString) -> Maybe (ByteString -> m ()) -> NineFile m
- Network.NineP.Server: Directory :: m [NineFile m] -> m (Maybe (NineFile m)) -> (String -> 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 -> ErrorT NineError m (NineFile m)) -> (String -> Word32 -> ErrorT NineError m (NineFile m)) -> m () -> m Stat -> (Stat -> m ()) -> m Word32 -> NineFile m
- Network.NineP.Server: run9PServer :: EmbedIO m => Config m -> IO ()
+ Network.NineP.Server: run9PServer :: (EmbedIO m) => Config m -> IO ()

Files

Network-NineP.cabal view
@@ -1,5 +1,5 @@ Name:                Network-NineP-Version:             0.2.0+Version:             0.3.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.2+Tested-With:         GHC == 7.8.4  Source-repository head   type:              git@@ -18,7 +18,7 @@ Source-repository this   type:              git   location:          https://github.com/l29ah/Network-NineP.git-  tag:               0.2.0+  tag:               0.3.0  Library   Build-Depends:@@ -26,13 +26,13 @@     bytestring >= 0.9.2.1 && < 0.11,     containers >= 0.4.2.1 && < 0.6,     NineP >= 0.0.2 && < 0.1,-    network >= 2.3.0.14 && < 2.6,+    network >= 2.3.0.14 && < 2.7,     binary >= 0.5.1.0 && < 0.8,-    mtl >= 2.1.2 && < 2.2,+    mtl >= 2.1.2 && < 2.3,     monad-loops >= 0.3.3.0 && < 0.5,     regex-posix >= 0.95.2 && < 0.96,     mstate >= 0.2.4 && < 0.3,-    transformers >= 0.3.0.0 && < 0.4,+    transformers >= 0.3.0.0 && < 0.5,     stateref >= 0.3 && < 0.4,     convertible >= 1.0.11.1 && < 1.2   Exposed-modules:
Network/NineP/Error.hs view
@@ -25,11 +25,12 @@ 	noMsg = undefined 	strMsg = OtherError +-- |See also: @linux/net/9p/error.c@ instance Show NineError where 	show (ENotImplemented s) = s ++ " is not implemented"-	show ENotADir = "tried to walk into a non-directory"-	show EDir = "tried to write to a directory"-	show (ENoFile s) = "file " ++ s ++ " not found"+	show ENotADir = "not a directory"+	show EDir = "Is a directory"+	show (ENoFile s) = "file not found" 	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"
Network/NineP/File.hs view
@@ -6,9 +6,13 @@ {-# LANGUAGE ScopedTypeVariables, FlexibleContexts, OverloadedStrings #-}  module Network.NineP.File-	( simpleFile+	( isDir+	, simpleFile 	, simpleFileBy+	, simpleDirectory 	, rwFile+	, memoryFile+	, memoryDirectory 	) where  import Control.Concurrent.Chan@@ -16,7 +20,9 @@ import Control.Monad.EmbedIO import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as B+import Data.Bits import Data.Convertible.Base+import Data.IORef import Data.StateRef import Data.Word import Prelude hiding (read)@@ -24,14 +30,18 @@ import Network.NineP.Error import Network.NineP.Internal.File +-- |Tests if the file is a directory+isDir :: Word32	-- ^Permissions+	-> Bool+isDir perms = testBit perms 31+ simpleRead :: (Monad m, EmbedIO m) => m ByteString -> Word64 -> Word32 -> ErrorT NineError m ByteString-simpleRead get offset count = case offset of-	_ -> do+simpleRead get offset count = do 		r <- lift $ tryE $ get 		either (throwError . OtherError . (show :: SomeException -> String))-				(return . B.take (fromIntegral count)) r-	--_ -> throwError $ OtherError "can't read at offset"+				(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 put offset d = case offset of 	_ -> do@@ -51,24 +61,63 @@ rwFile name rc wc = simpleFileBy name (maybe (fst nulls) id rc, maybe (snd nulls) id wc) (id, id)  -- FIXME sane errors+-- |Placeholder source and sink nulls :: MonadIO m => (m a, a -> m ()) nulls = (throw $ Underflow, const $ return ())  -- |A file that reads from and writes to the supplied 'Ref' instances, with converstion to the appropriate types. See 'Network.NineP.File.Instances', 'Data.Convertible.Instances' and 'Data.StateRef.Instances'. Use '()', if the file is meant to be read-only/write-only. simpleFile :: forall a b m rr wr. (Monad m, EmbedIO m, ReadRef rr m a, Convertible a ByteString, WriteRef wr m b, Convertible ByteString b)-		=> String-		-> rr-		-> wr+		=> String	-- ^File name+		-> rr	-- ^Reading function+		-> wr	-- ^Writing function 		-> NineFile m simpleFile name rr wr = simpleFileBy name (readReference rr, writeReference wr) (convert, convert) +-- Shouldn't we make it simpler? -- |Typeclass-free version of 'simpleFile'. simpleFileBy :: forall a b m. (Monad m, EmbedIO m)-		=> String-		-> (m a, b -> m ())-		-> (a -> ByteString, ByteString -> b)+		=> String	-- ^File name+		-> (m a, b -> m ())	-- ^Reading and writing handle+		-> (a -> ByteString, ByteString -> b)	-- ^Type conversion handles 		-> NineFile m simpleFileBy name (rd, wr) (rdc, wrc) = (boringFile name :: NineFile m) { 		read = simpleRead $ liftM rdc $ rd, 		write = simpleWrite $ wr . wrc  	}++-- |A file that stores its contents in the form of 'IORef' 'ByteString'+memoryFile :: forall m. (Monad m, EmbedIO m)+	=> String	-- ^File name+	-> IO (NineFile m)+memoryFile name = do+	c <- newIORef "" :: IO (IORef ByteString)+	return $ simpleFileBy name (+			liftIO $ readIORef c,+			liftIO . writeIORef c+		) (id, id)++-- |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)+simpleDirectory name newfile newdir = do+	files <- newIORef [] :: IO (IORef [(String, NineFile m)])+	return (boringDir name [] :: NineFile m) {+		create = \name perms -> do+			nf <- (if isDir perms then newdir else newfile) name+			let nelem = (name, nf)+			liftIO $ atomicModifyIORef' files (\l -> (nelem:l, ()))+			return nf,+		getFiles = liftIO $ liftM (map snd) $ readIORef files,+		descend = \name -> do+			d <- liftIO $ readIORef files+			maybe (throwError $ 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)
Network/NineP/Internal/File.hs view
@@ -32,6 +32,8 @@ 		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),+		-- |Create a file under this directory.+		create :: String -> Word32 -> ErrorT NineError m (NineFile m), 		remove :: m (), 		-- |The directory stat must return only stat for @.@. 		stat :: m Stat,@@ -52,16 +54,17 @@         (const $ return ()) 	(return 0) --- |A dumb directory that can't do anything but provide the files it contains.+-- |A dumb directory that can't do anything but provide the files it contains. An user can create files, but they won't show up in listing and will essentially be 'boringFile's. boringDir :: (Monad m, EmbedIO m) => String -> [(String, NineFile m)] -> NineFile m 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 		Just f -> return f),-        remove = (return ()),-        stat = (return $ boringStat {st_name = name}),-        wstat = (const $ return ()),+	create = (\name perms -> return $ boringFile name),+	remove = (return ()),+	stat = (return $ boringStat {st_name = name}),+	wstat = (const $ return ()), 	version = (return 0), 	parent = return Nothing } 
Network/NineP/Internal/Msg.hs view
@@ -10,10 +10,10 @@ 	, rclunk 	, rauth 	, ropen+	, rcreate 	, rread 	, rwrite 	, rremove-	, rcreate 	, rflush 	) where @@ -134,10 +134,22 @@ ropen (Msg _ t (Topen fid mode)) = do 	f <- lookup fid 	checkPerms f mode-	q <- open f+	qid <- open f 	iou <- iounit-	return $ return $ Msg TRopen t $ Ropen q iou+	return $ return $ Msg TRopen t $ Ropen qid iou +rcreate (Msg _ t (Tcreate fid name perm mode)) = do+	f <- lookup fid+	-- TODO check permissions to create+	case f of+		RegularFile {} -> throwError ENotADir+		Directory {} -> do+			nf <- mapErrorT call $ (create f) name perm+			insert fid nf+			qid <- open f+			iou <- iounit+			return $ return $ Msg TRcreate t $ Rcreate qid iou+ rread :: (Monad m, EmbedIO m) => Msg -> Nine m [Msg] rread (Msg _ t (Tread fid offset count)) = do 	f <- lookup fid@@ -169,23 +181,12 @@ rwstat (Msg _ t (Twstat fid stat)) = do 	-- TODO check perms 	f <- lookup fid-	throwError $ ENotImplemented "wstat"+	-- TODO implement+	return $ return $ Msg TRwstat t $ Rwstat  rremove (Msg _ t (Tremove fid)) = do 	-- TODO check perms 	f <- lookup fid 	throwError $ ENotImplemented "remove"--rcreate (Msg _ t (Tcreate fid name perm mode)) = do-	-- TODO check perms-	--dir <- lookup fid-	if testBit mode 31-		then do -			throwError $ ENotImplemented "create directory"-		else do-			throwError $ ENotImplemented "create file"-	--q <- open f-	-- TODO iounit-	--return $ return $ Msg TRcreate t $ Rcreate  rflush _ = return []
Test.hs view
@@ -17,9 +17,10 @@  boringwr _ c = return $ B.take (fromIntegral c) "i am so very boring" -cfg = Config {-	root = boringDir "/" [("lol", (boringFile "lol") { write = spamwr })],-	addr = "unix!/tmp/h9pt"-}--main = run9PServer cfg+main = do+	memd <- memoryDirectory "/" :: IO (NineFile IO)+	run9PServer $ Config {+			root = boringDir "/" [("lol", (boringFile "lol") { write = spamwr }), ("memd", memd)],+			addr = "unix!/tmp/h9pt",+			monadState = undefined+		}