diff --git a/src/system/libroot/posix/dirent.c b/src/system/libroot/posix/dirent.c index 09f5f5f8c4..198c23d9bd 100644 --- a/src/system/libroot/posix/dirent.c +++ b/src/system/libroot/posix/dirent.c @@ -243,7 +243,26 @@ readdir(DIR* dir) int readdir_r(DIR* dir, struct dirent* entry, struct dirent** _result) { - ssize_t count = _kern_read_dir(dir->fd, entry, sizeof(struct dirent) + ssize_t count; + + if (dir->seek_position != dir->current_position) { + if (do_seek_dir(dir) != 0) + return -1; + } + + if (dir->entries_left > 0) { + *_result + = (struct dirent *)((uint8 *)&dir->first_entry + dir->next_entry); + + dir->entries_left--; + dir->next_entry += (*_result)->d_reclen; + dir->seek_position++; + dir->current_position++; + + return 0; + } + + count = _kern_read_dir(dir->fd, entry, sizeof(struct dirent) + B_FILE_NAME_LENGTH, 1); if (count < B_OK) return count; @@ -251,8 +270,13 @@ readdir_r(DIR* dir, struct dirent* entry, struct dirent** _result) if (count == 0) { // end of directory *_result = NULL; - } else + } else { *_result = entry; + dir->entries_left = count - 1; + dir->next_entry = dir->first_entry.d_reclen; + dir->seek_position++; + dir->current_position++; + } return 0; } diff --git a/src/tests/system/libroot/posix/dirent_test.cpp b/src/tests/system/libroot/posix/dirent_test.cpp index 833417e8ee..da5a4709c4 100644 --- a/src/tests/system/libroot/posix/dirent_test.cpp +++ b/src/tests/system/libroot/posix/dirent_test.cpp @@ -6,15 +6,18 @@ #include #include +#include int main(int argc, char** argv) { + dirent *buf, *dirent; DIR* dir = opendir("."); + printf("first pass:\n"); while (true) { - dirent* dirent = readdir(dir); + dirent = readdir(dir); if (dirent == NULL) break; @@ -23,6 +26,48 @@ main(int argc, char** argv) //printf(" left: %u, next: %d\n", dir->entries_left, dir->next_entry); } + rewinddir(dir); + printf("second pass:\n"); + while (true) { + dirent = readdir(dir); + if (dirent == NULL) + break; + + printf("Entry: dev %ld, ino %Ld, name \"%s\"\n", dirent->d_dev, + dirent->d_ino, dirent->d_name); + //printf(" left: %u, next: %d\n", dir->entries_left, dir->next_entry); + } + + closedir(dir); + + dirent = NULL; + buf = (struct dirent*)malloc(sizeof(struct dirent) + NAME_MAX); + + dir = opendir("."); + + printf("first pass:\n"); + while (true) { + if (readdir_r(dir, buf, &dirent) != 0 || dirent == NULL) + break; + + printf("Entry: dev %ld, ino %Ld, name \"%s\"\n", dirent->d_dev, + dirent->d_ino, dirent->d_name); + //printf(" left: %u, next: %d\n", dir->entries_left, dir->next_entry); + } + + rewinddir(dir); + printf("second pass:\n"); + while (true) { + if (readdir_r(dir, buf, &dirent) != 0 || dirent == NULL) + break; + + printf("Entry: dev %ld, ino %Ld, name \"%s\"\n", dirent->d_dev, + dirent->d_ino, dirent->d_name); + //printf(" left: %u, next: %d\n", dir->entries_left, dir->next_entry); + } + + closedir(dir); + return 0; }