diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | System/Sendfile.hsc | 87 | ||||
-rw-r--r-- | include/HsUnix.h | 11 |
3 files changed, 98 insertions, 2 deletions
@@ -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); |