tfoertsch has asked for the wisdom of the Perl Monks concerning the following question:

I have an open file descriptor, say 8, and access mode bits, say O_RDONLY at C-level. And I want to convert them into a perl filehandle. How to do this in XS?

Thanks,
Torsten

  • Comment on How to convert a file descriptor plus access mode bits into a perl filehandle?

Replies are listed 'Best First'.
Re: How to convert a file descriptor plus access mode bits into a perl filehandle?
by ikegami (Patriarch) on Sep 10, 2008 at 16:06 UTC

    Don't know about XS, but in Perl,

    open(my $fh, '<&=', $fd) or die($!);

    open

      I think, this is a more exact solution in perl:
      sub open_fd { my ($fd, $flags)=@_; use Fcntl qw/O_APPEND O_RDONLY O_WRONLY O_RDWR O_ACCMODE/; use POSIX (); use IO::Handle (); if( ($flags & O_ACCMODE) == O_RDONLY ) { $flags='<'; } elsif( ($flags & O_ACCMODE) == O_WRONLY ) { if( $flags & O_APPEND ) { $flags='>>'; } else { $flags='>'; } } elsif( ($flags & O_ACCMODE) == O_RDWR ) { if( $flags & O_APPEND ) { $flags='+>>'; } else { $flags='+>'; } } else { POSIX::close($fd); return undef; } return IO::Handle->new_from_fd($fd, $flags); }
      How about the equivalent XS?

        Three notes.

        • Using IO::Handle is a step backwards. There's definitely no equivalent to IO::Handle in XS. You'd have to call the Perl method from C if that's what you wanted to use it. Fortunately, new_from_fd just ends up calling open, so there's no need to involve IO::Handle.

        • POSIX::close($fd); is really misplaced. It doesn't belong there at all.

        • In fact, it works out better if you convert the mode from the O_ constants to a Perl mode in a separate function.

        So here's what we have in C-ish Perl:

        use Fcntl qw( O_APPEND O_RDONLY O_WRONLY O_RDWR O_ACCMODE ); sub file_mode_from_c { my ($c_mode) = @_; $c_mode &= O_ACCMODE | O_APPEND; my $p_mode; if ( $c_mode == O_RDONLY ) { $p_mode = '<'; } elsif ( $c_mode == O_WRONLY ) { $p_mode = '>'; } elsif ( $c_mode == (O_WRONLY|O_APPEND) ) { $p_mode = '>>'; } elsif ( $c_mode == O_RDWR ) { $p_mode = '+>'; } elsif ( $c_mode == (O_RDWR|O_APPEND) ) { $p_mode = '+>>'; } return $p_mode; } my $p_mode = file_mode_from_c($c_mode) or die("..."); open(my $fh, "$p_mode=", $fd) or die("...: $!");

        So again, all you need to know is how to call open. I don't know the XS equivalent of open though. (Upd: Looks like PerlIO *PerlIO_fdopen(int fd, const char *mode);, thanks to Anonymous Monk's link to perlapio )

Re: How to convert a file descriptor plus access mode bits into a perl filehandle?
by Anonymous Monk on Sep 11, 2008 at 08:30 UTC