Spec::IO(3)

Title
DRAFT: Synopsis 16: IPC / IO / Signals

Version
 Author:        Largely, the authors of the related Perl 5 docs.
 Maintainer:    Larry Wall <larry@wall.org>
 Contributions: Mark Stosberg <mark@summersault.com>
 Date:          12 Sep 2006
 Last Modified: 1 May 2007
 Version:       17

This is a draft document. Many of these functions will work as in Perl 5, except we're trying to rationalize everything into packages. For now you can assume most of the important functions will automatically be in the * namespace. However, with IO operations in particular, many of them are really methods on an IO handle, and if there is a corresponding global function, it's merely an exported version of the method.

As a starting point, you can help by finding the official Perl 5 documentation for these functions and copying it here.

Filehandles, files, and directories

:X
    IO ~~ :X
    EXPR ~~ :X
          $file.:X
          $file ~~ :X

        A file test, where X is one of the letters listed below. This unary operator takes one argument, either a filename or a filehandle, and tests the associated file to see if something is true about it.

        A Pair used as a pattern is treated as a file test.

            :r  File is readable by effective uid/gid.
            :w  File is writable by effective uid/gid.
            :x  File is executable by effective uid/gid.
            :o  File is owned by effective uid.

            :R  File is readable by real uid/gid.
            :W  File is writable by real uid/gid.
            :X  File is executable by real uid/gid.
            :O  File is owned by real uid.

            :e  File exists.
            :z  File has zero size (is empty).
            :s  File has nonzero size (returns size in bytes).

            :f  File is a plain file.
            :d  File is a directory.
            :l  File is a symbolic link.
            :p  File is a named pipe (FIFO), or Filehandle is a pipe.
            :S  File is a socket.
            :b  File is a block special file.
            :c  File is a character special file.
            :t  Filehandle is opened to a tty.

            :u  File has setuid bit set.
            :g  File has setgid bit set.
            :k  File has sticky bit set.

            :T  File is an ASCII text file (heuristic guess).
            :B  File is a "binary" file (opposite of :T).

            :M  Script start time minus file modification time, in days.
            :A  Same for access time.
            :C  Same for inode change time (Unix, may differ for other platforms)

        The interpretation of the file permission operators ":r", ":R", ":w", ":W", ":x", and ":X" is by default based solely on the mode of the file and the uids and gids of the user. There may be other reasons you can't actually read, write, or execute the file. Such reasons may be for example network filesystem access controls, ACLs (access control lists), read-only filesystems, and unrecognized executable formats.

        Also note that, for the superuser on the local filesystems, the ":r", ":R", ":w", and ":W" tests always return 1, and ":x" and ":X" return 1 if any execute bit is set in the mode. Scripts run by the superuser may thus need to do a stat() to determine the actual mode of the file, or temporarily set their effective uid to something else.

        If you are using ACLs, there is a pragma called "filetest" that may produce more accurate results than the bare stat() mode bits. When under the "use filetest 'access'" the above-mentioned filetests will test whether the permission can (not) be granted using the access() family of system calls. Also note that the ":x" and ":X" may under this pragma return true even if there are no execute permission bits set (nor any extra execute permission ACLs). This strangeness is due to the underlying system calls' definitions. Read the documentation for the "filetest" pragma for more information.

        The ":T" and ":B" switches work as follows. The first block or so of the file is examined for odd characters such as strange control codes or characters with the high bit set. If too many strange characters (>30%) are found, it's a ":B" file; otherwise it's a ":T" file. Also, any file containing null in the first block is considered a binary file. If ":T" or ":B" is used on a filehandle, the current IO buffer is examined rather than the first block. Both ":T" and ":B" return true on a null file, or a file at EOF when testing a filehandle. Because you have to read a file to do the ":T" test, on most occasions you want to use a ":f" against the file first, as in "next unless $file ~~ :f && $file ~~ :T ".

        You can test multiple features using junctions:

          if -$filename ~~ :r & :w & :x  {...}

        Or pass multiple tests together in OO style:

          if $filename.TEST(:e,:x) {...}

    chown
            our Int multi chown ($uid = -1, $gid = -1, *@files)

        Changes the owner (and group) of a list of files. The first two elements of the list must be the numeric uid and gid, in that order. A value of -1 in either position is interpreted by most systems to leave that value unchanged. Returns the number of files successfully changed.

            $count = chown $uid, $gid, ’foo’, ’bar’;
            chown $uid, $gid, @filenames;

        On systems that support "fchown", you might pass file handles among the files. On systems that don’t support "fchown", passing file handles produces a fatal error at run time.

        Here’s an example that looks up nonnumeric uids in the passwd file:

           $user = prompt "User: ";
           $pattern = prompt "Files: ";

           ($login,$pass,$uid,$gid) = getpwnam($user)
               or die "$user not in passwd file";

           @ary = glob($pattern);      # expand filenames
           chown $uid, $gid, @ary;

        On most systems, you are not allowed to change the ownership of the file unless you’re the superuser, although you should be able to change the group to any of your secondary groups. On insecure systems, these restrictions may be relaxed, but this is not a portable assumption. On POSIX systems, you can detect this condition this way:

            use POSIX qw(sysconf _PC_CHOWN_RESTRICTED);
            $can_chown_giveaway = not sysconf(_PC_CHOWN_RESTRICTED);

    chmod LIST
        Changes the permissions of a list of files. The first element of the list must be the numerical mode, which should probably be an octal number, and which definitely should not be a string of octal digits: "0o644" is okay, 0644 is not. Returns the number of files successfully changed.

            $cnt = chmod 0o755, 'foo', 'bar';
            chmod 0o755, @executables;
            $mode = '0644'; chmod $mode, 'foo';      # !!! sets mode to --w----r-T
            $mode = '0o644'; chmod $mode, 'foo';     # this is better
            $mode = 0o644;   chmod $mode, 'foo';     # this is best

    close IO
    IO.close
        Closes the file or pipe associated with the file handle, returning true only if IO buffers are successfully flushed and closes the system file descriptor. Closes the currently selected filehandle if the argument is omitted.

        You don't have to close IO if you are immediately going to do another "open" on it, because "open" will close it for you. (See "open".) However, an explicit "close" on an input file resets the line counter ($.), while the implicit close done by "open" does not.

        If the file handle came from a piped open, "close" will additionally return false if one of the other system calls involved fails, or if the program exits with non-zero status. (If the only problem was that the program exited non-zero, $! will be set to 0.) Closing a pipe also waits for the process executing on the pipe to complete, in case you want to look at the output of the pipe afterwards, and implicitly puts the exit status value of that command into $!.

    connect
         my $fh = connect($hostname, 80);

        Attempts to connect to a remote host and returns an IO handle if successful. The call fails with an exception if it cannot connect.

    IO.fcntl
        Available only as a handle method.

    glob
    IO.ioctl
        Available only as a handle method.

    link
    IO.listen
        Available only as a handle method.

    lstat
        Returns a stat buffer. If the lstat succeeds, the stat buffer evaluates to true, and additional file tests may be performed on the value. If the stat fails, all subsequent tests on the stat buffer also evaluate to false.

    mkdir
    IO.name
        The ".name" method returns the name of the file/socket/uri the handle was opened with, if known. Returns undef otherwise. There is no corresponding "name()" function.

    open
            # Read
            my $fh = open($filename);

            # Write
            my $fh = open($filename, :w);

    IO.fdopen
            our IO method fdopen(Int $fd)

        Associate an IO object with an already-open file descriptor, presumably passed in from the parent process.

    IO::Dir::open EXPR
          my $dir = IO::Dir::open('.');

        Opens a directory named EXPR for processing. Makes the directory looks like a list of autochomped lines, so just use ordinary IO operators after the open.

    readlink
    rename
    rmdir FILENAME
    rmdir
        Deletes the directory specified by FILENAME if that directory is empty. If it succeeds it returns true, otherwise it returns false and sets $! (errno). If FILENAME is omitted, uses $_.

    stat
    IO.stat
        Returns a stat buffer. If the lstat succeeds, the stat buffer evaluates to true, and additional file tests may be performed on the value. If the stat fails, all subsequent tests on the stat buffer also evaluate to false.

    symlink
    syscall
    sysopen
    umask
    unlink LIST
    unlink
        Deletes a list of files. Returns the number of files successfully deleted.

            $cnt = unlink 'a', 'b', 'c';

        Be warned that unlinking a directory can inflict damage on your filesystem. Finally, using "unlink" on directories is not supported on many operating systems. Use "rmdir" instead.

        It is an error to use bare "unlink" without arguments.

    utime

