| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |  * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-16 18:55:41 +02:00
										 |  |  | #include <AK/Vector.h>
 | 
					
						
							| 
									
										
										
										
											2020-09-16 20:46:33 +02:00
										 |  |  | #include <LibCore/DirIterator.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | namespace Core { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | DirIterator::DirIterator(DeprecatedString path, Flags flags) | 
					
						
							| 
									
										
										
										
											2021-04-17 00:48:07 +02:00
										 |  |  |     : m_path(move(path)) | 
					
						
							| 
									
										
										
										
											2020-02-16 14:10:47 +13:00
										 |  |  |     , m_flags(flags) | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-17 00:48:07 +02:00
										 |  |  |     m_dir = opendir(m_path.characters()); | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |     if (!m_dir) { | 
					
						
							| 
									
										
										
										
											2023-03-01 15:55:15 +00:00
										 |  |  |         m_error = Error::from_errno(errno); | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | DirIterator::~DirIterator() | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |     if (m_dir) { | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |         closedir(m_dir); | 
					
						
							|  |  |  |         m_dir = nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-23 11:37:14 -05:00
										 |  |  | DirIterator::DirIterator(DirIterator&& other) | 
					
						
							|  |  |  |     : m_dir(other.m_dir) | 
					
						
							| 
									
										
										
										
											2023-03-01 15:55:15 +00:00
										 |  |  |     , m_error(move(other.m_error)) | 
					
						
							| 
									
										
										
										
											2021-11-23 11:37:14 -05:00
										 |  |  |     , m_next(move(other.m_next)) | 
					
						
							|  |  |  |     , m_path(move(other.m_path)) | 
					
						
							|  |  |  |     , m_flags(other.m_flags) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     other.m_dir = nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool DirIterator::advance_next() | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |     if (!m_dir) | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |     while (true) { | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |         errno = 0; | 
					
						
							|  |  |  |         auto* de = readdir(m_dir); | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |         if (!de) { | 
					
						
							| 
									
										
										
										
											2023-03-17 16:04:19 +00:00
										 |  |  |             if (errno != 0) { | 
					
						
							|  |  |  |                 m_error = Error::from_errno(errno); | 
					
						
							|  |  |  |                 dbgln("DirIteration error: {}", m_error.value()); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |             m_next.clear(); | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-16 16:34:42 +02:00
										 |  |  | #ifdef AK_OS_SOLARIS
 | 
					
						
							|  |  |  |         m_next = DirectoryEntry::from_stat(m_dir, *de); | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |         m_next = DirectoryEntry::from_dirent(*de); | 
					
						
							| 
									
										
										
										
											2023-06-16 16:34:42 +02:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (m_next->name.is_empty()) | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |         if (m_flags & Flags::SkipDots && m_next->name.starts_with('.')) | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |         if (m_flags & Flags::SkipParentAndBaseDir && (m_next->name == "." || m_next->name == "..")) | 
					
						
							| 
									
										
										
										
											2020-02-15 13:06:08 +13:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |         return !m_next->name.is_empty(); | 
					
						
							| 
									
										
										
										
											2020-02-15 13:04:09 +13:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | bool DirIterator::has_next() | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |     if (m_next.has_value()) | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return advance_next(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  | Optional<DirectoryEntry> DirIterator::next() | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |     if (!m_next.has_value()) | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  |         advance_next(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-02 15:39:07 +00:00
										 |  |  |     auto result = m_next; | 
					
						
							|  |  |  |     m_next.clear(); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DeprecatedString DirIterator::next_path() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto entry = next(); | 
					
						
							|  |  |  |     if (entry.has_value()) | 
					
						
							|  |  |  |         return entry->name; | 
					
						
							|  |  |  |     return ""; | 
					
						
							| 
									
										
										
										
											2019-05-27 09:26:54 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-04 18:02:33 +00:00
										 |  |  | DeprecatedString DirIterator::next_full_path() | 
					
						
							| 
									
										
										
										
											2020-02-16 14:10:47 +13:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-07-03 12:32:46 +02:00
										 |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     builder.append(m_path); | 
					
						
							|  |  |  |     if (!m_path.ends_with('/')) | 
					
						
							|  |  |  |         builder.append('/'); | 
					
						
							|  |  |  |     builder.append(next_path()); | 
					
						
							| 
									
										
										
										
											2022-12-06 01:12:49 +00:00
										 |  |  |     return builder.to_deprecated_string(); | 
					
						
							| 
									
										
										
										
											2020-02-16 14:10:47 +13:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-14 21:05:18 +02:00
										 |  |  | int DirIterator::fd() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_dir) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     return dirfd(m_dir); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-02 12:34:39 +01:00
										 |  |  | } |