Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

sup_fs.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: sup_fs.c,v 1.11 2007/10/25 20:26:56 tat Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <sys/stat.h>
00013 #include <sys/types.h>
00014 #include <unistd.h>
00015 #include <fcntl.h>
00016 #include <klone/supplier.h>
00017 #include <klone/io.h>
00018 #include <klone/utils.h>
00019 
00020 static int fs_is_valid_uri(http_t *h, request_t *rq, const char *uri, 
00021         size_t len, time_t *mtime)
00022 {
00023     struct stat st; 
00024     char fqn[1+U_FILENAME_MAX];
00025 
00026     dbg_return_if (uri == NULL, 0);
00027     dbg_return_if (mtime == NULL, 0);
00028     dbg_return_if (len > U_FILENAME_MAX, 0);
00029 
00030     u_unused_args(h);
00031 
00032     memcpy(fqn, uri, len);
00033     fqn[len] = 0;
00034 
00035     /* fqn must be already normalized */
00036     if(strstr(fqn, ".."))
00037         return 0; 
00038 
00039     if(stat(fqn, &st) == 0 && S_ISREG(st.st_mode))
00040     {
00041         *mtime = st.st_mtime;
00042 
00043         return 1;
00044     } else
00045         return 0;
00046 }
00047 
00048 static int fs_serve(request_t *rq, response_t *rs)
00049 {
00050     enum { BUFSZ = 4096 };
00051     io_t *io = NULL, *out = NULL;;
00052     const char *mime_type, *fqn;
00053     size_t c;
00054     char buf[BUFSZ];
00055     struct stat st;
00056 
00057     dbg_err_if (rq == NULL);
00058     dbg_err_if (rs == NULL);
00059     
00060     /* output stream */
00061     out = response_io(rs);
00062     dbg_err_if(out == NULL);
00063 
00064     fqn = request_get_resolved_filename(rq);
00065 
00066     /* we need file size */
00067     dbg_err_if(stat(fqn, &st));
00068     dbg_err_if(response_set_content_length(rs, st.st_size));
00069 
00070     /* guess the mime type append a Content-Type field to the response*/
00071     mime_type = u_guess_mime_type(fqn);
00072     dbg_err_if(response_set_content_type(rs, mime_type));
00073 
00074     /* add a Last-Modified field */
00075     dbg_err_if(response_set_last_modified(rs, st.st_mtime));
00076 
00077     /* print the reponse header */
00078     dbg_err_if(response_print_header_to_io(rs, out));
00079 
00080     /* if this's a HEAD request don't print the file content */
00081     if(response_get_method(rs) == HM_HEAD)
00082         return 0;
00083 
00084     /* open and write out the whole file */
00085     dbg_err_if(u_file_open(request_get_resolved_filename(rq), O_RDONLY, &io));
00086 
00087     while((c = io_read(io, buf, BUFSZ)) > 0)
00088         dbg_err_if(io_write(out, buf, c) < 0);
00089 
00090     io_free(io);
00091 
00092     return 0;
00093 err:
00094     if(io)
00095         io_free(io);
00096     return ~0;
00097 }
00098 
00099 static int fs_init(void)
00100 {
00101     return 0;
00102 }
00103 
00104 static void fs_term(void)
00105 {
00106     return;
00107 }
00108 
00109 supplier_t sup_fs = {
00110     "fs supplier",
00111     fs_init,
00112     fs_term,
00113     fs_is_valid_uri,
00114     fs_serve
00115 };
00116