diff --git a/samtools.cabal b/samtools.cabal
--- a/samtools.cabal
+++ b/samtools.cabal
@@ -1,5 +1,5 @@
 Name:                samtools
-Version:             0.2.1
+Version:             0.2.1.1
 Synopsis:            Binding to the C samtools library
 Description:         Binding to the C samtools library, which reads and
                      writes SAM format alignments, both binary and tab-
@@ -32,7 +32,7 @@
 Library
   Exposed-modules:     Bio.SamTools.Bam, Bio.SamTools.Cigar,
                        Bio.SamTools.BamIndex, Bio.SamTools.FaIdx
-  Other-modules:       Bio.SamTools.LowLevel, Bio.SamTools.Internal, C2HS
+  Other-modules:       Bio.SamTools.LowLevel, Bio.SamTools.Internal
   Build-depends:       base >= 4.2 && < 5, bytestring, vector >= 0.7, seqloc >= 0.3.1
   Hs-Source-Dirs:      src
   Build-tools:         c2hs
@@ -62,7 +62,7 @@
   Main-is:             SamTest.hs
   Other-modules:       Bio.SamTools.Bam, Bio.SamTools.Cigar,
                        Bio.SamTools.BamIndex, Bio.SamTools.FaIdx,
-                       Bio.SamTools.LowLevel, Bio.SamTools.Internal, C2HS
+                       Bio.SamTools.LowLevel, Bio.SamTools.Internal
   Build-depends:       base >= 4.2 && < 5, bytestring, vector >= 0.7, seqloc >= 0.3.1, process, filepath
   Hs-Source-Dirs:      src, test
   Build-tools:         c2hs
diff --git a/src/Bio/SamTools/Bam.hs b/src/Bio/SamTools/Bam.hs
--- a/src/Bio/SamTools/Bam.hs
+++ b/src/Bio/SamTools/Bam.hs
@@ -58,7 +58,7 @@
 import Foreign hiding (new)
 import Foreign.C.Types
 import Foreign.C.String
-import System.IO.Unsafe (unsafeInterleaveIO)
+import qualified System.IO.Unsafe as Unsafe
 import qualified Data.Vector as V
 
 import Bio.SeqLoc.OnSeq
@@ -72,7 +72,7 @@
 -- | 'Just' the reference target sequence ID in the target set, or
 -- 'Nothing' for an unmapped read
 targetID :: Bam1 -> Maybe Int
-targetID b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromTID . getTID
+targetID b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromTID . getTID
   where fromTID ctid | ctid < 0 = Nothing
                      | otherwise = Just $! fromIntegral ctid
 
@@ -89,12 +89,12 @@
 -- | 'Just' the 0-based index of the leftmost aligned position on the
 -- target sequence, or 'Nothing' for an unmapped read
 position :: Bam1 -> Maybe Int64
-position b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromPos . getPos
+position b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromPos . getPos
   where fromPos cpos | cpos < 0 = Nothing
                      | otherwise = Just $! fromIntegral cpos
 
 isFlagSet :: BamFlag -> Bam1 -> Bool
-isFlagSet f b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM isfset . getFlag
+isFlagSet f b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM isfset . getFlag
   where isfset = (== f) . (.&. f)
 
 -- | Is the read paired
@@ -143,24 +143,24 @@
 
 -- | CIGAR description of the alignment
 cigars :: Bam1 -> [Cigar]
-cigars b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p -> do
+cigars b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p -> do
   nc <- getNCigar p
   liftM (map toCigar) $! peekArray nc . bam1Cigar $ p
 
 -- | Name of the query sequence
 queryName :: Bam1 -> BS.ByteString
-queryName b = unsafePerformIO $ withForeignPtr (ptrBam1 b) (return . bam1QName)
+queryName b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) (return . bam1QName)
 
 -- | 'Just' the length of the query sequence, or 'Nothing' when it is
 -- unavailable.
 queryLength :: Bam1 -> Maybe Int64
-queryLength b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromc . getLQSeq
+queryLength b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromc . getLQSeq
   where fromc clq | clq < 1 = Nothing
                   | otherwise = Just $! fromIntegral clq
 
 -- | 'Just' the query sequence, or 'Nothing' when it is unavailable
 querySeq :: Bam1 -> Maybe BS.ByteString
-querySeq b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p -> 
+querySeq b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p -> 
   let seqarr = bam1Seq p
       getQSeq l | l < 1 = return Nothing
                 | otherwise = return $! Just $! 
@@ -170,7 +170,7 @@
 -- | 'Just' the query qualities, or 'Nothing' when it is
 -- unavailable. These are returned in ASCII format, i.e., /q/ + 33.
 queryQual :: Bam1 -> Maybe BS.ByteString
