mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
Introduce a virFileDeleteTree method
Introduce a method virFileDeleteTree for recursively deleting an entire directory tree Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
b7f1d218d8
commit
035cdaa00b
@ -1264,6 +1264,7 @@ virEventPollUpdateTimeout;
|
|||||||
|
|
||||||
# util/virfile.h
|
# util/virfile.h
|
||||||
virFileClose;
|
virFileClose;
|
||||||
|
virFileDeleteTree;
|
||||||
virFileDirectFdFlag;
|
virFileDirectFdFlag;
|
||||||
virFileFclose;
|
virFileFclose;
|
||||||
virFileFdopen;
|
virFileFdopen;
|
||||||
|
@ -644,3 +644,86 @@ int virFileLoopDeviceAssociate(const char *file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virFileDeleteTree:
|
||||||
|
*
|
||||||
|
* Recursively deletes all files / directories
|
||||||
|
* starting from the directory @dir. Does not
|
||||||
|
* follow symlinks
|
||||||
|
*
|
||||||
|
* NB the algorithm is not efficient, and is subject to
|
||||||
|
* race conditions which can be exploited by malicious
|
||||||
|
* code. It should not be used in any scenarios where
|
||||||
|
* performance is important, or security is critical.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -108,4 +108,6 @@ int virFileUpdatePerm(const char *path,
|
|||||||
int virFileLoopDeviceAssociate(const char *file,
|
int virFileLoopDeviceAssociate(const char *file,
|
||||||
char **dev);
|
char **dev);
|
||||||
|
|
||||||
|
int virFileDeleteTree(const char *dir);
|
||||||
|
|
||||||
#endif /* __VIR_FILES_H */
|
#endif /* __VIR_FILES_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user