develooper Front page | perl.perl5.porters | Postings from December 2009

[perl #71714] Fw: PATCH remove redundant stat from Win32's opendir()

December 29, 2009 10:51
[perl #71714] Fw: PATCH remove redundant stat from Win32's opendir()
Message ID:
# New Ticket Created by 
# Please include the string:  [perl #71714]
# in the subject line of all future correspondence about this issue. 
# <URL: >

This is a bug report for perl from alex@AMELIE,
generated with the help of perlbug 1.36 running under perl 5.10.0.

[Please enter your report here]

Resubmitting patches to perlbug as per Jesse's request.

>From: <>
>To: <>
>Sent: Tuesday, December 15, 2009 9:52 PM
>Subject: PATCH remove redundant stat from Win32's opendir()

> Hey All,
> Here's a patch that removes an unnecesary call to win32_stat() by
> the opendir code on Win32. This provides a noticeable speed up when
> recursively traversing a directory eg. calls to File::Find::find().
> Note it does change behaviour in the following cases:
> 1. The patch makes directory names longer than MAX_PATH fail and
> sets errno to ENAMETOOLONG ("Filename too long"). Currently, in
> this case errno is not actually set in win32_opendir. Consider:
>  c:\> perl -e "$!=0 ; opendir C, ('Q'x300) or die $!
>  Bad file descriptor at -e line 1.
>  c:\> perl -e "$!=11 ; opendir C, ('Q'x300) or die $!
>  Resource temporarily unavailable at -e line 1.
> Note that when $!=0, pp_open_dir() has to resort to setting errno
> to EBADF. This looks like an oversight in the original code as I
> doubt this was the intended error code in this case.
> 2. The patch makes a zero length directory name fail and sets errno
> to EINVAL. Currently "" is passed to win32_stat which happens to set
> errno to ENOENT (i guess that's consistent over all Windows versions).
> This looks like an oversight - why stat a filename that cannot possibly
> exist? ie. setting errno to ENOENT here seems accidental. EINVAL
> makes more sense. (I can't find a "Filename too short" error code ;-)
> In the above 2 cases, it's straightforward to change the patch code
> to maintain backward compatibility. I don't have any great
> attachment to changing the error codes and if someone wants to
> argue for backwards compatibility i'll not haggle.
> Probably of more interest is...
> 3. If the directory is actually a regular file then currently errno
> is not set, and so (as in case 1) errno ends up being set to EBADF.
> The patched version will 'fail' via the same code path as if it's
> just a non existant file/directory name (FindFirstFile will return
> ERROR_PATH_NOT_FOUND) and so errno gets set to ENOENT.
> In this case both error codes are plainly wrong: there's
> no file descriptor to be bad, and since it *is* a file it cannot
> be said to be "No such file or directory".
> Much better would be ENOTDIR ("Not a directory").
> [Changing the patched version to make a distinction between where the
> directory to be opened is neither-a-regular-file-nor-directory (ENOENT)
> and is is-not-a-directory-(because-it's-a-regular-file) (ENOTDIR) would
> require adding a stat in the ERROR_PATH_NOT_FOUND case.
> Or alternatively just use ENOTDIR for both cases - but this would
> expose a change in error code in the common case of
> neither-a-regular-file-nor-directory.]
> Cheers, alex.

[Please do not change anything below this line]
Site configuration information for perl 5.10.0:

Configured by adam at Mon Aug 11 04:41:10 2008.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
    osname=MSWin32, osvers=5.1, archname=MSWin32-x86-multi-thread
    hint=recommended, useposix=true, d_sigaction=undef
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
    cc='gcc', ccflags 
    optimize='-s -O2',
    ccversion='', gccversion='3.4.5', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='long long', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='g++', ldflags ='-s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\lib"'
    libs= -lmsvcrt -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 
 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32
    perllibs= -lmsvcrt -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 
 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32
    libc=-lmsvcrt, so=dll, useshrplib=true, libperl=libperl510.a
  Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-mdll -s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\lib"'

Locally applied patches:

@INC for perl 5.10.0:

Environment for perl 5.10.0:
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
Files\Microsoft SDK\Bin\.;C:\Program Files\Microsoft SDK\Bin\WinNT\.;C:\Program 
Files\Git\cmd;C:\Program Files\Microsoft Visual Studio\VC98\Bin;C:\Program Files\Microsoft 
SDK\Bin\.;C:\Program Files\Microsoft SDK\Bin\WinNT;C:\cygwin\bin
    PERL_BADLANG (unset)
    SHELL (unset) Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About