Adding initial send-file interface.

This commit is contained in:
Alex Shinn 2013-08-18 18:36:24 +09:00
parent a32edf7138
commit 7a27341ecd
5 changed files with 52 additions and 1 deletions

View file

@ -641,6 +641,10 @@
#define SEXP_USE_MAIN_HELP ! SEXP_USE_NO_FEATURES
#endif
#ifndef SEXP_USE_SEND_FILE
#define SEXP_USE_SEND_FILE (!defined(_WIN32) && !defined(PLAN9))
#endif
#if SEXP_USE_NATIVE_X86
#undef SEXP_USE_BOEHM
#define SEXP_USE_BOEHM 1

View file

@ -11,7 +11,8 @@
make-filtered-input-port string-count
open-input-bytevector open-output-bytevector get-output-bytevector
string->utf8 utf8->string
write-string write-u8 read-u8 peek-u8)
write-string write-u8 read-u8 peek-u8 send-file
is-a-socket?)
(import (chibi) (chibi ast))
(include-shared "io/io")
(include "io/io.scm"))

View file

@ -164,6 +164,27 @@
(port-line-set! in (+ (string-count #\newline str 0 n) (port-line in)))
res))
;;> Sends the entire contents of a file or input port to an output port.
(define (send-file fd-port-or-filename . o)
(let* ((in (if (string? fd-port-or-filename)
(open-input-file fd-port-or-filename)
fd-port-or-filename))
(out (if (pair? o) (car o) (current-output-port)))
(fd (if (port? in) (port-fileno in) in))
(sock (if (port? out) (port-fileno out) out)))
(if (and fd sock (is-a-socket? sock))
(let lp ((start 0))
(let ((res (%send-file fd sock start)))
(cond
((not res) (lp start))
((not (zero? res)) (lp (+ start res))))))
(let lp ()
(let ((str (read-string 8192 in)))
(cond ((not (eof-object? str))
(display str out)
(lp))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; higher order port operations

View file

@ -20,6 +20,11 @@
(c-include "port.c")
(define-c boolean (is-a-socket? "sexp_is_a_socket_p") (fileno))
(define-c errno (%send-file "sexp_send_file")
(fileno fileno off_t (default 0 off_t) (result off_t)))
(define-c sexp (%make-custom-input-port "sexp_make_custom_input_port")
((value ctx sexp) (value self sexp) sexp sexp sexp))

View file

@ -375,3 +375,23 @@ sexp sexp_peek_u8 (sexp ctx, sexp self, sexp in) {
sexp_push_char(ctx, sexp_unbox_fixnum(res), in);
return res;
}
int sexp_is_a_socket_p (int fd) {
#if defined(PLAN9) || defined(_WIN32)
return 0;
#else
struct stat statbuf;
fstat(fd, &statbuf);
return S_ISSOCK(statbuf.st_mode);
#endif
}
int sexp_send_file (int fd, int s, off_t offset, off_t len, off_t* res) {
#if SEXP_USE_SEND_FILE
*res = len;
return sendfile(fd, s, offset, res, NULL, 0);
#else
*res = 0;
return 22; /* EINVAL */
#endif
}