File Coverage

lib/Sys/Sendfile.xs
Criterion Covered Total %
statement 8 10 80.0
branch 7 10 70.0
condition n/a
subroutine n/a
pod n/a
total 15 20 75.0


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__ || defined __DragonFly__
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             #ifndef _MSC_VER
29             #include
30             #endif
31             #include
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);
72 2 100         Off_t real_count = SvOK(count) ? SvUV(count) : 0u;
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)) {
78             #if defined OS_WIN32
79             struct w32_stat info;
80             #else
81             struct stat info;
82             #endif
83 1 50         if (fstat(in, &info) == -1)
84 0           XSRETURN_EMPTY;
85 1           real_count = info.st_size - real_offset;
86             }
87             #endif
88             #if defined OS_LINUX
89             {
90 2           ssize_t success = sendfile(out, in, &real_offset, real_count);
91 2 50         if (success == -1)
92 0           XSRETURN_EMPTY;
93             else
94 2           XSRETURN_IV(success);
95             }
96             #elif defined OS_BSD
97             off_t bytes;
98             int ret = sendfile(in, out, real_offset, real_count, NULL, &bytes, 0);
99             if (ret == -1 && bytes == 0 && ! (errno == EAGAIN || errno == EINTR))
100             XSRETURN_EMPTY;
101             else
102             XSRETURN_IV(bytes);
103             #elif defined OS_X
104             off_t bytes = real_count;
105             int ret = sendfile(in, out, real_offset, &bytes, NULL, 0);
106             if (ret == -1 && bytes == 0 && ! (errno == EAGAIN || errno == EINTR))
107             XSRETURN_EMPTY;
108             else
109             XSRETURN_IV(bytes);
110             #elif defined OS_WIN32
111             HANDLE hFile = (HANDLE)TO_SOCKET(in);
112             int ret;
113             if (SvOK(offset))
114             SetFilePointer(hFile, real_offset, NULL, FILE_BEGIN);
115             ret = TransmitFile(TO_SOCKET(out), hFile, (DWORD)real_count, 0, NULL, NULL, 0);
116             if (!ret)
117             XSRETURN_EMPTY;
118             else
119             XSRETURN_IV(real_count);
120             #else
121             int ret;
122             void* buffer = mmap(NULL, real_count, PROT_READ, MAP_SHARED | MAP_FILE, in, real_offset);
123             if (buffer == MAP_FAILED)
124             XSRETURN_EMPTY;
125             ret = write(out, buffer, real_count);
126             if (ret == -1)
127             XSRETURN_EMPTY;
128             else
129             XSRETURN_IV(ret);
130             #endif
131             }