As posted here: http://www.mail-archive.com/[email protected]/msg17650.html I've implemented an iterative apr_dir_remove_recursive It's now attached as fileutil.c
This is based only on APR functions so a single entry of this implementation should do it for all systems. I'm not sure where it's best place is inside the structure of APR, so any suggestions are welcome :) -- Lucian Adrian Grijincu
#include "apr_general.h"
#include "apr.h"
#include "apr_file_io.h"
#include "apr_errno.h"
#include "apr_strings.h"
#define APR_DIR_REMOVE_RECURSIVELY_ARRSIZE (6) /*what would be a propper value? */
#define PATH_SEPARATOR '/' /*is one defined in a header somewhere else ? */
apr_status_t
apr_dir_remove_recursive(const char *param_path, apr_pool_t * pool)
{
apr_status_t status, retcode, dirstatus;
apr_dir_t *this_dir;
apr_finfo_t this_entry;
apr_pool_t *array_pool, *loop_pool;
apr_array_header_t *arr;
apr_int32_t flags = APR_FINFO_TYPE | APR_FINFO_NAME;
char *dir_path, *file_path;
int dir_is_empty;
retcode = APR_SUCCESS;
status = apr_pool_create(&array_pool, pool);
if (status != APR_SUCCESS) {
return status;
}
status = apr_pool_create(&loop_pool, pool);
if (status != APR_SUCCESS) {
apr_pool_destroy(array_pool);
return status;
}
arr = apr_array_make(array_pool, APR_DIR_REMOVE_RECURSIVELY_ARRSIZE,
sizeof(const char *));
if (arr == NULL) {
apr_pool_destroy(array_pool);
apr_pool_destroy(loop_pool);
return APR_ENOMEM;
}
*(const char **) apr_array_push(arr) = param_path;
while (!apr_is_empty_array(arr)) {
apr_pool_clear(loop_pool);
dir_path = apr_array_pstrcat(loop_pool, arr, PATH_SEPARATOR);
if (dir_path == NULL) {
retcode = APR_ENOMEM;
break;
}
dir_is_empty = 1;
dirstatus = apr_dir_open(&this_dir, dir_path, loop_pool);
if (dirstatus != APR_SUCCESS) {
retcode = dirstatus;
}
else {
for (dirstatus = apr_dir_read(&this_entry, flags, this_dir);
dirstatus == APR_SUCCESS;
dirstatus = apr_dir_read(&this_entry, flags, this_dir)) {
if (this_entry.filetype == APR_DIR) {
if (this_entry.name[0] == '.'
&& (this_entry.name[1] == '\0'
|| (this_entry.name[1] == '.'
&& this_entry.name[2] == '\0')))
continue;
*(const char **) apr_array_push(arr) =
apr_pstrdup(array_pool, this_entry.name);
dir_is_empty = 0;
break;
}
else {
file_path =
apr_pstrcat(loop_pool, dir_path, PATH_SEPARATOR,
this_entry.name, NULL);
status = apr_file_remove(file_path, loop_pool);
if ((status != APR_SUCCESS) && (retcode != APR_SUCCESS)) {
retcode = status;
}
}
}
if (!(APR_STATUS_IS_ENOENT(dirstatus))
&& (retcode != APR_SUCCESS)) {
retcode = dirstatus;
}
dirstatus = apr_dir_close(this_dir);
if ((dirstatus != APR_SUCCESS) && (retcode != APR_SUCCESS)) {
retcode = dirstatus;
}
}
if (dir_is_empty) {
dirstatus = apr_dir_remove(dir_path, loop_pool);
if ((dirstatus != APR_SUCCESS) && (retcode != APR_SUCCESS)) {
retcode = dirstatus;
}
apr_array_pop(arr);
}
}
apr_pool_destroy(array_pool);
apr_pool_destroy(loop_pool);
return retcode;
}
#include <apr_file_io.h>
#include <apr_file_info.h>
#include <apr_pools.h>
#include <errno.h>
apr_status_t
apr_dir_remove_recursive(const char *param_path, apr_pool_t * pool);
int main(int argn, char * argv[])
{
const char *path = "/tmp/dir1/dir2/dir3";
apr_status_t rc = 0;
apr_pool_t * pool;
apr_finfo_t finfo;
apr_initialize();
atexit(apr_terminate);
rc |= apr_pool_create(&pool, NULL);
rc |= apr_dir_make_recursive (path, APR_UREAD|APR_UWRITE|APR_UEXECUTE|APR_GSETID|APR_GREAD|APR_GWRITE|APR_GEXECUTE|APR_WREAD|APR_WWRITE|APR_WEXECUTE, pool);
rc = apr_dir_remove_recursive("/tmp/dir1", pool);
if(rc)
{
printf("apr_dir_remove_recursive failed[%d]\n", rc);
return rc;
}
rc = apr_stat(&finfo, path, APR_FINFO_NAME|APR_FINFO_DIRENT, pool);
if(APR_ENOENT != rc)
{
errno = rc;
perror("");
printf("apr_stat failed[%d]\n", rc);
return rc;
}
return 0;
}
Makefile
Description: Binary data
