diff --git a/Network/Sendfile/Linux.hsc b/Network/Sendfile/Linux.hsc
--- a/Network/Sendfile/Linux.hsc
+++ b/Network/Sendfile/Linux.hsc
@@ -2,7 +2,9 @@
 
 module Network.Sendfile.Linux (
     sendfile
+  , sendfile'
   , sendfileFd
+  , sendfileFd'
   , sendfileWithHeader
   , sendfileFdWithHeader
   ) where
@@ -24,6 +26,7 @@
 import Network.Socket
 import System.Posix.Files
 import System.Posix.IO
+import qualified System.Posix.IO.ByteString as B
 import System.Posix.Types
 
 #include <sys/sendfile.h>
@@ -65,6 +68,13 @@
     setup = openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
     teardown = closeFd
 
+sendfile' :: Fd -> ByteString -> FileRange -> IO () -> IO ()
+sendfile' dst path range hook = bracket setup teardown $ \src ->
+    sendfileFd' dst src range hook
+  where
+    setup = B.openFd path ReadOnly Nothing defaultFileFlags{nonBlock=True}
+    teardown = closeFd
+
 -- |
 -- Simple binding for sendfile() of Linux.
 -- Used system calls:
@@ -80,22 +90,24 @@
 -- Chucking is inevitable if the socket is non-blocking (this is the
 -- default) and the file is large. The action is called after a chunk
 -- is sent and bofore waiting the socket to be ready for writing.
-
 sendfileFd :: Socket -> Fd -> FileRange -> IO () -> IO ()
-sendfileFd sock fd range hook =
+sendfileFd sock fd range hook = sendfileFd' dst fd range hook
+  where
+    dst = Fd $ fdSocket sock
+
+sendfileFd' :: Fd -> Fd -> FileRange -> IO () -> IO ()
+sendfileFd' dst src range hook =
     alloca $ \offp -> case range of
         EntireFile -> do
             poke offp 0
             -- System call is very slow. Use PartOfFile instead.
-            len <- fileSize <$> getFdStatus fd
+            len <- fileSize <$> getFdStatus src
             let len' = fromIntegral len
-            sendfileloop dst fd offp len' hook
+            sendfileloop dst src offp len' hook
         PartOfFile off len -> do
             poke offp (fromIntegral off)
             let len' = fromIntegral len
-            sendfileloop dst fd offp len' hook
-  where
-    dst = Fd $ fdSocket sock
+            sendfileloop dst src offp len' hook
 
 sendfileloop :: Fd -> Fd -> Ptr COff -> CSize -> IO () -> IO ()
 sendfileloop dst src offp len hook = do
@@ -121,12 +133,12 @@
 
 -- Dst Src in order. take care
 foreign import ccall unsafe "sendfile"
-    c_sendfile32 :: Fd -> Fd -> Ptr COff -> CSize -> IO (#type ssize_t)
+    c_sendfile32 :: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize
 
 foreign import ccall unsafe "sendfile64"
-    c_sendfile64 :: Fd -> Fd -> Ptr COff -> CSize -> IO (#type ssize_t)
+    c_sendfile64 :: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize
 
-c_sendfile :: Fd -> Fd -> Ptr COff -> CSize -> IO (#type ssize_t)
+c_sendfile :: Fd -> Fd -> Ptr COff -> CSize -> IO CSsize
 c_sendfile
   | isLargeOffset = c_sendfile64
   | otherwise     = c_sendfile32
@@ -191,16 +203,16 @@
         siz = fromIntegral len
     sendloop s buf siz
   where
-    MkSocket s _ _ _ _ = sock
+    s = Fd $ fdSocket sock
     PS fptr off len = bs
 
-sendloop :: CInt -> Ptr CChar -> CSize -> IO ()
+sendloop :: Fd -> Ptr CChar -> CSize -> IO ()
 sendloop s buf len = do
     bytes <- c_send s buf len (#const MSG_MORE)
     if bytes == -1 then do
         errno <- getErrno
         if errno == eAGAIN then do
-            threadWaitWrite (Fd s)
+            threadWaitWrite s
             sendloop s buf len
           else
             throwErrno "Network.SendFile.Linux.sendloop"
@@ -212,4 +224,4 @@
             sendloop s ptr left
 
 foreign import ccall unsafe "send"
-  c_send :: CInt -> Ptr CChar -> CSize -> CInt -> IO (#type ssize_t)
+  c_send :: Fd -> Ptr CChar -> CSize -> CInt -> IO CSsize
diff --git a/System/Linux/Sendfile.hs b/System/Linux/Sendfile.hs
new file mode 100644
--- /dev/null
+++ b/System/Linux/Sendfile.hs
@@ -0,0 +1,47 @@
+module System.Linux.Sendfile (
+    sendfile
+  , sendfileFd
+  ) where
+
+import Data.ByteString (ByteString)
+import Network.Sendfile.Linux (sendfile', sendfileFd')
+import Network.Sendfile.Types (FileRange)
+import System.Posix.Types (Fd)
+
+-- |
+-- Simple binding for sendfile() of Linux.
+-- Used system calls:
+--
+--  - EntireFile -- open(), stat(), sendfile(), and close()
+--
+--  - PartOfFile -- open(), sendfile(), and close()
+--
+-- If the size of the file is unknown when sending the entire file,
+-- specifying PartOfFile is much faster.
+--
+-- The fourth action argument is called when a file is sent as chunks.
+-- Chucking is inevitable if the socket is non-blocking (this is the
+-- default) and the file is large. The action is called after a chunk
+-- is sent and bofore waiting the socket to be ready for writing.
+
+sendfile :: Fd -> ByteString -> FileRange -> IO () -> IO ()
+sendfile = sendfile'
+
+-- |
+-- Simple binding for sendfile() of Linux.
+-- Used system calls:
+--
+--  - EntireFile -- stat() and sendfile()
+--
+--  - PartOfFile -- sendfile()
+--
+-- If the size of the file is unknown when sending the entire file,
+-- specifying PartOfFile is much faster.
+--
+-- The fourth action argument is called when a file is sent as chunks.
+-- Chucking is inevitable if the socket is non-blocking (this is the
+-- default) and the file is large. The action is called after a chunk
+-- is sent and bofore waiting the socket to be ready for writing.
+
+sendfileFd :: Fd -> Fd -> FileRange -> IO () -> IO ()
+sendfileFd = sendfileFd'
diff --git a/simple-sendfile.cabal b/simple-sendfile.cabal
--- a/simple-sendfile.cabal
+++ b/simple-sendfile.cabal
@@ -1,5 +1,5 @@
 Name:                   simple-sendfile
-Version:                0.2.21
+Version:                0.2.22
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -39,6 +39,7 @@
     else
       if os(linux)
         CPP-Options:    -DOS_Linux
+        Exposed-Modules: System.Linux.Sendfile
         Other-Modules:  Network.Sendfile.Linux
         Build-Depends:  unix
       else
