aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--System/Sendfile.hsc87
-rw-r--r--include/HsUnix.h11
3 files changed, 98 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index b997a0d..5f59511 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ PACKAGE = unix
PACKAGE_DEPS = base
SRC_HADDOCK_OPTS += -t "Haskell Core Libraries (unix package)"
-SRC_HSC2HS_OPTS += -Iinclude
+SRC_HSC2HS_OPTS += -Iinclude -I../../mk/
SRC_HC_OPTS += -Iinclude
include $(TOP)/mk/target.mk
diff --git a/System/Sendfile.hsc b/System/Sendfile.hsc
new file mode 100644
index 0000000..c85a1e6
--- /dev/null
+++ b/System/Sendfile.hsc
@@ -0,0 +1,87 @@
+{-# OPTIONS -fglasgow-exts -cpp #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module : System.Sendfile
+-- Copyright : (c) Volker Stolz 2003
+-- License : BSD-style (see the file libraries/core/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : provisional
+-- Portability : fallback NYI
+--
+-- "System.Sendfile.sendfile" is a low-level method for efficently passing
+-- data from one file descriptor to another.
+-- The intended audience includes for example web server authors. Please
+-- note that this function is highly platform dependent.
+--
+-----------------------------------------------------------------------------
+
+module System.Sendfile (sendfile) where
+
+#include "config.h"
+#include "HsUnix.h"
+
+import Foreign
+import Foreign.C
+import System.IO (Handle)
+import System.Posix.IO (handleToFd)
+import System.Posix.Types (Fd, COff)
+
+-- |'sendfile' transmits the contents of an open file to a stream socket
+-- opened for writing with as little overhead as possible. This function
+-- is not defined by any standard!
+-- Notice that passing 0 as 'count' may result in undefined behaviour and
+-- should be avoided. On Linux, nothing is transmitted while on FreeBSD
+-- the entire file will be sent.
+
+sendfile :: Handle -- Input
+ -> Handle -- Output
+ -> Int -- Offset
+ -> Int -- Nr. of bytes to transmit
+ -> IO ()
+sendfile inH outH startpos count = do
+
+#ifdef HAVE_LINUX_SENDFILE
+
+ inFd <- handleToFd inH
+ outFd <- handleToFd outH
+ offsetptr <- malloc
+ poke offsetptr (fromIntegral startpos)
+ throwErrnoIfMinus1_ "sendfile" $ c_sendfile outFd inFd offsetptr (fromIntegral count)
+ free offsetptr
+ return ()
+
+foreign import ccall unsafe "sendfile"
+ c_sendfile :: Fd -> Fd -> Ptr COff -> CSize -> IO CSize
+
+#else /* Linux */
+# ifdef HAVE_BSD_SENDFILE
+
+ inFd <- handleToFd inH
+ outFd <- handleToFd outH
+ offsetptr <- malloc
+ rc <- sendfileLoop inFd outFd (fromIntegral startpos) (fromIntegral count) offsetptr
+ free offsetptr
+ return ()
+ where
+ sendfileLoop :: Fd -> Fd -> COff -> CSize -> Ptr COff -> IO CInt
+ sendfileLoop inFd outFd start c offsetptr = do
+ rc <- c_sendfile inFd outFd start c nullPtr offsetptr 0
+ if rc == -1
+ then do
+ err <- getErrno
+ case err of
+ eAGAIN -> do
+ offset <- peek offsetptr -- now contains # of bytes written
+ sendfileLoop inFd outFd (start+offset) (c-(fromIntegral offset)) offsetptr
+ otherwise -> throwErrno "sendfile"
+ else
+ return rc
+
+foreign import ccall unsafe "sendfile"
+ c_sendfile :: Fd -> Fd -> COff -> CSize -> Ptr a -> Ptr COff -> CInt -> IO CInt
+
+# else /* BSD */
+ error "Sorry, sendfile(2) is not supported on your platform and currently no fallback is available"
+# endif /* ERROR */
+#endif
diff --git a/include/HsUnix.h b/include/HsUnix.h
index 914151c..5488f71 100644
--- a/include/HsUnix.h
+++ b/include/HsUnix.h
@@ -1,5 +1,5 @@
/* -----------------------------------------------------------------------------
- * $Id: HsUnix.h,v 1.3 2002/12/19 13:52:55 simonmar Exp $
+ * $Id: HsUnix.h,v 1.4 2003/01/17 17:01:14 stolz Exp $
*
* (c) The University of Glasgow 2002
*
@@ -52,6 +52,15 @@
#include <grp.h>
#endif
+#ifdef HAVE_BSD_SENDFILE
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_LINUX_SENDFILE
+#include <sys/sendfile.h>
+#endif
+
extern int execvpe(char *name, char **argv, char **envp);
extern void pPrPr_disableITimers (void);