summaryrefslogtreecommitdiffstats
path: root/lldb/source/Host/posix/FileSystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Host/posix/FileSystem.cpp')
-rw-r--r--lldb/source/Host/posix/FileSystem.cpp52
1 files changed, 34 insertions, 18 deletions
diff --git a/lldb/source/Host/posix/FileSystem.cpp b/lldb/source/Host/posix/FileSystem.cpp
index 1ec53e2cc66..52698039b46 100644
--- a/lldb/source/Host/posix/FileSystem.cpp
+++ b/lldb/source/Host/posix/FileSystem.cpp
@@ -82,27 +82,43 @@ FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
{
if (recurse)
{
- DIR *dirp = opendir(file_spec.GetCString());
- if (!dirp)
- {
- error.SetErrorToErrno();
- return error;
- }
- struct dirent *direntp;
- while (error.Success() && (direntp = readdir(dirp)))
+ // Save all sub directories in a list so we don't recursively call this function
+ // and possibly run out of file descriptors if the directory is too deep.
+ std::vector<FileSpec> sub_directories;
+
+ FileSpec::ForEachItemInDirectory (file_spec.GetCString(), [&error, &sub_directories](FileSpec::FileType file_type, const FileSpec &spec) -> FileSpec::EnumerateDirectoryResult {
+ if (file_type == FileSpec::eFileTypeDirectory)
+ {
+ // Save all directorires and process them after iterating through this directory
+ sub_directories.push_back(spec);
+ }
+ else
+ {
+ // Update sub_spec to point to the current file and delete it
+ error = FileSystem::Unlink(spec);
+ }
+ // If anything went wrong, stop iterating, else process the next file
+ if (error.Fail())
+ return FileSpec::eEnumerateDirectoryResultQuit;
+ else
+ return FileSpec::eEnumerateDirectoryResultNext;
+ });
+
+ if (error.Success())
{
- if (direntp->d_type == DT_DIR)
- error = DeleteDirectory(FileSpec{direntp->d_name, false}, true);
- else if (::unlink(direntp->d_name) != 0)
- error.SetErrorToErrno();
+ // Now delete all sub directories with separate calls that aren't
+ // recursively calling into this function _while_ this function is
+ // iterating through the current directory.
+ for (const auto &sub_directory : sub_directories)
+ {
+ error = DeleteDirectory(sub_directory, recurse);
+ if (error.Fail())
+ break;
+ }
}
- if (closedir(dirp) != 0)
- error.SetErrorToErrno();
- if (error.Fail())
- return error;
- return DeleteDirectory(file_spec, false);
}
- else
+
+ if (error.Success())
{
if (::rmdir(file_spec.GetCString()) != 0)
error.SetErrorToErrno();
OpenPOWER on IntegriCloud