]> granicus.if.org Git - apache/blobdiff - modules/cache/mod_file_cache.c
adjust remaining modules to use the new handler hook method (Alan Edwards)
[apache] / modules / cache / mod_file_cache.c
index 2a267e3eec1013c98cbe0283eb362d58687c8c53..2271287748b05c2cfa18c346f419cd121aca01ce 100644 (file)
 #include "http_request.h"
 #include "http_core.h"
 #include "apr_mmap.h"
+#include "apr_strings.h"
 
-module MODULE_VAR_EXPORT file_cache_module;
-static ap_pool_t *pconf;
-static int once_through = 0;
+module AP_MODULE_DECLARE_DATA file_cache_module;
 
 typedef struct {
 #if APR_HAS_SENDFILE
-    ap_file_t *file;
+    apr_file_t *file;
 #endif
-    char *filename;
-    ap_finfo_t finfo;
+    const char *filename;
+    apr_finfo_t finfo;
     int is_mmapped;
 #if APR_HAS_MMAP
-    ap_mmap_t *mm;
+    apr_mmap_t *mm;
 #endif
 } a_file;
 
 typedef struct {
-    ap_array_header_t *files;
+    apr_array_header_t *files;
 } a_server_config;
 
 
-static void *create_server_config(ap_pool_t *p, server_rec *s)
+static void *create_server_config(apr_pool_t *p, server_rec *s)
 {
-    a_server_config *sconf = ap_palloc(p, sizeof(*sconf));
+    a_server_config *sconf = apr_palloc(p, sizeof(*sconf));
 
-    sconf->files = ap_make_array(p, 20, sizeof(a_file));
+    sconf->files = apr_make_array(p, 20, sizeof(a_file));
     return sconf;
 }
 
-static ap_status_t open_file(ap_file_t **file, const char *filename, int flg1, int flg2, 
-                             ap_pool_t *p)
+#if APR_HAS_SENDFILE
+static apr_status_t open_file(apr_file_t **file, const char *filename, int flg1, int flg2, 
+                             apr_pool_t *p)
 {
-    ap_status_t rv;
+    apr_status_t rv;
 #ifdef WIN32
     /* The Windows file needs to be opened for overlapped i/o, which APR doesn't
      * support.
@@ -175,21 +175,21 @@ static ap_status_t open_file(ap_file_t **file, const char *filename, int flg1, i
                        FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, /* file attributes */
                        NULL);            /* handle to file with attributes to copy */
     if (hFile != INVALID_HANDLE_VALUE) {
-        rv = ap_put_os_file(file, &hFile, p);
+        rv = apr_put_os_file(file, &hFile, p);
     }
     else {
         rv = GetLastError();
         *file = NULL;
     }
 #else
-    rv = ap_open(file, filename, flg1, flg2, p);
+    rv = apr_open(file, filename, flg1, flg2, p);
 #endif
 
     return rv;
 }
+#endif /* APR_HAS_SENDFILE */
 
-#if APR_HAS_SENDFILE
-static ap_status_t cleanup_file_cache(void *sconfv)
+static apr_status_t cleanup_file_cache(void *sconfv)
 {
     a_server_config *sconf = sconfv;
     size_t n;
@@ -198,30 +198,20 @@ static ap_status_t cleanup_file_cache(void *sconfv)
     n = sconf->files->nelts;
     file = (a_file *)sconf->files->elts;
     while(n) {
-        ap_close(file->file);
-        ++file;
-        --n;
-    }
-    return APR_SUCCESS;
-}
-#endif
 #if APR_HAS_MMAP
-static ap_status_t cleanup_mmap(void *sconfv)
-{
-    a_server_config *sconf = sconfv;
-    size_t n;
-    a_file *file;
-
-    n = sconf->files->nelts;
-    file = (a_file *)sconf->files->elts;
-    while(n) {
-           ap_mmap_delete(file->mm);
+        if (file->is_mmapped) { 
+           apr_mmap_delete(file->mm);
+        } 
+        else 
+#endif 
+#if APR_HAS_SENDFILE
+            apr_close(file->file); 
+#endif
            ++file;
            --n;
     }
     return APR_SUCCESS;
 }
-#endif
 
 static const char *cachefile(cmd_parms *cmd, void *dummy, const char *filename)
 
