File Handling
pkg std =
type dir
type diriter
/* well-known file descriptors */
const In
const Out
const Err
/* seek options */
const Seekset : whence
const Seekcur : whence
const Seekend : whence
/* open options */
const Oread : fdopt
const Owrite : fdopt
const Ordwr : fdopt
const Otrunc : fdopt
const Ocreat : fdopt
const Ocexec : fdopt
const Oappend : fdopt
const Odir : fdopt
/* directory handling */
const byentry : (d : dir# -> diriter)
const diropen : (p : byte[:] -> std.result(dir#, byte[:]))
const dirread : (d : dir# -> std.option(byte[:]))
const dirclose : (d : dir# -> void)
const dirname : (p : byte[:] -> byte[:])
const mkdir : (path : byte[:], mode : int64 -> int64)
const mkpath : (p : byte[:] -> bool)
const chdir : (path : byte[:] -> bool)
/* file handling */
const open : (path : byte[:], opts : fdopt -> std.result(fd, errno))
const openmode : (path : byte[:], opts : fdopt, mode : int64 -> std.result(fd, errno))
const mktemp : (base : byte[:], opts : fdopt, mode : int64 -> std.result((fd, byte[:]), errno)
const mkdtemp : (base : byte[:], mode : int64 -> std.result(byte[:], errno)
const close : (fd : fd -> int64)
const creat : (path : byte[:], mode : int64 -> fd)
const read : (fd : fd, buf : byte[:] -> std.result(size, errno))
const pread : (fd : fd, buf : byte[:], off : off -> std.result(size, errno))
const readall : (fd : fd, buf : byte[:] -> std.result(size, errno))
const write : (fd : fd, buf : byte[:] -> std.result(size, errno))
const pwrite : (fd : fd, buf : byte[:], off : off -> std.result(size, errno))
const writeall : (fd : fd, buf : byte[:] -> std.result(size, errno))
const seek : (fd : fd, delta : off, whence : whence -> off)
const pipe : (fds : fd[2]# -> int64)
const dup2 : (ofd : fd, nfd : fd -> fd)
const remove : (path : byte[:] -> bool)
const unlink : (path : byte[:] -> int)
/* path manipulation */
const basename : (p : byte[:] -> byte[:])
const pathcat : (a : byte[:], b : byte[:] -> byte[:])
const pathjoin : (p : byte[:][:] -> byte[:])
const pathnorm : (p : byte[:] -> byte[:])
const getcwd : (-> byte[:])
/* file properties */
const fmtime : (f : byte[:] -> result(time, errno))
const fsize : (f : byte[:] -> result(off, errno))
const fexists : (f : byte[:] -> bool)
const fisdir : (f : byte[:] -> bool)
/* convenience functions */
const slurp : (path : byte[:] -> result(byte[:], byte[:]))
const fslurp : (path : fd -> result(byte[:], byte[:]))
const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool)
const fblat : (f : fd, buf : byte[:] -> bool)
;;
Data Types and Constants
Libstd's file APIs are generally relatively thin wrappers around the host OS functions. They are a portable subset of this functionality, designed for both ease of use and portability.
type dir = struct
;;
The directory struct represents the current state of a directory walk.
/* seek options */
const Seekset : whence
const Seekcur : whence
const Seekend : whence
These are a set of values which describe from where to seek within the file.
/* open options */
const Ordonly : fdopt
const Owronly : fdopt
const Ordwr : fdopt
const Otrunc : fdopt
const Ocreat : fdopt
These are a set of options that are passed to the open variants describing what mode to open the file in. These are bit masks which be OR'ed together to combine them.
Ordonly
and Owronly
request permission to read and write the file,
respectively. Ordwr
requests both read and write permissions. Otrunc
indicates that the file should be truncated to zero bytes in length before it
is opened. Ocreat
indicates that the file should be created if it does not
exist instead of returning an error. Odir
indicates that this file should
be opened as a directory.
Ocreat
does not create the path leading to it, and will return an error if
that path does not exist.
/* constants */
const In
const Out
const Err
The constants In
, Out
, and Err
respectively are defined to the system
stdin, stdout, and stderr file descriptors.
Directories
const diropen : (p : byte[:] -> std.result(dir#, byte[:]))
The diropen
function opens a path as a directory, and returns a pointer
to an object which tracks the state of the directory, allowing for reading
file names one by one from this directory.
Returns: Either a directory wrapped up in the `Ok
branch of the result,
or a string describing the failure reason in the `Err
branch.
const dirread : (d : dir# -> std.option(byte[:]))
The dirread
reads a single entry from the directory, opened with diropen
,
returning it as a string. The returned string must be freed by the caller.
Returns `Some entry
, or `None
at the end of the directory.
const dirclose : (d : dir# -> void)
dirclose
closes a directory for reading. This frees all associated
resources, returning them to the system. The directory passed in must have
been opened with diropen
.
Returns: Nothing.
const mkdir : (path : byte[:], mode : int64 -> errno)
mkdir
creates the directory specified in path
. with the mode mode
. It
requires the parent directory to exist and be writable. Absolute paths will
be created relative to the root of the file system, and relative paths will
be created relative to the current working directory, as usual.
If the directory already exists, this is counted as a failure to create the directory.
Returns: Enone on success, or the error that caused the failure if it fails.
const mkpath : (path : byte[:] -> errno)
mkpath
creates a full path specified by path
. It creates all of the
path components required to create the full path specified. It requires
the parent of the first directory entry that is not currently in existence
to be writable.
Absolute paths will be created relative to the root of the file system, and relative paths will be created relative to the current working directory, as usual.
Returns: Enone on success, or the error that caused the directory creation to fail on failure.
const chdir : (path : byte[:] -> bool)
Chdir changes the current working directory to the path specified in path
.
Returns True on success, false on failure.
const byentry : (d : dir# -> diriter)
Returns a directory iterator that can be used in a for loop.
Files
const open : (path : byte[:], opts : fdopt -> result(fd, errno))
const openmode : (path : byte[:], opts : fdopt, mode : int64 -> result(fd, errno))
Open opens the file path
for I/O according to the flags reqeusted in opts
,
and returns a result containing the file descriptor or error. The mode is a
combination of the modes specified above: Ordonly
, Owronly
, Ordwr
,
Otrunc
, or Ocreat
.
Openmode is similar to open, however, if Ocreate is passed, it the file requested will be created with the permissions passed in.
Returns: either a valid file descriptor on success, or an error describing why the open failed on failure.
const mktemp : (base : byte[:], opts : fdopt, mode : int64 -> std.result((fd, byte[:]), errno)
Mktemp is similar to openmode, however instead of taking a full path as
its first argument, it generates a unique name for a file in temporary
storage by appending a random string to the base name base
. The mode
provided is in addition to the implicit Ocreat | Oexcl.
Returns: Either a successful result containing the tuple of file descriptor
opened and path generated, or an error describing the failure. The path
is allocated with std.slalloc
, and must be freed by the caller using
std.slfree
. The file descriptor must be closed as ususal.
const mkdtemp : (base : byte[:], mode : int64 -> std.result(byte[:], errno)
mkdtemp
is to mkdir
as mktemp
is to openmode
. Like mktemp
, it
generates a unique name for a new directory in temporary storage by
appending a random string to the base name base
.
Returns: Either a successful result containing the path generated (in this case,
the directory now exists), or an error describing the failure. The path is
allocated with std.slalloc
, and must be freed by the caller using std.slfree
.
const close : (fd : fd -> void)
Closes closes the file descriptor. If the file descriptor is valid, close is guaranteed to close it. If it is not valid, this is a no-op.
const read : (fd : fd, buf : byte[:] -> result(size, errno))
Reads up to the length of buf
from the file descriptor fd
, at the current
offset within the file, advancing the offset by the count of bytes read. The
buffer may not be filled entirely when the read completes. For example, when
reading from a console, often only one line will be returned at a time.
Conventionally, 0
bytes are returned at the end of the file.
Returns: Either the number of bytes read on success, or the error that caused a failure reading on failure.
const write : (fd : fd, buf : byte[:] -> result(size, errno))
Write writes up to the length of buf
to the file descriptor, writing the
bytes at the current offset. The offset is advanced by the number of bytes
that were written, extending the file size if necessary. Write is not
guaranteed to write the full buffer.
Returns: The number of bytes written on success, or the error that caused the failure on error.
const seek : (fd : fd, delta : off, whence : whence -> result(off, errno))
Seek changes the current offset within the file descriptor fd
by delta
.
This delta can be treated in three different ways, depending on the value of
`whence.
If whence
is Seekset, then delta
is treated as an absolute value to seek
to, and the offset is set to delta
. If whence
is Seekcur
, then delta
is added to the current offset. If whence
is Seekend
, then delta
is
added to the size of the file.
Returns: Either the new offset within the file on success, or the error that occurred on failure.
const pipe : (fds : fd[2]# -> errno)
Pipe creates a unidirectional channel for communication between processes. Two file descriptors are returned in the array fd. Data written to fd[1] is available in fd[0]. The pipe may or may not be buffered.
Returns: Enone on success, otherwise, returns the error that caused this call to fail.
const dup2 : (ofd : fd, nfd : fd -> result(fd, errno))
Dup2 copies the old fd ofd
to the new fd nfd
. If the file descriptor
nfd
is already open, then it is implicitly closed by this call before
the fd is copied. This is done atomically.
Returns: Either the new fd used, on success, or an error describing the failure.
const remove : (path : byte[:] -> errno)
Remove removes the file specified from the directory in which it is contained.
The user must have write permissions for the directory in order to remove
files from it. If path
is a directory, it must be empty.
Returns: Enone on success, otherwise the error that caused the failure.
Path Manipulation
const basename : (p : byte[:] -> byte[:])
const dirname : (p : byte[:] -> byte[:])
Given a string of the form "foo/bar/baz", dirname()
returns the directory
component of it -- in other words, everything up to the final /
. It ignores
trailing slashes. It
The caller is responsible for freeing the path with slfree
.
For example, dirname("foo/bar//")
will return "foo/bar"
.
const pathcat : (a : byte[:], b : byte[:] -> byte[:])
Pathcat joins two paths together, using '/' as a directory
separator. The paths are normalized before being returned. This
call is shorthand for std.pathjoin([a, b][:])
.
The caller is responsible for freeing the path with slfree
.
Returns: A concatenated path.
const pathjoin : (p : byte[:][:] -> byte[:])
Pathcat joins a list of paths together, using '/' as a directory
separator. The paths are normalized before being returned. This
call is shorthand for std.pathjoin([a, b][:])
.
The caller is responsible for freeing the path with slfree
.
Returns: A concatenated path.
const pathnorm : (p : byte[:] -> byte[:])
Pathnorm does a purely lexical normalization of the path. It removes
redundant components, doubled /
characters, and similar. The returned
path is equivalent to the original input path.
The caller is responsible for freeing the path with slfree
.
Returns: A new normalized path.
const getcwd : (-> byte[:])
Returns the current working directory of the program. The caller is
responsible for freeing the path with slfree
.
Returns: A string representing the working directory.
File Properties
const fmtime : (f : byte[:] -> result(time, errno))
Returns either the last modification time of the file f
, or
the error that was encountered extracting this information.
const fsize : (f : byte[:] -> result(off, errno))
Returns either the size in bytes of the file f
, or
the error that was encountered extracting this information.
const fexists : (f : byte[:] -> bool)
Returns true
if the file is able to be stat
ed, or false
if this fails.
const fisdir : (f : byte[:] -> bool)
Returns true
if the file is a directory that is able to be stat
ed, or
false
if this fails.
Convenience Functions
const slurp : (path : byte[:] -> result(byte[:], errno))
Reads all bytes from path
until the end of file.
Returns either the file data, or the failure encountered.
const fslurp : (fd : fd -> result(byte[:], errno))
Reads all bytes from the file descriptor fd
until the end of file.
Returns either the file data, or the failure encountered.
const blat : (path : byte[:], buf : byte[:], perm : int64 -> bool)
Creates the file path
with permissions perm
, and writes as much of
buf
as it can into it.
Returns Enone if no errors were encountered. Otherwise, the error is returned.
const fblat : (f : fd, buf : byte[:] -> bool)
Writes as much of buf
as it can into the file descriptor fd
.
Returns Enone if no errors were encountered. Otherwise, the error is returned.