static apr_status_t store_array(apr_file_t *fd, apr_array_header_t* arr) { int i; apr_status_t rv; struct iovec iov[2]; apr_size_t amt; const char **elts; elts = (const char **) arr->elts; for (i = 0; i < arr->nelts; i++) { iov[0].iov_base = (char*) elts[i]; iov[0].iov_len = strlen(elts[i]); iov[1].iov_base = CRLF; iov[1].iov_len = sizeof(CRLF) - 1; rv = apr_file_writev(fd, (const struct iovec *) &iov, 2, &amt); if (rv != APR_SUCCESS) { return rv; } } iov[0].iov_base = CRLF; iov[0].iov_len = sizeof(CRLF) - 1; return apr_file_writev(fd, (const struct iovec *) &iov, 1, &amt); }
static apr_status_t store_table(apr_file_t *fd, apr_table_t *table) { int i; apr_status_t rv; struct iovec iov[4]; apr_size_t amt; apr_table_entry_t *elts; elts = (apr_table_entry_t *) apr_table_elts(table)->elts; for (i = 0; i < apr_table_elts(table)->nelts; ++i) { if (elts[i].key != NULL) { iov[0].iov_base = elts[i].key; iov[0].iov_len = strlen(elts[i].key); iov[1].iov_base = ": "; iov[1].iov_len = sizeof(": ") - 1; iov[2].iov_base = elts[i].val; iov[2].iov_len = strlen(elts[i].val); iov[3].iov_base = CRLF; iov[3].iov_len = sizeof(CRLF) - 1; rv = apr_file_writev(fd, (const struct iovec *) &iov, 4, &amt); if (rv != APR_SUCCESS) { return rv; } } } iov[0].iov_base = CRLF; iov[0].iov_len = sizeof(CRLF) - 1; rv = apr_file_writev(fd, (const struct iovec *) &iov, 1, &amt); return rv; }
void logging_log(config_t *cfg, loglevel_e level, const char *fmt, ...) { va_list ap; char date[APR_RFC822_DATE_LEN]; struct iovec vec[4]; apr_size_t blen; if (cfg->loglevel < level) return; va_start(ap, fmt); apr_pool_clear(cfg->errorlog_p); apr_rfc822_date(date, apr_time_now()); vec[0].iov_base = date; vec[0].iov_len = APR_RFC822_DATE_LEN-1; vec[1].iov_base = " "; vec[1].iov_len = 2; vec[2].iov_base = apr_pvsprintf(cfg->errorlog_p, fmt, ap); vec[2].iov_len = strlen(vec[2].iov_base); vec[3].iov_base = "\n"; vec[3].iov_len = 1; if (level == LOGLEVEL_NOISE) { apr_file_writev(cfg->errorlog_fperr,&vec[2],2,&blen); } if (cfg->loglevel > LOGLEVEL_NONE && cfg->errorlog_fp) { apr_file_writev(cfg->errorlog_fp,vec,4,&blen); } va_end(ap); }
static void test_writev_buffered(abts_case *tc, void *data) { apr_file_t *f; apr_size_t nbytes; struct iovec vec[2]; const char *fname = "data/testwritev_buffered.dat"; APR_ASSERT_SUCCESS(tc, "open file for writing", apr_file_open(&f, fname, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, APR_OS_DEFAULT, p)); nbytes = strlen(TESTSTR); APR_ASSERT_SUCCESS(tc, "buffered write", apr_file_write(f, TESTSTR, &nbytes)); vec[0].iov_base = LINE1; vec[0].iov_len = strlen(LINE1); vec[1].iov_base = LINE2; vec[1].iov_len = strlen(LINE2); APR_ASSERT_SUCCESS(tc, "writev of size 2 to file", apr_file_writev(f, vec, 2, &nbytes)); APR_ASSERT_SUCCESS(tc, "close for writing", apr_file_close(f)); file_contents_equal(tc, fname, TESTSTR LINE1 LINE2, strlen(TESTSTR) + strlen(LINE1) + strlen(LINE2)); }
static void test_writev_buffered(CuTest *tc) { apr_status_t rv; apr_file_t *f; apr_size_t nbytes; struct iovec vec[2]; const char *fname = "data/testwritev_buffered.dat"; rv = apr_file_open(&f, fname, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, APR_OS_DEFAULT, p); CuAssertIntEquals(tc, APR_SUCCESS, rv); nbytes = strlen(TESTSTR); rv = apr_file_write(f, TESTSTR, &nbytes); CuAssertIntEquals(tc, APR_SUCCESS, rv); vec[0].iov_base = LINE1; vec[0].iov_len = strlen(LINE1); vec[1].iov_base = LINE2; vec[1].iov_len = strlen(LINE2); rv = apr_file_writev(f, vec, 2, &nbytes); CuAssertIntEquals(tc, APR_SUCCESS, rv); rv = apr_file_close(f); CuAssertIntEquals(tc, APR_SUCCESS, rv); file_contents_equal(tc, fname, TESTSTR LINE1 LINE2, strlen(TESTSTR) + strlen(LINE1) + strlen(LINE2)); }
static void test_writev(abts_case *tc, void *data) { apr_file_t *f; apr_size_t nbytes; struct iovec vec[5]; const char *fname = "data/testwritev.txt"; APR_ASSERT_SUCCESS(tc, "open file for writing", apr_file_open(&f, fname, APR_WRITE|APR_CREATE|APR_TRUNCATE, APR_OS_DEFAULT, p)); vec[0].iov_base = LINE1; vec[0].iov_len = strlen(LINE1); APR_ASSERT_SUCCESS(tc, "writev of size 1 to file", apr_file_writev(f, vec, 1, &nbytes)); file_contents_equal(tc, fname, LINE1, strlen(LINE1)); vec[0].iov_base = LINE1; vec[0].iov_len = strlen(LINE1); vec[1].iov_base = LINE2; vec[1].iov_len = strlen(LINE2); vec[2].iov_base = LINE1; vec[2].iov_len = strlen(LINE1); vec[3].iov_base = LINE1; vec[3].iov_len = strlen(LINE1); vec[4].iov_base = LINE2; vec[4].iov_len = strlen(LINE2); APR_ASSERT_SUCCESS(tc, "writev of size 5 to file", apr_file_writev(f, vec, 5, &nbytes)); APR_ASSERT_SUCCESS(tc, "close for writing", apr_file_close(f)); file_contents_equal(tc, fname, LINE1 LINE1 LINE2 LINE1 LINE1 LINE2, strlen(LINE1)*4 + strlen(LINE2)*2); }
static void test_writev_buffered_seek(CuTest *tc) { apr_file_t *f; apr_status_t rv; apr_off_t off = 0; struct iovec vec[3]; apr_size_t nbytes = strlen(TESTSTR); char *str = apr_pcalloc(p, nbytes+1); const char *fname = "data/testwritev_buffered.dat"; rv = apr_file_open(&f, fname, APR_WRITE | APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p); rv = apr_file_read(f, str, &nbytes); CuAssertIntEquals(tc, APR_SUCCESS, rv); CuAssertStrEquals(tc, TESTSTR, str); rv = apr_file_seek(f, APR_SET, &off); CuAssertIntEquals(tc, APR_SUCCESS, rv); vec[0].iov_base = LINE1; vec[0].iov_len = strlen(LINE1); vec[1].iov_base = LINE2; vec[1].iov_len = strlen(LINE2); vec[2].iov_base = TESTSTR; vec[2].iov_len = strlen(TESTSTR); rv = apr_file_writev(f, vec, 3, &nbytes); CuAssertIntEquals(tc, APR_SUCCESS, rv); rv = apr_file_close(f); CuAssertIntEquals(tc, APR_SUCCESS, rv); file_contents_equal(tc, fname, LINE1 LINE2 TESTSTR, strlen(LINE1) + strlen(LINE2) + strlen(TESTSTR)); rv = apr_file_remove(fname, p); CuAssertIntEquals(tc, APR_SUCCESS, rv); }
static void test_writev_buffered_seek(abts_case *tc, void *data) { apr_file_t *f; apr_status_t rv; apr_off_t off = 0; struct iovec vec[3]; apr_size_t nbytes = strlen(TESTSTR); char *str = apr_pcalloc(p, nbytes+1); const char *fname = "data/testwritev_buffered.dat"; APR_ASSERT_SUCCESS(tc, "open file for writing", apr_file_open(&f, fname, APR_FOPEN_WRITE | APR_FOPEN_READ | APR_FOPEN_BUFFERED, APR_OS_DEFAULT, p)); rv = apr_file_read(f, str, &nbytes); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_STR_EQUAL(tc, TESTSTR, str); APR_ASSERT_SUCCESS(tc, "buffered seek", apr_file_seek(f, APR_SET, &off)); vec[0].iov_base = LINE1; vec[0].iov_len = strlen(LINE1); vec[1].iov_base = LINE2; vec[1].iov_len = strlen(LINE2); vec[2].iov_base = TESTSTR; vec[2].iov_len = strlen(TESTSTR); APR_ASSERT_SUCCESS(tc, "writev of size 2 to file", apr_file_writev(f, vec, 3, &nbytes)); APR_ASSERT_SUCCESS(tc, "close for writing", apr_file_close(f)); file_contents_equal(tc, fname, LINE1 LINE2 TESTSTR, strlen(LINE1) + strlen(LINE2) + strlen(TESTSTR)); APR_ASSERT_SUCCESS(tc, "remove file", apr_file_remove(fname, p)); }
static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info) { disk_cache_conf *conf = ap_get_module_config(r->server->module_config, &disk_cache_module); apr_status_t rv; apr_size_t amt; disk_cache_object_t *dobj = (disk_cache_object_t*) h->cache_obj->vobj; disk_cache_info_t disk_info; struct iovec iov[2]; /* This is flaky... we need to manage the cache_info differently */ h->cache_obj->info = *info; if (r->headers_out) { const char *tmp; tmp = apr_table_get(r->headers_out, "Vary"); if (tmp) { apr_array_header_t* varray; apr_uint32_t format = VARY_FORMAT_VERSION; /* If we were initially opened as a vary format, rollback * that internal state for the moment so we can recreate the * vary format hints in the appropriate directory. */ if (dobj->prefix) { dobj->hdrsfile = dobj->prefix; dobj->prefix = NULL; } mkdir_structure(conf, dobj->hdrsfile, r->pool); rv = apr_file_mktemp(&dobj->tfd, dobj->tempfile, APR_CREATE | APR_WRITE | APR_BINARY | APR_EXCL, r->pool); if (rv != APR_SUCCESS) { return rv; } amt = sizeof(format); apr_file_write(dobj->tfd, &format, &amt); amt = sizeof(info->expire); apr_file_write(dobj->tfd, &info->expire, &amt); varray = apr_array_make(r->pool, 6, sizeof(char*)); tokens_to_array(r->pool, tmp, varray); store_array(dobj->tfd, varray); apr_file_close(dobj->tfd); dobj->tfd = NULL; rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server, "disk_cache: rename tempfile to varyfile failed: %s -> %s", dobj->tempfile, dobj->hdrsfile); apr_file_remove(dobj->tempfile, r->pool); return rv; } dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); tmp = regen_key(r->pool, r->headers_in, varray, dobj->name); dobj->prefix = dobj->hdrsfile; dobj->hashfile = NULL; dobj->datafile = data_file(r->pool, conf, dobj, tmp); dobj->hdrsfile = header_file(r->pool, conf, dobj, tmp); } } rv = apr_file_mktemp(&dobj->hfd, dobj->tempfile, APR_CREATE | APR_WRITE | APR_BINARY | APR_BUFFERED | APR_EXCL, r->pool); if (rv != APR_SUCCESS) { return rv; } disk_info.format = DISK_FORMAT_VERSION; disk_info.date = info->date; disk_info.expire = info->expire; disk_info.entity_version = dobj->disk_info.entity_version++; disk_info.request_time = info->request_time; disk_info.response_time = info->response_time; disk_info.status = info->status; disk_info.name_len = strlen(dobj->name); iov[0].iov_base = (void*)&disk_info; iov[0].iov_len = sizeof(disk_cache_info_t); iov[1].iov_base = (void*)dobj->name; iov[1].iov_len = disk_info.name_len; rv = apr_file_writev(dobj->hfd, (const struct iovec *) &iov, 2, &amt); if (rv != APR_SUCCESS) { return rv; } if (r->headers_out) { apr_table_t *headers_out; headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, r->server); if (!apr_table_get(headers_out, "Content-Type") && r->content_type) { apr_table_setn(headers_out, "Content-Type", ap_make_content_type(r, r->content_type)); } headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out); rv = store_table(dobj->hfd, headers_out); if (rv != APR_SUCCESS) { return rv; } } /* Parse the vary header and dump those fields from the headers_in. */ /* FIXME: Make call to the same thing cache_select calls to crack Vary. */ if (r->headers_in) { apr_table_t *headers_in; headers_in = ap_cache_cacheable_hdrs_out(r->pool, r->headers_in, r->server); rv = store_table(dobj->hfd, headers_in); if (rv != APR_SUCCESS) { return rv; } } apr_file_close(dobj->hfd); /* flush and close */ /* Remove old file with the same name. If remove fails, then * perhaps we need to create the directory tree where we are * about to write the new headers file. */ rv = apr_file_remove(dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { mkdir_structure(conf, dobj->hdrsfile, r->pool); } rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server, "disk_cache: rename tempfile to hdrsfile failed: %s -> %s", dobj->tempfile, dobj->hdrsfile); apr_file_remove(dobj->tempfile, r->pool); return rv; } dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Stored headers for URL %s", dobj->name); return APR_SUCCESS; }
static apr_status_t handle_response(serf_request_t *request, serf_bucket_t *response, void *handler_baton, apr_pool_t *pool) { serf_status_line sl; apr_status_t status; handler_baton_t *ctx = handler_baton; if (!response) { /* A NULL response probably means that the connection was closed while this request was already written. Just requeue it. */ serf_connection_t *conn = serf_request_get_conn(request); serf_connection_request_create(conn, setup_request, handler_baton); return APR_SUCCESS; } status = serf_bucket_response_status(response, &sl); if (status) { return status; } while (1) { struct iovec vecs[64]; int vecs_read; apr_size_t bytes_written; status = serf_bucket_read_iovec(response, 8000, 64, vecs, &vecs_read); if (SERF_BUCKET_READ_ERROR(status)) return status; /* got some data. print it out. */ if (vecs_read) { apr_file_writev(ctx->output_file, vecs, vecs_read, &bytes_written); } /* are we done yet? */ if (APR_STATUS_IS_EOF(status)) { if (ctx->print_headers) { serf_bucket_t *hdrs; hdrs = serf_bucket_response_get_headers(response); while (1) { status = serf_bucket_read_iovec(hdrs, 8000, 64, vecs, &vecs_read); if (SERF_BUCKET_READ_ERROR(status)) return status; if (vecs_read) { apr_file_writev(ctx->output_file, vecs, vecs_read, &bytes_written); } if (APR_STATUS_IS_EOF(status)) { break; } } } apr_atomic_inc32(&ctx->completed_requests); return APR_EOF; } /* have we drained the response so far? */ if (APR_STATUS_IS_EAGAIN(status)) return status; /* loop to read some more. */ } /* NOTREACHED */ }