#include "commons/commons_dir_iter.h" #include "commons/commons_array.h" #include "commons/commons_file.h" #include "commons/commons_mem.h" #include "commons/commons_platform.h" #include "commons/commons_platform_linux.h" #include "commons/commons_region_alloc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include struct _dir_iter { DIR* handle; int fd; }; auto API DirIter_Create(region_alloc& alloc, byteview path) -> dir_iter { DIR* d = opendir(Span_CStr(path)); if (!d) return nullptr; _dir_iter& self = RegionAlloc_Alloc<_dir_iter>(alloc); self.handle = d; self.fd = dirfd(d); return &self; } auto API DirIter_Next(dir_iter self, file_metadata& out) -> bool { errno = 0; struct dirent* de = readdir(self->handle); if (!de) { ASSERT(errno == 0); return false; } MemZero(&out); InlineString_Assign(out.fileName, Span_FromCStr(de->d_name, 256)); struct stat st; if (fstatat(self->fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0) { out.fileSize = (uint64_t)st.st_size; out.lastWriteTime = (uint64_t)st.st_mtime; out.lastAccessTime = (uint64_t)st.st_atime; out.creationTime = (uint64_t)st.st_ctime; if (S_ISDIR(st.st_mode)) out.attributes |= file_attribute::Directory; } else if (de->d_type == DT_DIR) { out.attributes |= file_attribute::Directory; } if (de->d_name[0] == '.') out.attributes |= file_attribute::Hidden; return true; } void API DirIter_Destroy(dir_iter& self) { closedir(self->handle); }