/*
* Copyright ©2026 Soham Pardeshi. All rights reserved.
* Permission is hereby granted to students registered for University of
* Washington CSE 333 for use solely during Summer Quarter 2026 for
* purposes of the course. No other use, copying, distribution, or
* modification is permitted without prior written consent. Copyrights
* for third-party components of this work must be honored. Instructors
* interested in reusing these course materials should contact the author.
*/
#include "dirutil.h"
#include <dirent.h> // for DIR, struct dirent, opendir, readdir, closedir
#include <stdlib.h> // for malloc, free
#include <string.h> // for strcmp
// The definition of struct dir_iter, hidden from callers.
struct dir_iter {
DIR* dirp; // the underlying POSIX directory stream
struct dirent* current; // the entry we're currently pointing at, or NULL
};
// Helper: reads the next entry from dirp, skipping "." and "..".
// Returns the resulting dirent pointer (NULL if there are no more entries).
static struct dirent* GetNextRealEntry(DIR* dirp) {
struct dirent* entry = readdir(dirp);
// No more entries
if (entry == NULL) {
return NULL;
}
char* entry_name = entry->d_name;
// Skip the special entries "." and ".."
if (strcmp(entry_name, ".") == 0 || strcmp(entry_name, "..") == 0) {
return GetNextRealEntry(dirp);
}
return entry;
}
DirIter* DirIter_Allocate(const char* dirname) {
DIR* dirp = opendir(dirname);
if (dirp == NULL) {
return NULL;
}
DirIter* iter = (DirIter*) malloc(sizeof(DirIter));
if (iter == NULL) {
closedir(dirp);
return NULL;
}
iter->dirp = dirp;
iter->current = GetNextRealEntry(dirp); // prime the first entry
return iter;
}
void DirIter_Free(DirIter* iter) {
closedir(iter->dirp);
free(iter);
}
bool DirIter_IsValid(DirIter* iter) {
return iter->current != NULL;
}
bool DirIter_Next(DirIter* iter) {
iter->current = GetNextRealEntry(iter->dirp);
return iter->current != NULL;
}
const char* DirIter_Get(DirIter* iter) {
return iter->current->d_name;
}