Input and Output
getc
        our Bool method getc (IO $self: *@LIST)

    Returns the next character from the input stream attached to IO, or the undefined value at end of file, or if there was an error (in the latter case $! is set).

print
        our Bool method print (IO $self: *@LIST)
        our Bool multi print (*@LIST)
        our Bool method print (Str $self: IO $io)

    Prints a string or a list of strings. Returns Bool::True if successful, Failure otherwise. The IO handle, if supplied, must be an object that supports I/O. Indirect objects in Perl 6 must always be followed by a colon, and any indirect object more complicated than a variable should be put into parentheses.

    If IO is omitted, prints to $*DEFOUT, which is aliased to $*OUT when the program starts but may be temporarily or permanently rebound to some other file handle. The form with leading dot prints $_ to $*DEFOUT unless an explicit filehandle is supplied.

    It is a compiler error to use a bare "print" without arguments. (However, it's fine if you have an explicit argument list that evaluates to the empty list at runtime.)

    There is are no variables corresponding to Perl 5's $, and "$\" variables. Use "join" to interpose separators; use filehandle properties to change line endings.

say
        our Bool method say (IO $self: *@LIST)
        our Bool multi say (*@LIST)
        our Bool method say (Str $self: IO $io)

    This is identical to print() except that it auto-appends a newline after the final argument.

        Was:    print "Hello, world!\n";
        Now:    say   "Hello, world!";

    As with "print", it is a compiler error to use a bare "say" without arguments.

printf
        our Bool method printf (IO $self: Str $fmt, *@LIST)
        our Bool multi printf (Str $fmt, *@LIST)

    The function form works as in Perl 5 and always prints to $*DEFOUT. The method form uses IO handles as objects, not formats.

Unfiled

IO.fileno
IO.flock
IO.getpeername
IO.eof
IO.accept
/[get|set][host|net|proto|serv|sock].*/
alarm
IO.bind
IO.binmode
IO.lines
        our List multi method lines (IO $handle:) is export;
        our List multi lines (Str $filename);

    Returns all the lines of a file as a (lazy) List regardless of context. See also "slurp".

pipe
    Gone, see Pipe.pair

prompt
        our Str prompt (Str $prompt)

IO.read
IO.readline
Str.readpipe
IO.recv
IO.seek
select(both)
    Gone. (Note: for subsecond sleep, just use sleep with a fractional argument.)

IO.send
IO.setsockopt
IO.shutdown
IO.slurp
        our Item multi method slurp (IO $handle: *%opts) is export;
        our Item multi slurp (Str $filename, *%opts);

    Slurps the entire file into a Str or Buf regardless of context. (See also "lines".) Whether a Str or Buf is returned depends on the options.

socket
socketpair
    Gone, see Socket.pair

IO.sysread
IO.sysseek
IO.syswrite
IO.tell
IO.truncate
warn LIST
Str.warn
    Prints a warning just like Perl 5, except that it is always sent to the object in $*DEFERR, which is just standard error ($*ERR).

Pipe.to
        our IO method to(Str $command, *%opts)

    Opens a one-way pipe writing to $command. IO redirection for stderr is specified with :err(IO) or :err<Str>. Other IO redirection is done with feed operators. XXX how to specify "2>&1"?

Pipe.from
        our IO method from(Str $command, *%opts)

    Opens a one-way pipe reading from $command. IO redirection for stderr is specified with :err(IO) or :err<Str>. Other IO redirection is done with feed operators. XXX how to specify "2>&1"?

Pipe.pair
        our List of IO method pair()

    A wrapper for pipe(2), returns a pair of IO objects representing the reader and writer ends of the pipe.

       ($r, $w) = Pipe.pair;

Socket.pair
        our List of IO method pair(Int $domain, Int $type, Int $protocol)

    A wrapper for socketpair(2), returns a pair of IO objects representing the reader and writer ends of the socket.

       use Socket;
       ($r, $w) = Socket.pair(AF_UNIX, SOCK_STREAM, PF_UNSPEC);

Additions
Please post errors and feedback to perl6-language. If you are making a general laundry list, please separate messages by topic.