=encoding utf8

=head1 NAME

POSIX::1003::FdIO - POSIX handling file descriptors

=head1 SYNOPSIS

  use POSIX::1003::FdIO;

  $fd = openfd($fn, O_RDWR);
  defined $fd or die $!;   # $fd==0 is valid value! (STDIN)

  $fd = openfd($fn, O_WRONLY|O_TRUNC);
  $fd = openfd($fn, O_CREAT|O_WRONLY, 0640);

  my $buf;
  $bytes_read    = readfd($fd, $buf, BUFSIZ);
  $bytes_written = writefd($fd, $buf, 5);

  $off_t = seekfd($fd, 0, SEEK_SET);  # rewind!
  $fd2   = dupfd($fd);

  closefd($fd) or die $!;

  my ($r, $w) = pipefd();
  writefd($w, "hello", 5);
  readfd($r, $buf, 5);
  closefd($r) && closefd($w) or die $!;

  my $fh = fdopen($fd, 'w') or die $!;

=head1 DESCRIPTION

Most people believe that the C<sys*> commands in Perl Core are not
capable of doing unbuffered IO. For those people, we have this module.
But there is more in file-descriptor space, missing from Core.

The question whether C<sysread()> or L<readfd()|POSIX::1003::FdIO/"Standard POSIX"> is meassurable faster
cannot be answered.

The C<fcntl()> command has its separate module L<POSIX::1003::Fcntl|POSIX::1003::Fcntl>.
Locking functions are locate there as well, because they are often
implemented via C<fcntl>.

=head1 FUNCTIONS

=head2 Overview

Perl defaults to use file-handles, avoiding file descriptors. For
that reason, the C<fread> of POSIX is the C<read> of Perl; that's
confusing.  But the POSIX standard is confused as well: some function
names which start with an C<f> are actually for file-descriptors, other
for file-handles!

The POSIX module, distributed with Perl, makes you write C<CORE::read()>
and C<POSIX::read()> explicitly. However, C<POSIX::read()> is the same
as C<CORE::sysread()>!

To avoid conflicts with function names in Perl core, and the confusion
that the POSIX created, all exported function names provided by this
module contain 'fd' in their name.

    POSIX    Perl-Core POSIX.pm  POSIX::1003::FdIO
 FH fseek     seek
 FD lseek     sysseek   lseek    seekfd
 FH fopen     open
 FD open      sysopen            openfd   # sysopen is clumpsy
 FD fdopen    open               fdopen   # IO::Handle->new_from_fd
 FH fclose    close
 FD close     close     close    closefd
 FH fread     read
 FD read      sysread   read     readfd
 FH fwrite    print
 FD write     syswrite  write    writefd
 FH           pipe,open                   # buffered unless $|=0
 FD pipe                pipe     pipefd
 FH stat      stat
 FD fstat               fstat    statfd
 FN lstat     lstat
 FH ftell     tell
 FD                              tellfd   # tell on fd not in POSIX
 FH rewind              rewind
 FD                              rewindfd # rewind on fd not in POSIX
 FD creat               creat    creatfd
 FD dup                          dupfd
 FD fcntl     fcntl              (many)   # see ::Fcntl
 FD flock     flock              flockfd  # see ::Fcntl
 FD lockf                        lockf    # see ::Fcntl
 FN truncate  truncate
 FD ftruncate                    truncfd

Works on: FH=file handle, FD=file descriptor, FN=file name

=head2 Standard POSIX

=over 4

=item B<closefd>($fd)

Always check the return code: C<undef> on error, cause in C<$!>.
  closefd $fd or die $!;

There is no C<sysclose()> in core, because C<sysopen()> does unbuffered
IO via its perl-style file-handle: when you open with C<CORE::sysopen()>,
you must close with C<CORE::close()>.

=item B<creatfd>($filename, $mode)

Implemented via L<openfd()|POSIX::1003::FdIO/"Standard POSIX">, which is true by definition of POSIX.

