Stat-related methods for File — split out from IoFile.c so the stat(2) surface can be built out (or stubbed) independently of the core stream API. IoFile_statInit is called from IoFile_proto and bolts these methods onto the File proto. The struct stat buffer is lazily allocated and cached in IoFileData->info on first use, then shared by every subsequent protectionMode / userId / size / isDirectory query until the file is freed. The S_ISLNK and S_ISSOCK macros are stubbed to 0 under WASI, where the type bits are unavailable; lstat falls back to stat for the same reason.
Guard used at the top of every read/write/position method: raises a File exception via IoState_error_ if the stream pointer is NULL. Callers must check IOSTATE->errorRaised afterward and bail out.
Companion to assertOpen: raises a File exception unless the current mode allows writing (r+, a+, or w). Keeps write/atPut/flush failures consistent regardless of which specific fputc/UArray_writeTo call would have failed at the libc level.
Clones self and overrides its path. Useful for iterating siblings in a directory without cloning the proto each time.
Ensures the file exists by opening it for writing and immediately closing — a best-effort touch that leaves a zero-byte file so a subsequent fopen in read+ mode succeeds. Returns 1 on success.
Registered as the tag's freeFunc. Closes any open stream (via IoFile_justClose, which also handles pclose for pipe-flagged files and records the exitStatus), frees the stat info block, then frees the IoFileData payload.
Low-level close shared by Io-level close, free, and reopen paths. Preserves stdout/stdin by never calling fclose on them. Pipe-flagged files go through pclose and publish the child process's exit status into the Io-visible "exitStatus" slot; other streams use fclose and reset flags. Leaves DATA(self)->stream NULL so subsequent assertOpen calls fail fast.
fileExists on the receiver's current path. Used before create/open to decide whether to fabricate the file.
GC mark callback. Only the path and mode symbols are Io objects on IoFileData; the FILE* is a foreign pointer and info is a malloc'd struct stat, neither of which the collector touches.
Convenience constructor: look up the File proto and clone it.
Builds the File tag with clone / mark / free function pointers. Stream serialization via writeToStream/readFromStream is left commented out — FILE* handles cannot be resurrected from bytes.
Clones the proto and assigns a path in one step. The file is not opened; callers open with the desired mode afterward.
Wraps an already-open FILE* in a File clone. Used to expose stdin / stdout / stderr to Io code without reopening them.
Creates the File proto: allocates zeroed IoFileData with empty path, default mode "r+", no stream, installs the full method table, and calls IoFile_statInit to attach the stat-related methods from IoFile_stat.c. All user-visible File objects are clones of this proto.
Reads the entire file at DATA(self)->path into a UArray, interns it as an IoSymbol and returns it. Shared helper behind Io-visible `contents` and several subclasses.
Registered as the tag's cloneFunc. Copies the proto's IoFileData (so path/mode come along) but resets stream, stat-info pointer, and flags — the clone is not yet open even if the proto was. This is why `File clone open` reliably produces a freshly opened file.
Inverse of writeToStream: restores path and mode from a binary stream. Leaves the FILE* null; the caller must open the file explicitly.
Shared helper behind readBufferOfLength and readStringOfLength: reads up to the length argument from the current stream into a new UArray. Returns NULL (not nil) at EOF so callers can distinguish "read nothing" from "error", which IoState_error_ converts to an Io exception.
Installs the stat-related method table on the File proto. Called from IoFile_proto after the core methods are registered so the two tables coexist on a single proto without either module needing to know the other's contents.
Returns the cached struct stat, calling IoFile_stat first if no buffer has been populated yet. All Io-level stat-field accessors funnel through this so they share one populated buffer per File.
Persists a File's path and mode through the binary-stream serializer. The live FILE* is not persisted — on read the file must be reopened. Currently only reachable if File is wired as a tag's writeFunc.
Internal helper: returns nonzero if stat(path) succeeds. Small wrapper so the existence check is expressed uniformly across this module.
Small POSIX helper: widens a time_t-only timestamp into the struct timeval that IoDate_newWithTimeval_ wants. The companion timespec2timeval is only compiled on platforms that expose the higher- resolution stat timestamps.