@@ -230,40 +220,40 @@ static const char *cachefile(cmd_parms *cmd, void *dummy, const char *filename)
     a_server_config *sconf;
     a_file *new_file;
     a_file tmp;
-    ap_file_t *fd = NULL;
-    ap_status_t rc;
+    apr_file_t *fd = NULL;
+    apr_status_t rc;
 
     /* canonicalize the file name? */
     /* os_canonical... */
-    if (ap_stat(&tmp.finfo, filename, NULL) != APR_SUCCESS) {
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
-           "file_cache: unable to stat(%s), skipping", filename);
+    if ((rc = apr_stat(&tmp.finfo, filename, cmd->temp_pool)) != APR_SUCCESS) {
+       ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
+           "mod_file_cache: unable to stat(%s), skipping", filename);
        return NULL;
     }
     if (tmp.finfo.filetype != APR_REG) {
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
-           "file_cache: %s isn't a regular file, skipping", filename);
+       ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server,
+           "mod_file_cache: %s isn't a regular file, skipping", filename);
        return NULL;
     }
 
-    /* Note: open_file should call ap_open for Unix and CreateFile for Windows.
+    /* Note: open_file should call apr_open for Unix and CreateFile for Windows.
      * The Windows file needs to be opened for async I/O to allow multiple threads
      * to serve it up at once.
      */
     rc = open_file(&fd, filename, APR_READ, APR_OS_DEFAULT, cmd->pool);
     if (rc != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
-                     "file_cache: unable to open(%s, O_RDONLY), skipping", filename);
+                     "mod_file_cache: unable to open(%s, O_RDONLY), skipping", filename);
        return NULL;
     }
     tmp.file = fd;
-    tmp.filename = ap_pstrdup(cmd->pool, filename);
+    tmp.filename = apr_pstrdup(cmd->pool, filename);
     sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module);
-    new_file = ap_push_array(sconf->files);
+    new_file = apr_push_array(sconf->files);
     *new_file = tmp;
     if (sconf->files->nelts == 1) {
        /* first one, register the cleanup */
-       ap_register_cleanup(cmd->pool, sconf, cleanup_file_cache, ap_null_cleanup);
+       apr_register_cleanup(cmd->pool, sconf, cleanup_file_cache, apr_null_cleanup);
     }
 
     new_file->is_mmapped = FALSE;
@@ -271,7 +261,7 @@ static const char *cachefile(cmd_parms *cmd, void *dummy, const char *filename)
     return NULL;
 #else
     /* Sendfile not supported on this platform */
-    ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
+    ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server,
                  "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", filename);
     return NULL;
 #endif
@@ -283,39 +273,42 @@ static const char *mmapfile(cmd_parms *cmd, void *dummy, const char *filename)
     a_server_config *sconf;
     a_file *new_file;
     a_file tmp;
-    ap_file_t *fd = NULL;
+    apr_file_t *fd = NULL;
+    apr_status_t rc;
+    const char *fspec;
 
-    if (ap_stat(&tmp.finfo, filename, pconf) != APR_SUCCESS) {
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
+    fspec = ap_os_case_canonical_filename(cmd->pool, filename);
+    if ((rc = apr_stat(&tmp.finfo, fspec, cmd->temp_pool)) != APR_SUCCESS) {
+       ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
            "mod_file_cache: unable to stat(%s), skipping", filename);
        return NULL;
     }
     if ((tmp.finfo.filetype) != APR_REG) {
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
+       ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server,
            "mod_file_cache: %s isn't a regular file, skipping", filename);
        return NULL;
     }
-    if (ap_open(&fd, filename, APR_READ, APR_OS_DEFAULT, pconf) != APR_SUCCESS) {
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
-           "mod_file_cache: unable to open(%s, O_RDONLY), skipping", filename);
+    if ((rc = apr_open(&fd, fspec, APR_READ, APR_OS_DEFAULT, 
+                       cmd->temp_pool)) != APR_SUCCESS) { 
+       ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
+                     "mod_file_cache: unable to open %s, skipping", 
+                     filename);
        return NULL;
     }
