From 01b2ebcef044b1aaea39a3ec3b5d3ccf0f08e444 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Mon, 22 Dec 2008 05:04:59 +0100 Subject: [PATCH] Added a really basic sendfile implementation. --- src/.gitignore | 1 + src/Makefile.am | 2 +- src/sendfile.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/sendfile.c diff --git a/src/.gitignore b/src/.gitignore index bc7940f..8c14912 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,4 @@ /htparser /debugsink /dirplex +/sendfile diff --git a/src/Makefile.am b/src/Makefile.am index e8e6c70..7b5457e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -bin_PROGRAMS = htparser dirplex +bin_PROGRAMS = htparser dirplex sendfile noinst_PROGRAMS = debugsink htparser_SOURCES = htparser.c diff --git a/src/sendfile.c b/src/sendfile.c new file mode 100644 index 0000000..76c0ad4 --- /dev/null +++ b/src/sendfile.c @@ -0,0 +1,109 @@ +/* + ashd - A Sane HTTP Daemon + Copyright (C) 2008 Fredrik Tolf + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include + +static void passdata(int in, int out) +{ + int ret, len, off; + char *buf; + + buf = smalloc(65536); + while(1) { + len = read(in, buf, 65536); + if(len < 0) { + flog(LOG_ERR, "sendfile: could not read input: %s", strerror(errno)); + break; + } + if(len == 0) + break; + for(off = 0; off < len; off += ret) { + ret = write(out, buf + off, len - off); + if(ret < 0) { + flog(LOG_ERR, "sendfile: could not write output: %s", strerror(errno)); + break; + } + } + } + free(buf); +} + +static int strrcmp(char *str, char *end) +{ + return(strcmp(str + strlen(str) - strlen(end), end)); +} + +static char *getmimetype(char *file, struct stat *sb) +{ + /* Rewrite with libmagic. */ + if(!strrcmp(file, ".html")) + return("text/html"); + if(!strrcmp(file, ".xhtml")) + return("application/xhtml+xml"); + if(!strrcmp(file, ".txt")) + return("text/plain"); + return("application/octet-stream"); +} + +int main(int argc, char **argv) +{ + char *file; + struct stat sb; + int fd; + + if(argc < 4) { + flog(LOG_ERR, "usage: sendfile METHOD URL REST"); + exit(1); + } + if((file = getenv("REQ_X_ASH_FILE")) == NULL) { + flog(LOG_ERR, "sendfile: needs to be called with the X-Ash-File header"); + exit(1); + } + if(*argv[3]) { + simpleerror(1, 404, "Not Found", "The requested URL has no corresponding resource."); + exit(0); + } + if(stat(file, &sb) || ((fd = open(file, O_RDONLY)) < 0)) { + flog(LOG_ERR, "sendfile: could not stat input file %s: %s", file, strerror(errno)); + simpleerror(1, 500, "Internal Error", "The server could not access its own data."); + exit(1); + } + + printf("HTTP/1.1 200 OK\r\n"); + printf("Content-Type: %s\r\n", getmimetype(file, &sb)); + printf("Content-Length: %ji\r\n", (intmax_t)sb.st_size); + printf("\r\n"); + fflush(stdout); + if(strcasecmp(argv[1], "head")) + passdata(fd, 1); + return(0); +} -- 2.11.0