Packages

Complete, safe, ergonomic file operations for all Gleam targets

Current section

Files

Jump to
fio src fio.erl
Raw

src/fio.erl

-module(fio).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/fio.gleam").
-export([read/1, read_bits/1, write/2, write_bits/2, append/2, append_bits/2, write_atomic/2, write_bits_atomic/2, delete/1, delete_directory/1, delete_all/1, exists/1, file_info/1, link_info/1, is_directory/1, is_file/1, is_symlink/1, copy/2, rename/2, create_symlink/2, create_hard_link/2, read_link/1, set_permissions/2, set_permissions_octal/2, create_directory/1, create_directory_all/1, list/1, current_directory/0, tmp_dir/0, touch/1, with_temp_file/1, with_temp_directory/1, list_recursive/1, copy_directory/2, checksum/2, verify_checksum/3, join/2, split/1, base_name/1, directory_name/1, extension/1, strip_extension/1, stem/1, with_extension/2, join_all/1, is_absolute/1, expand/1, safe_relative/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
-file("src/fio.gleam", 11).
?DOC(" Read a UTF-8 text file. Returns `NotUtf8(path)` on invalid UTF-8.\n").
-spec read(binary()) -> {ok, binary()} | {error, fio@error:fio_error()}.
read(Path) ->
fio@internal@io:read(Path).
-file("src/fio.gleam", 16).
?DOC(" Read a file as raw bytes (`BitArray`).\n").
-spec read_bits(binary()) -> {ok, bitstring()} | {error, fio@error:fio_error()}.
read_bits(Path) ->
fio@internal@io:read_bits(Path).
-file("src/fio.gleam", 23).
?DOC(" Write UTF-8 text to a file (creates/overwrites).\n").
-spec write(binary(), binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
write(Path, Content) ->
fio@internal@io:write(Path, Content).
-file("src/fio.gleam", 28).
?DOC(" Write raw bytes (`BitArray`) to a file (creates/overwrites).\n").
-spec write_bits(binary(), bitstring()) -> {ok, nil} |
{error, fio@error:fio_error()}.
write_bits(Path, Content) ->
fio@internal@io:write_bits(Path, Content).
-file("src/fio.gleam", 33).
?DOC(" Append UTF-8 text to a file (creates if missing).\n").
-spec append(binary(), binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
append(Path, Content) ->
fio@internal@io:append(Path, Content).
-file("src/fio.gleam", 38).
?DOC(" Append raw bytes (`BitArray`) to a file.\n").
-spec append_bits(binary(), bitstring()) -> {ok, nil} |
{error, fio@error:fio_error()}.
append_bits(Path, Content) ->
fio@internal@io:append_bits(Path, Content).
-file("src/fio.gleam", 45).
?DOC(
" Write UTF-8 text atomically: writes to a sibling temp file, then renames\n"
" it into place with a single `rename(2)` syscall.\n"
" Readers never observe partial content. Returns `AtomicFailed` on error.\n"
).
-spec write_atomic(binary(), binary()) -> {ok, nil} |
{error, fio@error:fio_error()}.
write_atomic(Path, Content) ->
fio@internal@io:write_atomic(Path, Content).
-file("src/fio.gleam", 51).
?DOC(
" Write raw bytes (`BitArray`) atomically.\n"
" Same atomic guarantee as `write_atomic`.\n"
).
-spec write_bits_atomic(binary(), bitstring()) -> {ok, nil} |
{error, fio@error:fio_error()}.
write_bits_atomic(Path, Content) ->
fio@internal@io:write_bits_atomic(Path, Content).
-file("src/fio.gleam", 61).
?DOC(" Delete a file (not a directory).\n").
-spec delete(binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
delete(Path) ->
fio@internal@io:delete_file(Path).
-file("src/fio.gleam", 66).
?DOC(" Delete an empty directory.\n").
-spec delete_directory(binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
delete_directory(Path) ->
fio@internal@io:delete_directory(Path).
-file("src/fio.gleam", 71).
?DOC(" Delete a path recursively; idempotent (succeeds if missing).\n").
-spec delete_all(binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
delete_all(Path) ->
fio@internal@io:delete_recursive(Path).
-file("src/fio.gleam", 78).
?DOC(" Check if a path exists (file, directory, or symlink).\n").
-spec exists(binary()) -> boolean().
exists(Path) ->
fio@internal@io:exists(Path).
-file("src/fio.gleam", 83).
?DOC(" Get file metadata (follows symlinks).\n").
-spec file_info(binary()) -> {ok, fio@types:file_info()} |
{error, fio@error:fio_error()}.
file_info(Path) ->
fio@internal@io:file_info(Path).
-file("src/fio.gleam", 88).
?DOC(" Get file metadata without following symlinks.\n").
-spec link_info(binary()) -> {ok, fio@types:file_info()} |
{error, fio@error:fio_error()}.
link_info(Path) ->
fio@internal@io:link_info(Path).
-file("src/fio.gleam", 93).
?DOC(" Check if a path is a directory (follows symlinks).\n").
-spec is_directory(binary()) -> {ok, boolean()} | {error, fio@error:fio_error()}.
is_directory(Path) ->
fio@internal@io:is_directory(Path).
-file("src/fio.gleam", 98).
?DOC(" Check if a path is a regular file (follows symlinks).\n").
-spec is_file(binary()) -> {ok, boolean()} | {error, fio@error:fio_error()}.
is_file(Path) ->
fio@internal@io:is_file(Path).
-file("src/fio.gleam", 103).
?DOC(" Check if a path is a symbolic link (does not follow symlinks).\n").
-spec is_symlink(binary()) -> {ok, boolean()} | {error, fio@error:fio_error()}.
is_symlink(Path) ->
fio@internal@io:is_symlink(Path).
-file("src/fio.gleam", 110).
?DOC(" Copy a file from source to destination.\n").
-spec copy(binary(), binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
copy(Src, Dest) ->
fio@internal@io:copy_file(Src, Dest).
-file("src/fio.gleam", 115).
?DOC(" Rename or move a file or directory.\n").
-spec rename(binary(), binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
rename(Src, Dest) ->
fio@internal@io:rename(Src, Dest).
-file("src/fio.gleam", 122).
?DOC(" Create a symbolic link.\n").
-spec create_symlink(binary(), binary()) -> {ok, nil} |
{error, fio@error:fio_error()}.
create_symlink(Target, Link) ->
fio@internal@io:create_symlink(Target, Link).
-file("src/fio.gleam", 130).
?DOC(" Create a hard link to an existing file.\n").
-spec create_hard_link(binary(), binary()) -> {ok, nil} |
{error, fio@error:fio_error()}.
create_hard_link(Target, Link) ->
fio@internal@io:create_hard_link(Target, Link).
-file("src/fio.gleam", 138).
?DOC(" Read the target path of a symbolic link.\n").
-spec read_link(binary()) -> {ok, binary()} | {error, fio@error:fio_error()}.
read_link(Path) ->
fio@internal@io:read_link(Path).
-file("src/fio.gleam", 145).
?DOC(" Set file permissions using the `FilePermissions` type.\n").
-spec set_permissions(binary(), fio@types:file_permissions()) -> {ok, nil} |
{error, fio@error:fio_error()}.
set_permissions(Path, Permissions) ->
fio@internal@io:set_permissions(Path, Permissions).
-file("src/fio.gleam", 153).
?DOC(" Set file permissions with an octal integer.\n").
-spec set_permissions_octal(binary(), integer()) -> {ok, nil} |
{error, fio@error:fio_error()}.
set_permissions_octal(Path, Mode) ->
fio@internal@io:set_permissions_octal(Path, Mode).
-file("src/fio.gleam", 160).
?DOC(" Create a directory. Parent directory must exist.\n").
-spec create_directory(binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
create_directory(Path) ->
fio@internal@io:create_directory(Path).
-file("src/fio.gleam", 165).
?DOC(" Create a directory and all parent directories.\n").
-spec create_directory_all(binary()) -> {ok, nil} |
{error, fio@error:fio_error()}.
create_directory_all(Path) ->
fio@internal@io:create_directory_all(Path).
-file("src/fio.gleam", 170).
?DOC(" List the contents of a directory (names only).\n").
-spec list(binary()) -> {ok, list(binary())} | {error, fio@error:fio_error()}.
list(Path) ->
fio@internal@io:list_directory(Path).
-file("src/fio.gleam", 177).
?DOC(" Get the current working directory.\n").
-spec current_directory() -> {ok, binary()} | {error, fio@error:fio_error()}.
current_directory() ->
fio@internal@io:current_directory().
-file("src/fio.gleam", 182).
?DOC(" Get the system temporary directory path.\n").
-spec tmp_dir() -> binary().
tmp_dir() ->
fio@internal@io:tmp_dir().
-file("src/fio.gleam", 187).
?DOC(" Touch a file: create or update modification time.\n").
-spec touch(binary()) -> {ok, nil} | {error, fio@error:fio_error()}.
touch(Path) ->
fio@internal@io:touch(Path).
-file("src/fio.gleam", 195).
?DOC(
" Run a callback with a path to a temporary file that is automatically\n"
" deleted when the callback returns (even if it returns an Error).\n"
).
-spec with_temp_file(
fun((binary()) -> {ok, EQG} | {error, fio@error:fio_error()})
) -> {ok, EQG} | {error, fio@error:fio_error()}.
with_temp_file(Callback) ->
Path = fio@path:join(
fio@internal@io:tmp_dir(),
fio_ffi:unique_name(<<"fio_tmp_file_"/utf8>>)
),
Result = Callback(Path),
_ = fio@internal@io:delete_file(Path),
Result.
-file("src/fio.gleam", 208).
?DOC(
" Run a callback with a path to a temporary directory that is automatically\n"
" deleted (recursively) when the callback returns.\n"
).
-spec with_temp_directory(
fun((binary()) -> {ok, EQL} | {error, fio@error:fio_error()})
) -> {ok, EQL} | {error, fio@error:fio_error()}.
with_temp_directory(Callback) ->
Path = fio@path:join(
fio@internal@io:tmp_dir(),
fio_ffi:unique_name(<<"fio_tmp_dir_"/utf8>>)
),
Result = begin
_pipe = fio@internal@io:create_directory(Path),
gleam@result:'try'(_pipe, fun(_) -> Callback(Path) end)
end,
_ = fio@internal@io:delete_recursive(Path),
Result.
-file("src/fio.gleam", 224).
?DOC(" Recursively list files and directories (paths relative to `path`).\n").
-spec list_recursive(binary()) -> {ok, list(binary())} |
{error, fio@error:fio_error()}.
list_recursive(Path) ->
fio@recursive:list_recursive(Path).
-file("src/fio.gleam", 229).
?DOC(" Recursively copy a directory and its contents.\n").
-spec copy_directory(binary(), binary()) -> {ok, nil} |
{error, fio@error:fio_error()}.
copy_directory(Src, Dest) ->
fio@recursive:copy_directory(Src, Dest).
-file("src/fio.gleam", 237).
?DOC(
" Compute a file checksum using the specified algorithm.\n"
" Returns a hex-encoded string.\n"
).
-spec checksum(binary(), fio@types:hash_algorithm()) -> {ok, binary()} |
{error, fio@error:fio_error()}.
checksum(Path, Algorithm) ->
Algo_str = case Algorithm of
sha256 ->
<<"sha256"/utf8>>;
sha512 ->
<<"sha512"/utf8>>;
md5 ->
<<"md5"/utf8>>
end,
fio@internal@io:checksum(Path, Algo_str).
-file("src/fio.gleam", 250).
?DOC(" Verify that a file's checksum matches the expected hex-encoded hash.\n").
-spec verify_checksum(binary(), binary(), fio@types:hash_algorithm()) -> {ok,
boolean()} |
{error, fio@error:fio_error()}.
verify_checksum(Path, Expected, Algorithm) ->
_pipe = checksum(Path, Algorithm),
gleam@result:map(_pipe, fun(Actual) -> Actual =:= Expected end).
-file("src/fio.gleam", 262).
?DOC(" Join two path segments.\n").
-spec join(binary(), binary()) -> binary().
join(Left, Right) ->
fio@path:join(Left, Right).
-file("src/fio.gleam", 267).
?DOC(" Split a path into its segments.\n").
-spec split(binary()) -> list(binary()).
split(Path_str) ->
fio@path:split(Path_str).
-file("src/fio.gleam", 272).
?DOC(" Get the base name (filename) of a path.\n").
-spec base_name(binary()) -> binary().
base_name(Path_str) ->
fio@path:base_name(Path_str).
-file("src/fio.gleam", 277).
?DOC(" Get the directory portion of a path.\n").
-spec directory_name(binary()) -> binary().
directory_name(Path_str) ->
fio@path:directory_name(Path_str).
-file("src/fio.gleam", 282).
?DOC(" Get the file extension (without dot).\n").
-spec extension(binary()) -> {ok, binary()} | {error, nil}.
extension(Path_str) ->
fio@path:extension(Path_str).
-file("src/fio.gleam", 287).
?DOC(" Remove the extension from a path.\n").
-spec strip_extension(binary()) -> binary().
strip_extension(Path_str) ->
fio@path:strip_extension(Path_str).
-file("src/fio.gleam", 292).
?DOC(" Get the stem (filename without extension).\n").
-spec stem(binary()) -> binary().
stem(Path_str) ->
fio@path:stem(Path_str).
-file("src/fio.gleam", 297).
?DOC(" Change the extension of a path.\n").
-spec with_extension(binary(), binary()) -> binary().
with_extension(Path_str, Ext) ->
fio@path:with_extension(Path_str, Ext).
-file("src/fio.gleam", 302).
?DOC(" Join a list of path segments.\n").
-spec join_all(list(binary())) -> binary().
join_all(Segments) ->
fio@path:join_all(Segments).
-file("src/fio.gleam", 307).
?DOC(" Check if a path is absolute.\n").
-spec is_absolute(binary()) -> boolean().
is_absolute(Path_str) ->
fio@path:is_absolute(Path_str).
-file("src/fio.gleam", 313).
?DOC(
" Expand/normalize a path, resolving `.` and `..` segments.\n"
" Returns `Error(Nil)` if `..` would go above the root.\n"
).
-spec expand(binary()) -> {ok, binary()} | {error, nil}.
expand(Path_str) ->
fio@path:expand(Path_str).
-file("src/fio.gleam", 319).
?DOC(
" Validate that a path is a safe relative path (does not escape root).\n"
" On Windows it also normalizes backslashes into `/`.\n"
).
-spec safe_relative(binary()) -> {ok, binary()} | {error, nil}.
safe_relative(Path_str) ->
fio@path:safe_relative(Path_str).