mod_annot editor

Annotate Section

Bucket functions

Firstly we introduce two functions to deal with the data insertions: one for the files, one for the simple entity replacements:

Creating a File bucket requires an open filehandle and a byte range within the file. Since we're transmitting the entire file, we just stat its size to set the byte range. We open it with a shared lock and with sendfile enabled for maximum performance.

static apr_bucket* txt_file_bucket(request_rec* r, const char* fname) {
  apr_file_t* file = NULL ;
  apr_finfo_t finfo ;
  if ( apr_stat(&finfo, fname, APR_FINFO_SIZE, r->pool) != APR_SUCCESS ) {
    return NULL ;
  if ( apr_file_open(&file, fname, APR_READ|APR_SHARELOCK|APR_SENDFILE_ENABLED,
	APR_OS_DEFAULT, r->pool ) != APR_SUCCESS ) {
    return NULL ;
  if ( ! file ) {
    return NULL ;
  return apr_bucket_file_create(file, 0, finfo.size, r->pool,
	r->connection->bucket_alloc) ;

Creating the simple text replacements, we can just make a bucket of an inline string. The appropriate bucket type for such data is transient:

static apr_bucket* txt_esc(char c, apr_bucket_alloc_t* alloc ) {
  switch (c) {
    case '<': return apr_bucket_transient_create("&lt;", 4, alloc) ;
    case '>': return apr_bucket_transient_create("&gt;", 4, alloc) ;
    case '&': return apr_bucket_transient_create("&amp;", 5, alloc) ;
    case '"': return apr_bucket_transient_create("&quot;", 6, alloc) ;
    default: return NULL ;	/* shut compilers up */

Actually this is not the most efficient way to do this. We will discuss alternative formulations of the above below.