static void test_insertfile(abts_case *tc, void *ctx) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb; const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242; apr_off_t count; apr_file_t *f; apr_bucket *e; ABTS_ASSERT(tc, "open test file", apr_file_open(&f, TIF_FNAME, APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE | APR_FOPEN_CREATE | APR_FOPEN_SPARSE, APR_OS_DEFAULT, p) == APR_SUCCESS); if (apr_file_trunc(f, bignum)) { apr_file_close(f); apr_file_remove(TIF_FNAME, p); ABTS_NOT_IMPL(tc, "Skipped: could not create large file"); return; } bb = apr_brigade_create(p, ba); e = apr_brigade_insert_file(bb, f, 0, bignum, p); ABTS_ASSERT(tc, "inserted file was not at end of brigade", e == APR_BRIGADE_LAST(bb)); /* check that the total size of inserted buckets is equal to the * total size of the file. */ count = 0; for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); e = APR_BUCKET_NEXT(e)) { ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1); count += e->length; } ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum); apr_brigade_destroy(bb); /* Truncate the file to zero size before close() so that we don't * actually write out the large file if we are on a non-sparse file * system - like Mac OS X's HFS. Otherwise, pity the poor user who * has to wait for the 8GB file to be written to disk. */ apr_file_trunc(f, 0); apr_file_close(f); apr_bucket_alloc_destroy(ba); apr_file_remove(TIF_FNAME, p); }
static void test_file_trunc(abts_case *tc, void *data) { apr_status_t rv; apr_file_t *f; const char *fname = "data/testtruncate.dat"; const char *s; apr_size_t nbytes; apr_finfo_t finfo; apr_file_remove(fname, p); /* Test unbuffered */ rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_READ | APR_FOPEN_WRITE, APR_FPROT_UREAD | APR_FPROT_UWRITE, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); s = "some data"; nbytes = strlen(s); rv = apr_file_write(f, s, &nbytes); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_SIZE_EQUAL(tc, strlen(s), nbytes); rv = apr_file_trunc(f, 4); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_file_close(f); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_ASSERT(tc, "File size mismatch, expected 4", finfo.size == 4); rv = apr_file_remove(fname, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); /* Test buffered */ rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED, APR_FPROT_UREAD | APR_FPROT_UWRITE, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); nbytes = strlen(s); rv = apr_file_write(f, s, &nbytes); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_SIZE_EQUAL(tc, strlen(s), nbytes); rv = apr_file_trunc(f, 4); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_file_close(f); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_ASSERT(tc, "File size mismatch, expected 4", finfo.size == 4); rv = apr_file_remove(fname, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); }
/* Regression test for PR 34708, where a file bucket will keep * duplicating itself on being read() when EOF is reached * prematurely. */ static void test_truncfile(abts_case *tc, void *data) { apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_file_t *f = make_test_file(tc, "testfile.txt", "hello"); apr_bucket *e; const char *buf; apr_size_t len; apr_brigade_insert_file(bb, f, 0, 5, p); apr_file_trunc(f, 0); e = APR_BRIGADE_FIRST(bb); ABTS_ASSERT(tc, "single bucket in brigade", APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb)); apr_bucket_file_enable_mmap(e, 0); ABTS_ASSERT(tc, "read gave APR_EOF", apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF); ABTS_ASSERT(tc, "read length 0", len == 0); ABTS_ASSERT(tc, "still a single bucket in brigade", APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb)); apr_file_close(f); apr_brigade_destroy(bb); apr_bucket_alloc_destroy(ba); }
/* syncs a filehandle (Transfer all file modified data and metadata to disk.) */ void MVM_file_truncate(MVMThreadContext *tc, MVMObject *oshandle, MVMint64 offset) { apr_status_t rv; MVMOSHandle *handle; verify_filehandle_type(tc, oshandle, &handle, "truncate filehandle"); if ((rv = apr_file_trunc(handle->body.file_handle, (apr_off_t)offset)) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "Failed to truncate filehandle: "); } }
static int file_truncate(lua_State *L) { apr_status_t status; lua_apr_file *file; apr_off_t offset; file = file_check(L, 1, 1); offset = luaL_optlong(L, 2, 0); status = apr_file_trunc(file->handle, offset); return push_status(L, status); }
int lc_truncateLogFile(void) { apr_status_t status=0; int cur_pid=getpid(); if(refreshLogger.status!=APR_SUCCESS||cur_pid!=refreshLogger.pid) { //printf("\nLogfile has not been opened.\n"); return FALSE; } status=apr_file_trunc(refreshLogger.logger.file,0); //if(status!=APR_SUCCESS) //printf("\nFailed to truncate logfile - %s\n", refreshLogger.filepath); return status; }
/* After a error, truncate the current file and write out an error * message, which must be contained in status->errbuf. The process is * terminated on failure. */ static void truncate_and_write_error(rotate_status_t *status) { apr_size_t buflen = strlen(status->errbuf); if (apr_file_trunc(status->current.fd, 0) != APR_SUCCESS) { fprintf(stderr, "Error truncating the file %s\n", status->current.name); exit(2); } if (apr_file_write_full(status->current.fd, status->errbuf, buflen, NULL) != APR_SUCCESS) { fprintf(stderr, "Error writing error (%s) to the file %s\n", status->errbuf, status->current.name); exit(2); } }
int logcore_truncateLogFile(){ apr_status_t status=0; int cur_pid; cur_pid=getpid(); if(rLogFile.status!=APR_SUCCESS||cur_pid!=rLogFile.pid){ //printf("\nLogfile has not been opened.\n"); return FALSE; } status=apr_file_trunc(rLogFile.logfile_hndl,0); //if(status!=APR_SUCCESS) //printf("\nFailed to truncate logfile - %s\n", rLogFile.logfile_name); return status; }
apr_status_t truncate_file(char* fn, apr_pool_t* pool) { apr_file_t *fp = NULL; apr_status_t status; status = apr_file_open(&fp, fn, APR_WRITE|APR_CREATE|APR_TRUNCATE, APR_UREAD|APR_UWRITE, pool); if (status == APR_SUCCESS) { status = apr_file_trunc(fp, 0); apr_file_close(fp); } if (status != APR_SUCCESS) { gpmon_warningx(FLINE, 0, "harvest process truncate file %s failed", fn); } else { TR1(("harvest truncated file %s: ok\n", fn)); } return status; }
APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, apr_size_t reqsize, const char *file, apr_pool_t *pool) { static apr_size_t memblock = 0; HANDLE hMap, hFile; apr_status_t rv; apr_size_t size; apr_file_t *f; void *base; void *mapkey; DWORD err, sizelo, sizehi; reqsize += sizeof(memblock_t); if (!memblock) { SYSTEM_INFO si; GetSystemInfo(&si); memblock = si.dwAllocationGranularity; } /* Compute the granualar multiple of the pagesize */ size = memblock * (1 + (reqsize - 1) / memblock); sizelo = (DWORD)size; #ifdef _WIN64 sizehi = (DWORD)(size >> 32); #else sizehi = 0; #endif if (!file) { /* Do Anonymous, which must be passed as a duplicated handle */ #ifndef _WIN32_WCE hFile = INVALID_HANDLE_VALUE; #endif mapkey = NULL; } else { /* Do file backed, which is not an inherited handle * While we could open APR_EXCL, it doesn't seem that Unix * ever did. Ignore that error here, but fail later when * we discover we aren't the creator of the file map object. */ rv = apr_file_open(&f, file, APR_READ | APR_WRITE | APR_BINARY | APR_CREATE, APR_UREAD | APR_UWRITE, pool); if ((rv != APR_SUCCESS) || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) { return rv; } rv = apr_file_trunc(f, size); /* res_name_from_filename turns file into a pseudo-name * without slashes or backslashes, and prepends the \global * prefix on Win2K and later */ mapkey = res_name_from_filename(file, 1, pool); } #if APR_HAS_UNICODE_FS IF_WIN_OS_IS_UNICODE { hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, sizehi, sizelo, mapkey); } #endif #if APR_HAS_ANSI_FS ELSE_WIN_OS_IS_ANSI { hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, sizehi, sizelo, mapkey); } #endif err = apr_get_os_error(); if (file) { apr_file_close(f); } if (hMap && APR_STATUS_IS_EEXIST(err)) { CloseHandle(hMap); return APR_EEXIST; } if (!hMap) { return err; } base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); if (!base) { CloseHandle(hMap); return apr_get_os_error(); } *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t)); (*m)->pool = pool; (*m)->hMap = hMap; (*m)->memblk = base; (*m)->size = size; (*m)->usrmem = (char*)base + sizeof(memblock_t); (*m)->length = reqsize - sizeof(memblock_t);; (*m)->memblk->length = (*m)->length; (*m)->memblk->size = (*m)->size; (*m)->filename = file ? apr_pstrdup(pool, file) : NULL; apr_pool_cleanup_register((*m)->pool, *m, shm_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; }
void nx_expr_proc__xm_fileop_file_truncate(nx_expr_eval_ctx_t *eval_ctx, nx_module_t *module, nx_expr_arg_list_t *args) { nx_expr_arg_t *arg; nx_value_t file; nx_expr_arg_t *offset; nx_value_t offsetval; nx_exception_t e; apr_off_t offs = 0; apr_status_t rv; apr_pool_t *pool; apr_file_t *fd; ASSERT(module != NULL); ASSERT(args != NULL); arg = NX_DLIST_FIRST(args); ASSERT(arg != NULL); ASSERT(arg->expr != NULL); nx_expr_evaluate(eval_ctx, &file, arg->expr); if ( file.defined != TRUE ) { throw_msg("'file' is undef"); } if ( file.type != NX_VALUE_TYPE_STRING ) { nx_value_kill(&file); throw_msg("string type required for 'file'"); } if ( (offset = NX_DLIST_NEXT(arg, link)) != NULL ) { ASSERT(offset->expr != NULL); try { nx_expr_evaluate(eval_ctx, &offsetval, offset->expr); } catch(e) { nx_value_kill(&file); rethrow(e); } if ( offsetval.defined != TRUE ) { nx_value_kill(&file); throw_msg("'offset' is undef"); } if ( offsetval.type != NX_VALUE_TYPE_INTEGER ) { nx_value_kill(&offsetval); nx_value_kill(&file); throw_msg("integer type required for 'offset'"); } offs = (apr_off_t) offsetval.integer; } pool = nx_pool_create_core(); if ( (rv = apr_file_open(&fd, file.string->buf, APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool)) != APR_SUCCESS ) { log_aprerror(rv, "failed to open file '%s' when trying to truncate", file.string->buf); } if ( rv == APR_SUCCESS ) { if ( (rv = apr_file_trunc(fd, offs)) != APR_SUCCESS ) { log_aprerror(rv, "failed to truncate file '%s' to length %lu", file.string->buf, (long unsigned int) offs); } apr_file_close(fd); } apr_pool_destroy(pool); nx_value_kill(&file); }
SWITCH_DECLARE(switch_status_t) switch_file_trunc(switch_file_t *thefile, int64_t offset) { return apr_file_trunc(thefile, offset); }
/** * This is not thread safe, must ensure that modules are not running, * otherwise lock config_cache_mutex */ void nx_config_cache_write() { nx_ctx_t *ctx; nx_cc_item_t *item; nx_value_t *version = NULL; nx_exception_t e; apr_hash_index_t *idx; const char *key; apr_ssize_t keylen; ctx = nx_ctx_get(); ASSERT(ctx != NULL); if ( ctx->nocache == TRUE ) { log_debug("NoCache is TRUE, not writing config cache"); return; } if ( apr_hash_count(ctx->config_cache) == 0 ) { // no items to write log_debug("no entries found, not writing configcache.dat"); return; } log_debug("nx_config_cache_write()"); if ( ctx->ccfile == NULL ) { CHECKERR_MSG(apr_file_open(&(ctx->ccfile), ctx->ccfilename, APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE, APR_OS_DEFAULT, ctx->pool), "couldn't open config cache '%s' for writing", ctx->ccfilename); } else { CHECKERR_MSG(apr_file_trunc(ctx->ccfile, 0), "failed to truncate '%s'", ctx->ccfilename); } version = nx_value_new_string(NX_CONFIG_CACHE_VERSION); try { CHECKERR_MSG(nx_value_to_file(version, ctx->ccfile), "couldn't write version to cache file"); idx = apr_hash_first(NULL, ctx->config_cache); while ( idx != NULL ) { apr_hash_this(idx, (const void **) &key, &keylen, (void **) &item); idx = apr_hash_next(idx); if ( item->used == FALSE ) { // only write items which have been read or written continue; } _write_item(ctx->ccfile, item); item->needflush = FALSE; } } catch(e) { nx_value_free(version); rethrow(e); } log_debug("config cache written to %s", ctx->ccfilename); }
APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, apr_size_t reqsize, const char *filename, apr_pool_t *pool) { apr_shm_t *new_m; apr_status_t status; #if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON struct shmid_ds shmbuf; apr_uid_t uid; apr_gid_t gid; #endif #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \ APR_USE_SHMEM_MMAP_ZERO int tmpfd; #endif #if APR_USE_SHMEM_SHMGET apr_size_t nbytes; #endif #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET || \ APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM apr_file_t *file; /* file where metadata is stored */ #endif /* Check if they want anonymous or name-based shared memory */ if (filename == NULL) { #if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->reqsize = reqsize; new_m->realsize = reqsize + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */ new_m->filename = NULL; #if APR_USE_SHMEM_MMAP_ZERO status = apr_file_open(&file, "/dev/zero", APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } status = apr_os_file_get(&tmpfd, file); if (status != APR_SUCCESS) { return status; } new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE, MAP_SHARED, tmpfd, 0); if (new_m->base == (void *)MAP_FAILED) { return errno; } status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } /* store the real size in the metadata */ *(apr_size_t*)(new_m->base) = new_m->realsize; /* metadata isn't usable */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #elif APR_USE_SHMEM_MMAP_ANON new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0); if (new_m->base == (void *)MAP_FAILED) { return errno; } /* store the real size in the metadata */ *(apr_size_t*)(new_m->base) = new_m->realsize; /* metadata isn't usable */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #endif /* APR_USE_SHMEM_MMAP_ZERO */ #elif APR_USE_SHMEM_SHMGET_ANON new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->reqsize = reqsize; new_m->realsize = reqsize; new_m->filename = NULL; new_m->shmkey = IPC_PRIVATE; if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize, SHM_R | SHM_W | IPC_CREAT)) < 0) { return errno; } if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { return errno; } new_m->usable = new_m->base; if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) { return errno; } apr_uid_current(&uid, &gid, pool); shmbuf.shm_perm.uid = uid; shmbuf.shm_perm.gid = gid; if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) { return errno; } /* Remove the segment once use count hits zero. * We will not attach to this segment again, since it is * anonymous memory, so it is ok to mark it for deletion. */ if (shmctl(new_m->shmid, IPC_RMID, NULL) == -1) { return errno; } apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #else /* It is an error if they want anonymous memory but we don't have it. */ return APR_ENOTIMPL; /* requested anonymous but we don't have it */ #endif } /* Name-based shared memory */ else { new_m = apr_palloc(pool, sizeof(apr_shm_t)); new_m->pool = pool; new_m->reqsize = reqsize; new_m->filename = apr_pstrdup(pool, filename); #if APR_USE_SHMEM_MMAP_SHM const char *shm_name = make_shm_open_safe_name(filename, pool); #endif #if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM new_m->realsize = reqsize + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */ /* FIXME: Ignore error for now. * * status = apr_file_remove(file, pool);*/ status = APR_SUCCESS; #if APR_USE_SHMEM_MMAP_TMP /* FIXME: Is APR_OS_DEFAULT sufficient? */ status = apr_file_open(&file, filename, APR_READ | APR_WRITE | APR_CREATE | APR_EXCL, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } status = apr_os_file_get(&tmpfd, file); if (status != APR_SUCCESS) { apr_file_close(file); /* ignore errors, we're failing */ apr_file_remove(new_m->filename, new_m->pool); return status; } status = apr_file_trunc(file, new_m->realsize); if (status != APR_SUCCESS && status != APR_ESPIPE) { apr_file_close(file); /* ignore errors, we're failing */ apr_file_remove(new_m->filename, new_m->pool); return status; } new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, MAP_SHARED, tmpfd, 0); /* FIXME: check for errors */ status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } #endif /* APR_USE_SHMEM_MMAP_TMP */ #if APR_USE_SHMEM_MMAP_SHM /* FIXME: SysV uses 0600... should we? */ tmpfd = shm_open(shm_name, O_RDWR | O_CREAT | O_EXCL, 0644); if (tmpfd == -1) { return errno; } status = apr_os_file_put(&file, &tmpfd, APR_READ | APR_WRITE | APR_CREATE | APR_EXCL, pool); if (status != APR_SUCCESS) { return status; } status = apr_file_trunc(file, new_m->realsize); if (status != APR_SUCCESS && status != APR_ESPIPE) { shm_unlink(shm_name); /* we're failing, remove the object */ return status; } new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, MAP_SHARED, tmpfd, 0); /* FIXME: check for errors */ status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } #endif /* APR_USE_SHMEM_MMAP_SHM */ /* store the real size in the metadata */ *(apr_size_t*)(new_m->base) = new_m->realsize; /* metadata isn't usable */ new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #elif APR_USE_SHMEM_SHMGET new_m->realsize = reqsize; /* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think. */ status = apr_file_open(&file, filename, APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_EXCL, APR_OS_DEFAULT, pool); if (status != APR_SUCCESS) { return status; } /* ftok() (on solaris at least) requires that the file actually * exist before calling ftok(). */ new_m->shmkey = our_ftok(filename); if (new_m->shmkey == (key_t)-1) { apr_file_close(file); return errno; } if ((new_m->shmid = shmget(new_m->shmkey, new_m->realsize, SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) { apr_file_close(file); return errno; } if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { apr_file_close(file); return errno; } new_m->usable = new_m->base; if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) { apr_file_close(file); return errno; } apr_uid_current(&uid, &gid, pool); shmbuf.shm_perm.uid = uid; shmbuf.shm_perm.gid = gid; if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) { apr_file_close(file); return errno; } nbytes = sizeof(reqsize); status = apr_file_write(file, (const void *)&reqsize, &nbytes); if (status != APR_SUCCESS) { apr_file_close(file); return status; } status = apr_file_close(file); if (status != APR_SUCCESS) { return status; } apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, apr_pool_cleanup_null); *m = new_m; return APR_SUCCESS; #else return APR_ENOTIMPL; #endif } }