diff options
Diffstat (limited to 'lldb/source/Host/posix/FileSystem.cpp')
-rw-r--r-- | lldb/source/Host/posix/FileSystem.cpp | 52 |
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(); |