Serenity Operating System
at master 114 lines 2.3 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/Vector.h> 9#include <LibCore/DirIterator.h> 10#include <errno.h> 11 12namespace Core { 13 14DirIterator::DirIterator(DeprecatedString path, Flags flags) 15 : m_path(move(path)) 16 , m_flags(flags) 17{ 18 m_dir = opendir(m_path.characters()); 19 if (!m_dir) { 20 m_error = Error::from_errno(errno); 21 } 22} 23 24DirIterator::~DirIterator() 25{ 26 if (m_dir) { 27 closedir(m_dir); 28 m_dir = nullptr; 29 } 30} 31 32DirIterator::DirIterator(DirIterator&& other) 33 : m_dir(other.m_dir) 34 , m_error(move(other.m_error)) 35 , m_next(move(other.m_next)) 36 , m_path(move(other.m_path)) 37 , m_flags(other.m_flags) 38{ 39 other.m_dir = nullptr; 40} 41 42bool DirIterator::advance_next() 43{ 44 if (!m_dir) 45 return false; 46 47 while (true) { 48 errno = 0; 49 auto* de = readdir(m_dir); 50 if (!de) { 51 m_error = Error::from_errno(errno); 52 m_next.clear(); 53 return false; 54 } 55 56 m_next = DirectoryEntry::from_dirent(*de); 57 58 if (m_next->name.is_empty()) 59 return false; 60 61 if (m_flags & Flags::SkipDots && m_next->name.starts_with('.')) 62 continue; 63 64 if (m_flags & Flags::SkipParentAndBaseDir && (m_next->name == "." || m_next->name == "..")) 65 continue; 66 67 return !m_next->name.is_empty(); 68 } 69} 70 71bool DirIterator::has_next() 72{ 73 if (m_next.has_value()) 74 return true; 75 76 return advance_next(); 77} 78 79Optional<DirectoryEntry> DirIterator::next() 80{ 81 if (!m_next.has_value()) 82 advance_next(); 83 84 auto result = m_next; 85 m_next.clear(); 86 return result; 87} 88 89DeprecatedString DirIterator::next_path() 90{ 91 auto entry = next(); 92 if (entry.has_value()) 93 return entry->name; 94 return ""; 95} 96 97DeprecatedString DirIterator::next_full_path() 98{ 99 StringBuilder builder; 100 builder.append(m_path); 101 if (!m_path.ends_with('/')) 102 builder.append('/'); 103 builder.append(next_path()); 104 return builder.to_deprecated_string(); 105} 106 107int DirIterator::fd() const 108{ 109 if (!m_dir) 110 return -1; 111 return dirfd(m_dir); 112} 113 114}