File
Source: runtime/io/file.pep
OpenOptions
struct OpenOptions
Describes how File.open_with (or OpenOptions.open) opens a file:
which access it asks for, and whether the file is created or truncated.
A builder in the style of Rust’s std::fs::OpenOptions. A new
OpenOptions has every option off; each setter stores its flag and
returns this same OpenOptions, so calls chain. The rules, checked when
the file is opened:
- At least one of
read,writeorappendmust be set, or opening fails withis_invalid_input(). create,create_newandtruncateneedwriteorappend, or opening fails withis_invalid_input().appendimplies write access, and every write goes to the current end of the file whatever the position; it wins overwrite.createopens an existing file as it is (combine withtruncateto empty it) and creates a missing one.create_newcreates the file and fails withis_already_exists()when it already exists, atomically (O_EXCLon POSIX,CREATE_NEWon Windows);createis then irrelevant.truncateempties an existing file on open.- Without
createorcreate_new, a missing file fails withis_not_found().
On POSIX a created file gets mode 0666 (or the mode set) less the
process umask, and the descriptor is opened close-on-exec. On Windows every file is opened
sharing read, write and delete access with other openers.
See also
File.open_with
Example
var r = OpenOptions().read(true).write(true).create(true).open(Path("data.bin"));
if (r.is_err()) {
return 1;
}
var f = r.value();
Constructor
OpenOptions()
construct()
Creates an OpenOptions with every option off. Set at least one of
read, write or append before opening.
Methods
read
read(v: bool): OpenOptions
Sets whether the file is opened for reading.
Parameters
v— true to request read access
Returns
- this
OpenOptions, for chaining
write
write(v: bool): OpenOptions
Sets whether the file is opened for writing. Writes go to the current position and overwrite what is there.
Parameters
v— true to request write access
Returns
- this
OpenOptions, for chaining
append
append(v: bool): OpenOptions
Sets append mode: the file is opened for writing and every write
goes to the current end of the file, whatever the position (seeking
still moves the position for reads). Implies write access, and takes
precedence over write.
Parameters
v— true to open in append mode
Returns
- this
OpenOptions, for chaining
truncate
truncate(v: bool): OpenOptions
Sets whether an existing file is truncated to 0 bytes when it is
opened. Requires write or append.
Parameters
v— true to truncate an existing file
Returns
- this
OpenOptions, for chaining
create
create(v: bool): OpenOptions
Sets whether a missing file is created. An existing file is opened as
it is unless truncate is also set. Requires write or append.
Parameters
v— true to create the file when it is missing
Returns
- this
OpenOptions, for chaining
create_new
create_new(v: bool): OpenOptions
Sets whether the file must be newly created: opening fails with
is_already_exists() when the path already exists. The check and the
creation are one atomic step. Requires write or append.
Parameters
v— true to require that the file does not exist yet
Returns
- this
OpenOptions, for chaining
mode
mode(mode: Mode): OpenOptions
Sets the permission bits a file gets when this open creates it, so it
never exists with the default mode: on POSIX the mode_t bits passed
to open, less the process umask, as Metadata.permissions reports
them (493, octal 755, for rwxr-xr-x). An existing file keeps its
mode. Ignored on Windows and WASI; use File.set_read_only there.
Parameters
mode— the permission bits for a new file; 438 (octal 666) by default
Returns
- this
OpenOptions, for chaining
Example
var script = OpenOptions().write(true).create_new(true).mode(493).open(Path("run.sh"));
open
open(path: Path): IoResult<File>
Opens path with these options. The same as
File.open_with(path, this).
Parameters
path— the file to open
Returns
- the open
File, positioned at the start; an error when the options break a rule (is_invalid_input()), the path is empty or missing (is_not_found()), it exists undercreate_new(is_already_exists()), or the system refuses (is_permission_denied()and others)
See also
File.open_with
Example
var log = OpenOptions().append(true).create(true).open(Path("log.txt")).value();
log.write_all("started");
FileType
enum FileType
The kind of a file system object, as Metadata.file_type and
DirEntry.file_type report it.
A symlink is reported as Symlink only where links are not followed
(Path.symlink_metadata() and directory listings); on Windows that is any
reparse point, junctions included, even one that points to a directory.
See also
Metadata
Example
import io;
var m = io.Path("notes.txt").metadata();
if (m.is_ok()) {
match (m.value().file_type) {
File => { print("a file"); }
Directory => { print("a directory"); }
Symlink, Other => { print("something else"); }
}
}
Cases
File
File
A regular file. On Windows, anything that is neither a directory nor a reparse point.
Directory
Directory
A directory.
Symlink
Symlink
A symbolic link itself (on Windows, any reparse point).
Other
Other
Anything else, such as a FIFO, socket or device on POSIX.
SeekFrom
enum SeekFrom
Where File.seek measures its offset from, with the offset itself.
See also
File.seek
Example
var f = File.open(Path("data.bin")).value();
var length = f.seek(SeekFrom.End(0)).value(); # at the end
f.seek(SeekFrom.Start(4)); # 4 bytes in
var at = f.seek(SeekFrom.Current(-2)).value(); # 2
Cases
Start
Start(offset: Offset)
offset bytes from the start of the file.
Parameters
offset— the new position; negative is an error
Current
Current(offset: Offset)
offset bytes from the current position.
Parameters
offset— the distance to move; negative moves back
End
End(offset: Offset)
offset bytes from the end of the file.
Parameters
offset— the distance from the end; negative moves back from it
StdStream
enum StdStream
One of the process’s standard streams, as File.std_file takes it.
See also
File.std_file
Cases
Input
Input
Standard input: file descriptor 0 on POSIX, STD_INPUT_HANDLE on
Windows.
Output
Output
Standard output: file descriptor 1 on POSIX, STD_OUTPUT_HANDLE on
Windows.
Error
Error
Standard error: file descriptor 2 on POSIX, STD_ERROR_HANDLE on
Windows.
Metadata
struct Metadata
Describes a file system object: its kind, size, read-only flag, permission bits and timestamps, as a snapshot taken when it was queried.
Returned by File.metadata(), Path.metadata() (which follows
symlinks), Path.symlink_metadata() (which does not) and
DirEntry.metadata(). The timestamps are nanoseconds since the Unix
epoch (1970-01-01 00:00:00 UTC). On POSIX the metadata comes from
statx (Linux) or stat (macOS); on Windows from
GetFileInformationByHandle.
Example
var m = Path("notes.txt").metadata();
if (m.is_ok() && m.value().is_file) {
var bytes = m.value().size;
}
Fields
size
ulong size
The file’s length in bytes.
file_type
FileType file_type
The kind of object: File, Directory, Symlink or Other. It
agrees with is_file, is_directory and is_symlink, except that a
Windows reparse point to a directory is Symlink with both
is_directory and is_symlink set.
is_file
bool is_file
Whether this is a regular file. On Windows, anything that is neither a directory nor a reparse point (symlink) counts as a file.
is_directory
bool is_directory
Whether this is a directory.
is_symlink
bool is_symlink
Whether this is a symbolic link itself. Only metadata that does not
follow links (Path.symlink_metadata()) can report one. On Windows
this is any reparse point (FILE_ATTRIBUTE_REPARSE_POINT), which
includes junctions.
read_only
bool read_only
Whether the file is read-only: on POSIX, no write permission bit
(0222) is set for anyone; on Windows, FILE_ATTRIBUTE_READONLY is set.
modified
long modified
The time of the last modification of the contents, in nanoseconds since the Unix epoch.
accessed
long accessed
The time of the last access, in nanoseconds since the Unix epoch (file systems mounted with noatime or relatime update it rarely or never).
created
long? created
The creation (birth) time, in nanoseconds since the Unix epoch; none where the platform does not report one, such as on Linux file systems that do not record it.
permissions
Mode permissions
The raw permission bits: on POSIX the mode_t permission bits
(mode & 07777, for example 256 for owner read); on Windows the
FILE_ATTRIBUTE_* bits.
Constructor
Metadata()
construct()
Creates a Metadata with every number zero, every flag false,
file_type Other and created none. Metadata is normally obtained
from a query such as File.metadata().
File
[NotCopyable( "owns an operating-system handle and cannot be copied; send its path, and open the file again on the receiving thread" )] struct File
An open file, or a standard stream, read and written through its
platform handle (a file descriptor on POSIX, a HANDLE on Windows).
Open one with File.open (read-only), File.create (write-only,
created or truncated), or File.open_with / OpenOptions.open for
anything else. The static conveniences read_bytes, read_to_string,
write_bytes, write_text, copy, rename and remove work on a
whole file by path.
I/O is unbuffered: each read and write is one system call. Reads and
writes start at the current position and move it forward; the seek_*
methods move it explicitly. A write to a standard stream first flushes
the output print has buffered, so the two never come out of order.
Closing: the File’s destructor closes an owned handle when the last
reference to the File is released, and ignores any error. Call close()
to close earlier or to observe the error. The standard streams
(stdin(), stdout(), stderr()) are never closed by a File. Every
operation on a closed File fails with an error that none of the
IoError predicates identify (EBADF on POSIX, ERROR_INVALID_HANDLE
on Windows).
Errors are IoError values carrying the platform’s code; use its
predicates (is_not_found(), is_permission_denied(), …) to tell
kinds apart portably.
Example
var f = File.create(Path("out.txt")).value();
f.write_all("hello");
f.close();
var text = File.read_to_string(Path("out.txt")).value(); # "hello"
Fields
path
Path path
The path the File was opened with; <stdin>, <stdout> or
<stderr> for a standard stream, and empty for a File() never
opened.
Constructor
File()
construct()
Creates a closed File that owns nothing yet: is_open() is false and
every I/O method fails. Use File.open, File.create or
File.open_with to get an open one.
Static methods
open
static open(path: Path): IoResult<File>
Opens an existing file for reading only. The position starts at 0.
A directory can be opened this way too, but reading it fails with
is_is_a_directory().
Parameters
path— the file to open
Returns
- the open
File; an error withis_not_found()when the path is empty or does not exist,is_permission_denied()when access is refused, or another platform error
Example
var r = File.open(Path("config.txt"));
if (r.is_err() && r.error().is_not_found()) {
return 0;
}
var text = r.value().read_string();
create
static create(path: Path): IoResult<File>
Opens a file for writing only, creating it if it is missing and truncating it to 0 bytes if it exists.
On POSIX a created file gets mode 0666 less the process umask.
Parameters
path— the file to create or truncate
Returns
- the open
File, empty and positioned at 0; an error withis_not_found()when the path is empty or its parent directory does not exist,is_permission_denied()when access is refused, or another platform error (on POSIX,is_is_a_directory()when the path is a directory)
Example
var f = File.create(Path("report.txt")).value();
f.write_all("done");
open_with
static open_with(path: Path, options: OpenOptions): IoResult<File>
Opens path as options describe. OpenOptions.open is the same
call written as a builder.
The options are checked first, as in Rust: at least one of read, write or append is required, and create, create_new or truncate require write or append. The position starts at 0 (append mode still writes at the end).
Parameters
path— the file to openoptions— the access mode and creation behavior
Returns
- the open
File; an error withis_invalid_input()when no access mode is set or create, create_new or truncate is set without write or append;is_not_found()when the path is empty, or the file (or a parent directory) is missing and neither create nor create_new is set;is_already_exists()when create_new is set and the path exists;is_permission_denied()when access is refused; or another platform error
Example
var opts = OpenOptions().write(true).create_new(true);
var r = File.open_with(Path("lock"), opts);
if (r.is_err() && r.error().is_already_exists()) {
return 1;
}
std_file
static std_file(stream: StdStream, name: String): File
Returns a File for one of the process’s standard streams. The File
does not own the handle, so neither close() nor the destructor
closes the stream. stdin(), stdout() and stderr() are the usual
way to call this.
On Windows a process without a console or redirection may get a null handle, and the File is then not open.
Parameters
stream— the streamname— the display name stored in the File’spath, such as<stdout>
Returns
- a File on that stream, that does not close the stream when released
Example
var err = File.std_file(StdStream.Error, "<stderr>");
err.write_all("warning");
std_file
[Deprecated("use 'std_file' with a 'StdStream' instead")] static std_file(which: int, name: String): File
Deprecated: use std_file(StdStream, String) instead. Returns a File
for the standard stream numbered which, as std_file does for the
matching StdStream.
Parameters
which— the stream: 0 for standard input, 1 for standard output, 2 for standard errorname— the display name stored in the File’spath
Returns
- a File on that stream; a File that is not open for any other
which
stdin
static stdin(): File
Returns a File reading the process’s standard input. Each call returns a new File on the same stream; the stream is never closed by a File. A read returns 0 at end of input (on Windows, also when the writing end of a pipe has closed).
Returns
- a File on standard input, named
<stdin>
stdout
static stdout(): File
Returns a File writing to the process’s standard output. Each call
returns a new File on the same stream, and close() only marks that
File closed: the stream stays usable. Writes are unbuffered, and each
one first flushes what print has buffered, so output from print
and from this File comes out in program order.
Returns
- a File on standard output, named
<stdout>
Example
var out = File.stdout();
out.write_all("hello");
stderr
static stderr(): File
Returns a File writing to the process’s standard error. Each call
returns a new File on the same stream, and close() only marks that
File closed: the stream stays usable. Writes are unbuffered, and each
one first flushes what print has buffered.
Returns
- a File on standard error, named
<stderr>
adopt
static adopt(transfer: FileTransfer): IoResult<File>
Takes the handle out of transfer (see into_transfer) into a new
File on the calling thread, whose path is empty. Only the first
adopt of a token gets the handle.
Parameters
transfer— the token frominto_transfer
Returns
- the File; an error when the token is empty (already adopted, or made from a closed File)
read_bytes
static read_bytes(path: Path): IoResult<u8[]>
Reads the whole file at path into a byte array (Rust’s
fs::read).
Parameters
path— the file to read
Returns
- the file’s bytes; an error as for
File.open(such asis_not_found()) orread_all
Example
var r = File.read_bytes(Path("image.png"));
if (r.is_ok()) {
var n = r.value().count;
}
read_to_string
static read_to_string(path: Path): IoResult<String>
Reads the whole file at path as UTF-8 text (Rust’s
fs::read_to_string).
Parameters
path— the file to read
Returns
- the file’s text; an error with
is_invalid_input()when it is not valid UTF-8, or an error as forFile.open(such asis_not_found()) orread_all
Example
var r = File.read_to_string(Path("notes.txt"));
if (r.is_err()) {
return 1;
}
var text = r.value();
write_bytes
static write_bytes(path: Path, data: u8[]): IoResult<void>
Writes data as the whole contents of the file at path, creating
it or replacing what it held (Rust’s fs::write), then closes it.
Not atomic: the file is truncated first, so a failure part way leaves it truncated or partly written.
Parameters
path— the file to writedata— the new contents
Returns
- an Ok result once the data is written and the file closed; an error as for
File.create(such asis_not_found()for a missing parent directory),write_all, orclose
Example
var data = Array<u8>();
data.append(1 as u8);
File.write_bytes(Path("one.bin"), data);
write_text
static write_text(path: Path, s: String): IoResult<void>
Writes s as UTF-8 as the whole contents of the file at path,
creating it or replacing what it held, then closes it. No newline is
added.
Not atomic: the file is truncated first, so a failure part way leaves it truncated or partly written.
Parameters
path— the file to writes— the new contents
Returns
- an Ok result once the text is written and the file closed; an error as for
File.create(such asis_not_found()for a missing parent directory),write_all, orclose
Note
- this is the design proposal’s
write_to_string; a staticwritewould clash with the instancewrite
Example
var r = File.write_text(Path("hello.txt"), "hello, world");
if (r.is_err()) {
return 1;
}
copy
static copy(from: Path, to: Path): IoResult<ulong>
Copies the contents of the file from to to, creating to or
truncating it first, in 64 KiB chunks.
Only the contents are copied: to keeps its own permissions and
timestamps (a new file gets the defaults of File.create). A failure
part way leaves to partly written.
Parameters
from— the file to copyto— the destination file
Returns
- the number of bytes copied;
is_invalid_input()whenfromandtoare the same file (after resolving symlinks), which truncatingtowould empty before it was read; otherwise an error as forFile.openonfrom(such asis_not_found()),File.createonto, or a read, write or close failure
Example
var n = File.copy(Path("a.txt"), Path("b.txt")).value();
rename
static rename(from: Path, to: Path): IoResult<void>
Renames or moves from to to, replacing an existing file at to
(rename on POSIX, MoveFileExW with MOVEFILE_REPLACE_EXISTING on
Windows).
Works for directories too. Moving between file systems (volumes) fails rather than copying.
Parameters
from— the existing pathto— the new path
Returns
- an Ok result on success; an error with
is_not_found()whenfrom(or the parent ofto) does not exist or, on POSIX, either path is empty,is_permission_denied()when access is refused, or another platform error
Example
File.rename(Path("draft.txt"), Path("final.txt"));
symlink
static symlink(target: Path, link: Path): IoResult<void>
Creates a symbolic link at link that points to the file target
(symlink on POSIX, CreateSymbolicLinkW on Windows). Use
Directory.symlink for a link to a directory: Windows makes the two
kinds differently, and a file link to a directory does not open
there. POSIX makes the same link either way.
target is stored as given and need not exist; a relative target is
resolved against the directory that holds the link, not the current
directory. On Windows, making a symlink needs Developer Mode or an
administrator, and fails with is_permission_denied() otherwise.
Parameters
target— the path the link points tolink— where to create the link
Returns
- an Ok result once the link exists; an error with
is_already_exists()when something is already atlink,is_not_found()when its parent is missing or a path is empty,is_permission_denied(), or another platform error
See also
Path.read_link
Example
File.symlink(Path("app-1.2.so"), Path("lib/app.so"));
remove
static remove(path: Path): IoResult<void>
Deletes the file at path. A symlink is removed itself, not its
target. Directories are not removed: use Directory.remove or
Directory.remove_all.
Parameters
path— the file to delete
Returns
- an Ok result on success; an error with
is_not_found()when the path does not exist (on POSIX, also when it is empty); when it is a directory,is_is_a_directory()on Linux andis_permission_denied()on macOS and Windows;is_permission_denied()when access is refused (on Windows also for a read-only file); or another platform error
Example
var r = File.remove(Path("old.txt"));
if (r.is_err() && !r.error().is_not_found()) {
return 1;
}
Methods
is_open
is_open(): bool
Returns whether the File holds a valid handle: true after a
successful open, false after close() and for a File() never
opened.
Returns
- true while the File is open
check_open
check_open(): IoResult<void>
Checks that the File is open, for use before an operation.
Returns
- an Ok result when the File is open; an error with the message “file is closed” otherwise (code
EBADFon POSIX,ERROR_INVALID_HANDLEon Windows; noIoErrorpredicate holds)
read
read(buffer: u8[], max: ulong): IoResult<ulong>
Reads up to max bytes from the current position and appends them
to buf, growing it; the bytes already in buf are kept. Advances
the position by the count read.
One system call: the read may be partial, returning fewer than max
bytes before the end of the file (always so for pipes and terminals),
and a single call moves at most about 2 GiB on POSIX or 1 GiB on
Windows. Loop until it returns 0 to read everything, or use
read_all. On POSIX an interrupted read (EINTR) is retried. On
failure buffer keeps its previous contents.
Parameters
buffer— the array the bytes are appended tomax— the most bytes to read; 0 reads nothing and returns 0
Returns
- the number of bytes appended, 0 at end of file; an error when the File is closed, or
is_is_a_directory()when it is a directory, or another platform error
Example
var buf = Array<u8>();
while (true) {
var r = f.read(buf, 4096);
if (r.is_err() || r.value() == 0) {
break;
}
}
read_all
read_all(): IoResult<u8[]>
Reads everything from the current position to the end of the file, in 64 KiB chunks, leaving the position at the end.
Returns
- a new array of the bytes read (empty at end of file); an error when the File is closed,
is_is_a_directory()when it is a directory, or another platform error, in which case the bytes read so far are discarded
read_string
read_string(): IoResult<String>
Reads everything from the current position to the end of the file,
as read_all does, and returns it as UTF-8 text.
The bytes must be strictly valid UTF-8 (RFC 3629: no overlong forms, surrogates, or code points past U+10FFFF). A byte-order mark is kept as part of the text.
Returns
- the text read (empty at end of file); an error with
is_invalid_input()when the bytes are not valid UTF-8, or any errorread_allreturns
write
write(data: u8[]): IoResult<ulong>
Writes bytes from data at the current position (or at the end, in
append mode) with a single system call, and advances the position.
The write may be partial: it can write fewer than data.count
bytes, and one call moves at most about 2 GiB on POSIX or 1 GiB on
Windows. Use write_all to write everything. On POSIX an interrupted
write (EINTR) is retried.
Parameters
data— the bytes to write
Returns
- the number of bytes written, which may be less than
data.count; an error when the File is closed or was not opened for writing, or another platform error
write_all
write_all(data: u8[]): IoResult<void>
Writes all of data, repeating the write until every byte is
written. Advances the position by data.count.
If an error occurs part of data may already have been written.
Parameters
data— the bytes to write
Returns
- an Ok result once every byte is written; an error when the File is closed or was not opened for writing, when a write makes no progress (“failed to write the whole buffer”, with code
EIOon POSIX orERROR_WRITE_FAULTon Windows), or another platform error
write_all
write_all(s: String): IoResult<void>
Writes all of the UTF-8 bytes of s, as write_all does for bytes.
No newline or terminator is added.
Parameters
s— the text to write
Returns
- an Ok result once every byte is written; an error as for
write_all(u8[])
Example
var f = File.create(Path("greeting.txt")).value();
var r = f.write_all("hello, world");
if (r.is_err()) {
return 1;
}
write_string
[Deprecated("use 'write_all' instead", "write_all")] write_string(s: String): IoResult<void>
Deprecated: use write_all instead. Writes all of the UTF-8 bytes of
s, exactly like write_all(s).
Parameters
s— the text to write
Returns
- an Ok result once every byte is written; an error as for
write_all
See also
write_all
seek
seek(from: SeekFrom): IoResult<Offset>
Moves the position as from says: to an offset from the start, from
the current position, or from the end of the file.
Seeking past the end is allowed; a later write there fills the gap with zeros. A position before the start of the file is an error. Seeking a stream that has no position (a pipe or a terminal) fails on POSIX and has platform-defined results on Windows.
Parameters
from— the origin and the offset from it
Returns
- the new position, in bytes from the start of the file; an error when the File is closed, the resulting position would be negative (on POSIX, with
is_invalid_input()), or the stream cannot seek
Example
var f = File.open(Path("data.bin")).value();
var length = f.seek(SeekFrom.End(0)).value();
f.seek(SeekFrom.Start(0));
seek_start
seek_start(pos: Offset): IoResult<Offset>
Moves the position to pos bytes from the start of the file, like
seek(SeekFrom.Start(pos)) without allocating the SeekFrom.
Seeking past the end is allowed; a later write there fills the gap with zeros.
Parameters
pos— the new position, in bytes from the start
Returns
- the new position, in bytes from the start of the file; an error as for
seek
See also
seek
seek_end
seek_end(delta: Offset): IoResult<Offset>
Moves the position to delta bytes from the end of the file, like
seek(SeekFrom.End(delta)). seek_end(0) moves to the end and
returns the file’s length.
Parameters
delta— the offset from the end of the file, in bytes; negative moves back from the end
Returns
- the new position, in bytes from the start of the file; an error as for
seek
See also
seek
seek_current
seek_current(delta: Offset): IoResult<Offset>
Moves the position by delta bytes from where it is, like
seek(SeekFrom.Current(delta)). seek_current(0) returns the
current position without moving it.
Parameters
delta— the offset from the current position, in bytes; negative moves back
Returns
- the new position, in bytes from the start of the file; an error as for
seek
See also
seek
seek
[Deprecated("use 'seek' with a 'SeekFrom' instead")] seek(offset: Offset, whence: int): IoResult<Offset>
Deprecated: use seek(SeekFrom) instead. Moves the position by
offset relative to the origin whence.
Parameters
offset— the offset in bytes from the origin; may be negativewhence— the origin: 0 the start of the file, 1 the current position, 2 the end of the file
Returns
- the new position, in bytes from the start of the file; an error as for
seek(SeekFrom), or whenwhenceis not 0, 1 or 2
set_length
set_length(size: ulong): IoResult<void>
Truncates or extends the file to exactly size bytes; bytes added
are zeros. The position is kept, even when it is now past the end.
The File must have been opened for writing.
Parameters
size— the new length, in bytes
Returns
- an Ok result on success; an error when the File is closed, was not opened for writing, or the system refuses the size
set_len
[Deprecated("use 'set_length' instead", "set_length")] set_len(size: ulong): IoResult<void>
Deprecated: use set_length instead. Truncates or extends the file to
exactly size bytes.
Parameters
size— the new length, in bytes
Returns
- the same as
set_length(size)
sync
sync(): IoResult<void>
Flushes the file’s contents and metadata to the storage device,
waiting until they are written (fsync on POSIX,
FlushFileBuffers on Windows). Writes are already unbuffered in the
process; this forces them out of the operating system’s cache.
On Windows the File must have been opened with write access.
Returns
- an Ok result once the data is durable; an error when the File is closed or the device reports a failure, or another platform error
lock
lock(): IoResult<void>
Takes an exclusive advisory lock on the whole file, waiting until no
other holder has a lock on it, shared or exclusive. Modeled on Rust’s
File::lock.
The lock belongs to this File: another File opened on the same path
(in this process or another) contends with it, and it is released by
unlock, by close, or when the File is destroyed. Taking a lock
while this File already holds one is platform-defined, as in Rust:
POSIX converts the lock, Windows may wait forever. The lock is
advisory on POSIX (flock(LOCK_EX)): it binds only those who also
lock. On Windows (LockFileEx) it also stops other handles from
reading or writing the file while held. The wait blocks the calling
thread, also inside a task. WASI has no file locks.
Returns
- an Ok result once the lock is held; an error when the File is closed, on WASI, or another platform error
See also
try_lockunlock
Example
var f = OpenOptions().write(true).create(true).open(Path(".pep/fetch.lock")).value();
if (f.lock().is_ok()) {
# ... work no other locker does at the same time ...
f.unlock();
}
lock_shared
lock_shared(): IoResult<void>
Takes a shared advisory lock on the whole file, waiting until no
other holder has an exclusive lock on it. Any number of Files can
hold a shared lock at once. Modeled on Rust’s File::lock_shared;
otherwise as lock (flock(LOCK_SH) on POSIX, LockFileEx without
LOCKFILE_EXCLUSIVE_LOCK on Windows).
Returns
- an Ok result once the lock is held; an error as for
lock
See also
lock
try_lock
try_lock(): IoResult<bool>
Takes an exclusive advisory lock on the whole file if no other
holder has a lock on it, without waiting. Modeled on Rust’s
File::try_lock; otherwise as lock.
Returns
- true when the lock is now held, false when another holder has a lock on the file (Rust’s
TryLockError::WouldBlock); an error as forlock
See also
lock
Example
var held = f.try_lock();
if (held.is_ok() && !held.value()) {
print("another process holds the lock\n");
}
try_lock_shared
try_lock_shared(): IoResult<bool>
Takes a shared advisory lock on the whole file if no other holder
has an exclusive lock on it, without waiting. Modeled on Rust’s
File::try_lock_shared; otherwise as lock_shared.
Returns
- true when the lock is now held, false when another holder has an exclusive lock on the file; an error as for
lock
See also
lock_shared
unlock
unlock(): IoResult<void>
Releases the lock this File holds, shared or exclusive. Releasing a
File that holds none is not an error. Closing or destroying the File
releases its lock too. Modeled on Rust’s File::unlock.
Returns
- an Ok result once the lock is released; an error when the File is closed, on WASI, or another platform error
See also
lock
metadata
metadata(): IoResult<Metadata>
Queries the metadata of the open file itself (the target, when it was opened through a symlink): size, kind, read-only flag, permission bits and timestamps.
Returns
- the file’s
Metadata; an error when the File is closed, or another platform error
Example
var size = f.metadata().value().size;
set_permissions
set_permissions(mode: Mode): IoResult<void>
Sets the permission bits of the open file (fchmod on POSIX).
mode holds the raw platform bits, as Metadata.permissions reports
them: on POSIX the mode_t bits mode & 07777 (493, octal 755, for
rwxr-xr-x). On Windows it is the FILE_ATTRIBUTE_* word, and only
FILE_ATTRIBUTE_READONLY (1) is applied; the File needs write access
there. WASI has no permission bits, and this fails. set_read_only
and set_executable change one property portably.
Parameters
mode— the new permission bits
Returns
- an Ok result once they are set; an error when the File is closed,
is_permission_denied()when the caller does not own the file (or on Windows the File was opened without write access), or another platform error
See also
Path.set_permissions
Example
var f = File.create(Path("run.sh")).value();
f.set_permissions(493); # octal 755: rwxr-xr-x
set_read_only
set_read_only(read_only: bool): IoResult<void>
Makes the open file read-only, or writable again: the portable part
of set_permissions.
On POSIX, read-only clears every write bit (octal 222), and writable
sets only the owner’s (octal 200), so a file never becomes writable
by group or others this way. On Windows it sets or clears
FILE_ATTRIBUTE_READONLY, and the File needs write access. Fails on
WASI, which has no permission bits.
Parameters
read_only— true to make the file read-only, false to make it writable by its owner
Returns
- an Ok result once the file is changed; an error as for
metadata()orset_permissions
See also
Metadata.read_only
set_executable
set_executable(executable: bool): IoResult<void>
Makes the open file executable, or not, without raw permission bits.
On POSIX, executable adds an execute bit for each class (owner, group,
others) that may read the file, as chmod +x does with the usual
umask; not executable clears all three. Windows has no execute bit
(an extension such as .exe decides) and WASI no permission bits, so
there this does nothing and succeeds.
Parameters
executable— true to make the file executable, false to stop it
Returns
- an Ok result once the file is changed; an error as for
metadata()orset_permissions
Example
var f = File.create(Path("run.sh")).value();
f.write_all("#!/bin/sh\necho hi\n");
f.set_executable(true);
set_modified
set_modified(time: long): IoResult<void>
Sets the open file’s modification time, leaving its access time
alone (futimens on POSIX, SetFileTime on Windows).
On Windows the File needs write access, and the time is kept to 100 ns. A later write to the file sets its modification time again, so call this after the last write.
Parameters
time— the new time, in nanoseconds since the Unix epoch, asMetadata.modifiedreports it
Returns
- an Ok result once the time is set; an error when the File is closed,
is_permission_denied()when the caller does not own the file (or on Windows the File was opened without write access), or another platform error
See also
Path.set_modified
set_accessed
set_accessed(time: long): IoResult<void>
Sets the open file’s access time, leaving its modification time
alone (futimens on POSIX, SetFileTime on Windows).
On Windows the File needs write access, and the time is kept to 100 ns.
Parameters
time— the new time, in nanoseconds since the Unix epoch, asMetadata.accessedreports it
Returns
- an Ok result once the time is set; an error as for
set_modified
See also
Path.set_accessed
close
close(): IoResult<void>
Closes the File now, to observe the error the system reports (for example a deferred write failure). Without it the destructor closes the handle and ignores errors.
Idempotent: closing a closed File succeeds. The File counts as
closed afterwards even when closing reports an error, so the handle
is never closed twice. A standard stream is only marked closed: the
stream stays open, and File.stdout() and the like still work.
Returns
- an Ok result on success or when already closed; the platform error when closing an owned handle fails
Example
var f = File.create(Path("out.bin")).value();
f.write_all("data");
if (f.close().is_err()) {
return 1;
}
into_transfer
into_transfer(): FileTransfer
Moves the file’s handle into a FileTransfer, which another thread
takes with File.adopt, and leaves this File closed. A File is not
thread-safe, so this is how a thread hands one to another, such as
the pipe from a child process’s standard output to the thread that
reads it while this one writes to the child.
Returns
- the token; for a closed File, one that
adoptfails on
Example
import async;
import [File, Path] from io;
var transfer = File.open(Path("notes.txt")).value().into_transfer();
var reader = async.Thread.spawn(() => {
var mine = File.adopt(transfer).value();
var text = mine.read_all();
});
reader.join();
FileTransfer
[Shared] struct FileTransfer
A file’s handle on its way from one thread to another: made by
File.into_transfer, taken by File.adopt. Unlike a File, it is
thread-safe, so a shared function (a body for async.spawn or
Thread.spawn) can capture it and a Channel can carry it. If no one
adopts it, the handle is closed when the last reference goes, unless it
is one the File did not own (a standard stream).
Constructor
FileTransfer()
construct(handle: FileHandle, owned: bool)
Wraps a file handle. File.into_transfer makes these; use it.
Parameters
handle— the handle, or an invalid one for an empty tokenowned— whether the File the token came from closed its handle