1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
/* ISC license. */
#include <skalibs/sysdeps.h>
#ifdef SKALIBS_HASSENDFILE
#include <sys/types.h>
#include <sys/sendfile.h>
#include <limits.h>
#include <skalibs/uint64.h>
#include <skalibs/strerr.h>
#include <skalibs/tai.h>
#include <skalibs/unix-timed.h>
struct sendfile_s
{
int fd ;
buffer *out ;
off_t pos ;
uint64_t n ;
} ;
static int s_getfd (void *p)
{
struct sendfile_s *sf = p ;
return buffer_fd(sf->out) ;
}
static int s_isnonempty (void *p)
{
struct sendfile_s *sf = p ;
return !!sf->n ;
}
static int s_flush (void *p)
{
struct sendfile_s *sf = p ;
while (sf->n)
{
ssize_t r = sendfile(buffer_fd(sf->out), sf->fd, &sf->pos, sf->n > SSIZE_MAX ? SSIZE_MAX : sf->n) ;
if (r == -1) return 0 ;
sf->n -= r ;
}
return 1 ;
}
void send_file (buffer *b, int fd, off_t size, char const *fn, tain const *deadline, tain *stamp)
{
struct sendfile_s sf = { .fd = fd, .out = b, .pos = 0, .n = size } ;
if (!buffer_timed_flush(b, deadline, stamp))
strerr_diefu1sys(111, "write to network") ;
if (!timed_flush(&sf, &s_getfd, &s_isnonempty, &s_flush, deadline, stamp))
strerr_diefu3sys(111, "sendfile ", fn, " to network") ;
}
#else
#include <sys/uio.h>
#include <unistd.h>
#include <stdint.h>
#include <skalibs/uint64.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr.h>
#include <skalibs/tai.h>
#include <skalibs/unix-timed.h>
void send_file (buffer *b, int fd, uint64_t n, char const *fn, tain const *deadline, tain *stamp)
{
struct iovec v[2] ;
ssize_t r ;
if (!n) goto flushit ;
fillit:
buffer_wpeek(b, v) ;
r = allreadv(fd, v, 2) ;
if (r == -1) strerr_diefu2sys(111, "read from ", fn) ;
if (!r) strerr_diefu3x(111, "send ", fn, ": file was truncated") ;
if (r > n)
{
r = n ;
strerr_warnw2x("sending elongated file: ", fn) ;
}
buffer_wseek(b, r) ;
n -= r ;
flushit:
if (!buffer_timed_flush(b, deadline, stamp))
strerr_diefu1sys(111, "write to network") ;
if (n) goto fillit ;
}
#endif
|