diff --git a/Codec/Compression/BZip/Stream.hsc b/Codec/Compression/BZip/Stream.hsc
--- a/Codec/Compression/BZip/Stream.hsc
+++ b/Codec/Compression/BZip/Stream.hsc
@@ -1,6 +1,7 @@
+{-# OPTIONS_GHC -fno-warn-missing-methods #-}
 -----------------------------------------------------------------------------
 -- |
--- Copyright   :  (c) 2006 Duncan Coutts
+-- Copyright   :  (c) 2006-2008 Duncan Coutts
 -- License     :  BSD-style
 --
 -- Maintainer  :  duncan.coutts@worc.ox.ac.uk
@@ -370,25 +371,21 @@
   toEnum (#{const BZ_STREAM_END}) = StreamEnd
   toEnum other = error ("unexpected bzip2 status: " ++ show other)
 
-isFatalError :: CInt -> Bool
-isFatalError n | n >= 0 = False
-isFatalError _          = True
+failIfError :: CInt -> Stream ()
+failIfError errno
+  | errno >= 0 = return ()
+  | otherwise  = fail (getErrorMessage errno)
 
-throwError :: CInt -> Stream a
-throwError (#{const BZ_SEQUENCE_ERROR})
-  = fail "incorrect sequence of calls"
-throwError (#{const BZ_PARAM_ERROR})
-  = fail "incorrect parameter"
-throwError (#{const BZ_MEM_ERROR})
-  = fail "not enough memory"
-throwError (#{const BZ_DATA_ERROR})
-  = fail "compressed data stream is corrupt"
-throwError (#{const BZ_DATA_ERROR_MAGIC})
-  = fail "data stream is not a bzip2 file"
-throwError (#{const BZ_CONFIG_ERROR})
-  = fail "configuration error in bzip2 lib"
-throwError other
-  = fail ("unknown or impossible error code: " ++ show other)
+getErrorMessage :: CInt -> String
+getErrorMessage errno = case errno of
+ #{const BZ_SEQUENCE_ERROR}   -> "incorrect sequence of calls"
+ #{const BZ_PARAM_ERROR}      -> "incorrect parameter"
+ #{const BZ_MEM_ERROR}        -> "not enough memory"
+ #{const BZ_DATA_ERROR}       -> "compressed data stream is corrupt"
+ #{const BZ_DATA_ERROR_MAGIC} -> "data stream is not a bzip2 file"
+ #{const BZ_CONFIG_ERROR}     -> "configuration error in bzip2 lib"
+ other                        -> "unknown or impossible error code: "
+                              ++ show other
 
 data Action =
     Run
@@ -498,6 +495,11 @@
   stream <- getStreamState
   unsafeLiftIO (withForeignPtr stream f)
 
+withStreamState :: (StreamState -> IO a) -> Stream a
+withStreamState f = do
+  stream <- getStreamState
+  unsafeLiftIO (withForeignPtr stream (f . StreamState))
+
 setInAvail :: Int -> Stream ()
 setInAvail val = withStreamPtr $ \ptr ->
   #{poke bz_stream, avail_in} ptr (fromIntegral val :: CUInt)
@@ -528,40 +530,36 @@
 
 decompressInit :: Verbosity -> MemoryLevel -> Stream ()
 decompressInit verbosity memoryLevel = do
-  err <- withStreamPtr $ \ptr ->
-    bzDecompressInit ptr
+  err <- withStreamState $ \bzstream ->
+    bzDecompressInit bzstream
       (fromIntegral (fromEnum verbosity))
       (fromIntegral (fromEnum memoryLevel))
-  if isFatalError err
-    then throwError err
-    else do stream <- getStreamState
-            unsafeLiftIO $ addForeignPtrFinalizer bzDecompressEnd stream
+  failIfError err
+  getStreamState >>= unsafeLiftIO . addForeignPtrFinalizer bzDecompressEnd
 
 compressInit :: BlockSize -> Verbosity -> WorkFactor -> Stream ()
 compressInit blockSize verbosity workFactor = do
-  err <- withStreamPtr $ \ptr ->
-    bzCompressInit ptr
+  err <- withStreamState $ \bzstream ->
+    bzCompressInit bzstream
       (fromIntegral (fromEnum blockSize))
       (fromIntegral (fromEnum verbosity))
       (fromIntegral (fromEnum workFactor))
-  if isFatalError err
-    then throwError err
-    else do stream <- getStreamState
-            unsafeLiftIO $ addForeignPtrFinalizer bzCompressEnd stream
+  failIfError err
+  getStreamState >>= unsafeLiftIO . addForeignPtrFinalizer bzCompressEnd
 
 decompress_ :: Stream Status
 decompress_ = do
-  err <- withStreamPtr (\ptr -> bzDecompress ptr)
-  if isFatalError err
-    then throwError err
-    else return (toEnum (fromIntegral err))
+  err <- withStreamState $ \bzstream ->
+    bzDecompress bzstream
+  failIfError err
+  return (toEnum (fromIntegral err))
 
 compress_ :: Action -> Stream Status
 compress_ action = do
-  err <- withStreamPtr (\ptr -> bzCompress ptr (fromIntegral (fromEnum action)))
-  if isFatalError err
-    then throwError err
-    else return (toEnum (fromIntegral err))
+  err <- withStreamState $ \bzstream ->
+    bzCompress bzstream (fromIntegral (fromEnum action))
+  failIfError err
+  return (toEnum (fromIntegral err))
 
 -- | This never needs to be used as the stream's resources will be released
 -- automatically when no longer needed, however this can be used to release
@@ -574,23 +572,23 @@
 ----------------------
 -- The foreign imports
 
-data StreamState = StreamState ()
+newtype StreamState = StreamState (Ptr StreamState)
 
 foreign import ccall unsafe "bzlib.h BZ2_bzDecompressInit"
-  bzDecompressInit :: Ptr StreamState -> CInt -> CInt -> IO CInt
+  bzDecompressInit :: StreamState -> CInt -> CInt -> IO CInt
 
 foreign import ccall unsafe "bzlib.h BZ2_bzDecompress"
-  bzDecompress :: Ptr StreamState -> IO CInt
+  bzDecompress :: StreamState -> IO CInt
 
 foreign import ccall unsafe "bzlib.h &BZ2_bzDecompressEnd"
   bzDecompressEnd :: FinalizerPtr StreamState
 
 
 foreign import ccall unsafe "bzlib.h BZ2_bzCompressInit"
-  bzCompressInit :: Ptr StreamState -> CInt -> CInt -> CInt -> IO CInt
+  bzCompressInit :: StreamState -> CInt -> CInt -> CInt -> IO CInt
 
 foreign import ccall unsafe "bzlib.h BZ2_bzCompress"
-  bzCompress :: Ptr StreamState -> CInt -> IO CInt
+  bzCompress :: StreamState -> CInt -> IO CInt
 
 foreign import ccall unsafe "bzlib.h &BZ2_bzCompressEnd"
   bzCompressEnd :: FinalizerPtr StreamState
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2006-2007, Duncan Coutts
+Copyright (c) 2006-2008, Duncan Coutts
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/bunzip2.hs b/bunzip2.hs
new file mode 100644
--- /dev/null
+++ b/bunzip2.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import qualified Data.ByteString.Lazy as B
+import qualified Codec.Compression.BZip as BZip
+
+main = B.interact BZip.decompress
diff --git a/bzip2.hs b/bzip2.hs
new file mode 100644
--- /dev/null
+++ b/bzip2.hs
@@ -0,0 +1,6 @@
+module Main where
+
+import qualified Data.ByteString.Lazy as B
+import qualified Codec.Compression.BZip as BZip
+
+main = B.interact BZip.compress
diff --git a/bzlib.cabal b/bzlib.cabal
--- a/bzlib.cabal
+++ b/bzlib.cabal
@@ -1,15 +1,26 @@
 name:            bzlib
-version:         0.4.0.1
-copyright:       (c) 2006-2007 Duncan Coutts
+version:         0.4.0.3
+copyright:       (c) 2006-2008 Duncan Coutts
 license:         BSD3
 license-file:    LICENSE
 author:          Duncan Coutts <duncan@haskell.org>
 maintainer:      Duncan Coutts <duncan@haskell.org>
+category:        Codec
 synopsis:        Compression and decompression in the bzip2 format
+description:     This package provides a pure interface for compressing and 
+                 decompressing streams of data represented as lazy 
+                 'ByteString's. It uses the bz2 C library so it has high
+                 performance.
+                 .
+                 It provides a convenient high level api suitable for most
+                 tasks and for the few cases where more control is needed it
+                 provides access to the full bzip2 feature set.
 stability:       provisional
 build-type:      Simple
 cabal-version:   >= 1.2.1
 extra-source-files: cbits/bzlib_private.h
+                    -- demo programs:
+                    bzip2.hs bunzip2.hs
 
 flag bytestring-in-base
   description: In the ghc-6.6 era the bytestring modules were
@@ -27,9 +38,9 @@
   else
     build-depends: base < 2.0 || >= 2.2, bytestring >= 0.9
   includes:        bzlib.h
-  ghc-options:     -fvia-C
+  ghc-options:     -Wall
   if !os(windows)
-    -- Normally we use the the standard system zlib:
+    -- Normally we use the the standard system bz2 lib:
     extra-libraries: bz2
   else
     -- However for the benefit of users of Windows (which does not have zlib
