From e9495f7a2897fcb4a16220a0baa0acd6a053da7d Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Mon, 30 Jun 2014 08:40:08 +0200 Subject: [PATCH] utils os: Added sdb_remove_all() to recursively remove a path. --- src/include/utils/os.h | 17 +++++++++---- src/utils/os.c | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/include/utils/os.h b/src/include/utils/os.h index 26f7e59..2e6c547 100644 --- a/src/include/utils/os.h +++ b/src/include/utils/os.h @@ -37,11 +37,7 @@ extern "C" { /* * sysdb_mkdir_all: * Recursively create the directory 'pathname' (similar to 'mkdir -p' on the - * command line) and ensure that its mode is 'mode'. Any newly created - * directories will have permissions according the the specified mode - * (modified by the process's umask in the usual way). The function will - * always ensure the specified permissions for the specified directory, even - * if it exists already. + * command line) using file permissions as specified by 'mode'. * * Returns: * - 0 on success @@ -50,6 +46,17 @@ extern "C" { int sdb_mkdir_all(const char *pathname, mode_t mode); +/* + * sdb_remove_all: + * Recursively deletes the specified path from the filesystem. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_remove_all(const char *pathname); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/utils/os.c b/src/utils/os.c index 08cb188..7858825 100644 --- a/src/utils/os.c +++ b/src/utils/os.c @@ -36,7 +36,10 @@ #include #include +#include + #include +#include #include #include @@ -86,5 +89,56 @@ sdb_mkdir_all(const char *pathname, mode_t mode) return status; } /* sdb_mkdir_all */ +int +sdb_remove_all(const char *pathname) +{ + struct stat st; + + if ((! pathname) || (! *pathname)) { + errno = EINVAL; + return -1; + } + + memset(&st, 0, sizeof(st)); + if (stat(pathname, &st)) + return -1; + + if (S_ISDIR(st.st_mode)) { + DIR *d = opendir(pathname); + + if (! d) + return -1; + + while (42) { + struct dirent de; + struct dirent *res = NULL; + + char filename[strlen(pathname) + sizeof(de.d_name) + 2]; + + memset(&de, 0, sizeof(de)); + if (readdir_r(d, &de, &res)) { + closedir(d); + return -1; + } + + if (! res) + break; + + if ((de.d_name[0] == '.') && ((de.d_name[1] == '\0') + || ((de.d_name[1] == '.')&& (de.d_name[2] == '\0')))) + continue; + + snprintf(filename, sizeof(filename), + "%s/%s", pathname, de.d_name); + if (sdb_remove_all(filename)) { + closedir(d); + return -1; + } + } + closedir(d); + } + return remove(pathname); +} /* sdb_remove_all */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ -- 2.30.2