file_buckets.c revision 251877
1/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <apr_pools.h> 17 18#include "serf.h" 19#include "serf_bucket_util.h" 20 21typedef struct { 22 apr_file_t *file; 23 24 serf_databuf_t databuf; 25 26} file_context_t; 27 28 29static apr_status_t file_reader(void *baton, apr_size_t bufsize, 30 char *buf, apr_size_t *len) 31{ 32 file_context_t *ctx = baton; 33 34 *len = bufsize; 35 return apr_file_read(ctx->file, buf, len); 36} 37 38serf_bucket_t *serf_bucket_file_create( 39 apr_file_t *file, 40 serf_bucket_alloc_t *allocator) 41{ 42 file_context_t *ctx; 43#if APR_HAS_MMAP 44 apr_finfo_t finfo; 45 const char *file_path; 46 47 /* See if we'd be better off mmap'ing this file instead. 48 * 49 * Note that there is a failure case here that we purposely fall through: 50 * if a file is buffered, apr_mmap will reject it. However, on older 51 * versions of APR, we have no way of knowing this - but apr_mmap_create 52 * will check for this and return APR_EBADF. 53 */ 54 apr_file_name_get(&file_path, file); 55 apr_stat(&finfo, file_path, APR_FINFO_SIZE, 56 serf_bucket_allocator_get_pool(allocator)); 57 if (APR_MMAP_CANDIDATE(finfo.size)) { 58 apr_status_t status; 59 apr_mmap_t *file_mmap; 60 status = apr_mmap_create(&file_mmap, file, 0, finfo.size, 61 APR_MMAP_READ, 62 serf_bucket_allocator_get_pool(allocator)); 63 64 if (status == APR_SUCCESS) { 65 return serf_bucket_mmap_create(file_mmap, allocator); 66 } 67 } 68#endif 69 70 /* Oh, well. */ 71 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx)); 72 ctx->file = file; 73 74 serf_databuf_init(&ctx->databuf); 75 ctx->databuf.read = file_reader; 76 ctx->databuf.read_baton = ctx; 77 78 return serf_bucket_create(&serf_bucket_type_file, allocator, ctx); 79} 80 81static apr_status_t serf_file_read(serf_bucket_t *bucket, 82 apr_size_t requested, 83 const char **data, apr_size_t *len) 84{ 85 file_context_t *ctx = bucket->data; 86 87 return serf_databuf_read(&ctx->databuf, requested, data, len); 88} 89 90static apr_status_t serf_file_readline(serf_bucket_t *bucket, 91 int acceptable, int *found, 92 const char **data, apr_size_t *len) 93{ 94 file_context_t *ctx = bucket->data; 95 96 return serf_databuf_readline(&ctx->databuf, acceptable, found, data, len); 97} 98 99static apr_status_t serf_file_peek(serf_bucket_t *bucket, 100 const char **data, 101 apr_size_t *len) 102{ 103 file_context_t *ctx = bucket->data; 104 105 return serf_databuf_peek(&ctx->databuf, data, len); 106} 107 108const serf_bucket_type_t serf_bucket_type_file = { 109 "FILE", 110 serf_file_read, 111 serf_file_readline, 112 serf_default_read_iovec, 113 serf_default_read_for_sendfile, 114 serf_default_read_bucket, 115 serf_file_peek, 116 serf_default_destroy_and_data, 117}; 118