=item B<dup2fd>($fd, $newfd)

Copy file-descriptor $fd to an explicit $newfd number. When already
in use, the file at $newfd will be closed first.  Returns undef on
failure.

=item B<dupfd>($fd)

Copy the file-descriptor $fd into the lowest-numbered unused descriptor.
The new fd is returned, undef on failure.

=item B<fdopen>($fd, $mode)

Converts a $fd into an (buffered) FH.  You probably want to set binmode
after this.  $mode can be Perl-like '<', '>', '>>', or POSIX standard
'r', 'w', 'a'.  POSIX modes 'r+', 'w+', and 'a+' can probably not be
supported.

=item B<openfd>($filename, $flags, $mode)

Returned is an integer file descriptor (FD).  Returns C<undef> on
failure (and '0' is a valid FD!)

$flags are composed from the C<O_*> constants defined by this module (import
tag C<:mode>) The $mode field combines C<S_I*> constants defined by
L<POSIX::1003::FS|POSIX::1003::FS> (import tag C<:stat>).

=item B<pipefd>()

Returns the reader and writer file descriptors.
See also L<POSIX::1003::Fcntl::setfd_pipe_size()|POSIX::1003::Fcntl/"Additional">

example: 

  my ($r, $w) = pipefd;
  writefd($w, "hello", 5 );
  readfd($r, $buf, 5 );

=item B<readfd>( $fd, SCALAR, [$length] )

Read the maximum of $length bytes from $fd into the SCALAR. Returned is
the actual number of bytes read.  The value C<-1> tells you there is
an error, reported in C<$!>

B<Be warned> that a returned value smaller than $length does not mean
that the $fd has nothing more to offer: the end is reached only when 0
(zero) is returned.  Therefore, this reading is quite inconvenient.
You may want to use POSIX::Util subroutine readfd_all

=item B<seekfd>($fd, $offset, $whence)

The $whence is a C<SEEK_*> constant.

=item B<statfd>($fd)

Request file administration information about an open file. It returns
the same list of values as C<stat> on filenames.

=item B<truncfd>( $fd, [$length] )

[0.96] Shorten the file to the $length (defaults to 0).  The file offset
(your pointer in the file) is not changed, so you may need to L<seekfd()|POSIX::1003::FdIO/"Standard POSIX">
as well.  Behavior is undefined when $length is larger than the file size.

The POSIX name for this function is C<ftruncate>.

=item B<writefd>( $fd, $bytes, [$length] )

Attempt to write the first $length bytes of STRING to $fd. Returned is
the number of bytes actually written.  You have an error only when C<-1>
is returned.

=back

=head2 Additional

Zillions of Perl programs reimplement these functions. Let's simplify
code.

=over 4

=item B<rewindfd>($fd)

Seek to the beginning of the file.

=item B<tellfd>($fd)

Reports the location in the file. This call does not exist (not in POSIX,
nor on other UNIXes), however is a logical counterpart of the C<tell()> on
filenames.

=back

=head1 CONSTANTS

The following constants are exported, shown here with the values
discovered during installation of this module.

=for comment
#TABLE_FDIO_START

The constant names for this fdio module are inserted here during
installation.

=for comment
#TABLE_FDIO_END

You can limit the import to the C<SEEK_*> constants by explicitly
using the C<:seek> import tag.  Use the C<:mode> for all C<O_*>
constants, to be used with L<openfd()|POSIX::1003::FdIO/"Standard POSIX">.

=head1 SEE ALSO

This module is part of POSIX-1003 distribution version 1.02,
built on November 10, 2020. Website: F<http://perl.overmeer.net/CPAN>.  The code is based on L<POSIX>, which
is released with Perl itself.  See also L<POSIX::Util> for
additional functionality.

=head1 COPYRIGHTS

Copyrights 2011-2020 on the perl code and the related documentation
 by [Mark Overmeer]. For other contributors see ChangeLog.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
See F<http://dev.perl.org/licenses/>