-    if (ap_mmap_create(&tmp.mm, fd, 0, tmp.finfo.size, pconf) != APR_SUCCESS) {
-       int save_errno = errno;
-       ap_close(fd);
-       errno = save_errno;
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
+    if ((rc = apr_mmap_create(&tmp.mm, fd, 0, tmp.finfo.size, APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) { 
+       apr_close(fd);
+       ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
            "mod_file_cache: unable to mmap %s, skipping", filename);
        return NULL;
     }
-    ap_close(fd);
-    tmp.filename = ap_pstrdup(cmd->pool, filename);
+    apr_close(fd);
+    tmp.filename = fspec;
     sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module);
-    new_file = ap_push_array(sconf->files);
+    new_file = apr_push_array(sconf->files);
     *new_file = tmp;
     if (sconf->files->nelts == 1) {
        /* first one, register the cleanup */
-       ap_register_cleanup(cmd->pool, sconf, cleanup_mmap, ap_null_cleanup);
+       apr_register_cleanup(cmd->pool, sconf, cleanup_file_cache, apr_null_cleanup); 
     }
 
     new_file->is_mmapped = TRUE;
@@ -336,16 +329,13 @@ static int file_compare(const void *av, const void *bv)
     return strcmp(a->filename, b->filename);
 }
 
-static void file_cache_post_config(ap_pool_t *p, ap_pool_t *plog,
-                                   ap_pool_t *ptemp, server_rec *s)
+static void file_cache_post_config(apr_pool_t *p, apr_pool_t *plog,
+                                   apr_pool_t *ptemp, server_rec *s)
 {
     a_server_config *sconf;
     a_file *elts;
     int nelts;
 
-    once_through++;
-    pconf = p;    
-
     /* sort the elements of the main_server, by filename */
     sconf = ap_get_module_config(s->module_config, &file_cache_module);
     elts = (a_file *)sconf->files->elts;
@@ -371,7 +361,7 @@ static int file_cache_xlat(request_rec *r)
     sconf = ap_get_module_config(r->server->module_config, &file_cache_module);
 
     /* we only operate when at least one cachefile directive was used */
-    if (ap_is_empty_table(sconf->files))
+    if (apr_is_empty_table(sconf->files))
        return DECLINED;
 
     res = ap_core_translate(r);
@@ -395,79 +385,32 @@ static int file_cache_xlat(request_rec *r)
 }
 
 
-static int mmap_handler(request_rec *r, a_file *file, int rangestatus)
+static int mmap_handler(request_rec *r, a_file *file)
 {
 #if APR_HAS_MMAP
-    if (!rangestatus) {
-        ap_send_mmap (file->mm, r, 0, file->finfo.size);
-    }
-    else {
-        long length;
-        ap_off_t offset;
-        while (ap_each_byterange(r, &offset, &length)) {
-            ap_send_mmap(file->mm, r, offset, length);
-        }
-    }
+    ap_send_mmap (file->mm, r, 0, file->finfo.size);
 #endif
     return OK;
 }
 
