From 5dd1a81f9c97d852faa54e0d96482b69739fe8dc Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Mon, 24 Feb 2020 21:01:25 +0000 Subject: utils/file: Add netsurf_recursive_rm This is to be used to remove the disc cache (and other things if useful in the future) Signed-off-by: Daniel Silverstone --- utils/file.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils/file.h | 11 +++++++++ 2 files changed, 86 insertions(+) (limited to 'utils') diff --git a/utils/file.c b/utils/file.c index cc82657c9..7eff6a780 100644 --- a/utils/file.c +++ b/utils/file.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "desktop/gui_internal.h" @@ -35,6 +36,7 @@ #include "utils/nsurl.h" #include "utils/string.h" #include "utils/file.h" +#include "utils/dirent.h" /** * Generate a posix path from one or more component elemnts. @@ -307,3 +309,76 @@ 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) +{ + struct dirent **listing = NULL; /* directory entry listing */ + int nentries, ent; + nserror ret = NSERROR_OK; + struct stat ent_stat; /* stat result of leaf entry */ + char *leafpath = NULL; + const char *leafname; + + nentries = scandir(path, &listing, 0, alphasort); + + if (nentries < 0) { + switch (errno) { + case ENOENT: + return NSERROR_NOT_FOUND; + default: + return NSERROR_UNKNOWN; + } + } + + for (ent = 0; ent < nentries; ent++) { + leafname = listing[ent]->d_name; + if (strcmp(leafname, ".") == 0 || + strcmp(leafname, "..") == 0) + continue; + ret = netsurf_mkpath(&leafpath, NULL, 2, path, leafname); + if (ret != NSERROR_OK) goto out; + if (stat(leafpath, &ent_stat) != 0) { + goto out_via_errno; + } + if (S_ISDIR(ent_stat.st_mode)) { + ret = netsurf_recursive_rm(leafpath); + if (ret != NSERROR_OK) goto out; + } else { + if (unlink(leafpath) != 0) { + goto out_via_errno; + } + } + free(leafpath); + leafpath = NULL; + } + + 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: + if (listing != NULL) { + for (ent = 0; ent < nentries; ent++) { + free(listing[ent]); + } + free(listing); + } + + if (leafpath != NULL) { + free(leafpath); + } + + return ret; +} diff --git a/utils/file.h b/utils/file.h index 0282c350e..809ffe419 100644 --- a/utils/file.h +++ b/utils/file.h @@ -172,4 +172,15 @@ nserror netsurf_path_to_nsurl(const char *path, struct nsurl **url); */ nserror netsurf_mkdir_all(const char *fname); +/** + * Recursively remove a directory + * + * If this returns a failure code, there's an unpredictable amount left + * unremoved. + * + * @param path The path to recursively remove + * @return NSERROR_OK on success, or an error code on failure. + */ +nserror netsurf_recursive_rm(const char *path); + #endif -- cgit v1.2.3