Esempio n. 1
0
int lua_apr_dir_remove_recursive(lua_State *L)
{
  apr_status_t status;
  apr_pool_t *outer_pool; /* used to store todo/done arrays and directory pathnames */
  apr_pool_t *middle_pool; /* used to store directory handles (apr_dir_t structs) */
  apr_pool_t *inner_pool; /* used to store pathnames of non-subdirectory entries */
  apr_array_header_t *todo, *done;
  apr_dir_t *directory;
  apr_finfo_t info;
  char **top, *tmp;
  const char *filepath;
  int allocation_counter;

  directory = NULL;
  outer_pool = middle_pool = inner_pool = NULL;
  filepath = luaL_checkstring(L, 1);
  allocation_counter = 0;

  status = apr_pool_create(&outer_pool, NULL);
  if (APR_SUCCESS == status)
    status = apr_pool_create(&middle_pool, NULL);
  if (APR_SUCCESS == status)
    status = apr_pool_create(&inner_pool, NULL);
  if (APR_SUCCESS != status)
    goto cleanup;

# define out_of_memory do { \
    status = APR_ENOMEM; \
    goto cleanup; \
  } while (0)

# define push_filepath(stack, filepath) do { \
    const char **p = apr_array_push(stack); \
    if (p != NULL) *p = filepath; else out_of_memory; \
  } while (0)

  todo = apr_array_make(outer_pool, 0, sizeof filepath);
  done = apr_array_make(outer_pool, 0, sizeof filepath);
  if (todo == NULL || done == NULL)
    out_of_memory;

  push_filepath(todo, filepath);

  while ((top = apr_array_pop(todo))) {
    filepath = *(char**)top;
    apr_pool_clear(middle_pool);
    status = apr_dir_open(&directory, filepath, middle_pool);
    if (status != APR_SUCCESS) {
      directory = NULL;
      goto cleanup;
    }
    for (;;) {
      /* This is a compromise between having `inner_pool' grow almost unbounded
       * on very large directories (e.g. ~/Maildir/) and clearing it for every
       * non-subdirectory pathname that's allocated (very inefficient). */
      if (allocation_counter % 1000 == 0)
        apr_pool_clear(inner_pool);
      /* FIXME?! apr_dir_read() uses directory->pool (middle_pool) for allocation */
      status = apr_dir_read(&info, APR_FINFO_NAME|APR_FINFO_TYPE|APR_FINFO_LINK, directory);
      if (APR_STATUS_IS_ENOENT(status))
        break; /* no more entries */
      else if (status != APR_SUCCESS && status != APR_INCOMPLETE)
        goto cleanup; /* something went wrong */
      else if (filename_symbolic(info.name))
        continue; /* bogus entry */
      else if (info.filetype == APR_DIR) {
        /* recurse into subdirectory */
        status = apr_filepath_merge(&tmp, filepath, info.name, 0, outer_pool);
        if (status != APR_SUCCESS)
          goto cleanup;
        push_filepath(todo, tmp);
      } else {
        /* delete non-subdirectory entry */
        status = apr_filepath_merge(&tmp, filepath, info.name, 0, inner_pool);
        allocation_counter++;
        if (APR_SUCCESS == status)
          status = apr_file_remove(tmp, inner_pool);
        if (APR_SUCCESS != status)
          goto cleanup;
      }
    }
    status = apr_dir_close(directory);
    directory = NULL;
    if (status != APR_SUCCESS)
      goto cleanup;
    push_filepath(done, filepath);
  }

# undef out_of_memory
# undef push_filepath

  while ((top = apr_array_pop(done))) {
    filepath = *(char**)top;
    if (allocation_counter++ % 100 == 0)
      apr_pool_clear(middle_pool);
    status = apr_dir_remove(filepath, middle_pool);
    if (status != APR_SUCCESS)
      goto cleanup;
  }