-queryQual b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
+queryQual b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
   let getQQual l | l < 1 = return Nothing
                  | otherwise = do q0 <- peek $! bam1Qual p
                                   if q0 == 0xff
@@ -188,7 +188,7 @@
 -- sequence, or 'Nothing' when the mate is unmapped or the read is
 -- unpaired.
 mateTargetID :: Bam1 -> Maybe Int
-mateTargetID b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromTID . getMTID
+mateTargetID b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromTID . getMTID
   where fromTID ctid | ctid < 0 = Nothing
                      | otherwise = Just $! fromIntegral ctid
 
@@ -207,7 +207,7 @@
 -- mate alignment on the target, or 'Nothing' when the read is
 -- unpaired or the mate is unmapped.
 matePosition :: Bam1 -> Maybe Int64
-matePosition b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromPos . getMPos
+matePosition b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromPos . getMPos
   where fromPos cpos | cpos < 0  = Nothing
                      | otherwise = Just $! fromIntegral cpos
 
@@ -216,14 +216,14 @@
 -- pair do not align in the proper relative orientation on the same
 -- strand.
 insertSize :: Bam1 -> Maybe Int64
-insertSize b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromISize . getISize
+insertSize b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ liftM fromISize . getISize
   where fromISize cis | cis < 1 = Nothing
                       | otherwise = Just $! fromIntegral cis
 
 -- | 'Just' the match descriptor alignment field, or 'Nothing' when it
 -- is absent
 matchDesc :: Bam1 -> Maybe BS.ByteString
-matchDesc b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
+matchDesc b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
   withCAString "MD" $ \mdstr -> 
   do md <- bamAuxGet p mdstr
      if md == nullPtr
@@ -236,7 +236,7 @@
 -- | 'Just' the number of reported alignments, or 'Nothing' when this
 -- information is not present.
 nHits :: Bam1 -> Maybe Int
-nHits b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
+nHits b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
   withCAString "NH" $ \nhstr ->
   do nh <- bamAuxGet p nhstr
      if nh == nullPtr
@@ -246,7 +246,7 @@
 -- | 'Just' the number of mismatches in the alignemnt, or 'Nothing'
 -- when this information is not present
 nMismatch :: Bam1 -> Maybe Int
-nMismatch b = unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
+nMismatch b = Unsafe.unsafePerformIO $ withForeignPtr (ptrBam1 b) $ \p ->
   withCAString "NM" $ \nmstr ->
   do nm <- bamAuxGet p nmstr
      if nm == nullPtr
@@ -347,7 +347,7 @@
       b <- get1 h
       case b of Nothing -> closeInHandle h >> return []
                 Just b1 -> do
-                  bs <- unsafeInterleaveIO (getBams h)
+                  bs <- Unsafe.unsafeInterleaveIO (getBams h)
                   return (b1:bs)
 
 -- | Handle for writing SAM/BAM format alignments
diff --git a/src/Bio/SamTools/Internal.hs b/src/Bio/SamTools/Internal.hs
--- a/src/Bio/SamTools/Internal.hs
+++ b/src/Bio/SamTools/Internal.hs
@@ -5,6 +5,7 @@
 import qualified Data.ByteString.Char8 as BS
 import Foreign
 import Foreign.C.String
+import qualified System.IO.Unsafe as Unsafe
 
 import Bio.SamTools.LowLevel
 
@@ -38,11 +39,11 @@
   
 -- | Number of target sequences
 nTargets :: Header -> Int
-nTargets h = fromIntegral . unsafePerformIO $ withForeignPtr (unHeader h) getNTargets
+nTargets h = fromIntegral . Unsafe.unsafePerformIO $ withForeignPtr (unHeader h) getNTargets
 
 -- | Returns the list of target sequences
 targetSeqList :: Header -> [HeaderSeq]
-targetSeqList h = unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
+targetSeqList h = Unsafe.unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
   ntarg <- getNTargets bhdr
   names <- getTargetName bhdr
   lens <- getTargetLen bhdr
@@ -53,7 +54,7 @@
 
 -- | Returns a target sequence by ID, which is a 0-based index
 targetSeq :: Header -> Int -> HeaderSeq
-targetSeq h idx = unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
+targetSeq h idx = Unsafe.unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
   ntarg <- liftM fromIntegral . getNTargets $ bhdr
   when (idx < 0 || idx >= ntarg) $ ioError . userError $
     "Target id " ++ show idx ++ " > " ++ show (ntarg-1)
@@ -65,7 +66,7 @@
 
 -- | Returns a target sequence name by ID
 targetSeqName :: Header -> Int -> BS.ByteString
-targetSeqName h idx = unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
+targetSeqName h idx = Unsafe.unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
   ntarg <- liftM fromIntegral . getNTargets $ bhdr
   when (idx < 0 || idx >= ntarg) $ ioError . userError $
     "Target id " ++ show idx ++ " > " ++ show (ntarg - 1)
