Module: fs.stat

Source: ./fs/stat.reef


Overview

fs/stat - File metadata and type queries

Provides functions for querying file type and metadata via stat/lstat. All functions accept a path string and return the requested information.

Metadata accessors return Result[T, error.Error]: Ok(value) on success, Err(NotFound) when the path does not exist, Err(IoError) for other stat failures (e.g. a component of the path exists but is unusable). file_size and file_mtime are int64 (file sizes can exceed 2^31 bytes; mtime needs to survive the year-2038 rollover of a 32-bit time_t).

UID/GID name resolution returns Option[string]: None means there is no passwd/group entry for that id (not that the lookup itself failed — that's only possible via a bad path, which file_uid_name/file_gid_name report as Err).


Functions

fn is_file(path: string): bool

fn is_directory(path: string): bool

fn is_symlink(path: string): bool

fn is_pipe(path: string): bool

fn is_socket(path: string): bool

fn is_block_device(path: string): bool

fn is_char_device(path: string): bool

fn exists(path: string): bool

fn io_failure_kind(path: string): error.ErrorKind

The path exists, so whatever failed was I/O; it does not, so NotFound.

USE ONLY WHERE THE PATH IS EXPECTED TO EXIST BEFORE THE OPERATION -- opening for READ, deleting, renaming, stat'ing, removing a directory.

This constraint is load-bearing and predates the merge; io.buffer carried it as a warning on its own copy. fopen(path, "w"/"a") never creates the file on failure, so an exists()-recheck after a failed WRITE open always sees the path absent and would misclassify every write-open failure -- including permission-denied on the parent directory -- as NotFound. Write and append opens use a flat IoError instead (io.file's writeFile / appendFile / writeBinaryFile set that precedent, and io.stream.stream_open branches on mode before it gets here).

What the IoError case actually covers at the call sites: permission denied on the parent directory, a non-directory component in the path, a cross-device rename, a missing parent for the destination, and a directory that is not empty -- ENOTEMPTY is not separately observable through these runtime entry points.

fn access_failure_kind(path: string): error.ErrorKind

The path exists, so the refusal was about permission; it does not, so NotFound.

The distinction from io_failure_kind is the ErrorKind for the exists case, and it is a real one: a caller retrying on IoError should not retry a PermissionDenied. Once existence is ruled out, permission is the dominant real-world cause for the operations that use this -- EPERM, a read-only filesystem, not being the owner.

io.dir.change_dir wrote this inverted ("if not exists return NotFound; return PermissionDenied"), which is the same predicate and was the harder half to spot.

fn file_size(path: string): result.Result[int64, error.Error]

fn file_mode(path: string): result.Result[int, error.Error]

fn file_uid(path: string): result.Result[int, error.Error]

fn file_gid(path: string): result.Result[int, error.Error]

fn file_mtime(path: string): result.Result[int64, error.Error]

fn uid_name(uid: int): option.Option[string]

Resolves a uid to its passwd-database username. Returns None if there is no passwd entry for uid.

fn gid_name(gid: int): option.Option[string]

Resolves a gid to its group-database name. Returns None if there is no group entry for gid.

fn file_uid_name(path: string): result.Result[option.Option[string], error.Error]

Looks up the owning user's name for path in one call (stat + resolve). Err(NotFound/IoError) if path cannot be stat'd; otherwise Ok(uid_name(owner)), which is None if the owning uid has no passwd entry.

Implemented directly against the raw stat (rather than composing file_uid + uid_name through core.result's is_err/unwrap_err). Composing file_uid()/file_gid() here would work. Kept as the direct form for clarity rather than churning it.

fn file_gid_name(path: string): result.Result[option.Option[string], error.Error]

Looks up the owning group's name for path in one call (stat + resolve). Err(NotFound/IoError) if path cannot be stat'd; otherwise Ok(gid_name(group)), which is None if the owning gid has no group entry. (See file_uid_name's comment for why this is implemented against the raw stat rather than composing file_gid + gid_name.)


Generated by reefc doc