cleanup:

  if (directory != NULL)
    apr_dir_close(directory);
  if (inner_pool != NULL)
    apr_pool_destroy(inner_pool);
  if (middle_pool != NULL)
    apr_pool_destroy(middle_pool);
  if (outer_pool != NULL)
    apr_pool_destroy(outer_pool);

  return push_status(L, status);
}
Esempio n. 2
0
/* Implements serf__auth_handler_func_t callback. */
static apr_status_t
serf__handle_digest_auth(const serf__authn_scheme_t *scheme,
                         int code,
                         serf_request_t *request,
                         serf_bucket_t *response,
                         const char *auth_hdr,
                         const char *auth_attr,
                         apr_pool_t *pool)
{
    char *attrs;
    char *nextkv;
    const char *realm, *realm_name = NULL;
    const char *nonce = NULL;
    const char *algorithm = NULL;
    const char *qop = NULL;
    const char *opaque = NULL;
    const char *key;
    serf_connection_t *conn = request->conn;
    serf_context_t *ctx = conn->ctx;
    serf__authn_info_t *authn_info;
    digest_authn_info_t *digest_info;
    apr_status_t status;
    apr_pool_t *cred_pool;
    char *username, *password;

    /* Can't do Digest authentication if there's no callback to get
       username & password. */
    if (!ctx->cred_cb) {
        return SERF_ERROR_AUTHN_FAILED;
    }

    if (code == 401) {
        authn_info = serf__get_authn_info_for_server(conn);
    } else {
        authn_info = &ctx->proxy_authn_info;
    }
    digest_info = authn_info->baton;

    /* Need a copy cuz we're going to write NUL characters into the string.  */
    attrs = apr_pstrdup(pool, auth_attr);

    /* We're expecting a list of key=value pairs, separated by a comma.
       Ex. realm="SVN Digest",
       nonce="f+zTl/leBAA=e371bd3070adfb47b21f5fc64ad8cc21adc371a5",
       algorithm=MD5, qop="auth" */
    for ( ; (key = apr_strtok(attrs, ",", &nextkv)) != NULL; attrs = NULL) {
        char *val;

        val = strchr(key, '=');
        if (val == NULL)
            continue;
        *val++ = '\0';

        /* skip leading spaces */
        while (*key && *key == ' ')
            key++;

        /* If the value is quoted, then remove the quotes.  */
        if (*val == '"') {
            apr_size_t last = strlen(val) - 1;

            if (val[last] == '"') {
                val[last] = '\0';
                val++;
            }
        }

        if (strcmp(key, "realm") == 0)
            realm_name = val;
        else if (strcmp(key, "nonce") == 0)
            nonce = val;
        else if (strcmp(key, "algorithm") == 0)
            algorithm = val;
        else if (strcmp(key, "qop") == 0)
            qop = val;
        else if (strcmp(key, "opaque") == 0)
            opaque = val;

        /* Ignore all unsupported attributes. */
    }

    if (!realm_name) {
        return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE;
    }

    realm = serf__construct_realm(code == 401 ? HOST : PROXY,
                                  conn, realm_name,
                                  pool);

    /* Ask the application for credentials */
    apr_pool_create(&cred_pool, pool);
    status = serf__provide_credentials(ctx,
                                       &username, &password,
                                       request,
                                       code, scheme->name,
                                       realm, cred_pool);
    if (status) {
        apr_pool_destroy(cred_pool);
        return status;
    }

    digest_info->header = (code == 401) ? "Authorization" :
                                          "Proxy-Authorization";

    /* Store the digest authentication parameters in the context cached for
       this server in the serf context, so we can use it to create the
       Authorization header when setting up requests on the same or different
       connections (e.g. in case of KeepAlive off on the server).
       TODO: we currently don't cache this info per realm, so each time a request
       'switches realms', we have to ask the application for new credentials. */
    digest_info->pool = conn->pool;
    digest_info->qop = apr_pstrdup(digest_info->pool, qop);
    digest_info->nonce = apr_pstrdup(digest_info->pool, nonce);
    digest_info->cnonce = NULL;
    digest_info->opaque = apr_pstrdup(digest_info->pool, opaque);
    digest_info->algorithm = apr_pstrdup(digest_info->pool, algorithm);
    digest_info->realm = apr_pstrdup(digest_info->pool, realm_name);
    digest_info->username = apr_pstrdup(digest_info->pool, username);
    digest_info->digest_nc++;

    status = build_digest_ha1(&digest_info->ha1, username, password,
                              digest_info->realm, digest_info->pool);

    apr_pool_destroy(cred_pool);

    /* If the handshake is finished tell serf it can send as much requests as it
       likes. */
    serf__connection_set_pipelining(conn, 1);

    return status;
}
Esempio n. 3
0
apr_status_t sha1_file(const std::string& filename, std::string& checksum, bool binary, apr_pool_t* parentPool)
{
  apr_status_t ret = APR_SUCCESS;

  apr_pool_t* pool = NULL;
  ret = apr_pool_create(&pool, parentPool);
  if(ret == APR_SUCCESS)
  {
    apr_file_t* in = NULL;
    apr_int32_t flags = (binary ? APR_READ | APR_BINARY : APR_READ);

    ret = apr_file_open(&in, filename.c_str(), flags, APR_OS_DEFAULT, pool);
    if(ret == APR_SUCCESS)
    {
      unsigned char digest[APR_SHA1_DIGESTSIZE + 1];
      memset(digest, 0, APR_SHA1_DIGESTSIZE + 1);

      apr_sha1_ctx_t context;
      apr_sha1_init(&context);

      unsigned char buffer[512];
      memset(buffer, 0, sizeof(buffer));

      apr_size_t bytes_read = 0;
      ret = apr_file_read_full(in, buffer, sizeof(buffer) - 1, &bytes_read);

      if(ret == APR_SUCCESS || ret == APR_EOF)
      {
        if(binary) apr_sha1_update_binary(&context, buffer, bytes_read);
        else apr_sha1_update(&context, (const char*)buffer, bytes_read);
      }

      while(ret == APR_SUCCESS)
      {
        ret = apr_file_read_full(in, buffer, sizeof(buffer) - 1, &bytes_read);
        if(ret == APR_SUCCESS || ret == APR_EOF)
        {
          if(binary) apr_sha1_update_binary(&context, buffer, bytes_read);
          else apr_sha1_update(&context, (const char*)buffer, bytes_read);
        }
      }

      apr_sha1_final(digest, &context);

      if(ret == APR_EOF)
      {
        std::ostringstream oss;
        for(int i = 0; i < APR_SHA1_DIGESTSIZE; i++)
        {
          unsigned short letter = digest[i];
          oss << std::hex << std::setw(2) << std::setfill('0') << letter;
        }
        checksum = oss.str();
        ret = APR_SUCCESS;
      }
      apr_file_close(in);
    }
    apr_pool_destroy(pool);
  }
  
  return ret;
}
Esempio n. 4
0
static apr_status_t
lcn_document_writer_write_postings( lcn_document_writer_t *document_writer,
                                    const char *segment_name )
{
    apr_status_t s;
    apr_status_t s_save;

    apr_pool_t *pool = NULL;
    lcn_index_output_t *freq = NULL;
    lcn_index_output_t *prox = NULL;
    lcn_term_infos_writer_t *tis = NULL;

    /* TODO: TermVectorsWriter termVectorWriter = null */

    do
    {
        lcn_term_info_t ti;
        unsigned int field_ctr;
        unsigned int i;
        unsigned int j;

        LCNCE( apr_pool_create( &pool, document_writer->posting_table_pool ) );

        LCNCE( lcn_directory_create_output( document_writer->directory,
                                            &freq,
                                            apr_pstrcat( pool, segment_name, ".frq", NULL ),
                                            pool ));

        LCNCE( lcn_directory_create_output( document_writer->directory,
                                            &prox,
                                            apr_pstrcat( pool, segment_name, ".prx", NULL ),
                                            pool ));

        LCNCE( lcn_term_infos_writer_create( &tis,
                                             document_writer->directory,
                                             segment_name,
                                             document_writer->term_index_interval,
                                             pool ));

        for( field_ctr = 0;
             field_ctr < document_writer->sorted_postings->length;
             field_ctr++ )
        {
            unsigned int field_number;
            unsigned int *positions;
            lcn_field_info_t *field_info;
            unsigned int last_position;

            lcn_ptr_array_t *postings = (lcn_ptr_array_t*) document_writer->sorted_postings->arr[ field_ctr ];

            if ( 0 == postings->length )
            {
                continue;
            }

            LCNCM( lcn_field_infos_field_number( document_writer->field_infos,
                                                 &field_number,
                                                 lcn_term_field( ((lcn_posting_t*) postings->arr[0])->term ) ),
                   lcn_term_field( ((lcn_posting_t*) postings->arr[0])->term ) );

            for( i = 0; i < postings->length; i++ )
            {
                lcn_posting_t *posting = (lcn_posting_t*) postings->arr[ i ];
                unsigned int posting_freq = posting->freq;

                /* add an entry to the dictionary with pointers to prox and freq files */
                ti.doc_freq = 1;
                ti.freq_pointer = lcn_index_output_get_file_pointer( freq );
                ti.prox_pointer = lcn_index_output_get_file_pointer( prox );
                ti.skip_offset  = -1;

                LCNCE( lcn_term_infos_writer_add_term ( tis,
                                                        posting->term,
                                                        &ti,
                                                        field_number ));

                /* add an entry to the freq file */

                if ( 1 == posting_freq )  /* optimize freq == 1 */
                {
                    LCNCE( lcn_index_output_write_vint( freq, 1 )); /* set low bit of doc num */
                }
                else
                {
                    LCNCE( lcn_index_output_write_vint( freq, 0 ));              /* the document number */
                    LCNCE( lcn_index_output_write_vint( freq, posting_freq ));   /* frequency in doc    */
                }

                last_position = 0;
                positions = posting->positions;

                for( j = 0; j < posting_freq; j++ )  /* use delta-encoding */
                {
                    unsigned int position = positions[j];
                    LCNCE( lcn_index_output_write_vint( prox, position - last_position ));
                    last_position = position;
                }

#if 0
        if (termVectorWriter != null && termVectorWriter.isFieldOpen()) {
            termVectorWriter.addTerm(posting.term.text(), postingFreq, posting.positions, posting.offsets);
        }
#endif

        LCNCE( lcn_field_infos_by_number ( document_writer->field_infos,
                                           &field_info,
                                           field_number ));

        if ( LCN_TRUE == lcn_field_info_store_term_vector( field_info ) )
        {
            fprintf(stderr, "TODO: store term_vector\n" );
#if 0
            if (termVectorWriter == null) {
              termVectorWriter =
                new TermVectorsWriter(directory, segment, fieldInfos);
              termVectorWriter.openDocument();
            }
            termVectorWriter.openField(currentField);
#endif
        }
#if 0
        else if (termVectorWriter != null) {
            termVectorWriter.closeField();
        }
#endif
            }
        }

#if 0
      if (termVectorWriter != null)
        termVectorWriter.closeDocument();
#endif

    }
    while(0);

    /*
     * make an effort to close all streams we can but remember and re-throw
     * the first exception encountered in this process
     */

    if ( NULL != freq )
    {
        s_save = lcn_index_output_close( freq );
        s = ( s ? s : s_save );
    }

    if ( NULL != prox )
    {
        s_save = lcn_index_output_close( prox );
        s = ( s ? s : s_save );
    }

    if ( NULL != tis )
    {
        s_save = lcn_term_infos_writer_close( tis );
        s = ( s ? s : s_save );
    }

    if ( NULL != pool )
    {
        apr_pool_destroy( pool );
    }

    /* TODO if (termVectorWriter  != null)
     * try {  termVectorWriter.close(); } catch (IOException e) { if (keep == null) keep = e; }
     */

    return (apr_status_t) s;
}
Esempio n. 5
0
int jk_resolve(char *host,
               int port,
               struct sockaddr_in *rc) 
{
    int x;

