If you think a bug might affect users in the 57 release, please set the correct tracking and status flags for Release Management.

PR_ReadDir does not notify correcly end of directory

RESOLVED FIXED in 4.6

Status

NSPR
NSPR
RESOLVED FIXED
13 years ago
13 years ago

People

(Reporter: Mathieu Poumeyrol, Assigned: Wan-Teh Chang)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment, 1 obsolete attachment)

2.47 KB, patch
Brian Ryner (not reading)
: review+
Details | Diff | Splinter Review
(Reporter)

Description

13 years ago
User-Agent:       Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/188 (KHTML, like Gecko) Safari/188
Build Identifier: 

PR_ReadDir sets NSPR error status to PR_UNKNOWN_ERROR instead of PR_NO_MORE_FILES_ERROR when 
reaching end of directory.

The cause is readdir returns NULL and set errno to 0 when reaching the end of the directory, whereas 
_MD_unix_readdir_error from unix_errors.c only except ENOENT in such a case.

Reproducible: Always

Steps to Reproduce:
#include <prio.h>

int main()
{
    PRDir * dir = PR_OpenDir(".");
    while(PR_ReadDir(dir, PR_SKIP_BOTH)) ;
    PR_fprintf(PR_STDERR, "PR_GetError returns %d\n", PR_GetError());
    return 0;
}
Actual Results:  
PR_GetError returns -5994
PR_UNKNOWN_ERROR better, but still wrong...

Expected Results:  
PR_GetError returns -5939 
That is PR_NO_MORE_FILES -> OK.

if the program says "PR_GetError returns 0" you have to apply the patch from #279323.
(Reporter)

Comment 1

13 years ago
Created attachment 176727 [details] [diff] [review]
fix proposal
(Assignee)

Comment 2

13 years ago
Created attachment 176803 [details] [diff] [review]
fix proposal v1.1

Thanks for the bug report and fix.

The Single UNIX Specification Version 3 also
recommends that we set errno to 0 before each
readdir call, which is what my patch does.  I
also fix the similar code in BeOS.  Not sure
if that's correct or needed though.
Attachment #176727 - Attachment is obsolete: true
(Assignee)

Comment 3

13 years ago
Here is the URL for the readdir man page in the
Single UNIX Specification Version 3:
http://www.opengroup.org/onlinepubs/009695399/functions/readdir.html
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
(Assignee)

Updated

13 years ago
Attachment #176803 - Flags: review?(bryner)
Attachment #176803 - Flags: review?(bryner) → review+
(Assignee)

Updated

13 years ago
Attachment #176803 - Flags: superreview?(thesuckiestemail)
(Assignee)

Comment 4

13 years ago
tqh, sergei_d: could you look up BeOS's readdir()
documentation and tell me what it says about readdir's
return value and errno when readir() reaches the end of
the directory?  Then, please review the BeOS portion of
my patch.  Please use the "superreview" checkbox
to indicate your review.  Thanks.
(Assignee)

Comment 5

13 years ago
I checked in the patch (proposal v1.1) on the
NSPR trunk (NSPR 4.6) and NSPRPUB_PRE_4_2_CLIENT_BRANCH
(Mozilla 1.8 Beta 2).

SUSv3 says:

  The readdir() function may fail if:

  [ENOENT]
      The current position of the directory stream is invalid.

This suggests that ENOENT doesn't mean the end of the
directory is encountered, so it is wrong to map ENOENT
to PR_NO_MORE_FILES_ERROR.  Not sure if we should fix
this though.
Status: ASSIGNED → RESOLVED
Last Resolved: 13 years ago
Resolution: --- → FIXED
Target Milestone: --- → 4.6

Comment 6

13 years ago
Comment on attachment 176803 [details] [diff] [review]
fix proposal v1.1

There is no BeOS specific docs on readdir so it should behave the same as most
others, returning NULL if no more entries.
Attachment #176803 - Flags: superreview?(thesuckiestemail) → superreview+
(Assignee)

Comment 7

13 years ago
tqh: do you know whether readdir() sets the errno
when it encounters the end of the directory?  This
is what I really want to know.

Comment 8

13 years ago
Wrote a program which reports: "readdir returned NULL with following errno: 0 No
Error"

int main() {
	DIR * aDir = opendir("/boot/home/");
	if( aDir == NULL ) {
		cout << "opendir failed: " << errno << " " << strerror(errno) << endl;
		return 1;	
	}
	
	struct dirent * aDirEntry;
	do {
		aDirEntry = readdir( aDir );	
		if( aDirEntry == NULL ) break;
		cout << aDirEntry->d_name << endl;
	} while( true );
	cout << "readdir returned NULL with following errno: " << errno << " " <<
strerror(errno) << endl;
	closedir(aDir);
	return 0;
}


(Assignee)

Comment 9

13 years ago
Thank you, tqh.
You need to log in before you can comment on or make changes to this bug.