diff --git a/Userland/Utilities/du.cpp b/Userland/Utilities/du.cpp index 829e98a3e4..737ac83dff 100644 --- a/Userland/Utilities/du.cpp +++ b/Userland/Utilities/du.cpp @@ -36,6 +36,26 @@ struct DuOption { size_t max_depth = SIZE_MAX; }; +struct VisitedFile { + dev_t device; + ino_t inode; +}; + +template<> +struct AK::Traits : public GenericTraits { + static unsigned hash(VisitedFile const& visited_file) + { + return pair_int_hash(u64_hash(visited_file.device), u64_hash(visited_file.inode)); + } + + static bool equals(VisitedFile const& a, VisitedFile const& b) + { + return a.device == b.device && a.inode == b.inode; + } +}; + +static HashTable s_visited_files; + static ErrorOr parse_args(Main::Arguments arguments, Vector& files, DuOption& du_option); static u64 print_space_usage(DeprecatedString const& path, DuOption const& du_option, size_t current_depth, bool inside_dir = false); @@ -144,6 +164,13 @@ u64 print_space_usage(DeprecatedString const& path, DuOption const& du_option, s } auto path_stat = path_stat_or_error.release_value(); + + VisitedFile visited_file { path_stat.st_dev, path_stat.st_ino }; + if (s_visited_files.contains(visited_file)) { + return 0; + } + s_visited_files.set(visited_file); + bool const is_directory = S_ISDIR(path_stat.st_mode); if (is_directory) { auto di = Core::DirIterator(path, Core::DirIterator::SkipParentAndBaseDir);