-
-static int sendfile_handler(request_rec *r, a_file *file, int rangestatus)
+static int sendfile_handler(request_rec *r, a_file *file)
 {
 #if APR_HAS_SENDFILE
-    long length;
-    ap_off_t offset = 0;
-    struct iovec iov;
-    ap_hdtr_t hdtr;
-    ap_hdtr_t *phdtr = &hdtr;
-    ap_int32_t flags = 0;
-
-    /* 
-     * We want to send any data held in the client buffer on the
-     * call to iol_sendfile. So hijack it then set outcnt to 0
-     * to prevent the data from being sent to the client again
-     * when the buffer is flushed to the client at the end of the 
-     * request.
-     */
-    iov.iov_base = r->connection->client->outbase;
-    iov.iov_len =  r->connection->client->outcnt;
-    r->connection->client->outcnt = 0;
-
-    /* initialize the ap_hdtr_t struct */
-    phdtr->headers = &iov;
-    phdtr->numheaders = 1;
-    phdtr->trailers = NULL;
-    phdtr->numtrailers = 0;
-
-    if (!rangestatus) {
-        length = file->finfo.size;
-
-        if (!r->connection->keepalive) {
-            /* Disconnect the socket after the send completes. This
-             * should leave the accept socket in a state ready to be
-             * reused for the next connection.
-             */
-            flags |= APR_SENDFILE_DISCONNECT_SOCKET;
-        }
-
-        iol_sendfile(r->connection->client->iol,
-                     file->file,
-                     phdtr,
-                     &offset,
-                     &length,
-                     flags);
+    apr_size_t nbytes;
+    apr_status_t rv = APR_EINIT;
+    apr_off_t offset = 0;
+
+    rv = apr_seek(file->file, APR_SET, &offset);
+    if (rv != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                      "seek failed");
+        return HTTP_INTERNAL_SERVER_ERROR;
     }
-    else {
-        while (ap_each_byterange(r, &offset, &length)) {
-            iol_sendfile(r->connection->client->iol, 
-                         file->file,
-                         phdtr,
-                         &offset,
-                         &length,
-                         flags);
-            phdtr = NULL;
-        }
+
+    rv = ap_send_fd(file->file, r, 0, file->finfo.size, &nbytes);
+    if (rv != APR_SUCCESS) {
+        /* ap_send_fd will log the error */
+        return HTTP_INTERNAL_SERVER_ERROR;
     }
 #endif
     return OK;
@@ -476,9 +419,13 @@ static int sendfile_handler(request_rec *r, a_file *file, int rangestatus)
 static int file_cache_handler(request_rec *r) 
 {
     a_file *match;
-    int rangestatus, errstatus;
+    int errstatus;
     int rc = OK;
 
+    if (strcmp(r->handler, "*.*")) {
+        return DECLINED;
+    }
+
     /* we don't handle anything but GET */
     if (r->method_number != M_GET) return DECLINED;
 
@@ -501,20 +448,19 @@ static int file_cache_handler(request_rec *r)
     ap_update_mtime(r, match->finfo.mtime);
     ap_set_last_modified(r);
     ap_set_etag(r);
-    if (((errstatus = ap_meets_conditions(r)) != OK)
-       || (errstatus = ap_set_content_length (r, match->finfo.size))) {
-           return errstatus;
+    if ((errstatus = ap_meets_conditions(r)) != OK) {
+       return errstatus;
     }
+    ap_set_content_length(r, match->finfo.size);
 
-    rangestatus = ap_set_byterange(r);
     ap_send_http_header(r);
 
     /* Call appropriate handler */
     if (!r->header_only) {    
         if (match->is_mmapped == TRUE)
-            rc = mmap_handler(r, match, rangestatus);
+            rc = mmap_handler(r, match);
         else
-            rc = sendfile_handler(r, match, rangestatus);
+            rc = sendfile_handler(r, match);
     }
 
     return rc;
@@ -523,14 +469,15 @@ static int file_cache_handler(request_rec *r)
 static command_rec file_cache_cmds[] =
 {
 AP_INIT_ITERATE("cachefile", cachefile, NULL, RSRC_CONF,
-     "A space seperated list of files to add to the file handle cache at config time"),
+     "A space separated list of files to add to the file handle cache at config time"),
 AP_INIT_ITERATE("mmapfile", mmapfile, NULL, RSRC_CONF,
-     "A space seperated list of files to mmap at config time"),
+     "A space separated list of files to mmap at config time"),
     {NULL}
 };
 
 static void register_hooks(void)
 {
+    ap_hook_handler(file_cache_handler, NULL, NULL, AP_HOOK_MIDDLE);
     ap_hook_post_config(file_cache_post_config, NULL, NULL, AP_HOOK_MIDDLE);
     ap_hook_translate_name(file_cache_xlat, NULL, NULL, AP_HOOK_MIDDLE);
     /* This trick doesn't work apparently because the translate hooks
@@ -539,15 +486,9 @@ static void register_hooks(void)
     ap_hook_translate_name(file_cache_xlat, aszPre, NULL, AP_HOOK_MIDDLE); 
     */
 
-};
-
-static const handler_rec file_cache_handlers[] =
-{
-    { "*/*", file_cache_handler },
-    { NULL }
-};
+}
 
-module MODULE_VAR_EXPORT file_cache_module =
+module AP_MODULE_DECLARE_DATA file_cache_module =
 {
     STANDARD20_MODULE_STUFF,
     NULL,                     /* create per-directory config structure */
@@ -555,6 +496,5 @@ module MODULE_VAR_EXPORT file_cache_module =
     create_server_config,     /* create per-server config structure */
     NULL,                     /* merge per-server config structures */
     file_cache_cmds,          /* command handlers */
-    file_cache_handlers,      /* handlers */
     register_hooks            /* register hooks */
 };