BrowserUk wrote:
In essence, what you are passing is not a filename (or a filehandle). If you remove the '<' and '>>', you'll then get the results you are hoping for.
I do understand what you are saying here. However, I'm not trying to have the file test succeed based on open's specical semantics, but rather I'm trying to _detect_ whether somebody else is trying to use open's 2 arg semantics with my module. I fully expect the file test to fail if somebody tries to use, for example, '>>testfile.log' as an argument to my module's 'new()' or 'open()' methods.
(Does that make sense?! :-) )
The use of '< file' in the two ar form of open is unique (and only applicable) to that call (open)...
This was my point! :-) As far as I knew, the only place where one was allowed to use the magic semantics of the first argument to 'open', is in the first argument to open!
However, for some weird reason, on Windows, a file test on '<testfile.log' (or '<<testfile.log', or even '<<<<<<<<testfile.log') returns true. However, I have just done some more digging, and I think it is a problem with Windows, rather than Perl.
C:\>perl -e "my $f=qq(<testfile.log); print ref($f); if (-f $f) { prin
+t qq(AS thinks this is a file\n); }"
AS thinks this is a file
C:\>dir "<testfile.log"
Volume in drive C has no label.
Volume Serial Number is D0C3-B79D
Directory of C:\
19/09/2003 15:03 0 testfile.log
1 File(s) 0 bytes
0 Dir(s) 1,764,376,576 bytes free
C:\>dir "<<testfile.log"
Volume in drive C has no label.
Volume Serial Number is D0C3-B79D
Directory of C:\
19/09/2003 15:03 0 testfile.log
1 File(s) 0 bytes
0 Dir(s) 1,764,376,576 bytes free
C:\>dir "<<<<<<<<<testfile.log"
Volume in drive C has no label.
Volume Serial Number is D0C3-B79D
Directory of C:\
19/09/2003 15:03 0 testfile.log
1 File(s) 0 bytes
0 Dir(s) 1,764,376,576 bytes free
Looks like this may just be another Microsoft "feature". How helpful of them! ;-)
Cheers, -- Dave :-)
$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
| [reply] [d/l] |
Update: FWIW, this "undocumented feature" is deep within the OS, using '<' in the argument to FindFirstFile/FindNextFile apis also treats it the same way as '*'. It appears that this is the only undocumented character that exhibits this behaviour. Weirdness indeed.
What can I say? Sorry, but I completely misread the sense of your constanation. Your right! It appears that CMD is treating '<' in the same way as '*'
P:\test>dir "<.bak"
Volume in drive P is Winnt
Volume Serial Number is D822-5AE5
Directory of P:\test
27/08/03 00:47 608 286744.pl8.bak
28/08/03 20:20 801 287272.pl8.bak
31/08/03 12:42 729 287900-2.pl8.bak
31/08/03 09:58 1,056 287900.pl8.bak
05/09/03 15:37 2,015 289016-2.pl8.bak
05/09/03 09:56 1,092 289106.pl8.bak
05/09/03 17:26 1,165 289250.pl8.bak
08/09/03 10:49 742 b-sort.pl8.bak
...
I'm really surprised that I have never encountered this behaviour before...but then, I would never have thought to look for it:)
It is weird, as far as I am aware, completely undocumented, and very annoying. I cannot even begin to fathom how and why this would have been done!
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.
| [reply] [d/l] |
open FILE, ">testfile.log" or die "Unable to create file: $!";
close FILE;
if (! -f "*estfile.log") {
print STDERR "Not a file *.\n";
}
if (! -f "|testfile.log") {
print STDERR "Not a file |.\n";
}
if (! -f "?estfile.log") {
print STDERR "Not a file ?.\n";
}
if (! -f "<testfile.log") {
print STDERR "Not a file <.\n";
}
if (! -f ">>testfile.log") {
print STDERR "Not a file >>.\n";
}
exit;
__END__
Not a file *.
Not a file |.
Not a file ?.
Not a file >>.
What I don't understand is why this is effectively performing a directory search in order to test one filename! Does Windows not have the equivalent of the Unix stat() system call? The -f operator should just be calling the perl stat function. Does anyone with a better understanding of Win32 Perl than I understand what is happening here?
(Should I fall back to matching the filename with a regex?)
Cheers, -- Dave :-)
$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
| [reply] [d/l] |
I see the same results using CMD.exe, but not using 4NT.exe shell. So it's not part of FindFirst/FindNext OS calls, but something in the shell.
Hmm, maybe 4NT does its own wildcard matching. But, I note that the driver level calls (through filemon) is only getting one call to DIRECTORY when I dir <.exe, even though it passed *.exe to the DIRECTORY call. Yet when doing a dir *.exe, it gets several calls to DIRECTORY before the last returns NO MORE FILES.
| [reply] |
Browser I dont have a wintel box handy right now, can you try this:
C:
cd c:\
dir "<c:\test\.bak"
my gut fealling tells me that what you are really doing is echoing a list of .bak extention filenames to dir. just like the shorthand for dir *.bak (dir .bak) does in many versions of dos.
-Waswas | [reply] [d/l] |
Why not just untaint the filename you are getting if you consider << >> < > tainted input?
-Waswas
| [reply] |
Ah, thinking around the problem: that's more like it!
What would you recommend I use to untaint the data in a portable way? I would expect to miss a lot of cases if I used a regular expression to do the job; that was why I tried to use a file test in the first place. My intention is not to be "too" restrictive in how my module is used (though the specification is not that clearly defined yet i.e. I'm making it up as I go ;-)).
Cheers, -- Dave :-)
$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print
| [reply] |