Re: -e " " returns true
by BrowserUk (Patriarch) on Jul 05, 2004 at 17:18 UTC
|
Seems to be a long standing bug with Win32 perl. I get the same results going back to 5.6.1 and also with 5.8.4.
I suggest you perlbug it.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
| [reply] |
|
I found a 1996 article in "Microsoft Systems Journal" which indicates that Win32 does some very odd things with filenames with spaces in them.
| [reply] |
|
On this occasion, it appears that the problem is internal to Perl--with caveats.
The problem occurs in these two lines from win32\win32.c (line numbers are approximate (5.8.4) because I've added debug code):
1222: pwbuffer = PerlDir_mapW(wbuffer);
...
1228: path = PerlDir_mapA(path);
Prior to these to lines the vars; path / wbuffer contain the bad paths being tested ( ' ', ' . . ' etc. ), but after they contain the fully expanded current working directory. They should not.
So, the problem is in the routines PerlDir_mapW() / PerlDir_mapA(). The stat being returned for non-existant directory paths is that of the current working directory.
But there, my trail grows cold. These functions are not functions, but #defines.
One path through the #defines in iperlsys.h has these resolved to:
#ifdef WIN32
#define PerlDir_mapA(dir) dir
#define PerlDir_mapW(dir) dir
#endif
But that can't be right because then they would be unchanged and the problem wouldn't occur.
The other branch of the #if defined(PERL_IMPLICIT_SYS) in iperlsys.h resolves them to entries in a vtable.
#ifdef WIN32
#define PerlDir_mapA(dir) \
(*PL_Dir->pMapPathA)(PL_Dir, (dir))
#define PerlDir_mapW(dir) \
(*PL_Dir->pMapPathW)(PL_Dir, (dir))
#endif
but search high'n'low, I cannot find out where these vtable entries are filled in?
It appears to be related to PL_curinterp and embedvar.h, but I tracked it back through about 6 levels of indirection before getting completely lost. It will take someone much cleverer than me to resolve this further.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
| [reply] [d/l] [select] |
|
To complete the picture, I finally tracked down the mysterious PerlDir_map(A|W) to win32\vdir.h. This appears to be a C++ Dir object class stolen from somewhere.
The MapPath(A|W) methods are very strange indeed. They eventually call GetFullPathName(A|W) to convert relative paths to absolute paths, but go through a heap of pre-conditioning of the input path before doing so. This pre-conditioning appears to be intended to work around bugs in that API that existed back then.
However, GetFullPathName still exibits some very peculiar bugs, including rendering various non-pathnames as the cwd as described earlier.
This problem is an accumulation of OS bugs, a couple of perl implementation fopars, and too many layers. It's gonna be a bitch to fix.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
| [reply] |
|
|
|
I found a 1996 article in "Microsoft Systems Journal" which indicates that Win32 does some very odd things with filenames with spaces in them.
This is no lie. I recommend against using any spaces
in filenames on any system (because, they don't gain
you anything underscores don't and they complicate
things such as the command line unnecessarily),
but _especially_ on Win32 (because the capability
is retrofitted and imperfect).
What gets especially icky is when you have spaces in
directory names. Lots of software, including some
Microsoft software and almost anything ported to
Windows from the POSIX world, fails in some fairly
weird ways in certain corner cases involving filenames
with spaces. Among other things, the association
mechanism in Explorer relies on the command line,
but the quoting capabilities there (_especially_ in
Win9x/Me) are sufficiently limited to create their
own edge cases, so that even if you set up the
association with quoted arguments there are still
things that can go wrong. The best practice is to
avoid putting spaces in any filenames or putting
any files in directories with spaces in them.
(On WinXP, it's okay to use your "My Documents"
folder, but I don't even recommend that on 9x/Me;
create your own C:\docs (or whatever) and use that,
and you'll have fewer problems.)
;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
| [reply] |
Re: -e " " returns true
by davorg (Chancellor) on Jul 05, 2004 at 15:50 UTC
|
$ cat test.pl
#!/usr/bin/perl
use strict;
use warnings;
my @files = (' ', ' . . ', ' .. ', ' ', ' . ');
foreach (@files) {
print "[$_] - ", -e $_ ? "yes\n" : "no\n";
}
$ ./test.pl
[ ] - no
[ . . ] - no
[ .. ] - no
[ ] - no
[ . ] - no
$ perl -v
This is perl, v5.8.3 built for i386-linux-thread-multi
--
< http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [d/l] |
|
ActivePerl Build 809
v5.8.3 built for MSWin32-x86-multi-thread
#!/usr/bin/perl
use strict;
use warnings;
my @files = (' ', ' . . ', ' .. ', ' ', ' . ');
foreach (@files) {
print "[$_] - ", -e $_ ? "yes\n" : "no\n";
}
__END__
[ ] - yes
[ . . ] - yes
[ .. ] - yes
[ ] - yes
[ . ] - yes
| [reply] [d/l] |
|
This is one of the times I really wish I was still on Linux.
Thanks for trying as well and all those fast replies.
Hans
| [reply] |
|
|
|
| [reply] |
|
Using davorg's script I had 5 yes's.
I have the same setup as PerlingTheUK.
wfsp
| [reply] |
Re: -e " " returns true
by pbeckingham (Parson) on Jul 05, 2004 at 15:48 UTC
|
I get differing results - the following prints nothing on Panther, Perl 5.8.1:
#! /usr/bin/perl -w
use strict;
print "File exists.\n" if -e ' ';
print "File exists.\n" if -e ' . . ';
print "File exists.\n" if -e ' .. ';
print "File exists.\n" if -e ' ';
print "File exists.\n" if -e '. ';
Update: Clarified code.
| [reply] [d/l] |
Re: -e " " returns true
by traveler (Parson) on Jul 05, 2004 at 22:13 UTC
|
I am pretty sure I learned this here, but I cannot find it with SS. Any combination of "." and " " returns true for -e on Windows. Even dir .. . gives a directory listing of the current directory (although dir ...... does not while dir . . . . . produces multiple listings of the current directory, but dir ". . . . ." doesn't). I thought someone here posted the reason, but I cannot find it.
--traveler | [reply] [d/l] [select] |
Re: -e " " returns true (perlbug 30622)
by demerphq (Chancellor) on Jul 07, 2004 at 20:32 UTC
|
| [reply] |