@@ -73,7 +74,7 @@
   peek (advancePtr names idx) >>= BS.packCString
 
 targetSeqLen :: Header -> Int -> Int64
-targetSeqLen h idx = unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
+targetSeqLen h idx = Unsafe.unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr -> do
   ntarg <- liftM fromIntegral . getNTargets $ bhdr
   when (idx < 0 || idx >= ntarg) $ ioError . userError $
     "Target id " ++ show idx ++ " > " ++ show (ntarg-1)
@@ -81,7 +82,7 @@
   liftM fromIntegral . peek $ advancePtr lens idx
 
 lookupTarget :: Header -> BS.ByteString -> Maybe Int
-lookupTarget h n = unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr ->
+lookupTarget h n = Unsafe.unsafePerformIO $ withForeignPtr (unHeader h) $ \bhdr ->
   liftM handleResult . bamGetTid bhdr $ n
     where handleResult res | res < 0 = Nothing    
                            | otherwise = Just $! fromIntegral res
@@ -92,7 +93,7 @@
                  }
 
 instance Show Bam1 where
-  show b = unsafePerformIO $ 
+  show b = Unsafe.unsafePerformIO $ 
            withForeignPtr (ptrBam1 b) $ \bp ->
            withForeignPtr (unHeader . header $ b) $ \hp -> do
              n <- bamFormat1 hp bp
diff --git a/src/Bio/SamTools/LowLevel.chs b/src/Bio/SamTools/LowLevel.chs
--- a/src/Bio/SamTools/LowLevel.chs
+++ b/src/Bio/SamTools/LowLevel.chs
@@ -42,7 +42,9 @@
                              )
 where
 
-import C2HS
+import Foreign hiding (Word)
+import Foreign.C
+
 import Control.Monad
 import qualified Data.ByteString.Char8 as BS
 
