On this page
- tecs.io.files
Functions
- assetPath
- assetRoot
- basePath
- cachePath
- copy
- createDirectory
- createSymlink
- createTemporaryDirectory
- createTemporaryFile
- currentDirectory
- exists
- glob
- info
- isDirectory
- isFile
- isSymlink
- lines
- load
- open
- preferenceIdentity
- preferencePath
- read
- readInto
- readLink
- remove
- rename
- setAssetRoot
- setPreferenceIdentity
- setReadOnly
- userFolder
- writablePath
- write
- writeAtomic
tecs.io.files
Resolves game paths and performs complete filesystem operations.
Use assetPath for shipped content, writablePath for persistent mutable state, and cachePath for data the application can reconstruct. Set the publisher and game names before resolving the first writable path:
local files <const> = tecs.io.files
files.setPreferenceIdentity("Ex Nihilo", "Starfarer")
local directory <const> = files.writablePath("saves")
local ok, reason = files.createDirectory(directory)
if not ok then
error(reason)
end
local path <const> = files.writablePath("saves/slot1.json")
local bytes <const> = tecs.data.encodeJSON({level = 3, hp = 100})
ok, reason = files.writeAtomic(path, bytes)
if not ok then
error(reason)
endFilesystem outcomes return a status and a platform reason. Invalid arguments raise because they indicate a defect in the calling program. An atomic write inside a system moves its commit to a worker and suspends the system until the result is ready. glob exposes a caller-owned pull stream so recursive enumeration does not retain a complete tree. Temporary files, temporary directories, and streams are Closeable and fit directly in tecs.scoped.
Every operation that accepts a filesystem location accepts either a string or an immutable Path. String results remain useful at Lua and platform boundaries; wrap one with tecs.io.Path.new when the next operation benefits from component-aware manipulation.
tecs.io.watcher polls paths recorded by read and the built-in asset loaders. It does not walk the whole asset tree.
open uses the standard Lua modes and returns one seekable file cursor. The SDL backend operates on the file directly. A storage backend without random access falls back to its required whole-file operations and retains the bytes until the file closes.
Module contents
Types
| Type | Kind | Description |
|---|---|---|
DirectoryEntry |
record | DirectoryEntry describes one streamed child. |
DirectoryStream |
record | DirectoryStream is a caller-owned pull cursor over directory entries. |
File |
interface | File is the seekable cursor returned by open. |
FileMode |
enum | FileMode selects standard read, write, append, or update behavior. |
GlobOptions |
record | GlobOptions controls pattern matching and traversal depth. |
Info |
record | Info describes one resolved path. |
LineIterator |
type | LineIterator yields each line in a file and returns nil at the end. |
PathInput |
type | PathInput accepts either a platform path string or an immutable path object. |
PathType |
enum | PathType identifies a file, directory or other platform object after following symbolic links. |
SymlinkKind |
enum | SymlinkKind selects a file or directory symbolic link. |
TemporaryOptions |
record | TemporaryOptions selects generated-name details. |
TemporaryPath |
record | TemporaryPath owns an automatically removed file or directory. |
UserFolder |
enum | UserFolder identifies a well-known platform folder. |
Functions
| Function | Kind | Description |
|---|---|---|
assetPath |
Static | Resolves relative against the asset root. |
assetRoot |
Static | Returns the root from which the engine reads content. |
basePath |
Static | Returns the directory that contains the executable. |
cachePath |
Static | Returns the system cache directory for this application and creates it if absent. |
copy |
Static | Copies the file at from to to, replacing whatever was at to. |
createDirectory |
Static | Creates path, and any parents it needs. |
createSymlink |
Static | Creates a symbolic link to a file or directory. |
createTemporaryDirectory |
Static | Creates an empty temporary directory owned by the returned resource. |
createTemporaryFile |
Static | Creates an empty temporary file owned by the returned resource. |
currentDirectory |
Static | Returns the process working directory. |
exists |
Static | Returns whether anything occupies path. |
glob |
Static | Opens a pull stream over entries under path that match pattern. |
info |
Static | Returns information about path, or nil when nothing occupies it. |
isDirectory |
Static | Returns whether path resolves to a directory. |
isFile |
Static | Returns whether path resolves to a regular file. |
isSymlink |
Static | Returns whether the final object named by path is a symbolic link. |
lines |
Static | Iterates over the lines in a whole file. |
load |
Static | Compiles a Lua file without running it. |
open |
Static | Opens a file through one seekable cursor. |
preferenceIdentity |
Static | Returns the publisher and game names used for writable user data. |
preferencePath |
Static | Returns the writable directory for this application and creates it if absent. |
read |
Static | Reads a whole file and returns its bytes, or nil when there is none there. |
readInto |
Static | Reads a whole file directly into an owned buffer. |
readLink |
Static | Returns the target spelling stored in a symbolic link. |
remove |
Static | Removes a file, or an empty directory. |
rename |
Static | Moves from to to, replacing whatever was at to. |
setAssetRoot |
Static | Overrides the asset root, for a test or a tool. |
setPreferenceIdentity |
Static | Sets the publisher and game names used for writable user data. |
setReadOnly |
Static | Changes the portable read-only state of a path. |
userFolder |
Static | Returns one of the platform's well-known folders. |
writablePath |
Static | Resolves relative against the writable root. |
write |
Static | Writes bytes to a file, replacing its complete contents. |
writeAtomic |
Static | Durably and atomically writes a complete file. |
Types
tecs.io.files.DirectoryEntry record
DirectoryEntry describes one streamed child.
record tecs.io.files.DirectoryEntry
path: Path
name: string
kind: storagebackend.PathType
depth: integer
symlink: boolean
endtecs.io.files.DirectoryEntry.path field
Read-only. Contains the complete immutable path to this entry.
tecs.io.files.DirectoryEntry.path: Pathtecs.io.files.DirectoryEntry.name field
Read-only. Contains the entry name relative to its immediate parent.
tecs.io.files.DirectoryEntry.name: stringtecs.io.files.DirectoryEntry.kind field
Read-only. Identifies the resolved object's kind.
tecs.io.files.DirectoryEntry.kind: storagebackend.PathTypetecs.io.files.DirectoryEntry.depth field
Read-only. Reports one for an immediate child and increases during a recursive glob.
tecs.io.files.DirectoryEntry.depth: integertecs.io.files.DirectoryEntry.symlink field
Read-only. Reports whether the final path itself is a symbolic link.
tecs.io.files.DirectoryEntry.symlink: booleantecs.io.files.DirectoryStream record
DirectoryStream is a caller-owned pull cursor over directory entries.
record tecs.io.files.DirectoryStream is Closeable
close: function(self): boolean, string
next: function(self): DirectoryEntry, string
skipDirectory: function(self): boolean
toArray: function(self): {DirectoryEntry}, string
endInterfaces
| Interface |
|---|
Closeable |
tecs.io.files.DirectoryStream:close Instance
function tecs.io.files.DirectoryStream.close(self): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
self |
DirectoryStream |
Returns
| Type | Description |
|---|---|
boolean |
|
string |
tecs.io.files.DirectoryStream:next Instance
Returns the next entry.
function tecs.io.files.DirectoryStream.next(
self
): DirectoryEntry, stringArguments
| Name | Type | Description |
|---|---|---|
self |
DirectoryStream |
The open stream to advance. |
Returns
| Type | Description |
|---|---|
DirectoryEntry |
Returns the next entry, or nil at the end or after close. |
string |
Returns a platform reason when traversal fails. Nil means end of stream. |
tecs.io.files.DirectoryStream:skipDirectory Instance
Prevents descent into the directory returned by the preceding next call.
The method returns false when the preceding entry was not a directory, was a symbolic link, had no deeper pattern component, or has already been skipped. Calling next first makes an earlier directory no longer eligible for pruning.
function tecs.io.files.DirectoryStream.skipDirectory(self): booleanArguments
| Name | Type | Description |
|---|---|---|
self |
DirectoryStream |
The open stream whose pending descent the caller controls. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether a pending directory descent was removed. |
tecs.io.files.DirectoryStream:toArray Instance
Consumes the remaining entries into an array and closes the stream.
Entries returned by earlier next calls are not repeated. A traversal failure discards the partial array and closes the stream.
function tecs.io.files.DirectoryStream.toArray(
self
): {DirectoryEntry}, stringArguments
| Name | Type | Description |
|---|---|---|
self |
DirectoryStream |
The open stream to consume. |
Returns
| Type | Description |
|---|---|
{DirectoryEntry} |
Returns every remaining entry, or nil when traversal fails. |
string |
Returns the platform reason when the first return is nil. |
tecs.io.files.File interface
File is the seekable cursor returned by open.
interface tecs.io.files.File is types.SeekableReader, types.SeekableWriter
endInterfaces
| Interface |
|---|
types.SeekableReader |
types.SeekableWriter |
tecs.io.files.FileMode enum
FileMode selects standard read, write, append, or update behavior.
enum tecs.io.files.FileMode
"a"
"a+"
"r"
"r+"
"w"
"w+"
endtecs.io.files.GlobOptions record
GlobOptions controls pattern matching and traversal depth.
record tecs.io.files.GlobOptions
caseInsensitive: boolean
maxDepth: integer
endtecs.io.files.GlobOptions.caseInsensitive field
Caller-writable. Matches ASCII letters without regard to case when true. Defaults to false, which compares every UTF-8 codepoint exactly on every platform including the ones whose filesystem is not.
tecs.io.files.GlobOptions.caseInsensitive: booleantecs.io.files.GlobOptions.maxDepth field
Caller-writable. Limits traversal to this many levels below the root. Zero yields no entries, one yields immediate children, and nil permits unlimited traversal. Defaults to nil.
tecs.io.files.GlobOptions.maxDepth: integertecs.io.files.Info record
Info describes one resolved path.
record tecs.io.files.Info
kind: PathType
size: integer
createdAt: number
modifiedAt: number
accessedAt: number
readOnly: boolean
endtecs.io.files.Info.kind field
Read-only. Identifies the resolved platform object's kind.
tecs.io.files.Info.size field
Read-only. Reports size in bytes. Zero for a directory.
tecs.io.files.Info.createdAt field
Read-only. Reports nanoseconds since the epoch as a double. Zero means the platform or filesystem does not record a creation time.
tecs.io.files.Info.modifiedAt field
Read-only. Reports modification time in nanoseconds since the epoch.
tecs.io.files.Info.modifiedAt: numbertecs.io.files.Info.accessedAt field
Read-only. Reports access time in nanoseconds since the epoch.
tecs.io.files.Info.accessedAt: numbertecs.io.files.Info.readOnly field
Read-only. Reports the portable read-only state of the resolved path.
tecs.io.files.LineIterator type
LineIterator yields each line in a file and returns nil at the end.
type tecs.io.files.LineIterator = function(): stringtecs.io.files.PathInput type
PathInput accepts either a platform path string or an immutable path object.
type tecs.io.files.PathInput = string | Pathtecs.io.files.PathType enum
PathType identifies a file, directory or other platform object after following symbolic links.
enum tecs.io.files.PathType
"directory"
"file"
"other"
endtecs.io.files.SymlinkKind enum
SymlinkKind selects a file or directory symbolic link.
enum tecs.io.files.SymlinkKind
"directory"
"file"
endtecs.io.files.TemporaryOptions record
TemporaryOptions selects generated-name details.
tecs.io.files.TemporaryOptions.directory field
Caller-writable. Selects the parent directory. Nil uses the operating system's temporary directory.
tecs.io.files.TemporaryOptions.directory: string | Pathtecs.io.files.TemporaryOptions.prefix field
Caller-writable. Prefixes the generated name. Defaults to "tecs-".
tecs.io.files.TemporaryOptions.prefix: stringtecs.io.files.TemporaryOptions.suffix field
Caller-writable. Suffixes the generated name. Defaults to an empty string.
tecs.io.files.TemporaryOptions.suffix: stringtecs.io.files.TemporaryPath record
TemporaryPath owns an automatically removed file or directory.
record tecs.io.files.TemporaryPath is Closeable
path: Path
close: function(self): boolean, string
persist: function(self, destination: string | Path): boolean, string
endInterfaces
| Interface |
|---|
Closeable |
tecs.io.files.TemporaryPath.path field
Read-only. Contains the exclusively created path.
tecs.io.files.TemporaryPath.path: Pathtecs.io.files.TemporaryPath:close Instance
function tecs.io.files.TemporaryPath.close(self): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
self |
TemporaryPath |
Returns
| Type | Description |
|---|---|
boolean |
|
string |
tecs.io.files.TemporaryPath:persist Instance
Moves the resource to a permanent, absent destination and relinquishes cleanup.
function tecs.io.files.TemporaryPath.persist(
self, destination: string | Path
): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
self |
TemporaryPath |
The open temporary resource. |
destination |
string | Path |
The caller supplies a destination which must not exist. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the resource became permanent. |
string |
Returns the platform reason when the first return is false. |
tecs.io.files.UserFolder enum
UserFolder identifies a well-known platform folder.
enum tecs.io.files.UserFolder
"desktop"
"documents"
"downloads"
"home"
"music"
"pictures"
"publicShare"
"savedGames"
"screenshots"
"templates"
"videos"
endFunctions
tecs.io.files.assetPath Static
Resolves relative against the asset root.
function tecs.io.files.assetPath(relative: PathInput): stringArguments
| Name | Type | Description |
|---|---|---|
relative |
PathInput |
The caller supplies a path under the content root with / separators. The function joins it without checking existence. |
Returns
| Type | Description |
|---|---|
string |
Returns the absolute path. |
tecs.io.files.assetRoot Static
Returns the root from which the engine reads content.
function tecs.io.files.assetRoot(): stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns TECS_ASSETS when set, otherwise the host-configured root or basePath. The value stays cached until the platform changes. |
tecs.io.files.basePath Static
Returns the directory that contains the executable.
function tecs.io.files.basePath(): stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns the directory with a trailing separator. It returns an empty string rather than nil when the platform declines to say, which is the case on some targets and is not an error: a caller falls back to a relative path. |
tecs.io.files.cachePath Static
Returns the system cache directory for this application and creates it if absent.
The operating system may empty this directory between any two runs. Store only reconstructable downloads, compiled artifacts, thumbnails and similar derived data here. Saves, settings and other durable state belong under preferencePath.
function tecs.io.files.cachePath(): stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns the directory with a trailing platform separator, named from the preference identity. |
tecs.io.files.copy Static
Copies the file at from to to, replacing whatever was at to.
The function refuses directories and requires an existing destination parent.
Arguments
| Name | Type | Description |
|---|---|---|
from |
PathInput |
The caller supplies the existing source file. |
to |
PathInput |
The caller supplies the destination file to replace. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform copied the file. |
string |
Returns the platform reason when the first return is false. |
tecs.io.files.createDirectory Static
Creates path, and any parents it needs.
It succeeds when the directory already exists.
function tecs.io.files.createDirectory(path: PathInput): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the directory to create. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform created or found the directory. |
string |
Returns the platform reason when the first return is false. |
tecs.io.files.createSymlink Static
Creates a symbolic link to a file or directory.
The target spelling is stored unchanged, so a relative target is resolved from the link's parent when later opened. kind is required because Windows must choose a file or directory link even for a dangling target.
function tecs.io.files.createSymlink(
target: PathInput, link: PathInput, kind: SymlinkKind
): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
target |
PathInput |
The caller supplies the target spelling to store. |
link |
PathInput |
The caller supplies the new link path. |
kind |
SymlinkKind |
The caller supplies "file" or "directory". |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform created the link. |
string |
Returns the platform or unsupported reason when the first return is false. |
tecs.io.files.createTemporaryDirectory Static
Creates an empty temporary directory owned by the returned resource.
Closing recursively removes its contents without following symbolic links. Call persist to keep the complete tree under an absent destination.
function tecs.io.files.createTemporaryDirectory(
options: TemporaryOptions
): TemporaryPath, stringArguments
| Name | Type | Description |
|---|---|---|
options |
TemporaryOptions |
The caller may select the parent, prefix, and suffix. |
Returns
| Type | Description |
|---|---|
TemporaryPath |
Returns the caller-owned temporary directory. |
string |
Returns the platform or unsupported reason when creation fails. |
tecs.io.files.createTemporaryFile Static
Creates an empty temporary file owned by the returned resource.
Creation is exclusive. Closing removes the file; garbage collection is a leak safety net, while tecs.scoped provides deterministic cleanup. Call persist to keep the file under an absent permanent destination.
function tecs.io.files.createTemporaryFile(
options: TemporaryOptions
): TemporaryPath, stringArguments
| Name | Type | Description |
|---|---|---|
options |
TemporaryOptions |
The caller may select the parent, prefix, and suffix. |
Returns
| Type | Description |
|---|---|
TemporaryPath |
Returns the caller-owned temporary file. |
string |
Returns the platform or unsupported reason when creation fails. |
tecs.io.files.currentDirectory Static
Returns the process working directory.
Command-line tools receive relative paths and resolve them against this directory. It is not where a game reads content from or writes state to: assetRoot, preferencePath and cachePath answer that, and say why. A platform with no working directory answers nil, which is most of the ones that are not a desktop.
function tecs.io.files.currentDirectory(): string, stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns the directory with a trailing separator, or nil when the platform has no working directory. |
string |
Returns the platform reason when the first return is nil. |
tecs.io.files.exists Static
Returns whether anything occupies path.
function tecs.io.files.exists(path: PathInput): booleanArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute or platform-resolvable path. |
Returns
| Type | Description |
|---|---|
boolean |
Returns true when the platform finds any object. |
tecs.io.files.glob Static
Opens a pull stream over entries under path that match pattern.
Recursive unless the pattern stops it: with no pattern this walks the whole tree below path. * and ? never match a separator, and ? consumes one UTF-8 codepoint, so "*" is one level, "*/*" is exactly two, and "*.png" matches only immediate children. Results include directories alongside files. Symbolic links are yielded but never followed. The order is the platform's own and is not sorted.
The stream retains only the unvisited names in each directory on its current descent. Close it when leaving early. After receiving a directory, call skipDirectory before next to prune that complete subtree. Call toArray to consume and close the stream when every remaining entry should be retained.
A fixed bound belongs in maxDepth; skipDirectory remains useful when descent depends on the entry itself. The checked example combines both.
function tecs.io.files.glob(
path: PathInput, pattern: string, options: GlobOptions
): DirectoryStream, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the directory to enumerate. |
pattern |
string |
The caller supplies /-separated * and ? wildcards, or nil to include every descendant recursively. |
options |
GlobOptions |
The caller supplies matching and depth options, or omits them for case-sensitive, unlimited traversal. |
Returns
| Type | Description |
|---|---|
DirectoryStream |
Returns a caller-owned stream, or nil when enumeration cannot start. |
string |
Returns the platform reason when the first return is nil. |
Examples
local files <const> = tecs.io.files
tecs.scoped(
"scan levels",
function(scope: tecs.Scope)
local stream, reason = files.glob(
files.assetPath("levels"), nil, {maxDepth = 2}
)
if stream == nil then
error(reason)
end
scope:own(stream)
while true do
local entry, nextReason = stream:next()
if entry == nil then
if nextReason ~= nil then
error(nextReason)
end
break
end
print(entry.depth, entry.path)
if
entry.kind == "directory" and entry.name == "generated"
then
stream:skipDirectory()
end
end
end
)tecs.io.files.info Static
Returns information about path, or nil when nothing occupies it.
Nil is the answer for a path that does not exist, for a broken symbolic link, and when the platform cannot search a directory; the second return separates them.
Arguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute or platform-resolvable path. |
Returns
| Type | Description |
|---|---|
Info |
Returns the path information, or nil when unavailable. |
string |
Returns the platform reason when the first return is nil. |
tecs.io.files.isDirectory Static
Returns whether path resolves to a directory.
function tecs.io.files.isDirectory(path: PathInput): booleanArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute or platform-resolvable path. |
Returns
| Type | Description |
|---|---|
boolean |
Returns true when the resolved object is a directory. |
tecs.io.files.isFile Static
Returns whether path resolves to a regular file.
function tecs.io.files.isFile(path: PathInput): booleanArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute or platform-resolvable path. |
Returns
| Type | Description |
|---|---|
boolean |
Returns true when the resolved object is a regular file. |
tecs.io.files.isSymlink Static
Returns whether the final object named by path is a symbolic link.
Unlike info, this function does not follow the final link. It does follow links in parent directories, so the result is path introspection and not a security boundary. A path that is absent or cannot be inspected returns false.
function tecs.io.files.isSymlink(path: PathInput): booleanArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute or platform-resolvable path. |
Returns
| Type | Description |
|---|---|
boolean |
Returns true when the final path itself is a symbolic link. |
tecs.io.files.lines Static
Iterates over the lines in a whole file.
The function reads and closes the file before it returns the iterator, so breaking the loop retains only the immutable bytes and no file descriptor. It strips LF and CRLF terminators, returns empty lines between adjacent terminators, and does not invent another empty line after a final terminator. Use open when the input is too large to hold whole.
function tecs.io.files.lines(path: PathInput): LineIterator, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the source file. |
Returns
| Type | Description |
|---|---|
LineIterator |
Returns a LineIterator that yields each line in order, or nil when the platform cannot read the file. |
string |
Returns the failure reason when the first return is nil. |
Examples
local files <const> = require("tecs.io.files")
local nextLine <const> = assert(files.lines("save.txt"))
for line in nextLine do
print(line)
endtecs.io.files.load Static
Compiles a Lua file without running it.
The function reads through the installed storage backend rather than loadfile, records the source for file watching, and uses @path as the compiler's chunk name. The default environment is the caller's global environment. A supplied environment is installed exactly as given and is not a security boundary unless the caller makes it one.
function tecs.io.files.load(
path: PathInput, environment: {string: any}
): function(...: any): any..., stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the Lua source file. |
environment |
{string : any} |
The caller supplies the globals visible when the chunk runs, or omits them to use the process globals. |
Returns
| Type | Description |
|---|---|
function(...: any): any... |
Returns the compiled chunk, or nil when reading or compilation fails. Calling the returned function executes the file. |
string |
Returns the read or compiler reason when the first return is nil. |
tecs.io.files.open Static
Opens a file through one seekable cursor.
The mode follows Lua's standard file modes. "r" opens an existing file for reading and is the default. "w" creates or truncates for writing. "a" creates or preserves for writes that always land at the end. Adding + permits both reading and writing. The cursor starts at byte zero except for "a"; "a+" starts at byte zero for reading while every write still lands at the current end. Seeks may not move past the end.
Close the file even after its last write succeeds. close flushes buffered bytes and can report a delayed storage failure. A backend without direct random access retains the complete file until close.
Arguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the file as a string or immutable Path. |
mode |
FileMode |
The caller selects "r", "w", "a", "r+", "w+", or "a+", or omits it for "r". |
Returns
| Type | Description |
|---|---|
File |
Returns a caller-owned File, or nil when the platform cannot open it. |
string |
Returns the platform reason when the first return is nil. |
Examples
local files <const> = require("tecs.io.files")
local file, reason = files.open("world.pack", "w+")
if file == nil then
error(reason)
end
local wrote, writeReason = file:write("HEADpayload bytes")
if not wrote then
file:close()
error(writeReason)
end
local position, seekReason = file:seek("start")
if position == nil then
file:close()
error(seekReason)
end
local header <const> = assert(file:read(4))
assert(header == "HEAD")
local closed, closeReason = file:close()
assert(closed, closeReason)tecs.io.files.preferenceIdentity Static
Returns the publisher and game names used for writable user data.
The pair starts as "tecs", "tecs" and changes when setPreferenceIdentity succeeds.
function tecs.io.files.preferenceIdentity(): string, stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns the current publisher, studio, or organization name. |
string |
Returns the current game or application name. |
tecs.io.files.preferencePath Static
Returns the writable directory for this application and creates it if absent.
function tecs.io.files.preferencePath(): stringArguments
None.
Returns
| Type | Description |
|---|---|
string |
Returns the directory with a trailing separator, named from the preference identity. This is where a build writes durable state; cachePath is the other writable root and holds only reconstructable data. |
tecs.io.files.read Static
Reads a whole file and returns its bytes, or nil when there is none there.
The binary string retains embedded NUL bytes. On the SDL backend the transfer uses SDL AsyncIO, suspending a system or blocking a direct caller while the same private completion advances.
function tecs.io.files.read(
path: PathInput, kind: string
): string, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute path or one from assetPath. |
kind |
string |
The caller supplies the content kind for watching, or omits it to record a document. |
Returns
| Type | Description |
|---|---|
string |
Returns the file bytes, or nil when the platform cannot read them. |
string |
Returns the failure reason when the first return is nil. The reason names the path, and on the SDL backend it carries the operating system's own detail behind it. |
tecs.io.files.readInto Static
Reads a whole file directly into an owned buffer.
The operation preserves bytes before offset, grows the destination as needed, and returns the number of bytes written. On the SDL backend the file transfer runs through SDL AsyncIO and never materializes a Lua string. Inside a system it may suspend the logical update; elsewhere the identical call blocks its caller until the transfer settles.
function tecs.io.files.readInto(
path: PathInput,
destination: IOBuffer,
offset: integer,
kind: string
): integer, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies an absolute path or one from assetPath. |
destination |
IOBuffer |
The caller supplies an open destination buffer and keeps ownership of it. |
offset |
integer |
The caller supplies a zero-based destination offset or omits it for zero. |
kind |
string |
The caller supplies the content kind for watching, or omits it to record a document. |
Returns
| Type | Description |
|---|---|
integer |
Returns the number of bytes copied into the destination. |
string |
Returns the platform reason when the first return is nil. |
tecs.io.files.readLink Static
Returns the target spelling stored in a symbolic link.
A relative target remains relative. The function does not resolve it against the link's parent and fails when path is not a symbolic link.
Arguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the symbolic link to inspect. |
Returns
| Type | Description |
|---|---|
Path |
Returns the stored target as an immutable Path. |
string |
Returns the platform or unsupported reason when the first return is nil. |
tecs.io.files.remove Static
Removes a file, or an empty directory.
It does not recurse and fails on a directory with anything in it. It succeeds when there is nothing at path: the result says the path is gone, not that this call is what removed it.
Emptying a tree requires a glob and a deepest-first loop:
local stream = assert(files.glob(root)) local paths = {} while true do local entry, reason = stream:next() if entry == nil then if reason ~= nil then error(reason) end break end paths[#paths + 1] = entry.path end stream:close() table.sort(paths, function(a, b) return #(a:toString()) > #(b:toString()) end) for _, path in ipairs(paths) do files.remove(path) end files.remove(root)
function tecs.io.files.remove(path: PathInput): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the file or empty directory to remove. |
Returns
| Type | Description |
|---|---|
boolean |
Returns true when nothing remains at path. |
string |
Returns the platform reason when the first return is false. |
tecs.io.files.rename Static
Moves from to to, replacing whatever was at to.
Directories move as well as files, and an existing destination is overwritten with no warning and nothing to undo it. Whether this works across filesystems is the platform's business.
Arguments
| Name | Type | Description |
|---|---|---|
from |
PathInput |
The caller supplies the existing source path. |
to |
PathInput |
The caller supplies the destination path to replace. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform moved the path. |
string |
Returns the platform reason when the first return is false. |
tecs.io.files.setAssetRoot Static
Overrides the asset root, for a test or a tool.
function tecs.io.files.setAssetRoot(root: PathInput)Arguments
| Name | Type | Description |
|---|---|---|
root |
PathInput |
The caller supplies the new content directory. The function adds a trailing separator only when needed. |
Returns
None.
tecs.io.files.setPreferenceIdentity Static
Sets the publisher and game names used for writable user data.
SDL combines these values with the current user and platform conventions to choose the directory returned by preferencePath. The defaults are "tecs" and "tecs". Later calls change which directory the next preferencePath, writablePath, or cachePath resolves.
function tecs.io.files.setPreferenceIdentity(
organization: string, application: string
)Arguments
| Name | Type | Description |
|---|---|---|
organization |
string |
The caller supplies a non-empty publisher, studio, or organization name. |
application |
string |
The caller supplies a non-empty game or application name. |
Returns
None.
tecs.io.files.setReadOnly Static
Changes the portable read-only state of a path.
On Unix, making a path read-only clears every write bit and making it writable restores only the owner's write bit. The API deliberately does not model platform ACLs, ownership, or executable bits.
function tecs.io.files.setReadOnly(
path: PathInput, readOnly: boolean
): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the existing path to change. |
readOnly |
boolean |
The caller supplies true to prevent ordinary writes. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform changed the state. |
string |
Returns the platform or unsupported reason when the first return is false. |
tecs.io.files.userFolder Static
Returns one of the platform's well-known folders.
Often nil, and legitimately so. A platform that has no such concept says so rather than inventing a path: macOS has no saved-games, screenshots or templates folder and answers nil for all three, and a platform that is not a desktop may have none of them. Treat every one of these as absent until it is not, and never as a place a build may write; preferencePath and cachePath are the two writable roots, with different durability.
function tecs.io.files.userFolder(which: UserFolder): string, stringArguments
| Name | Type | Description |
|---|---|---|
which |
UserFolder |
The caller supplies the well-known folder to resolve. |
Returns
| Type | Description |
|---|---|
string |
Returns the folder with a trailing separator, or nil when the platform has no matching folder. |
string |
Returns the platform reason when the first return is nil. |
tecs.io.files.writablePath Static
Resolves relative against the writable root.
function tecs.io.files.writablePath(relative: PathInput): stringArguments
| Name | Type | Description |
|---|---|---|
relative |
PathInput |
The caller supplies a path under the preference directory. |
Returns
| Type | Description |
|---|---|
string |
Returns the absolute path. |
tecs.io.files.write Static
Writes bytes to a file, replacing its complete contents.
The default SDL backend transfers through its bounded asynchronous file queue. The call suspends a logical update or blocks an ordinary caller until the complete write settles. It retains an immutable source range for SDL instead of copying a buffer through a Lua string. Embedded NUL bytes remain data and an empty input creates an empty file.
function tecs.io.files.write(
path: PathInput, bytes: storagebackend.ByteInput
): boolean, stringArguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the destination file. |
bytes |
storagebackend.ByteInput |
The caller supplies an immutable string or byte view and retains ownership. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform wrote the complete file. |
string |
Returns the platform reason when the first return is false. |
tecs.io.files.writeAtomic Static
Durably and atomically writes a complete file.
Inside a system on the SDL storage backend, the copy and commit run on a worker and suspend the logical world update. Outside a world update, the same call completes synchronously. Buffers and views are copied before a suspended write begins.
Arguments
| Name | Type | Description |
|---|---|---|
path |
PathInput |
The caller supplies the destination file. |
bytes |
ByteInput |
The caller supplies the complete binary contents. |
Returns
| Type | Description |
|---|---|
boolean |
Returns whether the platform confirmed the atomic durable write. |
string |
Returns the platform or unsupported reason when the first return is false. |
Examples
local save <const> = tecs.io.Path.new(
tecs.io.files.writablePath("saves"), "slot1.bin"
)
local ok, reason = tecs.io.files.writeAtomic(save, "snapshot bytes")
if not ok then
error(reason)
end