From 7b5edf6e8d4133db6b98f1c8cdea95ac4380f810 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 17 May 2022 20:58:47 +0100 Subject: [PATCH] Implemented buffering int readdir() --- photon/libc/sys/horizon/dirent.c | 126 +++++++++++++++++++------- photon/libc/sys/horizon/sys/_dirent.h | 13 ++- 2 files changed, 106 insertions(+), 33 deletions(-) diff --git a/photon/libc/sys/horizon/dirent.c b/photon/libc/sys/horizon/dirent.c index f55614b..15d0c4c 100644 --- a/photon/libc/sys/horizon/dirent.c +++ b/photon/libc/sys/horizon/dirent.c @@ -30,66 +30,128 @@ DIR *opendir(const char *path) int closedir(DIR *d) { close(d->fd); + for (int i = 0; i < d->cache_size; i++) { + if (d->dent_cache[i].d_namep) { + free(d->dent_cache[i].d_namep); + } + } + free(d); return 0; } -struct dirent *readdir(DIR *d) +static void clear_cache(DIR *d) { - mio_dirent dent; - int r = mio_getdents(d->fd, &dent, 1); - if (r < 1) { - __set_errno(-r); - return NULL; + for (int i = 0; i < d->cache_size; i++) { + if (d->dent_cache[i].d_namep) { + free(d->dent_cache[i].d_namep); + } + + d->dent_cache[i].d_namep = NULL; } - size_t name_max = sizeof(d->current_dent.d_name); - if (sizeof(dent.d_name) < name_max) { - name_max = sizeof(dent.d_name); - } - - d->current_dent.d_ino = dent.d_ino; - d->current_dent.d_type = dent.d_type; - memcpy(d->current_dent.d_name, dent.d_name, name_max); - - return &d->current_dent; + d->cache_size = d->cache_idx = 0; } -int readdir_r(DIR *d, struct dirent *entry, struct dirent **result) +static int refill(DIR *d) { - mio_dirent dent; - int r = mio_getdents(d->fd, &dent, 1); - if (r < 1) { - *result = NULL; + clear_cache(d); + + for (int i = 0; i < d->cache_size; i++) { + free(d->dent_cache[i].d_namep); + d->dent_cache[i].d_namep = NULL; + } + + d->cache_size = d->cache_idx = 0; + mio_dirent dent[__SYS_DENT_CACHE_SZ]; + + int r = mio_getdents(d->fd, dent, __SYS_DENT_CACHE_SZ); + if (r < 0) { __set_errno(-r); return -1; } - size_t name_max = sizeof(d->current_dent.d_name); - if (sizeof(dent.d_name) < name_max) { - name_max = sizeof(dent.d_name); + for (int i = 0; i < r; i++) { + struct __dentcache *cache_ent = &d->dent_cache[i]; + cache_ent->d_ino = dent[i].d_ino; + cache_ent->d_type = dent[i].d_type; + cache_ent->d_namep = strdup(dent[i].d_name); } - d->current_dent.d_ino = dent.d_ino; - d->current_dent.d_type = dent.d_type; - memcpy(d->current_dent.d_name, dent.d_name, name_max); - memcpy(entry, &d->current_dent, sizeof(*entry)); - *result = entry; + d->cache_idx = 0; + d->cache_size = r; + return 0; +} + +static void fill_dirent(DIR *d, struct dirent *out) +{ + if (d->cache_idx >= d->cache_size) { + return; + } + + struct __dentcache *cache_ent = &d->dent_cache[d->cache_idx]; + out->d_ino = cache_ent->d_ino; + out->d_type = cache_ent->d_type; + + if (cache_ent->d_namep) { + strncpy(out->d_name, cache_ent->d_namep, sizeof out->d_name - 1); + out->d_name[sizeof out->d_name - 1] = '\0'; + } +} + +struct dirent *readdir(DIR *d) +{ + if (d->cache_idx == d->cache_size) { + if (refill(d) != 0 || !d->cache_size) { + return NULL; + } + } + + fill_dirent(d, &d->cdent); + d->cache_idx++; + d->seek++; + return &d->cdent; +} + +int readdir_r(DIR *d, struct dirent *entry, struct dirent **result) +{ + if (d->cache_idx == d->cache_size) { + if (refill(d) != 0) { + return 1; + } + + if (d->cache_size == 0) { + if (result) { + *result = NULL; + } + + return 0; + } + } + + fill_dirent(d, entry); + d->seek++; + + if (result) { + *result = entry; + } return 0; } void rewinddir(DIR *d) { - mio_seek(d->fd, 0, SEEK_SET); + d->seek = mio_seek(d->fd, 0, SEEK_SET); + clear_cache(d); } void seekdir(DIR *d, long int off) { - mio_seek(d->fd, off, SEEK_SET); + d->seek = mio_seek(d->fd, off, SEEK_SET); + clear_cache(d); } long int telldir(DIR *d) { - return mio_seek(d->fd, 0, SEEK_CUR); + return d->seek; } diff --git a/photon/libc/sys/horizon/sys/_dirent.h b/photon/libc/sys/horizon/sys/_dirent.h index 6925c4e..e28841d 100644 --- a/photon/libc/sys/horizon/sys/_dirent.h +++ b/photon/libc/sys/horizon/sys/_dirent.h @@ -4,6 +4,14 @@ #include #include +#define __SYS_DENT_CACHE_SZ 4 + +struct __dentcache { + ino_t d_ino; + unsigned char d_type; + char *d_namep; +}; + struct dirent { ino_t d_ino; unsigned char d_type; @@ -12,7 +20,10 @@ struct dirent { typedef struct { int fd; - struct dirent current_dent; + long seek; + unsigned char cache_idx, cache_size; + struct __dentcache dent_cache[__SYS_DENT_CACHE_SZ]; + struct dirent cdent; } DIR; #endif