From: "Daniel P. Berrange" <berrange(a)redhat.com>
Introduce a method virFileDeleteTree for recursively deleting
an entire directory tree
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virfile.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virfile.h | 2 ++
3 files changed, 81 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 96eea0a..e297850 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1258,6 +1258,7 @@ virEventPollUpdateTimeout;
# util/virfile.h
virFileClose;
+virFileDeleteTree;
virFileDirectFdFlag;
virFileFclose;
virFileFdopen;
diff --git a/src/util/virfile.c b/src/util/virfile.c
index 4a9fa81..4d338e1 100644
--- a/src/util/virfile.c
+++ b/src/util/virfile.c
@@ -644,3 +644,81 @@ int virFileLoopDeviceAssociate(const char *file,
}
#endif /* __linux__ */
+
+
+/**
+ * virFileDeleteTree:
+ *
+ * Recursively deletes all files / directories
+ * starting from the directory @dir. Does not
+ * follow symlinks
+ */
+int virFileDeleteTree(const char *dir)
+{
+ DIR *dh = opendir(dir);
+ struct dirent *de;
+ char *filepath = NULL;
+ int ret = -1;
+
+ if (!dh) {
+ virReportSystemError(errno, _("Cannot open dir '%s'"),
+ dir);
+ return -1;
+ }
+
+ errno = 0;
+ while ((de = readdir(dh)) != NULL) {
+ struct stat sb;
+
+ if (STREQ(de->d_name, ".") ||
+ STREQ(de->d_name, ".."))
+ continue;
+
+ if (virAsprintf(&filepath, "%s/%s",
+ dir, de->d_name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (lstat(filepath, &sb) < 0) {
+ virReportSystemError(errno, _("Cannot access '%s'"),
+ filepath);
+ goto cleanup;
+ }
+
+ if (S_ISDIR(sb.st_mode)) {
+ if (virFileDeleteTree(filepath) < 0)
+ goto cleanup;
+ } else {
+ if (unlink(filepath) < 0 && errno != ENOENT) {
+ virReportSystemError(errno,
+ _("Cannot delete file '%s'"),
+ filepath);
+ goto cleanup;
+ }
+ }
+
+ VIR_FREE(filepath);
+ errno = 0;
+ }
+
+ if (errno) {
+ virReportSystemError(errno, _("Cannot read dir '%s'"),
+ dir);
+ goto cleanup;
+ }
+
+ if (rmdir(dir) < 0 && errno != ENOENT) {
+ virReportSystemError(errno,
+ _("Cannot delete directory '%s'"),
+ dir);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FREE(filepath);
+ closedir(dh);
+ return ret;
+}
diff --git a/src/util/virfile.h b/src/util/virfile.h
index c885b73..5f0dd2b 100644
--- a/src/util/virfile.h
+++ b/src/util/virfile.h
@@ -108,4 +108,6 @@ int virFileUpdatePerm(const char *path,
int virFileLoopDeviceAssociate(const char *file,
char **dev);
+int virFileDeleteTree(const char *dir);
+
#endif /* __VIR_FILES_H */
--
1.8.1.4