    /* TODO: Should be updated for IPV6 support. */
    /* for now use the correct type, in_addr_t */    
    /* except on NetWare since the MetroWerks compiler is so strict */
#if defined(NETWARE)
    u_long laddr;
#else
	in_addr_t laddr;
#endif

    rc->sin_port   = htons((short)port);
    rc->sin_family = AF_INET;

    /* Check if we only have digits in the string */
    for(x = 0 ; '\0' != host[x] ; x++) {
        if(!isdigit(host[x]) && host[x] != '.') {
            break;
        }
    }

    /* If we found also characters we shoud make name to IP resolution */
    if(host[x] != '\0') {

#ifdef HAVE_APR
        apr_pool_t *context;
        apr_sockaddr_t *remote_sa, *temp_sa;
        char *remote_ipaddr;

        /* May be we could avoid to recreate it each time ? */
        if (apr_pool_create(&context, NULL) != APR_SUCCESS)
            return JK_FALSE;

        if (apr_sockaddr_info_get(&remote_sa, host, APR_UNSPEC, (apr_port_t)port, 0, context)
            != APR_SUCCESS) 
            return JK_FALSE;

        /* Since we are only handling AF_INET (IPV4) address (in_addr_t) */
        /* make sure we find one of those.                               */
        temp_sa = remote_sa;
        while ((NULL != temp_sa) && (AF_INET != temp_sa->family))
            temp_sa = temp_sa->next;

        /* if temp_sa is set, we have a valid address otherwise, just return */
        if (NULL != temp_sa)
            remote_sa = temp_sa;
        else
            return JK_FALSE;

        apr_sockaddr_ip_get(&remote_ipaddr, remote_sa);
        laddr = inet_addr(remote_ipaddr);

        /* May be we could avoid to delete it each time ? */
        apr_pool_destroy(context);

#else /* HAVE_APR */

      /* XXX : WARNING : We should really use gethostbyname_r in multi-threaded env */
      /* Fortunatly when APR is available, ie under Apache 2.0, we use it */
        struct hostent *hoste = gethostbyname(host);
        if(!hoste) {
            return JK_FALSE;
        }

        laddr = ((struct in_addr *)hoste->h_addr_list[0])->s_addr;

#endif /* HAVE_APR */
    } else {
        /* If we found only digits we use inet_addr() */
        laddr = inet_addr(host);        
    }
    memcpy(&(rc->sin_addr), &laddr , sizeof(laddr));

    return JK_TRUE;
}
Esempio n. 6
0
/*
 * Let's do it.  We end up doing a lot of file opening and closing,
 * but what do we care?  This application isn't run constantly.
 */
