summaryrefslogtreecommitdiff
path: root/utils/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/file.c')
-rw-r--r--utils/file.c86
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;
+}