Determine read/write status of filehandles connected to memory objects.

Discussion in 'Perl Misc' started by Sisyphus, Mar 16, 2006.

  1. Sisyphus

    Sisyphus Guest

    Hi,

    On unix, with filehandles connected to normal files, we can query the
    read/write status of the filehandle by examining the return value of the
    fcntl() function:

    use Fcntl;
    # some code that creates the open $filehandle.
    my $fmode = fcntl($filehandle, F_GETFL, my $slush = 0);

    The value of $fmode will allow us to determine whether the filehandle is
    readonly, writeonly, or readable/writable.

    But with perl 5.8, it's possible to create filehandles connected to memory
    objects:

    use warnings;
    use strict;

    my ($fh1, $fh2, $var1, $var2);
    open $fh1, '>', \$var1 or die $!;
    print $fh1 "hello"; # $var1 contains "hello"

    open $fh2, '<', \$var1 or die $!;
    $var2 = <$fh2>; # $var2 contains "hello";

    close $fh1 or die $!;
    close $fh2 or die $!;

    print $var1, " ", $var2, "\n"; # prints "hello hello"
    __END__

    But now the fcntl() function is unable to provide information that I can use
    to determine the read/write status of $fh1and $fh2.
    For both $fh1 and $fh2 the fcntl() function will return undef - and fileno()
    will return -1.

    The question:
    How can I determine the read/write status of an open filehandle that's
    connected to a memory object ?

    Cheers,
    Rob
     
    Sisyphus, Mar 16, 2006
    #1
    1. Advertising

  2. Sisyphus

    Anno Siegel Guest

    Sisyphus <> wrote in comp.lang.perl.misc:
    > Hi,
    >
    > On unix, with filehandles connected to normal files, we can query the
    > read/write status of the filehandle by examining the return value of the
    > fcntl() function:
    >
    > use Fcntl;
    > # some code that creates the open $filehandle.
    > my $fmode = fcntl($filehandle, F_GETFL, my $slush = 0);
    >
    > The value of $fmode will allow us to determine whether the filehandle is
    > readonly, writeonly, or readable/writable.
    >
    > But with perl 5.8, it's possible to create filehandles connected to memory
    > objects:
    >
    > use warnings;
    > use strict;
    >
    > my ($fh1, $fh2, $var1, $var2);
    > open $fh1, '>', \$var1 or die $!;
    > print $fh1 "hello"; # $var1 contains "hello"
    >
    > open $fh2, '<', \$var1 or die $!;
    > $var2 = <$fh2>; # $var2 contains "hello";
    >
    > close $fh1 or die $!;
    > close $fh2 or die $!;
    >
    > print $var1, " ", $var2, "\n"; # prints "hello hello"
    > __END__
    >
    > But now the fcntl() function is unable to provide information that I can use
    > to determine the read/write status of $fh1and $fh2.
    > For both $fh1 and $fh2 the fcntl() function will return undef - and fileno()
    > will return -1.
    >
    > The question:
    > How can I determine the read/write status of an open filehandle that's
    > connected to a memory object ?


    I don't know of a built-in method. You can attempt to write an empty
    string to the filehandle and catch the warning if it fails:

    sub can_write {
    my $fh = shift;
    eval {
    use warnings FATAL => 'io';
    print $fh '';
    };
    not $@;
    }

    Alternatively one could try to use 4-arg select().

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Mar 16, 2006
    #2
    1. Advertising

  3. Sisyphus

    Sisyphus Guest

    "Anno Siegel" wrote
    ..
    ..
    >
    > I don't know of a built-in method. You can attempt to write an empty
    > string to the filehandle and catch the warning if it fails:
    >
    > sub can_write {
    > my $fh = shift;
    > eval {
    > use warnings FATAL => 'io';
    > print $fh '';
    > };
    > not $@;
    > }
    >


    Any script containing that subroutine that was run on pre-5.6 perl would, I
    believe, fail to compile - even if can_write() was never going to be called
    unless $] >= 5.008. (I know this shouldn't be a consideration, but I was
    hoping to do it in a way that wouldn't break pre-5.6 perls, if possible.) Is
    there perhaps a workaround to "use warnings FATAL => 'io';" involving
    'require warnings;' (and perhaps also 'import') ? I couldn't produce an
    incantation that worked.

    > Alternatively one could try to use 4-arg select().
    >


    Yes - otherwise this looks a possibility. Unfortunately, I find the 1-arg
    select() confusing enough. I'm not going to specifically request any help
    with potential code, as I haven't yet made a serious attempt to come to
    terms with the 4-arg version - but if someone likes to provide further
    hints/suggestions along those lines, then that's fine by me :)

    Thanks for your insight, Anno.

    Now ... back to 'perldoc -f select' ....

    Cheers,
    Rob
     
    Sisyphus, Mar 16, 2006
    #3
  4. Sisyphus

    Anno Siegel Guest

    Sisyphus <> wrote in comp.lang.perl.misc:
    >
    > "Anno Siegel" wrote
    > .
    > .
    > >
    > > I don't know of a built-in method. You can attempt to write an empty
    > > string to the filehandle and catch the warning if it fails:
    > >
    > > sub can_write {
    > > my $fh = shift;
    > > eval {
    > > use warnings FATAL => 'io';
    > > print $fh '';
    > > };
    > > not $@;
    > > }
    > >

    >
    > Any script containing that subroutine that was run on pre-5.6 perl would, I
    > believe, fail to compile - even if can_write() was never going to be called
    > unless $] >= 5.008. (I know this shouldn't be a consideration, but I was
    > hoping to do it in a way that wouldn't break pre-5.6 perls, if possible.) Is
    > there perhaps a workaround to "use warnings FATAL => 'io';" involving
    > 'require warnings;' (and perhaps also 'import') ? I couldn't produce an
    > incantation that worked.


    Use $SIG{ __WARN__} instead, that's been around forever.

    sub can_write {
    my $fh = shift;
    my $warned;
    local $SIG{ __WARN__} = sub { $warned ++ };
    print $fh '';
    return ! $warned;
    }

    A more specific test if the warning was indeed the text "Filehandle
    %s opened only for input" would be wise in both variants.

    > > Alternatively one could try to use 4-arg select().
    > >

    >
    > Yes - otherwise this looks a possibility. Unfortunately, I find the 1-arg
    > select() confusing enough. I'm not going to specifically request any help
    > with potential code, as I haven't yet made a serious attempt to come to
    > terms with the 4-arg version - but if someone likes to provide further
    > hints/suggestions along those lines, then that's fine by me :)


    Can't be done with select(). You'd need a file number for the handle
    you want to test, but fileno( $f) is -1 (invalid) if $f is a "stringy"
    filehandle.

    Anno

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Mar 16, 2006
    #4
  5. Sisyphus

    Sisyphus Guest

    "Anno Siegel" <-berlin.de> wrote in message n

    >
    > Use $SIG{ __WARN__} instead, that's been around forever.
    >
    > sub can_write {
    > my $fh = shift;
    > my $warned;
    > local $SIG{ __WARN__} = sub { $warned ++ };
    > print $fh '';
    > return ! $warned;
    > }
    >
    > A more specific test if the warning was indeed the text "Filehandle
    > %s opened only for input" would be wise in both variants.
    >
    > > > Alternatively one could try to use 4-arg select().

    ..
    ..
    >
    > Can't be done with select(). You'd need a file number for the handle
    > you want to test, but fileno( $f) is -1 (invalid) if $f is a "stringy"
    > filehandle.
    >


    Ok ... thanks again, Anno.

    Cheers,
    Rob
     
    Sisyphus, Mar 17, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. humbleaptience
    Replies:
    0
    Views:
    5,513
    humbleaptience
    Feb 22, 2006
  2. Dhruba Bandopadhyay
    Replies:
    0
    Views:
    5,249
    Dhruba Bandopadhyay
    May 12, 2006
  3. Sudhan
    Replies:
    1
    Views:
    661
  4. Replies:
    0
    Views:
    5,365
  5. Bernard Chan

    Perl 5.8.x, Unicode and In-memory Filehandles

    Bernard Chan, Mar 1, 2006, in forum: Perl Misc
    Replies:
    3
    Views:
    167
    Bernard Chan
    Mar 1, 2006
Loading...

Share This Page