int main(int argc, const char * const argv[])
{
    apr_file_t *fpw = NULL;
    const char *errstr = NULL;
    char line[MAX_STRING_LEN];
    char *pwfilename = NULL;
    char *user = NULL;
    char tn[] = "htpasswd.tmp.XXXXXX";
    char *dirname;
    char *scratch, cp[MAX_STRING_LEN];
    int found = 0;
    int i;
    int mask = 0;
    apr_pool_t *pool;
    int existing_file = 0;
    struct passwd_ctx ctx = { 0 };
#if APR_CHARSET_EBCDIC
    apr_status_t rv;
    apr_xlate_t *to_ascii;
#endif

    apr_app_initialize(&argc, &argv, NULL);
    atexit(terminate);
    apr_pool_create(&pool, NULL);
    apr_file_open_stderr(&errfile, pool);
    ctx.pool = pool;
    ctx.alg = ALG_APMD5;

#if APR_CHARSET_EBCDIC
    rv = apr_xlate_open(&to_ascii, "ISO-8859-1", APR_DEFAULT_CHARSET, pool);
    if (rv) {
        apr_file_printf(errfile, "apr_xlate_open(to ASCII)->%d" NL, rv);
        exit(1);
    }
    rv = apr_SHA1InitEBCDIC(to_ascii);
    if (rv) {
        apr_file_printf(errfile, "apr_SHA1InitEBCDIC()->%d" NL, rv);
        exit(1);
    }
    rv = apr_MD5InitEBCDIC(to_ascii);
    if (rv) {
        apr_file_printf(errfile, "apr_MD5InitEBCDIC()->%d" NL, rv);
        exit(1);
    }
#endif /*APR_CHARSET_EBCDIC*/

    check_args(argc, argv, &ctx, &mask, &user, &pwfilename);

    /*
     * Only do the file checks if we're supposed to frob it.
     */
    if (!(mask & APHTP_NOFILE)) {
        existing_file = exists(pwfilename, pool);
        if (existing_file) {
            /*
             * Check that this existing file is readable and writable.
             */
            if (!accessible(pool, pwfilename, APR_FOPEN_READ|APR_FOPEN_WRITE)) {
                apr_file_printf(errfile, "%s: cannot open file %s for "
                                "read/write access" NL, argv[0], pwfilename);
                exit(ERR_FILEPERM);
            }
        }
        else {
            /*
             * Error out if -c was omitted for this non-existant file.
             */
            if (!(mask & APHTP_NEWFILE)) {
                apr_file_printf(errfile,
                        "%s: cannot modify file %s; use '-c' to create it" NL,
                        argv[0], pwfilename);
                exit(ERR_FILEPERM);
            }
            /*
             * As it doesn't exist yet, verify that we can create it.
             */
            if (!accessible(pool, pwfilename, APR_FOPEN_WRITE|APR_FOPEN_CREATE)) {
                apr_file_printf(errfile, "%s: cannot create file %s" NL,
                                argv[0], pwfilename);
                exit(ERR_FILEPERM);
            }
        }
    }

    /*
     * All the file access checks (if any) have been made.  Time to go to work;
     * try to create the record for the username in question.  If that
     * fails, there's no need to waste any time on file manipulations.
     * Any error message text is returned in the record buffer, since
     * the mkrecord() routine doesn't have access to argv[].
     */
    if (!(mask & APHTP_DELUSER)) {
        i = mkrecord(&ctx, user);
        if (i != 0) {
            apr_file_printf(errfile, "%s: %s" NL, argv[0], errstr);
            exit(i);
        }
        if (mask & APHTP_NOFILE) {
            printf("%s" NL, ctx.out);
            exit(0);
        }
    }

    /*
     * We can access the files the right way, and we have a record
     * to add or update.  Let's do it..
     */
    if (apr_temp_dir_get((const char**)&dirname, pool) != APR_SUCCESS) {
        apr_file_printf(errfile, "%s: could not determine temp dir" NL,
                        argv[0]);
        exit(ERR_FILEPERM);
    }
    dirname = apr_psprintf(pool, "%s/%s", dirname, tn);

    if (apr_file_mktemp(&ftemp, dirname, 0, pool) != APR_SUCCESS) {
        apr_file_printf(errfile, "%s: unable to create temporary file %s" NL,
                        argv[0], dirname);
        exit(ERR_FILEPERM);
    }

    /*
     * If we're not creating a new file, copy records from the existing
     * one to the temporary file until we find the specified user.
     */
    if (existing_file && !(mask & APHTP_NEWFILE)) {
        if (apr_file_open(&fpw, pwfilename, APR_READ | APR_BUFFERED,
                          APR_OS_DEFAULT, pool) != APR_SUCCESS) {
            apr_file_printf(errfile, "%s: unable to read file %s" NL,
                            argv[0], pwfilename);
            exit(ERR_FILEPERM);
        }
        while (apr_file_gets(line, sizeof(line), fpw) == APR_SUCCESS) {
            char *colon;

            strcpy(cp, line);
            scratch = cp;
            while (apr_isspace(*scratch)) {
                ++scratch;
            }

            if (!*scratch || (*scratch == '#')) {
                putline(ftemp, line);
                continue;
            }
            /*
             * See if this is our user.
             */
            colon = strchr(scratch, ':');
            if (colon != NULL) {
                *colon = '\0';
            }
            else {
                /*
                 * If we've not got a colon on the line, this could well
                 * not be a valid htpasswd file.
                 * We should bail at this point.
                 */
                apr_file_printf(errfile, "%s: The file %s does not appear "
                                         "to be a valid htpasswd file." NL,
                                argv[0], pwfilename);
                apr_file_close(fpw);
                exit(ERR_INVALID);
            }
            if (strcmp(user, scratch) != 0) {
                putline(ftemp, line);
                continue;
            }
            else {
                if (!(mask & APHTP_DELUSER)) {
                    /* We found the user we were looking for.
                     * Add him to the file.
                    */
                    apr_file_printf(errfile, "Updating ");
                    putline(ftemp, ctx.out);
                    found++;
                }
                else {
                    /* We found the user we were looking for.
                     * Delete them from the file.
                     */
                    apr_file_printf(errfile, "Deleting ");
                    found++;
                }
            }
        }
        apr_file_close(fpw);
    }
    if (!found && !(mask & APHTP_DELUSER)) {
        apr_file_printf(errfile, "Adding ");
        putline(ftemp, ctx.out);
    }
    else if (!found && (mask & APHTP_DELUSER)) {
        apr_file_printf(errfile, "User %s not found" NL, user);
        exit(0);
    }
    apr_file_printf(errfile, "password for user %s" NL, user);

    /* The temporary file has all the data, just copy it to the new location.
     */
    if (apr_file_copy(dirname, pwfilename, APR_FILE_SOURCE_PERMS, pool) !=
        APR_SUCCESS) {
        apr_file_printf(errfile, "%s: unable to update file %s" NL,
                        argv[0], pwfilename);
        exit(ERR_FILEPERM);
    }
    apr_file_close(ftemp);
    return 0;
}
Esempio n. 7
0
int main (void)
{
    CuString *output = CuStringNew();
    CuSuite* sr = CuSuiteNew();
    apr_status_t s;
    apr_pool_t *main_pool;

    lcn_log_stream = stderr;

    do
    {
        if ( ! APR_SUCCESS == ( s = apr_initialize() ) )
        {
            char buf[1000];
            char *err = apr_strerror( s, buf, 1000 );
            fprintf(stderr, "%s", err );
            return 1;
        }

        LCNCE( apr_pool_create( &main_pool, NULL ) );
        LCNCE( lcn_atom_init ( main_pool ) );
    }
    while(0);

    setbuf(stdout, 0);

    CuSuiteAddSuite(sr, make_50_index_writer_suite());
    CuSuiteAddSuite(sr, make_50_checksum_index_output_suite());
    CuSuiteAddSuite(sr, make_ostream_suite());
    CuSuiteAddSuite(sr, make_ram_file_suite() ); 
   
#if 0
    CuSuiteAddSuite(sr, make_50_index_writer_suite());
    CuSuiteAddSuite(sr, make_50_crc32_suite());
    CuSuiteAddSuite(sr, make_ostream_suite());
    CuSuiteAddSuite(sr, make_50_checksum_index_output_suite());
#endif
#if 0
    CuSuiteAddSuite(sr, make_50_document_writer_suite());
    CuSuiteAddSuite(sr, make_50_index_writer_suite());
    CuSuiteAddSuite(sr, make_50_crc32_suite());
    CuSuiteAddSuite(sr, make_50_checksum_index_output_suite());
    CuSuiteAddSuite(sr, make_array_suite() );
    CuSuiteAddSuite(sr, make_atom_suite());
    CuSuiteAddSuite(sr, make_bitvector_suite());
    CuSuiteAddSuite(sr, make_boolean_clause_suite() );
    CuSuiteAddSuite(sr, make_boolean_query_suite() );
    CuSuiteAddSuite(sr, make_char_tokenizer_suite() );
    CuSuiteAddSuite(sr, make_compatibility_suite());
    CuSuiteAddSuite(sr, make_compound_file_suite());
    CuSuiteAddSuite(sr, make_compound_file_util_suite());
    CuSuiteAddSuite(sr, make_custom_hit_queue_suite() );
    CuSuiteAddSuite(sr, make_directory_suite());
    CuSuiteAddSuite(sr, make_document_suite() );
    CuSuiteAddSuite(sr, make_explanation_suite() );
    CuSuiteAddSuite(sr, make_field_fixed_size_suite());
    CuSuiteAddSuite(sr, make_field_infos_suite());
    CuSuiteAddSuite(sr, make_field_sorted_hit_queue_suite() );
    CuSuiteAddSuite(sr, make_filtered_query_suite());
    CuSuiteAddSuite(sr, make_fs_field_bitvector_suite() );
    CuSuiteAddSuite(sr, make_fs_field_query_suite() );
    CuSuiteAddSuite(sr, make_german_stem_filter_suite());
    CuSuiteAddSuite(sr, make_group_search_suite());
    CuSuiteAddSuite(sr, make_index_reader_suite());
    CuSuiteAddSuite(sr, make_index_searcher_suite() );
    CuSuiteAddSuite(sr, make_index_writer_bugs_suite());
    CuSuiteAddSuite(sr, make_index_writer_suite());
    CuSuiteAddSuite(sr, make_input_stream_suite());
    CuSuiteAddSuite(sr, make_linked_list_suite() );
    CuSuiteAddSuite(sr, make_lucene_list_suite());
    CuSuiteAddSuite(sr, make_lucene_util_suite());
    CuSuiteAddSuite(sr, make_match_all_docs_query_suite() );
    CuSuiteAddSuite(sr, make_multi_phrase_query_suite() );
    CuSuiteAddSuite(sr, make_multi_reader_suite());
    CuSuiteAddSuite(sr, make_multiple_fields_suite());
    CuSuiteAddSuite(sr, make_one_hit_query_suite() );
    CuSuiteAddSuite(sr, make_ordered_query_suite() );
    CuSuiteAddSuite(sr, make_ostream_suite());
    CuSuiteAddSuite(sr, make_prefix_query_suite() );
    CuSuiteAddSuite(sr, make_priority_queue_suite() );
    CuSuiteAddSuite(sr, make_query_bitvector_suite() );
    CuSuiteAddSuite(sr, make_query_parser_suite() );
    CuSuiteAddSuite(sr, make_query_tokenizer_suite() );
    CuSuiteAddSuite(sr, make_ram_file_suite() );
    CuSuiteAddSuite(sr, make_range_counting_suite());
    CuSuiteAddSuite(sr, make_score_doc_comparator_suite() );
    CuSuiteAddSuite(sr, make_scorer_suite() );
    CuSuiteAddSuite(sr, make_segment_infos_suite());
    CuSuiteAddSuite(sr, make_segment_term_enum_suite() );
    CuSuiteAddSuite(sr, make_similarity_suite() );
    CuSuiteAddSuite(sr, make_simple_analyzer_suite() );
    CuSuiteAddSuite(sr, make_sort_by_bitvector_suite() );
    CuSuiteAddSuite(sr, make_sort_field_suite() );
    CuSuiteAddSuite(sr, make_stop_filter_suite() );
    CuSuiteAddSuite(sr, make_string_buffer_suite() );
    CuSuiteAddSuite(sr, make_string_suite() );
    CuSuiteAddSuite(sr, make_term_docs_suite());
    CuSuiteAddSuite(sr, make_term_infos_reader_suite());
    CuSuiteAddSuite(sr, make_term_infos_writer_suite());
    CuSuiteAddSuite(sr, make_term_pos_query_suite() );
    CuSuiteAddSuite(sr, make_term_query_suite());
    CuSuiteAddSuite(sr, make_term_suite());
    CuSuiteAddSuite(sr, make_top_doc_collector_suite() );
#endif

    CuSuiteRun(sr);
    CuSuiteSummary(sr, output);
    CuSuiteDetails(sr, output);
    printf("%s\n", output->buffer);
    free( output->buffer );
    free( output );

    CuSuiteFree( sr );

    apr_terminate();

    return 0;
}
Esempio n. 8
0
host_portal_t *create_hportal(portal_context_t *hpc, void *connect_context, char *hostport, int min_conn, int max_conn, apr_time_t dt_connect)
{
    host_portal_t *hp;

    log_printf(15, "create_hportal: hpc=%p\n", hpc);
    tbx_type_malloc_clear(hp, host_portal_t, 1);
    assert_result(apr_pool_create(&(hp->mpool), NULL), APR_SUCCESS);

    char host[sizeof(hp->host)];
    int port;
    char *hp2 = strdup(hostport);
    char *bstate;
    int fin;

    host[0] = '\0';

    strncpy(host, tbx_stk_string_token(hp2, HP_HOSTPORT_SEPARATOR, &bstate, &fin), sizeof(host)-1);
    host[sizeof(host)-1] = '\0';
    port = atoi(bstate);
    free(hp2);
    log_printf(15, "create_hportal: hostport: %s host=%s port=%d min=%d max=%d dt=" TT "\n", hostport, host, port, min_conn, max_conn, dt_connect);

    strncpy(hp->host, host, sizeof(hp->host)-1);
    hp->host[sizeof(hp->host)-1] = '\0';

    //** Check if we can resolve the host's IP address
    char in_addr[6];
    if (tbx_dnsc_lookup(host, in_addr, NULL) != 0) {
        log_printf(1, "create_hportal: Can\'t resolve host address: %s:%d\n", host, port);
        hp->invalid_host = 0;
//     hp->invalid_host = 1;
    } else {
        hp->invalid_host = 0;
    }

    hp->port = port;
    snprintf(hp->skey, sizeof(hp->skey), "%s", hostport);
    hp->connect_context = hpc->fn->dup_connect_context(connect_context);

    hp->context = hpc;
    hp->min_conn = min_conn;
    hp->max_conn = max_conn;
    hp->dt_connect = dt_connect;
    hp->sleeping_conn = 0;
    hp->workload = 0;
    hp->executing_workload = 0;
    hp->cmds_processed = 0;
    hp->n_conn = 0;
    hp->conn_list = tbx_stack_new();
    hp->closed_que = tbx_stack_new();
    hp->que = tbx_stack_new();
    hp->direct_list = tbx_stack_new();
    hp->pause_until = 0;
    hp->stable_conn = max_conn;
    hp->closing_conn = 0;
    hp->failed_conn_attempts = 0;
    hp->successful_conn_attempts = 0;
    hp->abort_conn_attempts = hpc->abort_conn_attempts;

    apr_thread_mutex_create(&(hp->lock), APR_THREAD_MUTEX_DEFAULT, hp->mpool);
    apr_thread_cond_create(&(hp->cond), hp->mpool);

    return(hp);
}
Esempio n. 9
0
bool grab_gst_syms(std::string gst_dso_name,
		   std::string gst_dso_name_vid,
		   std::string gst_dso_name_aud)
{
	if (sSymsGrabbed)
	{
		// already have grabbed good syms
		return TRUE;
	}

	bool sym_error = false;
	bool rtn = false;
	apr_status_t rv;
	apr_dso_handle_t *sSymGSTDSOHandle = NULL;

#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0)

	//attempt to load the shared libraries
	apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
  
	if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
					       gst_dso_name.c_str(),
					       sSymGSTDSOMemoryPool) ))
	{
		INFOMSG("Found DSO: %s", gst_dso_name.c_str());
#include "llmediaimplgstreamer_syms_raw.inc"
      
		if ( sSymGSTDSOHandle )
		{
			sSymGSTDSOHandleG = sSymGSTDSOHandle;
			sSymGSTDSOHandle = NULL;
		}
      
		if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
					            gst_dso_name_aud.c_str(),
						       sSymGSTDSOMemoryPool) ))
		{
			INFOMSG("Found DSO: %s", gst_dso_name_aud.c_str());
#include "llmediaimplgstreamer_syms_rawa.inc"
			
			if ( sSymGSTDSOHandle )
			{
				sSymGSTDSOHandleA = sSymGSTDSOHandle;
				sSymGSTDSOHandle = NULL;
			}
	  
			if ( APR_SUCCESS ==
			     (rv = apr_dso_load(&sSymGSTDSOHandle,
						gst_dso_name_vid.c_str(),
						sSymGSTDSOMemoryPool) ))
			{
				INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str());
#include "llmediaimplgstreamer_syms_rawv.inc"
			}
			else
			{
				INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str());
				rtn = false; // failure
			}
		}
		else
		{
			INFOMSG("Couldn't load DSO: %s", gst_dso_name_aud.c_str());
			rtn = false; // failure
		}
		
		rtn = !sym_error;
	}
	else
	{
		INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str());
		rtn = false; // failure
	}

	if (sym_error)
	{
		WARNMSG("Failed to find necessary symbols in GStreamer libraries.");
	}
	
	if ( sSymGSTDSOHandle )
	{
		sSymGSTDSOHandleV = sSymGSTDSOHandle;
		sSymGSTDSOHandle = NULL;
	}
