in reply to Re: How to convert a file descriptor plus access mode bits into a perl filehandle?
in thread How to convert a file descriptor plus access mode bits into a perl filehandle?

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?
  • Comment on Re^2: How to convert a file descriptor plus access mode bits into a perl filehandle?
  • Download Code

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

    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 )