From 565bfc08c6d8779673f6435dacb701961ddacd1d Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 2 Oct 2012 15:37:36 +0200 Subject: [PATCH] Add a libfast sendfile() method to send files from disk --- src/libfast/request.c | 60 +++++++++++++++++++++++++++++++++++++++++++ src/libfast/request.h | 9 +++++++ 2 files changed, 69 insertions(+) diff --git a/src/libfast/request.c b/src/libfast/request.c index 3acd831b2..6ca474037 100644 --- a/src/libfast/request.c +++ b/src/libfast/request.c @@ -22,6 +22,11 @@ #include #include #include +#include +#include +#include +#include + #include #include @@ -275,6 +280,60 @@ METHOD(request_t, serve, void, FCGX_PutStr(chunk.ptr, chunk.len, this->req.out); } +METHOD(request_t, sendfile, bool, + private_request_t *this, char *path, char *mime) +{ + struct stat sb; + chunk_t data; + void *addr; + int fd, written; + char buf[24]; + + fd = open(path, O_RDONLY); + if (fd == -1) + { + return FALSE; + } + if (fstat(fd, &sb) == -1) + { + close(fd); + return FALSE; + } + addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) + { + close(fd); + return FALSE; + } + + /* FCGX does not like large integers, print to a buffer using libc */ + snprintf(buf, sizeof(buf), "%lld", (int64_t)sb.st_size); + FCGX_FPrintF(this->req.out, "Content-Length: %s\n", buf); + if (mime) + { + FCGX_FPrintF(this->req.out, "Content-Type: %s\n", mime); + } + FCGX_FPrintF(this->req.out, "\n"); + + data = chunk_create(addr, sb.st_size); + + while (data.len) + { + written = FCGX_PutStr(data.ptr, data.len, this->req.out); + if (written == -1) + { + munmap(addr, sb.st_size); + close(fd); + return FALSE; + } + data = chunk_skip(data, written); + } + + munmap(addr, sb.st_size); + close(fd); + return TRUE; +} + METHOD(request_t, render, void, private_request_t *this, char *template) { @@ -380,6 +439,7 @@ request_t *request_create(int fd, bool debug) .render = _render, .streamf = _streamf, .serve = _serve, + .sendfile = _sendfile, .set = _set, .setf = _setf, .get_ref = _get_ref, diff --git a/src/libfast/request.h b/src/libfast/request.h index c9c1f13e2..63a465bb8 100644 --- a/src/libfast/request.h +++ b/src/libfast/request.h @@ -184,6 +184,15 @@ struct request_t { */ void (*serve)(request_t *this, char *headers, chunk_t chunk); + /** + * Send a file from the file system. + * + * @param path path to file to serve + * @param mime mime type of file to send, or NULL + * @return TRUE if file served successfully + */ + bool (*sendfile)(request_t *this, char *path, char *mime); + /** * Increase the reference count to the stream. *