diff --git a/Data/ByteString.hs b/Data/ByteString.hs
--- a/Data/ByteString.hs
+++ b/Data/ByteString.hs
@@ -194,6 +194,7 @@
         hGetLine,               -- :: Handle -> IO ByteString
         hGetContents,           -- :: Handle -> IO ByteString
         hGet,                   -- :: Handle -> Int -> IO ByteString
+        hGetSome,               -- :: Handle -> Int -> IO ByteString
         hGetNonBlocking,        -- :: Handle -> Int -> IO ByteString
         hPut,                   -- :: Handle -> ByteString -> IO ()
         hPutStr,                -- :: Handle -> ByteString -> IO ()
@@ -256,6 +257,10 @@
 
 import System.IO                (hGetBufNonBlocking)
 
+#if MIN_VERSION_base(4,3,0)
+import System.IO                (hGetBufSome)
+#endif
+
 #if __GLASGOW_HASKELL__ >= 611
 import Data.IORef
 import GHC.IO.Handle.Internals
@@ -1937,6 +1942,32 @@
 #else
 hGetNonBlocking = hGet
 #endif
+
+-- | Like 'hGet', except that a shorter 'ByteString' may be returned
+-- if there are not enough bytes immediately available to satisfy the
+-- whole request.  'hGetSome' only blocks if there is no data
+-- available, and EOF has not yet been reached.
+--
+hGetSome :: Handle -> Int -> IO ByteString
+hGetSome hh i
+#if MIN_VERSION_base(4,3,0)
+    | i >  0    = createAndTrim i $ \p -> hGetBufSome hh p i
+#else
+    | i >  0    = let
+                   loop = do
+                     s <- hGetNonBlocking h i
+                     if not (null s)
+                        then return s
+                        else eof <- hIsEOF h
+                             if eof then return s
+                                    else hWaitForInput h (-1) >> loop
+                                         -- for this to work correctly, the
+                                         -- Handle should be in binary mode
+                                         -- (see GHC ticket #3808)
+                  in loop
+#endif
+    | i == 0    = return empty
+    | otherwise = illegalBufferSize hh "hGetSome" i
 
 illegalBufferSize :: Handle -> String -> Int -> IO a
 illegalBufferSize handle fn sz =
diff --git a/Data/ByteString/Lazy.hs b/Data/ByteString/Lazy.hs
--- a/Data/ByteString/Lazy.hs
+++ b/Data/ByteString/Lazy.hs
@@ -213,7 +213,7 @@
 import Data.Word                (Word8)
 import Data.Int                 (Int64)
 import System.IO                (Handle,stdin,stdout,openBinaryFile,IOMode(..)
-                                ,hClose,hWaitForInput,hIsEOF)
+                                ,hClose)
 import System.IO.Error          (mkIOError, illegalOperationErrorType)
 import System.IO.Unsafe
 #ifndef __NHC__
@@ -1168,21 +1168,19 @@
 --
 -- The handle is closed on EOF.
 --
+-- Note: the 'Handle' should be placed in binary mode with
+-- 'System.IO.hSetBinaryMode' for 'hGetContentsN' to
+-- work correctly.
+--
 hGetContentsN :: Int -> Handle -> IO ByteString
 hGetContentsN k h = lazyRead -- TODO close on exceptions
   where
     lazyRead = unsafeInterleaveIO loop
 
     loop = do
-        c <- S.hGetNonBlocking h k
-        --TODO: I think this should distinguish EOF from no data available
-        -- the underlying POSIX call makes this distincion, returning either
-        -- 0 or EAGAIN
+        c <- S.hGetSome h k -- only blocks if there is no data available
         if S.null c
-          then do eof <- hIsEOF h
-                  if eof then hClose h >> return Empty
-                         else hWaitForInput h (-1)
-                           >> loop
+          then do hClose h >> return Empty
           else do cs <- lazyRead
                   return (Chunk c cs)
 
@@ -1236,6 +1234,10 @@
 -- are read on demand, using the default chunk size.
 --
 -- Once EOF is encountered, the Handle is closed.
+--
+-- Note: the 'Handle' should be placed in binary mode with
+-- 'System.IO.hSetBinaryMode' for 'hGetContents' to
+-- work correctly.
 --
 hGetContents :: Handle -> IO ByteString
 hGetContents = hGetContentsN defaultChunkSize
diff --git a/Data/ByteString/Unsafe.hs b/Data/ByteString/Unsafe.hs
--- a/Data/ByteString/Unsafe.hs
+++ b/Data/ByteString/Unsafe.hs
@@ -153,10 +153,11 @@
 --
 unsafePackAddress :: Addr# -> IO ByteString
 unsafePackAddress addr# = do
-    p <- newForeignPtr_ cstr
+    p <- newForeignPtr_ (castPtr cstr)
     l <- c_strlen cstr
     return $ PS p 0 (fromIntegral l)
   where
+    cstr :: CString
     cstr = Ptr addr#
 {-# INLINE unsafePackAddress #-}
 
diff --git a/bytestring.cabal b/bytestring.cabal
--- a/bytestring.cabal
+++ b/bytestring.cabal
@@ -1,5 +1,5 @@
 Name:                bytestring
-Version:             0.9.1.7
+Version:             0.9.1.8
 Synopsis:            Fast, packed, strict and lazy byte arrays with a list interface
 Description:
     A time and space-efficient implementation of byte vectors using