#undef LL_GST_SYM

	sSymsGrabbed = !!rtn;
	return rtn;
}
Esempio n. 10
0
static smt_fileio_t *
    smt_fileio_new_ (
    char * file,                        //  Source file for call
    size_t line                         //  Line number for call
)
{
    smt_fileio_t *
        self = NULL;                    //  Object reference

#if (defined (BASE_ANIMATE)  ||  defined (BASE_ANIMATE_SMT_FILEIO)  ||  defined (BASE_ANIMATE_SMT_FILEIO_NEW))
    if (smt_fileio_animating)
        icl_console_print ("<smt_fileio_new_start"
#if (defined (BASE_THREADSAFE))
" thread=\"%pp\""
#endif
" file=\"%s\""
" line=\"%u\""
"/>"
#if (defined (BASE_THREADSAFE))
, apr_os_thread_current ()
#endif
, file, line);
#endif

#if (defined (BASE_TRACE)   || defined (BASE_TRACE_SMT_FILEIO)   || defined (BASE_TRACE_SMT_FILEIO_NEW))
    icl_trace_record (NULL, smt_fileio_dump, 1);
#endif

#if (defined (BASE_STATS)  ||  defined (BASE_STATS_SMT_FILEIO)  ||  defined (BASE_STATS_SMT_FILEIO_NEW))
    icl_stats_inc ("smt_fileio_new", &s_smt_fileio_new_stats);
#endif

    self = smt_fileio_alloc_ (file, line);
    if (self) {
        self->object_tag   = SMT_FILEIO_ALIVE;
#if defined (DEBUG)
        icl_mem_set_callback (self, smt_fileio_show_);
#endif

self->handle  = NULL;
self->io_size = 0;
self->eof     = FALSE;
icl_apr_assert (apr_pool_create (&self->pool, icl_global_pool));
apr_pool_tag (self->pool, "smt_fileio_new");
}
#if (defined (BASE_TRACE)   || defined (BASE_TRACE_SMT_FILEIO)   || defined (BASE_TRACE_SMT_FILEIO_NEW))
    icl_trace_record (NULL, smt_fileio_dump, 0x10000 + 1);
#endif

#if (defined (BASE_ANIMATE)   || defined (BASE_ANIMATE_SMT_FILEIO)   || defined (BASE_ANIMATE_SMT_FILEIO_NEW))
    if (smt_fileio_animating)
        icl_console_print ("<smt_fileio_new_finish"
#if (defined (BASE_THREADSAFE))
" thread=\"%pp\""
#endif
" file=\"%s\""
" line=\"%u\""
" self=\"%pp\""
"/>"
#if (defined (BASE_THREADSAFE))
, apr_os_thread_current ()
#endif
, file, line, self);
#endif


    return (self);
}
Esempio n. 11
0
void
svn_handle_error2(svn_error_t *err,
                  FILE *stream,
                  svn_boolean_t fatal,
                  const char *prefix)
{
  /* In a long error chain, there may be multiple errors with the same
     error code and no custom message.  We only want to print the
     default message for that code once; printing it multiple times
     would add no useful information.  The 'empties' array below
     remembers the codes of empty errors already seen in the chain.

     We could allocate it in err->pool, but there's no telling how
     long err will live or how many times it will get handled.  So we
     use a subpool. */
  apr_pool_t *subpool;
  apr_array_header_t *empties;
  svn_error_t *tmp_err;

  /* ### The rest of this file carefully avoids using svn_pool_*(),
     preferring apr_pool_*() instead.  I can't remember why -- it may
     be an artifact of r843793, or it may be for some deeper reason --
     but I'm playing it safe and using apr_pool_*() here too. */
  apr_pool_create(&subpool, err->pool);
  empties = apr_array_make(subpool, 0, sizeof(apr_status_t));

  tmp_err = err;
  while (tmp_err)
    {
      svn_boolean_t printed_already = FALSE;

      if (! tmp_err->message)
        {
          int i;

          for (i = 0; i < empties->nelts; i++)
            {
              if (tmp_err->apr_err == APR_ARRAY_IDX(empties, i, apr_status_t) )
                {
                  printed_already = TRUE;
                  break;
                }
            }
        }

      if (! printed_already)
        {
          print_error(tmp_err, stream, prefix);
          if (! tmp_err->message)
            {
              APR_ARRAY_PUSH(empties, apr_status_t) = tmp_err->apr_err;
            }
        }

      tmp_err = tmp_err->child;
    }

  svn_pool_destroy(subpool);

  fflush(stream);
  if (fatal)
    {
      /* Avoid abort()s in maintainer mode. */
      svn_error_clear(err);

      /* We exit(1) here instead of abort()ing so that atexit handlers
         get called. */
      exit(EXIT_FAILURE);
    }
}
Esempio n. 12
0
apr_status_t stomp_write(stomp_connection *connection, stomp_frame *frame, apr_pool_t* pool) {
   apr_status_t rc;

   btlogger_trace("stomp_write");
#define CHECK_SUCCESS if( rc!=APR_SUCCESS ) { return rc; }
   // Write the command.
   rc = stomp_write_buffer(connection, frame->command, strlen(frame->command));
   CHECK_SUCCESS;               
   rc = stomp_write_buffer(connection, "\n", 1);
   CHECK_SUCCESS;
   
   // Write the headers
   if( frame->headers != NULL ) {
      
      apr_hash_index_t *i;
      const void *key;
      void *value;
      for (i = apr_hash_first(NULL, frame->headers); i; i = apr_hash_next(i)) {
         apr_hash_this(i, &key, NULL, &value);

	 btlogger_trace("stomp_write header %s:%s", key, value);
         
         rc = stomp_write_buffer(connection, key, strlen(key));
         CHECK_SUCCESS;
         rc = stomp_write_buffer(connection, ":", 1);
         CHECK_SUCCESS;
         rc = stomp_write_buffer(connection, value, strlen(value));
         CHECK_SUCCESS;
         rc = stomp_write_buffer(connection, "\n", 1);
         CHECK_SUCCESS;  
      }

	  if(frame->body_length >= 0) {
		  apr_pool_t *length_pool;
		  char *length_string;

		  apr_pool_create(&length_pool, pool);
		  rc = stomp_write_buffer(connection, "content-length:", 15);
		  CHECK_SUCCESS;
		  
		  length_string = apr_itoa(length_pool, frame->body_length);
		  rc = stomp_write_buffer(connection, length_string, strlen(length_string));
		  CHECK_SUCCESS;
		  rc = stomp_write_buffer(connection, "\n", 1);
		  CHECK_SUCCESS;

		  btlogger_trace("stomp_write content-length %s", length_string);
		  apr_pool_destroy(length_pool);
	  }
   }
   rc = stomp_write_buffer(connection, "\n", 1);
   CHECK_SUCCESS;
   
   // Write the body.
   if( frame->body != NULL ) {
      int body_length = frame->body_length;
	  if(body_length < 0)
		  body_length = strlen(frame->body);
      rc = stomp_write_buffer(connection, frame->body, body_length);
      CHECK_SUCCESS;
   }
   btlogger_trace("stomp_write body");
   rc = stomp_write_buffer(connection, "\0\n", 2);
   btlogger_trace("stomp_write post-amble");
   CHECK_SUCCESS;
      
#undef CHECK_SUCCESS
                    
   return APR_SUCCESS;
}
Esempio n. 13
0
apr_status_t stomp_read_buffer(stomp_connection *connection, char **data, apr_pool_t *pool)
{
   apr_pool_t *tpool;
   apr_status_t rc;
   data_block_list *head, *tail;
   apr_size_t i=0;
   apr_size_t bytesRead=0;
   char *p;

   btlogger_trace("stomp_read_buffer");
   rc = apr_pool_create(&tpool, pool);
   if( rc != APR_SUCCESS ) {
      btlogger_warn("stomp_read_buffer could not apr_pool_create returning %d", rc);
      return rc;
   }
      
   head = tail = apr_pcalloc(tpool, sizeof(data_block_list));
   if( head == NULL ) {
      btlogger_warn("stomp_read_buffer could not apr_pcalloc returning APR_ENONMEM");
      return APR_ENOMEM;
   }
   
#define CHECK_SUCCESS if( rc!=APR_SUCCESS ) { apr_pool_destroy(tpool);	return rc; }
   
   // Keep reading bytes till end of frame is encountered.
	while( 1 ) {
      
		apr_size_t length = 1;
      apr_status_t rc = apr_socket_recv(connection->socket, tail->data+i, &length);
      CHECK_SUCCESS;
      
      if( length==1 ) {
         i++;
         bytesRead++;
         
         // Keep reading bytes till end of frame
         if( tail->data[i-1]==0 ) {
            char endline[1];
            // We expect a newline after the null.
            // tjj patch make sure the receive completes ok by assigning the status
            rc = apr_socket_recv(connection->socket, endline, &length);
            CHECK_SUCCESS;
            if( endline[0] != '\n' ) {
               btlogger_warn("stomp_read_buffer endline[0] != \\n returning APR_EGENERAL, character as a decimal: %d", endline[0]);
               btlogger_warn("tail->data length was: %d", bytesRead);
               btlogger_warn("tail->data was: %s", tail->data);
               return APR_EGENERAL;
            }
            break;
         }
         
         // Do we need to allocate a new block?
         if( i >= sizeof( tail->data) ) {            
            tail->next = apr_pcalloc(tpool, sizeof(data_block_list));
            if( tail->next == NULL ) {
               apr_pool_destroy(tpool);
               btlogger_warn("stomp_read_buffer could not apr_pcalloc (2nd block) returning APR_ENONMEM");
               return APR_ENOMEM;
            }
            tail=tail->next;
            i=0;
         }
      }      
	}
#undef CHECK_SUCCESS
   
   // Now we have the whole frame and know how big it is.  Allocate it's buffer
   *data = apr_pcalloc(pool, bytesRead);
   p = *data;
   if( p==NULL ) {
      apr_pool_destroy(tpool);
      btlogger_warn("stomp_read_buffer could not apr_pcalloc (3rd block) returning APR_ENONMEM");
      return APR_ENOMEM;
   }
   
   // Copy the frame over to the new buffer.
   for( ;head != NULL; head = head->next ) {
      int len = bytesRead > sizeof(head->data) ? sizeof(head->data) : bytesRead;
      memcpy(p,head->data,len);
      p+=len;
      bytesRead-=len;
   }
   
   apr_pool_destroy(tpool);
	return APR_SUCCESS;
}
Esempio n. 14
0
apr_status_t stomp_read_line(stomp_connection *connection, char **data, int* length, apr_pool_t *pool)
{
   apr_pool_t *tpool;
   apr_status_t rc;
   data_block_list *head, *tail;
   apr_size_t i=0;
   apr_size_t bytesRead=0;
   char *p;

   btlogger_trace("stomp_read_line");
   rc = apr_pool_create(&tpool, pool);
   if( rc != APR_SUCCESS ) {
      btlogger_warn("stomp_read_line could not apr_pool_create returning %d", rc);
      return rc;
   }
      
   head = tail = apr_pcalloc(tpool, sizeof(data_block_list));
   if( head == NULL ) {
      btlogger_warn("stomp_read_line could not apr_pcalloc returning APR_ENOMEM");
      return APR_ENOMEM;
   }

#define CHECK_SUCCESS if( rc!=APR_SUCCESS ) { apr_pool_destroy(tpool);	return rc; }
	
   while( 1 ) {
      
	  apr_size_t length = 1;
      apr_status_t rc = apr_socket_recv(connection->socket, tail->data+i, &length);
      CHECK_SUCCESS;
      
      if( length==1 ) {
         i++;
         bytesRead++;
         
         // Keep reading bytes till end of line
         if( tail->data[i-1]=='\n') {
            // Null terminate the string instead of having the newline
        	//btlogger_trace("Null terminating the string");
		    tail->data[i-1] = 0;
			break;
         } else if( tail->data[i-1]==0 ) {
			// Encountered 0 before end of line
			apr_pool_destroy(tpool);
			btlogger_warn("stomp_read_line tail->data[i-1]==0 returning APR_EGENERAL");
			btlogger_warn("tail->data length was: %d", bytesRead);
			btlogger_warn("tail->data was: %s", tail->data);
			return APR_EGENERAL;
		 }
         
         // Do we need to allocate a new block?
         if( i >= sizeof( tail->data) ) {            
            tail->next = apr_pcalloc(tpool, sizeof(data_block_list));
            if( tail->next == NULL ) {
               apr_pool_destroy(tpool);
               btlogger_warn("stomp_read_line could not apr_pcalloc (2nd code block) returning APR_ENOMEM");
               return APR_ENOMEM;
            }
            tail=tail->next;
            i=0;
         }
      }      
	}

#undef CHECK_SUCCESS
   // Now we have the whole frame and know how big it is.  Allocate it's buffer
   *data = apr_pcalloc(pool, bytesRead);
   p = *data;
   if( p==NULL ) {
      apr_pool_destroy(tpool);
      btlogger_warn("stomp_read_line could not apr_pcalloc (3rd code block) returning APR_ENOMEM");
      return APR_ENOMEM;
   }

   // Copy the frame over to the new buffer.
   *length = bytesRead - 1;
   for( ;head != NULL; head = head->next ) {
      int len = bytesRead > sizeof(head->data) ? sizeof(head->data) : bytesRead;
      memcpy(p,head->data,len);
      p+=len;
      bytesRead-=len;
   }
   
   apr_pool_destroy(tpool);
   return APR_SUCCESS;
}