/* ISC license. */ #include #ifdef SKALIBS_HASSPLICE #include #include #include #include #include #include #include #include #include #include #include "tipideed-internal.h" struct fixed_info_s { int fd ; size_t n ; } ; static int fixed_getfd (void *b) { struct fixed_info_s *si = b ; return si->fd ; } static ssize_t fixed_get (void *b) { struct fixed_info_s *si = b ; while (si->n) { ssize_t r = sanitize_read(splice(si->fd, 0, 1, 0, si->n, SPLICE_F_NONBLOCK)) ; if (r == -1) break ; if (!r) return 0 ; si->n -= r ; } return si->n ? -1 : 1 ; } void stream_fixed (int fd, size_t n, char const *fn) { tain deadline ; struct fixed_info_s si = { .fd = fd, .n = n } ; tain_add_g(&deadline, tain_less(&g.writetto, &g.cgitto) ? &g.cgitto : &g.writetto) ; if (timed_get_g(&si, &fixed_getfd, &fixed_get, &deadline) < 0) strerr_diefu3sys(111, "splice from ", fn, " to stdout") ; } void stream_infinite (int fd, char const *fn) { ssize_t r ; /* only works when fd is a pipe, which is the case for cgi; fcgi/scgi will need refactoring */ /* XXX: ignores timeouts, but this is just TOO GOOD to pass up */ /* no really, it is just optimal in 99.9% of cases, it is WORTH IT */ while ((r = splice(fd, 0, 1, 0, 65536, SPLICE_F_MORE)) > 0) ; /* You WISH you had written that line of code */ if (r == -1) strerr_diefu3sys(111, "splice from ", fn, " to stdout") ; } #else #include #include #include #include #include #include #include #include #include #include "tipideed-internal.h" void stream_fixed (int fd, size_t n, char const *fn) { tain deadline ; struct iovec v[2] ; size_t r ; if (!n) goto flushit ; fillit: buffer_wpeek(buffer_1, v) ; siovec_trunc(v, 2, n) ; tain_add_g(&deadline, &g.cgitto) ; r = timed_readv_g(fd, v, 2, &deadline) ; if (r == -1) strerr_diefu2sys(111, "read from resource ", fn) ; if (!r) strerr_dief3x(111, "resource ", fn, " provided less content than advertised in Content-Length") ; buffer_wseek(buffer_1, r) ; n -= r ; flushit: tain_add_g(&deadline, &g.writetto) ; if (!buffer_timed_flush_g(buffer_1, &deadline)) strerr_diefu1sys(111, "write to stdout") ; if (n) goto fillit ; } void stream_infinite (int fd, char const *fn) { tain deadline ; struct iovec v[2] ; size_t r ; for (;;) { buffer_wpeek(buffer_1, v) ; tain_add_g(&deadline, &g.cgitto) ; r = timed_readv_g(fd, v, 2, &deadline) ; if (r == -1) strerr_diefu2sys(111, "read from resource ", fn) ; if (!r) break ; tain_add_g(&deadline, &g.writetto) ; if (!buffer_timed_flush_g(buffer_1, &deadline)) strerr_diefu1sys(111, "write to stdout") ; } } #endif #include void stream_autochunk (buffer *b, char const *fn) { }