diff --git a/src/C2HS.hs b/src/C2HS.hs
deleted file mode 100644
--- a/src/C2HS.hs
+++ /dev/null
@@ -1,222 +0,0 @@
---  C->Haskell Compiler: Marshalling library
---
---  Copyright (c) [1999...2005] Manuel M T Chakravarty
---
---  Redistribution and use in source and binary forms, with or without
---  modification, are permitted provided that the following conditions are met:
--- 
---  1. Redistributions of source code must retain the above copyright notice,
---     this list of conditions and the following disclaimer. 
---  2. Redistributions in binary form must reproduce the above copyright
---     notice, this list of conditions and the following disclaimer in the
---     documentation and/or other materials provided with the distribution. 
---  3. The name of the author may not be used to endorse or promote products
---     derived from this software without specific prior written permission. 
---
---  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
---  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
---  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
---  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
---  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
---  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
---  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
---  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
---  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
---  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
---- Description ---------------------------------------------------------------
---
---  Language: Haskell 98
---
---  This module provides the marshaling routines for Haskell files produced by 
---  C->Haskell for binding to C library interfaces.  It exports all of the
---  low-level FFI (language-independent plus the C-specific parts) together
---  with the C->HS-specific higher-level marshalling routines.
---
-
-module C2HS (
-
-  -- * Re-export the language-independent component of the FFI 
-  module Foreign,
-
-  -- * Re-export the C language component of the FFI
-  module Foreign.C,
-
-  -- * Composite marshalling functions
-  withCStringLenIntConv, peekCStringLenIntConv, withIntConv, withFloatConv,
-  peekIntConv, peekFloatConv, withBool, peekBool, withEnum, peekEnum,
-
-  -- * Conditional results using 'Maybe'
-  nothingIf, nothingIfNull,
-
-  -- * Bit masks
-  combineBitMasks, containsBitMask, extractBitMasks,
-
-  -- * Conversion between C and Haskell types
-  cIntConv, cFloatConv, cToBool, cFromBool, cToEnum, cFromEnum
-) where 
-
-
-import Foreign
-       hiding       (Word)
-		    -- Should also hide the Foreign.Marshal.Pool exports in
-		    -- compilers that export them
---import CForeign
-import Foreign.C
-
---import Monad        (when, liftM)
-import Control.Monad (when, liftM)
-
-
--- Composite marshalling functions
--- -------------------------------
-
--- Strings with explicit length
---
-withCStringLenIntConv s f    = withCStringLen s $ \(p, n) -> f (p, cIntConv n)
-peekCStringLenIntConv (s, n) = peekCStringLen (s, cIntConv n)
-
--- Marshalling of numerals
---
-
-withIntConv   :: (Storable b, Integral a, Integral b) 
-	      => a -> (Ptr b -> IO c) -> IO c
-withIntConv    = with . cIntConv
-
-withFloatConv :: (Storable b, RealFloat a, RealFloat b) 
-	      => a -> (Ptr b -> IO c) -> IO c
-withFloatConv  = with . cFloatConv
-
-peekIntConv   :: (Storable a, Integral a, Integral b) 
-	      => Ptr a -> IO b
-peekIntConv    = liftM cIntConv . peek
-
-peekFloatConv :: (Storable a, RealFloat a, RealFloat b) 
-	      => Ptr a -> IO b
-peekFloatConv  = liftM cFloatConv . peek
-
--- Passing Booleans by reference
---
-
-withBool :: (Integral a, Storable a) => Bool -> (Ptr a -> IO b) -> IO b
-withBool  = with . fromBool
-
-peekBool :: (Integral a, Storable a) => Ptr a -> IO Bool
-peekBool  = liftM toBool . peek
-
-
--- Passing enums by reference
---
-
-withEnum :: (Enum a, Integral b, Storable b) => a -> (Ptr b -> IO c) -> IO c
-withEnum  = with . cFromEnum
-
-peekEnum :: (Enum a, Integral b, Storable b) => Ptr b -> IO a
-peekEnum  = liftM cToEnum . peek
-
-
--- Storing of 'Maybe' values
--- -------------------------
-
-instance Storable a => Storable (Maybe a) where
-  sizeOf    _ = sizeOf    (undefined :: Ptr ())
-  alignment _ = alignment (undefined :: Ptr ())
-
-  peek p = do
-	     ptr <- peek (castPtr p)
-	     if ptr == nullPtr
-	       then return Nothing
-	       else liftM Just $ peek ptr
-
-  poke p v = do
-	       ptr <- case v of
-		        Nothing -> return nullPtr
-			Just v' -> new v'
-               poke (castPtr p) ptr
-
-
--- Conditional results using 'Maybe'
--- ---------------------------------
-
--- Wrap the result into a 'Maybe' type.
---
--- * the predicate determines when the result is considered to be non-existing,
---   ie, it is represented by `Nothing'
---
--- * the second argument allows to map a result wrapped into `Just' to some
---   other domain
---
-nothingIf       :: (a -> Bool) -> (a -> b) -> a -> Maybe b
-nothingIf p f x  = if p x then Nothing else Just $ f x
-
--- |Instance for special casing null pointers.
---
-nothingIfNull :: (Ptr a -> b) -> Ptr a -> Maybe b
-nothingIfNull  = nothingIf (== nullPtr)
-
-
--- Support for bit masks
--- ---------------------
-
--- Given a list of enumeration values that represent bit masks, combine these
--- masks using bitwise disjunction.
---
-combineBitMasks :: (Enum a, Bits b) => [a] -> b
-combineBitMasks = foldl (.|.) 0 . map (fromIntegral . fromEnum)
-
--- Tests whether the given bit mask is contained in the given bit pattern
--- (i.e., all bits set in the mask are also set in the pattern).
---
-containsBitMask :: (Bits a, Enum b) => a -> b -> Bool
-bits `containsBitMask` bm = let bm' = fromIntegral . fromEnum $ bm
-			    in
-			    bm' .&. bits == bm'
-
--- |Given a bit pattern, yield all bit masks that it contains.
---
--- * This does *not* attempt to compute a minimal set of bit masks that when
---   combined yield the bit pattern, instead all contained bit masks are
---   produced.
---
-extractBitMasks :: (Bits a, Enum b, Bounded b) => a -> [b]
-extractBitMasks bits = 
-  [bm | bm <- [minBound..maxBound], bits `containsBitMask` bm]
-
-
--- Conversion routines
--- -------------------
-
--- |Integral conversion
---
-cIntConv :: (Integral a, Integral b) => a -> b
-cIntConv  = fromIntegral
-
--- |Floating conversion
---
-cFloatConv :: (RealFloat a, RealFloat b) => a -> b
-cFloatConv  = realToFrac
--- As this conversion by default goes via `Rational', it can be very slow...
-{-# RULES 
-  "cFloatConv/Float->Float"   forall (x::Float).  cFloatConv x = x;
-  "cFloatConv/Double->Double" forall (x::Double). cFloatConv x = x
- #-}
-
--- |Obtain C value from Haskell 'Bool'.
---
-cFromBool :: Num a => Bool -> a
-cFromBool  = fromBool
-
--- |Obtain Haskell 'Bool' from C value.
---
-cToBool :: Num a => a -> Bool
-cToBool  = toBool
-
--- |Convert a C enumeration to Haskell.
---
-cToEnum :: (Integral i, Enum e) => i -> e
-cToEnum  = toEnum . cIntConv
-
--- |Convert a Haskell enumeration to C.
---
-cFromEnum :: (Enum e, Integral i) => e -> i
-cFromEnum  = cIntConv . fromEnum
