File Coverage

lib/Sys/Sendfile.xs
Criterion Covered Total %
statement 8 10 80.0
branch 14 26 53.8
condition n/a
subroutine n/a
pod n/a
total 22 36 61.1


line stmt bran cond sub pod time code
1             /*
2             * This software is copyright (c) 2008, 2009 by Leon Timmermans .
3             *
4             * This is free software; you can redistribute it and/or modify it under
5             * the same terms as perl itself.
6             *
7             */
8              
9             #if defined linux || defined solaris || (defined (__SVR4) && defined (__sun))
10             #define OS_LINUX
11             #elif defined __FreeBSD__ || defined __FreeBSD_kernel__
12             #define OS_BSD
13             #elif defined __APPLE__
14             #define OS_X
15             #elif defined _WIN32
16             #define OS_WIN32
17             #else
18             #define OS_FALLBACK
19             #endif
20              
21             #if defined OS_LINUX
22             #include
23             #elif defined OS_BSD || defined OS_X
24             #include
25             #include
26             #include
27             #elif defined OS_WIN32
28             #include
29             #ifndef _MSC_VER
30             #include
31             #endif
32             #else
33             #include
34             #endif
35              
36             #ifndef _MSC_VER
37             #include
38             #ifndef MAP_FILE
39             #define MAP_FILE 0
40             #endif
41             #endif
42              
43             #define PERL_NO_GET_CONTEXT
44             #include "EXTERN.h"
45             #include "perl.h"
46             #include "XSUB.h"
47              
48             #define PERL_VERSION_ATLEAST(a,b,c) \
49             (PERL_VERSION > (b) \
50             || (PERL_VERSION == (b) && PERL_SUBVERSION >= (c)))
51              
52             #if defined(USE_SOCKETS_AS_HANDLES) || PERL_VERSION_ATLEAST(5,17,5)
53             # define TO_SOCKET(x) _get_osfhandle(x)
54             #else
55             # define TO_SOCKET(x) (x)
56             #endif /* USE_SOCKETS_AS_HANDLES */
57              
58             #define undef &PL_sv_undef
59              
60             MODULE = Sys::Sendfile PACKAGE = Sys::Sendfile
61              
62             SV*
63             sendfile(out, in, count = undef, offset = undef)
64             int out = PerlIO_fileno(IoOFP(sv_2io(ST(0))));
65             int in = PerlIO_fileno(IoIFP(sv_2io(ST(1))));
66             SV* count;
67             SV* offset;
68             PROTOTYPE: **@
69             CODE:
70             {
71 2 50         Off_t real_offset = SvOK(offset) ? SvUV(offset) : (off_t)lseek(in, 0, SEEK_CUR);
    50          
    50          
    0          
72 2 100         Off_t real_count = SvOK(count) ? SvUV(count) : 0u;
    50          
    50          
    50          
73             #if defined(OS_BSD) || defined(OS_X)
74             if (SvOK(count) && real_count == 0)
75             XSRETURN_IV(0);
76             #else
77 2 100         if (!SvOK(count)) {
    50          
    50          
78             struct stat info;
79 1 50         if (fstat(in, &info) == -1)
80 0           XSRETURN_EMPTY;
81 1           real_count = info.st_size - real_offset;
82             }
83             #endif
84             #if defined OS_LINUX
85             {
86 2           ssize_t success = sendfile(out, in, &real_offset, real_count);
87 2 50         if (success == -1)
88 0           XSRETURN_EMPTY;
89             else
90 2           XSRETURN_IV(success);
91             }
92             #elif defined OS_BSD
93             off_t bytes;
94             int ret = sendfile(in, out, real_offset, real_count, NULL, &bytes, 0);
95             if (ret == -1 && bytes == 0 && ! (errno == EAGAIN || errno == EINTR))
96             XSRETURN_EMPTY;
97             else
98             XSRETURN_IV(bytes);
99             #elif defined OS_X
100             off_t bytes = real_count;
101             int ret = sendfile(in, out, real_offset, &bytes, NULL, 0);
102             if (ret == -1 && bytes == 0 && ! (errno == EAGAIN || errno == EINTR))
103             XSRETURN_EMPTY;
104             else
105             XSRETURN_IV(bytes);
106             #elif defined OS_WIN32
107             HANDLE hFile = TO_SOCKET(in);
108             int ret;
109             if (SvOK(offset))
110             SetFilePointer(hFile, real_offset, NULL, FILE_BEGIN);
111             ret = TransmitFile(TO_SOCKET(out), hFile, (DWORD)real_count, 0, NULL, NULL, 0);
112             if (!ret)
113             XSRETURN_EMPTY;
114             else
115             XSRETURN_IV(real_count);
116             #else
117             int ret;
118             void* buffer = mmap(NULL, real_count, PROT_READ, MAP_SHARED | MAP_FILE, in, real_offset);
119             if (buffer == MAP_FAILED)
120             XSRETURN_EMPTY;
121             ret = write(out, buffer, real_count);
122             if (ret == -1)
123             XSRETURN_EMPTY;
124             else
125             XSRETURN_IV(ret);
126             #endif
127             }