diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2026-03-03 21:59:48 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2026-03-03 22:09:00 +0800 |
| commit | 5b20837cf59157f77d6bd49bc021d2be3479610f (patch) | |
| tree | 468cd2a7be6f40ecb928574b17a64363ee114e1c | |
| parent | 5a9973f55d239fc92a17daea9a1e89beac827670 (diff) | |
| download | cvn-5b20837cf59157f77d6bd49bc021d2be3479610f.tar.gz | |
Use dynamic stack and ignore repo in traverse().
| -rw-r--r-- | main.c | 48 |
1 files changed, 32 insertions, 16 deletions
@@ -13,13 +13,11 @@ #define REPO ".cvn" #define INDEX "index" -#define MAX_SUBDIRS 256 - static inline void init(int argc, char *argv[]); static inline void status(int argc, char *argv[]); -/* helpers */ static inline void traverse(void); +static inline uint8_t ignore(const char *path); struct command { char *name; @@ -99,20 +97,34 @@ static inline void status(int argc, char *argv[]) traverse(); } +static inline uint8_t ignore(const char *path) +{ + return strcmp(path, ".") == 0 || + strcmp(path, "..") == 0 || + strcmp(path, REPO) == 0; +} + static inline void traverse(void) { DIR *dir; char *path, *rel_path; struct stat st; struct dirent *entry; - int subdirs_len; - char *subdirs[MAX_SUBDIRS]; - - subdirs_len = 0; - subdirs[subdirs_len++] = strdup("."); - - while (subdirs_len) { - path = subdirs[--subdirs_len]; + int i, subdirs_len; + char **subdirs; + + i = 0; + // On 64-bit systems: 512 * 8 (ptr size) = 4096 - typical page size / 64 cache lines + // Page-aligned buffers that fit in CPU cache lines reduce mmu overhead (play well + // with the CPU's TLB (Tranlation Lookaside Buffer). + subdirs_len = 512; + subdirs = malloc(sizeof(subdirs[0]) * subdirs_len); + if (!subdirs) + err(1, "malloc() failed"); + subdirs[i++] = strdup("."); + + while (i > 0) { + path = subdirs[--i]; if (!(dir = opendir(path))) { warn("Failed to open directory %s", path); free(path); @@ -120,7 +132,7 @@ static inline void traverse(void) } while ((entry = readdir(dir)) != NULL) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + if (ignore(entry->d_name)) continue; if (asprintf(&rel_path, "%s/%s", path, entry->d_name) == -1) err(1, "asprintf() failed"); @@ -130,16 +142,20 @@ static inline void traverse(void) continue; } if (S_ISDIR(st.st_mode)) { - if (subdirs_len >= MAX_SUBDIRS) - errx(1, "Repository too large: directory tree too deep/wide"); - subdirs[subdirs_len++] = rel_path; + if (i >= subdirs_len) { + subdirs_len <<= 1; + subdirs = realloc(subdirs, sizeof(subdirs[0]) * subdirs_len); + if (!subdirs) + err(1, "realloc() failed"); + } + subdirs[i++] = rel_path; } else { printf("File: %s\n", rel_path); free(rel_path); } } - free(path); closedir(dir); } + free(subdirs); } |
