A filename may be the name of a file that does not (yet) exist.
I've been sitting on this reply for a day or so trying to decide if it contributes anything. I can't make up my mind, so I'll let you dismiss it or not.
If the sole purpose of the module is to determine if a passed parameter is an IO handle, then why does it have is_filename()?
Surely all that is needed, at most is:
...
unless( is_filehandle( $arg ) {
open $arg, '...', $arg or die $!;
}
...
And what does is_filename() mean when it reports true? For example, will it consider fred"bill"smith as valid? Which it possibly is on *nix, but not on NTFS.
Now with respect to making the required determination of whether the passed parameter represents a "legitimate" IO target, you dismissed my earlier suggestion of using fileno because it didn't work for ram files (IO::Scalar & open $fh, '>', \$ramfile) , (and IO:All object, but I'll get back to that!).
Running it against a simplified version of your test suite confirms that is the only failure:
I was aware of this, but I also contend that it is a bug in the implementation of ramfiles.
Why should I not be able to duplicate a ramfile handle using open $dup, '&=', fileno( $ramfh ) ... as I can with any other filehandle?
And I suspect that limitation -- the failure of an IO object to respond to fileno in an appropriate and consistent way -- is the cause of the IO::All object failure also.
Whilst I believe that to be a bug that needs fixing, it is a legitimate position to take to say that your module -- with its mechanism that detects a ramfile handle (and I assume an IO::All object) as a suitable target for many IO operations -- fulfills a useful function, now, that is otherwise not easily available unless and until those IO-like thingies do respond to fileno correctly.
When this thread came up, I knew that I had solved this problem (for ramfiles) sometime in the past. I did do a search of my system and PM, but failed to find the code. This morning I got around to checking my backups from my previous system and found it. This is how I did it: #! perl -slw
package main;
use strict;
use FileHandle;
use IO::File;
use IO::Socket::INET;
sub ok{
my( $code, $wanted, $label, $value ) = @_;
my $bool = $code->( $value );
return $label . ':' . ( $bool == $wanted ? 'Ack' : 'Nak' );
}
sub isIO{
local $^W;
my $arg = shift;
my $p = eval{ tell( $arg ) };
return defined( $p ) && $p >=0 ? 1 : 0;
}
my @handles = (
[0, "1", 1],
[0, "hashref", {}],
[0, "arrayref", []],
[0, "globref", \*INC],
[1, "in-memory", do {{ my $buf; open my $fh, "<", \$buf; $fh }}]
+,
[1, "FH1 glob", do {{ open FH1, "<", "nul"; *FH1 }}],
[1, "FH2 globref", do {{ open FH2, "<", "nul"; \*FH2 }}],
[1, "FH3 string", do {{ no strict; $FH3 = 'nul'; open FH3; FH3 }}
+],
[1, "STDIN glob", \*STDIN],
[1, "STDOUT glob", \*STDOUT],
[1, "plain read", do {{ open my $fh, "<", "nul"; $fh }}],
[1, "plain write", do {{ open my $fh, ">", "nul"; $fh }}],
[1, "FH read", FileHandle->new("< nul")],
[1, "FH write", FileHandle->new("> nul")],
[1, "I::F read", IO::File->new("< nul")],
[1, "I::F write", IO::File->new("> nul")],
[1, "pipe read", do {{ open my $fh, "ver |"; $fh }}],
[1, "pipe write", do {{ open my $fh, "| more"; $fh }}],
[1, "socket", IO::Socket::INET->new(LocalAddr => sprintf('loc
+alhost:%d', 10000 + rand 20000))],
);
print ok( \&isIO, @$_ ) for @handles;
__END__
[ 6:39:21.75] C:\test>junk6
1:Ack
hashref:Ack
arrayref:Ack
globref:Ack
in-memory:Ack
FH1 glob:Ack
FH2 globref:Ack
FH3 string:Ack
STDIN glob:Ack
STDOUT glob:Ack
plain read:Ack
plain write:Ack
FH read:Ack
FH write:Ack
I::F read:Ack
I::F write:Ack
pipe read:Ack
pipe write:Ack
socket:Ack
I haven't tested it against IO:All as I don't use it, but maybe there is something there that is useful to you.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
|