From 71f9f882d1479dc6767c874ab815332dff514f0b Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 23 Feb 2014 16:41:34 +0100 Subject: [PATCH] Fix readdir(3) not preserving errno in case of end-of-directory condition. --- libc/dirent/readdir.cpp | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/libc/dirent/readdir.cpp b/libc/dirent/readdir.cpp index 9811ef0c..c402d1b9 100644 --- a/libc/dirent/readdir.cpp +++ b/libc/dirent/readdir.cpp @@ -30,42 +30,30 @@ extern "C" struct dirent* readdir(DIR* dir) { + int old_errno = errno; + if ( !dir->read_func ) - { - dir->flags |= _DIR_ERROR; - errno = EBADF; - return NULL; - } + return dir->flags |= _DIR_ERROR, errno = EBADF, (struct dirent*) NULL; size_t size = dir->entrysize; - int status = dir->read_func(dir->user, dir->entry, &size); - if ( status < 0 ) - { - dir->flags |= _DIR_ERROR; - return NULL; - } - - if ( 0 < status ) + int status; + while ( 0 < (status = dir->read_func(dir->user, dir->entry, &size)) ) { struct dirent* biggerdir = (struct dirent*) malloc(size); if ( !biggerdir ) - { - dir->flags |= _DIR_ERROR; - return NULL; - } + return dir->flags |= _DIR_ERROR, (struct dirent*) NULL; free(dir->entry); dir->entry = biggerdir; dir->entrysize = size; - return readdir(dir); } + if ( status < 0 ) + return dir->flags |= _DIR_ERROR, (struct dirent*) NULL; + dir->flags &= ~_DIR_ERROR; if ( !dir->entry->d_name[0] ) - { - dir->flags |= _DIR_EOF; - return NULL; - } + return dir->flags |= _DIR_EOF, errno = old_errno, (struct dirent*) NULL; return dir->entry; }