diff options
Diffstat (limited to 'utils/file.c')
-rw-r--r-- | utils/file.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/utils/file.c b/utils/file.c index cc82657c9..75a8a1c03 100644 --- a/utils/file.c +++ b/utils/file.c @@ -26,6 +26,8 @@ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> +#include <fcntl.h> +#include <errno.h> #include "desktop/gui_internal.h" @@ -35,6 +37,11 @@ #include "utils/nsurl.h" #include "utils/string.h" #include "utils/file.h" +#include "utils/dirent.h" + +#ifdef nsamiga +#include "frontends/amiga/os3support.h" +#endif /** * Generate a posix path from one or more component elemnts. @@ -307,3 +314,82 @@ nserror netsurf_mkdir_all(const char *fname) { return guit->file->mkdir_all(fname); } + +/* exported interface documented in utils/file.h */ +nserror +netsurf_recursive_rm(const char *path) +{ + DIR *parent; + struct dirent *entry; + nserror ret = NSERROR_OK; + struct stat ent_stat; /* stat result of leaf entry */ + + parent = opendir(path); + if (parent == NULL) { + switch (errno) { + case ENOENT: + return NSERROR_NOT_FOUND; + default: + return NSERROR_UNKNOWN; + } + } + + while ((entry = readdir(parent))) { + char *leafpath = NULL; + + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) + continue; + + ret = netsurf_mkpath(&leafpath, NULL, 2, path, entry->d_name); + if (ret != NSERROR_OK) + goto out; + +#if (defined(HAVE_DIRFD) && defined(HAVE_FSTATAT)) + if (fstatat(dirfd(parent), entry->d_name, &ent_stat, + AT_SYMLINK_NOFOLLOW) != 0) { +#else + if (stat(leafpath, &ent_stat) != 0) { +#endif + free(leafpath); + goto out_via_errno; + } + if (S_ISDIR(ent_stat.st_mode)) { + ret = netsurf_recursive_rm(leafpath); + if (ret != NSERROR_OK) { + free(leafpath); + goto out; + } + } else { +#if (defined(HAVE_DIRFD) && defined(HAVE_UNLINKAT)) + if (unlinkat(dirfd(parent), entry->d_name, 0) != 0) { +#else + if (unlink(leafpath) != 0) { +#endif + free(leafpath); + goto out_via_errno; + } + } + + free(leafpath); + } + + if (rmdir(path) != 0) { + goto out_via_errno; + } + + goto out; + +out_via_errno: + switch (errno) { + case ENOENT: + ret = NSERROR_NOT_FOUND; + break; + default: + ret = NSERROR_UNKNOWN; + } +out: + closedir(parent); + + return ret; +} |