From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Introduce a method virFileDeleteTree for recursively deleting an entire directory tree Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list