/* Reopen logfile if filename is our logfile */ static boolean _reopen_logfile(const char *filename) { nx_ctx_t *ctx; const char *fname; apr_file_t *oldlog; ctx = nx_ctx_get(); if ( ctx->logfile != NULL ) { apr_file_name_get(&fname, ctx->logfile); if ( strcmp(fname, filename) == 0 ) { oldlog = ctx->logfile; CHECKERR_MSG(apr_file_open(&(ctx->logfile), filename, APR_WRITE | APR_CREATE | APR_APPEND, APR_OS_DEFAULT, ctx->pool), "couldn't open logfile '%s' for writing", filename); apr_file_close(oldlog); log_info("LogFile %s reopened", filename); return ( TRUE ); } } return ( FALSE ); }
/* Remove a temporary file F, which is of type apr_file_t *. First, try to close the file, ignoring any errors. Return an error if the remove fails. */ static apr_status_t cleanup_tempfile (void *f) { apr_file_t *file = f; apr_status_t apr_err; const char *fname; /* the file may or may not have been closed; try it */ apr_file_close (file); apr_err = apr_file_name_get (&fname, file); if (apr_err == APR_SUCCESS) apr_err = apr_file_remove (fname, apr_file_pool_get (file)); return apr_err; }
static void test_filename(abts_case *tc, void *data) { const char *str; apr_status_t rv; apr_file_t *filetest = NULL; rv = apr_file_open(&filetest, FILENAME, APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, p); APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv); rv = apr_file_name_get(&str, filetest); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_STR_EQUAL(tc, FILENAME, str); apr_file_close(filetest); }
static void test_filename(CuTest *tc) { const char *str; apr_status_t rv; apr_file_t *filetest = NULL; rv = apr_file_open(&filetest, FILENAME, APR_READ, APR_UREAD | APR_UWRITE | APR_GREAD, p); apr_assert_success(tc, "Opening test file " FILENAME, rv); rv = apr_file_name_get(&str, filetest); CuAssertIntEquals(tc, APR_SUCCESS, rv); CuAssertStrEquals(tc, FILENAME, str); apr_file_close(filetest); }
/* The last user to close a particular namespace should also remove the * lock file. Failure to do so, however, does not affect further uses * of the same namespace. */ static apr_status_t delete_lock_file(void *arg) { struct mutex_t *mutex = arg; const char *lock_name = NULL; /* locks have already been cleaned up. Simply close the file */ apr_status_t status = apr_file_close(mutex->lock_file); /* Remove the file from disk. This will fail if there ares still other * users of this lock file, i.e. namespace. */ apr_file_name_get(&lock_name, mutex->lock_file); if (lock_name) apr_file_remove(lock_name, mutex->pool); return status; }
int file_apache_get_file_size(file_handle_t* handler, int flags){ #ifndef TEST_APP apache_file_handler_t* afh = (apache_file_handler_t*)handler; apr_off_t offset = 0; apr_size_t size = 0; int rc; apr_finfo_t finfo; int exists; char* filename = NULL; rc = apr_file_name_get(&filename, afh->f); if (rc == APR_SUCCESS){ rc = apr_stat(&finfo, filename, APR_FINFO_MIN, afh->r->pool); if (rc == APR_SUCCESS) { return finfo.size; } } #endif return 0; }
static apr_status_t file_bucket_read(apr_bucket *e, const char **str, apr_size_t *len, apr_read_type_e block) { apr_bucket_file *a = e->data; apr_file_t *f = a->fd; apr_bucket *b = NULL; char *buf; apr_status_t rv; apr_size_t filelength = e->length; /* bytes remaining in file past offset */ apr_off_t fileoffset = e->start; #if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES apr_int32_t flags; #endif #if APR_HAS_MMAP if (file_make_mmap(e, filelength, fileoffset, a->readpool)) { return apr_bucket_read(e, str, len, block); } #endif #if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES if ((flags = apr_file_flags_get(f)) & APR_FOPEN_XTHREAD) { /* this file descriptor is shared across multiple threads and * this OS doesn't support that natively, so as a workaround * we must reopen the file into a->readpool */ const char *fname; apr_file_name_get(&fname, f); rv = apr_file_open(&f, fname, (flags & ~APR_FOPEN_XTHREAD), 0, a->readpool); if (rv != APR_SUCCESS) return rv; a->fd = f; } #endif *len = (filelength > APR_BUCKET_BUFF_SIZE) ? APR_BUCKET_BUFF_SIZE : filelength; *str = NULL; /* in case we die prematurely */ buf = apr_bucket_alloc(*len, e->list); /* Handle offset ... */ rv = apr_file_seek(f, APR_SET, &fileoffset); if (rv != APR_SUCCESS) { apr_bucket_free(buf); return rv; } rv = apr_file_read(f, buf, len); if (rv != APR_SUCCESS && rv != APR_EOF) { apr_bucket_free(buf); return rv; } filelength -= *len; /* * Change the current bucket to refer to what we read, * even if we read nothing because we hit EOF. */ apr_bucket_heap_make(e, buf, *len, apr_bucket_free); /* If we have more to read from the file, then create another bucket */ if (filelength > 0 && rv != APR_EOF) { /* for efficiency, we can just build a new apr_bucket struct * to wrap around the existing file bucket */ b = apr_bucket_alloc(sizeof(*b), e->list); b->start = fileoffset + (*len); b->length = filelength; b->data = a; b->type = &apr_bucket_type_file; b->free = apr_bucket_free; b->list = e->list; APR_BUCKET_INSERT_AFTER(e, b); } else { file_bucket_destroy(a); } *str = buf; return rv; }
static apr_status_t store_body(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b) { apr_status_t rv; cache_object_t *obj = h->cache_obj; cache_object_t *tobj = NULL; mem_cache_object_t *mobj = (mem_cache_object_t*) obj->vobj; apr_read_type_e eblock = APR_BLOCK_READ; apr_bucket *e; char *cur; int eos = 0; if (mobj->type == CACHE_TYPE_FILE) { apr_file_t *file = NULL; int fd = 0; int other = 0; /* We can cache an open file descriptor if: * - the brigade contains one and only one file_bucket && * - the brigade is complete && * - the file_bucket is the last data bucket in the brigade */ for (e = APR_BRIGADE_FIRST(b); e != APR_BRIGADE_SENTINEL(b); e = APR_BUCKET_NEXT(e)) { if (APR_BUCKET_IS_EOS(e)) { eos = 1; } else if (APR_BUCKET_IS_FILE(e)) { apr_bucket_file *a = e->data; fd++; file = a->fd; } else { other++; } } if (fd == 1 && !other && eos) { apr_file_t *tmpfile; const char *name; /* Open a new XTHREAD handle to the file */ apr_file_name_get(&name, file); mobj->flags = ((APR_SENDFILE_ENABLED & apr_file_flags_get(file)) | APR_READ | APR_BINARY | APR_XTHREAD | APR_FILE_NOCLEANUP); rv = apr_file_open(&tmpfile, name, mobj->flags, APR_OS_DEFAULT, r->pool); if (rv != APR_SUCCESS) { return rv; } apr_file_inherit_unset(tmpfile); apr_os_file_get(&(mobj->fd), tmpfile); /* Open for business */ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "mem_cache: Cached file: %s with key: %s", name, obj->key); obj->complete = 1; return APR_SUCCESS; } /* Content not suitable for fd caching. Cache in-memory instead. */ mobj->type = CACHE_TYPE_HEAP; } /* * FD cacheing is not enabled or the content was not * suitable for fd caching. */ if (mobj->m == NULL) { mobj->m = malloc(mobj->m_len); if (mobj->m == NULL) { return APR_ENOMEM; } obj->count = 0; } cur = (char*) mobj->m + obj->count; /* Iterate accross the brigade and populate the cache storage */ for (e = APR_BRIGADE_FIRST(b); e != APR_BRIGADE_SENTINEL(b); e = APR_BUCKET_NEXT(e)) { const char *s; apr_size_t len; if (APR_BUCKET_IS_EOS(e)) { const char *cl_header = apr_table_get(r->headers_out, "Content-Length"); if (cl_header) { apr_int64_t cl = apr_atoi64(cl_header); if ((errno == 0) && (obj->count != cl)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "mem_cache: URL %s didn't receive complete response, not caching", h->cache_obj->key); return APR_EGENERAL; } } if (mobj->m_len > obj->count) { /* Caching a streamed response. Reallocate a buffer of the * correct size and copy the streamed response into that * buffer */ mobj->m = realloc(mobj->m, obj->count); if (!mobj->m) { return APR_ENOMEM; } /* Now comes the crufty part... there is no way to tell the * cache that the size of the object has changed. We need * to remove the object, update the size and re-add the * object, all under protection of the lock. */ if (sconf->lock) { apr_thread_mutex_lock(sconf->lock); } /* Has the object been ejected from the cache? */ tobj = (cache_object_t *) cache_find(sconf->cache_cache, obj->key); if (tobj == obj) { /* Object is still in the cache, remove it, update the len field then * replace it under protection of sconf->lock. */ cache_remove(sconf->cache_cache, obj); /* For illustration, cache no longer has reference to the object * so decrement the refcount * apr_atomic_dec32(&obj->refcount); */ mobj->m_len = obj->count; cache_insert(sconf->cache_cache, obj); /* For illustration, cache now has reference to the object, so * increment the refcount * apr_atomic_inc32(&obj->refcount); */ } else if (tobj) { /* Different object with the same key found in the cache. Doing nothing * here will cause the object refcount to drop to 0 in decrement_refcount * and the object will be cleaned up. */ } else { /* Object has been ejected from the cache, add it back to the cache */ mobj->m_len = obj->count; cache_insert(sconf->cache_cache, obj); apr_atomic_inc32(&obj->refcount); } if (sconf->lock) { apr_thread_mutex_unlock(sconf->lock); } } /* Open for business */ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "mem_cache: Cached url: %s", obj->key); obj->complete = 1; break; } rv = apr_bucket_read(e, &s, &len, eblock); if (rv != APR_SUCCESS) { return rv; } if (len) { /* Check for buffer (max_streaming_buffer_size) overflow */ if ((obj->count + len) > mobj->m_len) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "mem_cache: URL %s exceeds the MCacheMaxStreamingBuffer (%" APR_SIZE_T_FMT ") limit and will not be cached.", obj->key, mobj->m_len); return APR_ENOMEM; } else { memcpy(cur, s, len); cur+=len; obj->count+=len; } } /* This should not fail, but if it does, we are in BIG trouble * cause we just stomped all over the heap. */ AP_DEBUG_ASSERT(obj->count <= mobj->m_len); } return APR_SUCCESS; }