static void test_removeall(abts_case *tc, void *data) { apr_status_t rv; rv = apr_dir_remove("data/one/two/three", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_remove("data/one/two", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_remove("data/one", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); }
/* Test for a (fixed) bug in apr_dir_read(). This bug only happened in threadless cases. */ static void test_uncleared_errno(abts_case *tc, void *data) { apr_file_t *thefile = NULL; apr_finfo_t finfo; apr_int32_t finfo_flags = APR_FINFO_TYPE | APR_FINFO_NAME; apr_dir_t *this_dir; apr_status_t rv; rv = apr_dir_make("dir1", APR_OS_DEFAULT, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_make("dir2", APR_OS_DEFAULT, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_file_open(&thefile, "dir1/file1", APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_CREATE, APR_OS_DEFAULT, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_file_close(thefile); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); /* Try to remove dir1. This should fail because it's not empty. However, on a platform with threads disabled (such as FreeBSD), `errno' will be set as a result. */ rv = apr_dir_remove("dir1", p); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv)); /* Read `.' and `..' out of dir2. */ rv = apr_dir_open(&this_dir, "dir2", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_read(&finfo, finfo_flags, this_dir); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_read(&finfo, finfo_flags, this_dir); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); /* Now, when we attempt to do a third read of empty dir2, and the underlying system readdir() returns NULL, the old value of errno shouldn't cause a false alarm. We should get an ENOENT back from apr_dir_read, and *not* the old errno. */ rv = apr_dir_read(&finfo, finfo_flags, this_dir); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); rv = apr_dir_close(this_dir); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); /* Cleanup */ rv = apr_file_remove("dir1/file1", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_remove("dir1", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_remove("dir2", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); }
static void test_remove_notthere(abts_case *tc, void *data) { apr_status_t rv; rv = apr_dir_remove("data/notthere", p); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); }
static void test_removeall_fail(abts_case *tc, void *data) { apr_status_t rv; rv = apr_dir_remove("data/one", p); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv)); }
static void test_remove(abts_case *tc, void *data) { apr_status_t rv; apr_finfo_t finfo; rv = apr_dir_remove("data/testdir", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); }
int lua_apr_dir_remove(lua_State *L) { apr_status_t status; apr_pool_t *memory_pool; const char *filepath; memory_pool = to_pool(L); filepath = luaL_checkstring(L, 1); status = apr_dir_remove(filepath, memory_pool); return push_status(L, status); }
static void test_mkdir_twice(abts_case *tc, void *data) { apr_status_t rv; rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv)); rv = apr_dir_remove("data/testdir", p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); }
void nx_expr_proc__xm_fileop_dir_remove(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 path; apr_status_t rv; apr_pool_t *pool; ASSERT(module != NULL); ASSERT(args != NULL); arg = NX_DLIST_FIRST(args); ASSERT(arg != NULL); ASSERT(arg->expr != NULL); nx_expr_evaluate(eval_ctx, &path, arg->expr); if ( path.defined != TRUE ) { throw_msg("'path' is undef"); } if ( path.type != NX_VALUE_TYPE_STRING ) { nx_value_kill(&path); throw_msg("string type required for 'path'"); } // TODO: remove contents before pool = nx_pool_create_core(); rv = apr_dir_remove(path.string->buf, pool); if ( APR_STATUS_IS_ENOENT(rv) ) { } else if ( rv == APR_SUCCESS ) { } else { log_aprerror(rv, "failed to remove directory '%s'", path.string->buf); } apr_pool_destroy(pool); nx_value_kill(&path); }
static void test_rmkdir_nocwd(abts_case *tc, void *data) { char *cwd, *path; APR_ASSERT_SUCCESS(tc, "make temp dir", apr_dir_make("dir3", APR_OS_DEFAULT, p)); APR_ASSERT_SUCCESS(tc, "obtain cwd", apr_filepath_get(&cwd, 0, p)); APR_ASSERT_SUCCESS(tc, "determine path to temp dir", apr_filepath_merge(&path, cwd, "dir3", 0, p)); APR_ASSERT_SUCCESS(tc, "change to temp dir", apr_filepath_set(path, p)); APR_ASSERT_SUCCESS(tc, "restore cwd", apr_filepath_set(cwd, p)); APR_ASSERT_SUCCESS(tc, "remove cwd", apr_dir_remove(path, p)); }
term_t bif_del_dir1(term_t Dir, process_t *ctx) { apr_status_t rs; apr_pool_t *tmp; const char *path; if (!is_string(Dir)) return A_BADARG; apr_pool_create(&tmp, 0); path = ltoz(Dir, tmp); rs = apr_dir_remove(path, tmp); if (rs == 0) result(A_OK); else result(make_tuple2(A_ERROR, decipher_status(rs), proc_gc_pool(ctx))); apr_pool_destroy(tmp); return AI_OK; }
static int remove_url(cache_handle_t *h, apr_pool_t *p) { apr_status_t rc; disk_cache_object_t *dobj; /* Get disk cache object from cache handle */ dobj = (disk_cache_object_t *) h->cache_obj->vobj; if (!dobj) { return DECLINED; } /* Delete headers file */ if (dobj->hdrsfile) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "disk_cache: Deleting %s from cache.", dobj->hdrsfile); rc = apr_file_remove(dobj->hdrsfile, p); if ((rc != APR_SUCCESS) && !APR_STATUS_IS_ENOENT(rc)) { /* Will only result in an output if httpd is started with -e debug. * For reason see log_error_core for the case s == NULL. */ ap_log_error(APLOG_MARK, APLOG_DEBUG, rc, NULL, "disk_cache: Failed to delete headers file %s from cache.", dobj->hdrsfile); return DECLINED; } } /* Delete data file */ if (dobj->datafile) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "disk_cache: Deleting %s from cache.", dobj->datafile); rc = apr_file_remove(dobj->datafile, p); if ((rc != APR_SUCCESS) && !APR_STATUS_IS_ENOENT(rc)) { /* Will only result in an output if httpd is started with -e debug. * For reason see log_error_core for the case s == NULL. */ ap_log_error(APLOG_MARK, APLOG_DEBUG, rc, NULL, "disk_cache: Failed to delete data file %s from cache.", dobj->datafile); return DECLINED; } } /* now delete directories as far as possible up to our cache root */ if (dobj->root) { const char *str_to_copy; str_to_copy = dobj->hdrsfile ? dobj->hdrsfile : dobj->datafile; if (str_to_copy) { char *dir, *slash, *q; dir = apr_pstrdup(p, str_to_copy); /* remove filename */ slash = strrchr(dir, '/'); *slash = '\0'; /* * now walk our way back to the cache root, delete everything * in the way as far as possible * * Note: due to the way we constructed the file names in * header_file and data_file, we are guaranteed that the * cache_root is suffixed by at least one '/' which will be * turned into a terminating null by this loop. Therefore, * we won't either delete or go above our cache root. */ for (q = dir + dobj->root_len; *q ; ) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "disk_cache: Deleting directory %s from cache", dir); rc = apr_dir_remove(dir, p); if (rc != APR_SUCCESS && !APR_STATUS_IS_ENOENT(rc)) { break; } slash = strrchr(q, '/'); *slash = '\0'; } } } return OK; }
/* * walk the cache directory tree */ static int process_dir(char *path, apr_pool_t *pool) { apr_dir_t *dir; apr_pool_t *p; apr_hash_t *h; apr_hash_index_t *i; apr_file_t *fd; apr_status_t status; apr_finfo_t info; apr_size_t len; apr_time_t current, deviation; char *nextpath, *base, *ext, *orig_basename; APR_RING_ENTRY(_direntry) anchor; DIRENTRY *d, *t, *n; ENTRY *e; int skip, retries; disk_cache_info_t disk_info; APR_RING_INIT(&anchor, _direntry, link); apr_pool_create(&p, pool); h = apr_hash_make(p); fd = NULL; skip = 0; deviation = MAXDEVIATION * APR_USEC_PER_SEC; if (apr_dir_open(&dir, path, p) != APR_SUCCESS) { return 1; } while (apr_dir_read(&info, 0, dir) == APR_SUCCESS && !interrupted) { if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) { continue; } d = apr_pcalloc(p, sizeof(DIRENTRY)); d->basename = apr_pstrcat(p, path, "/", info.name, NULL); APR_RING_INSERT_TAIL(&anchor, d, _direntry, link); } apr_dir_close(dir); if (interrupted) { return 1; } skip = baselen + 1; for (d = APR_RING_FIRST(&anchor); !interrupted && d != APR_RING_SENTINEL(&anchor, _direntry, link); d=n) { n = APR_RING_NEXT(d, link); base = strrchr(d->basename, '/'); if (!base++) { base = d->basename; } ext = strchr(base, '.'); /* there may be temporary files which may be gone before * processing, always skip these if not in realclean mode */ if (!ext && !realclean) { if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN) && strlen(base) == AP_TEMPFILE_NAMELEN) { continue; } } /* this may look strange but apr_stat() may return errno which * is system dependent and there may be transient failures, * so just blindly retry for a short while */ retries = STAT_ATTEMPTS; status = APR_SUCCESS; do { if (status != APR_SUCCESS) { apr_sleep(STAT_DELAY); } status = apr_stat(&info, d->basename, DIRINFO, p); } while (status != APR_SUCCESS && !interrupted && --retries); /* what may happen here is that apache did create a file which * we did detect but then does delete the file before we can * get file information, so if we don't get any file information * we will ignore the file in this case */ if (status != APR_SUCCESS) { if (!realclean && !interrupted) { continue; } return 1; } if (info.filetype == APR_DIR) { /* Make a copy of the basename, as process_dir modifies it */ orig_basename = apr_pstrdup(pool, d->basename); if (process_dir(d->basename, pool)) { return 1; } /* If asked to delete dirs, do so now. We don't care if it fails. * If it fails, it likely means there was something else there. */ if (deldirs && !dryrun) { apr_dir_remove(orig_basename, pool); } continue; } if (info.filetype != APR_REG) { continue; } if (!ext) { if (!strncasecmp(base, AP_TEMPFILE_BASE, AP_TEMPFILE_BASELEN) && strlen(base) == AP_TEMPFILE_NAMELEN) { d->basename += skip; d->type = TEMP; d->dsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); } continue; } if (!strcasecmp(ext, CACHE_HEADER_SUFFIX)) { *ext = '\0'; d->basename += skip; /* if a user manually creates a '.header' file */ if (d->basename[0] == '\0') { continue; } t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING); if (t) { d = t; } d->type |= HEADER; d->htime = info.mtime; d->hsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); continue; } if (!strcasecmp(ext, CACHE_DATA_SUFFIX)) { *ext = '\0'; d->basename += skip; /* if a user manually creates a '.data' file */ if (d->basename[0] == '\0') { continue; } t = apr_hash_get(h, d->basename, APR_HASH_KEY_STRING); if (t) { d = t; } d->type |= DATA; d->dtime = info.mtime; d->dsize = info.size; apr_hash_set(h, d->basename, APR_HASH_KEY_STRING, d); } } if (interrupted) { return 1; } path[baselen] = '\0'; for (i = apr_hash_first(p, h); i && !interrupted; i = apr_hash_next(i)) { void *hvalue; apr_uint32_t format; apr_hash_this(i, NULL, NULL, &hvalue); d = hvalue; switch(d->type) { case HEADERDATA: nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == DISK_FORMAT_VERSION) { apr_off_t offset = 0; apr_file_seek(fd, APR_SET, &offset); len = sizeof(disk_cache_info_t); if (apr_file_read_full(fd, &disk_info, len, &len) == APR_SUCCESS) { apr_file_close(fd); e = apr_palloc(pool, sizeof(ENTRY)); APR_RING_INSERT_TAIL(&root, e, _entry, link); e->expire = disk_info.expire; e->response_time = disk_info.response_time; e->htime = d->htime; e->dtime = d->dtime; e->hsize = d->hsize; e->dsize = d->dsize; e->basename = apr_pstrdup(pool, d->basename); break; } else { apr_file_close(fd); } } else if (format == VARY_FORMAT_VERSION) { /* This must be a URL that added Vary headers later, * so kill the orphaned .data file */ apr_file_close(fd); apr_file_remove(apr_pstrcat(p, path, "/", d->basename, CACHE_DATA_SUFFIX, NULL), p); } } else { apr_file_close(fd); } } /* we have a somehow unreadable headers file which is associated * with a data file. this may be caused by apache currently * rewriting the headers file. thus we may delete the file set * either in realclean mode or if the headers file modification * timestamp is not within a specified positive or negative offset * to the current time. */ current = apr_time_now(); if (realclean || d->htime < current - deviation || d->htime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->hsize; unsolicited += d->dsize; } break; /* single data and header files may be deleted either in realclean * mode or if their modification timestamp is not within a * specified positive or negative offset to the current time. * this handling is necessary due to possible race conditions * between apache and this process */ case HEADER: current = apr_time_now(); nextpath = apr_pstrcat(p, path, "/", d->basename, CACHE_HEADER_SUFFIX, NULL); if (apr_file_open(&fd, nextpath, APR_FOPEN_READ | APR_FOPEN_BINARY, APR_OS_DEFAULT, p) == APR_SUCCESS) { len = sizeof(format); if (apr_file_read_full(fd, &format, len, &len) == APR_SUCCESS) { if (format == VARY_FORMAT_VERSION) { apr_time_t expires; len = sizeof(expires); apr_file_read_full(fd, &expires, len, &len); apr_file_close(fd); if (expires < current) { delete_entry(path, d->basename, p); } break; } } apr_file_close(fd); } if (realclean || d->htime < current - deviation || d->htime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->hsize; } break; case DATA: current = apr_time_now(); if (realclean || d->dtime < current - deviation || d->dtime > current + deviation) { delete_entry(path, d->basename, p); unsolicited += d->dsize; } break; /* temp files may only be deleted in realclean mode which * is asserted above if a tempfile is in the hash array */ case TEMP: delete_file(path, d->basename, p); unsolicited += d->dsize; break; } } if (interrupted) { return 1; } apr_pool_destroy(p); if (benice) { apr_sleep(NICE_DELAY); } if (interrupted) { return 1; } return 0; }
void test_client_teardown(CuTest *tc) { aos_pool_t *p; aos_pool_create(&p, NULL); apr_dir_remove(TEST_DIR"/data/", p); aos_pool_destroy(p); }
bool remove(const std::string& path){ return APR_SUCCESS == check_apr(apr_dir_remove(path.c_str(), mPool)); }
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); }