No matching definitions.

tur/fs

stdlib/fs.tur

extended file-system operations (stat, readdir, fnmatch, walk).

Higher-level wrappers around sys/stat.h, dirent.h, and fnmatch.h.

Since: Phase B1

defopaque

StatInfo

(defopaque StatInfo :int)
defopaque linear

TmpFile

(defopaque TmpFile :int :linear)
defn

fs/stat

(fs/stat [path :cstr])

return file metadata for a path.

pathNUL-terminated path cstr

(Ok info) -- a StatInfo; inspect it with fs/stat-size, fs/stat-mtime, fs/stat-atime, fs/stat-mode, fs/stat-perms and fs/stat-kind, and release it with fs/stat-free -- or (Err e) when the path is inaccessible. A symlink is followed; fs/lstat describes the link itself.

(match (fs/stat "/etc/hosts")
  (Ok s)  (do (println (fs/stat-size s)) (fs/stat-free s))
  (Err e) (println (io-error/message e)))

Since: Phase B2

defn

fs/stat-free

(fs/stat-free [s :StatInfo] :void)

free the stat result returned by fs/stat.

sa StatInfo from a successful fs/stat
(fs/stat-free s)

Since: Phase B2

defn

fs/stat-size

(fs/stat-size [s :StatInfo] :int)

extract file size from a stat result.

sstat pointer from fs/stat

File size in bytes as :int.

(fs/stat-size info)  ; => 221

Since: Phase B2

defn

fs/stat-mtime

(fs/stat-mtime [s :StatInfo] :int)

extract modification time from a stat result.

sstat pointer from fs/stat

Modification time as a Unix timestamp (:int).

(fs/stat-mtime info)  ; => 1747123456

Since: Phase B2

defn

fs/stat-mode

(fs/stat-mode [s :StatInfo] :int)

extract file mode bits from a stat result.

sstat pointer from fs/stat

File mode bits as :int (same as st_mode from stat(2)).

(fs/stat-mode info)  ; => 33188

Since: Phase B2

defn

fs/stat-atime

(fs/stat-atime [s :StatInfo] :int)

extract the last-access time from a stat result.

sa StatInfo from fs/stat or fs/lstat

Last access time as a Unix timestamp in seconds (:int). Many systems mount with relatime or noatime, so it can lag behind the last read.

(fs/stat-atime info)  ; => 1747123456

Since: stdlib-os-surface P3

defopaque

Mode

(defopaque Mode :int)

the permission bits of a file (rwx for user / group / other, plus setuid, setgid and sticky).

A Mode, not a raw octal int, so fs/chmod's signature says what it takes and a byte count cannot be passed for one. Build one with mode/parse ("rw-r--r--"), adjust it with mode/with / mode/without, read it with mode/has? or mode/format. mode/of-bits and mode/bits convert to and from the st_mode integer for interop.

Since: stdlib-os-surface P3

defdata

PermClass

(defdata PermClass :copy (PermUser) (PermGroup) (PermOther))

whose permission a Mode bit grants: the owning user, the owning group, or everyone else.

Since: stdlib-os-surface P3

defdata

Perm

(defdata Perm :copy (PermRead) (PermWrite) (PermExec))

one permission: read, write or execute (search, on a directory).

Since: stdlib-os-surface P3

defn

mode/of-bits

(mode/of-bits [bits :int] :Mode)

a Mode from st_mode-style permission bits.

bitspermission bits; everything above the low 12 (the file type in a
full st_mode) is dropped

The Mode.

(mode/format (mode/of-bits 420))  ; => "rw-r--r--" (420 is octal 644)

Since: stdlib-os-surface P3

defn

mode/bits

(mode/bits [m :Mode] :int)

the permission bits of a Mode, as an int (octal 7777 at most).

ma Mode

The bits, for interop with C APIs that take a mode_t.

(mode/bits (mode/of-bits 493))  ; => 493 (octal 755)

Since: stdlib-os-surface P3

defn

mode/bit

(mode/bit [who :PermClass p :Perm] :int)

the single st_mode bit for who + perm (internal).

defn

mode/has?

(mode/has? [m :Mode who :PermClass p :Perm] :bool)

does a Mode grant a permission to a class?

ma Mode
whoPermUser, PermGroup or PermOther
pPermRead, PermWrite or PermExec

true when the bit is set.

(mode/has? (mode/of-bits 420) (PermUser) (PermWrite))  ; => true

Since: stdlib-os-surface P3

defn

mode/with

(mode/with [m :Mode who :PermClass p :Perm] :Mode)

a Mode with one more permission granted (chmod who+p).

mthe starting Mode
whoPermUser, PermGroup or PermOther
pPermRead, PermWrite or PermExec

m with the bit set.

(mode/format (mode/with (mode/of-bits 420) (PermUser) (PermExec)))  ; => "rwxr--r--"

Since: stdlib-os-surface P3

defn

mode/without

(mode/without [m :Mode who :PermClass p :Perm] :Mode)

a Mode with one permission removed (chmod who-p).

mthe starting Mode
whoPermUser, PermGroup or PermOther
pPermRead, PermWrite or PermExec

m with the bit cleared.

(mode/format (mode/without (mode/of-bits 420) (PermOther) (PermRead)))  ; => "rw-r-----"

Since: stdlib-os-surface P3

defn

mode/parse

(mode/parse [s :cstr] :(Option Mode))

a Mode from its ls(1) spelling, e.g. "rwxr-xr-x".

Nine characters, rwx for user, group and other, '-' for an unset bit. The execute slots also take ls's s / S (setuid, setgid: with and without execute) and t / T (sticky).

sthe nine-character permission string

(Some mode), or None when s is not exactly that shape.

(mode/parse "rw-r--r--")  ; => (Some mode) with bits 420 (octal 644)

Since: stdlib-os-surface P3

defn

mode/format

(mode/format [m :Mode] :cstr)

the ls(1) spelling of a Mode, e.g. "rwxr-xr-x".

ma Mode

A fresh nine-character heap cstr the caller owns (release with free). Setuid / setgid / sticky show as s / S / t / T, as ls prints them.

(mode/format (mode/of-bits 493))  ; => "rwxr-xr-x"

Since: stdlib-os-surface P3

defn

fs/stat-perms

(fs/stat-perms [s :StatInfo] :Mode)

the permission bits of a stat result, as a Mode.

sa StatInfo from fs/stat or fs/lstat

The Mode (the file-type bits of st_mode are dropped).

(mode/format (fs/stat-perms info))  ; => "rw-r--r--"

Since: stdlib-os-surface P3

defdata

FileKind

(defdata FileKind :copy (KindFile) (KindDir) (KindSymlink) (KindOther))

what a stat result describes.

KindSymlink only ever comes from fs/lstat: fs/stat follows the link. KindOther covers devices, FIFOs and sockets.

Since: stdlib-os-surface P3

defn

fs/stat-kind-code

(fs/stat-kind-code [s :StatInfo] :int)

0 file, 1 dir, 2 symlink, 3 other (internal).

defn

fs/stat-kind

(fs/stat-kind [s :StatInfo] :FileKind)

whether a stat result is a file, directory, symlink or other.

sa StatInfo from fs/stat or fs/lstat

KindFile, KindDir, KindSymlink (from fs/lstat only) or KindOther.

(match (fs/stat-kind info) (KindDir) (println "dir") _ (println "not a dir"))

Since: stdlib-os-surface P3

defn

fs/exists?

(fs/exists? [path :cstr])

test whether a path exists.

pathNUL-terminated path cstr

true if stat(2) succeeds on the path, false otherwise.

(fs/exists? "/etc/hosts")  ; => true

Since: Phase B2

defn

fs/file?

(fs/file? [path :cstr])

test whether a path is a regular file.

pathNUL-terminated path cstr

true if path is a regular file.

(fs/file? "/etc/hosts")  ; => true

Since: Phase B2

defn

fs/dir?

(fs/dir? [path :cstr])

test whether a path is a directory.

pathNUL-terminated path cstr

true if path is a directory.

(fs/dir? "/tmp")  ; => true

Since: Phase B2

defn

fs/mkdir

(fs/mkdir [path :cstr])

create a directory with mode 0755.

pathNUL-terminated path cstr

(Ok nil) on success, or (Err e) carrying the errno.

(fs/mkdir "/tmp/mydir")  ; => (Ok nil)

Since: Phase B2

defn

fs/mkdirp

(fs/mkdirp [path :cstr])

create a directory and all missing parent directories.

pathNUL-terminated path cstr

(Ok nil) on success (including when the directory already exists), or (Err e) for the first mkdir that failed for any other reason.

(fs/mkdirp "/tmp/a/b/c")  ; => (Ok nil)

Since: Phase B2

defn

fs/rmdir

(fs/rmdir [path :cstr])

remove an empty directory.

pathNUL-terminated path cstr

(Ok nil) on success, or (Err e) carrying the errno.

(fs/rmdir "/tmp/mydir")  ; => (Ok nil)

Since: Phase B2

defn

fs/rm

(fs/rm [path :cstr])

remove a regular file.

pathNUL-terminated path cstr

(Ok nil) on success, or (Err e) carrying the errno.

(fs/rm "/tmp/tmpfile.txt")  ; => (Ok nil)

Since: Phase B2

defn

fs/rename

(fs/rename [src :cstr dst :cstr])

rename or move a file.

srcsource path cstr
dstdestination path cstr

(Ok nil) on success, or (Err e) carrying the errno.

(fs/rename "/tmp/a.txt" "/tmp/b.txt")  ; => (Ok nil)

Since: Phase B2

defn

fs/copy

(fs/copy [src :cstr dst :cstr])

copy a file from src to dst using a read/write loop.

srcsource path cstr
dstdestination path cstr

(Ok nil) on success, or (Err e) carrying the errno.

(fs/copy "/etc/hosts" "/tmp/hosts.bak")  ; => (Ok nil)

Since: Phase B2

defn

fs/glob

(fs/glob [dir :cstr pattern :cstr])

list directory entries matching a fnmatch(3) pattern.

dirdirectory to search (e.g., "/tmp")
patternfnmatch pattern applied to entry names (e.g., "*.txt")

(Ok paths) -- a (Vec cstr) of fresh heap-allocated full paths, in directory order; release it with fs/paths-free -- or (Err e) when the directory cannot be opened.

(match (fs/glob "/tmp" "*.txt")
  (Ok v)  (do (println (vec-len v)) (fs/paths-free v))
  (Err e) (println (io-error/message e)))

Since: Phase B2

defn

fs/paths-free

(fs/paths-free [v :(Vec cstr)] :void)

free a (Vec cstr) of owned strings and the Vec itself.

Releases what fs/glob, fs/walk and fs/read-lines hand back (and env/all): every element string, then the vector. Do not use it on a Vec whose strings you did not get from one of those.

va (Vec cstr) whose element strings are heap-owned
(fs/paths-free paths)

Since: stdlib-os-surface P1

defn

fs/tmpfile

(fs/tmpfile)

create a unique temporary file in the system temp directory.

A linear TmpFile handle wrapping a pair { path-cstr, fd }. The path is heap-allocated; the fd is the open descriptor. Release exactly once with fs/tmpfile-free. Returns 0 on failure. The directory is resolved at run time: TMPDIR (else /tmp) on POSIX, GetTempPath on Windows -- never a hardcoded "/tmp", which a native Windows binary would resolve against the current drive root. Under -Xlinear the checker requires the handle be consumed exactly once (dropping it is TUR-E0100; freeing it twice is TUR-E0101).

(let [t (fs/tmpfile)] (fs/tmpfile-free t))

Since: Phase B2

defn

fs/tmpfile-path

(fs/tmpfile-path [^borrow t :TmpFile] :cstr)

extract the path from an fs/tmpfile pair.

ttmpfile pair from fs/tmpfile

The path cstr (owned by the pair; do not free separately).

(fs/tmpfile-path my-tmp)  ; => "/tmp/tur_aB3xYz"

Since: Phase B2

defn

fs/tmpfile-fd

(fs/tmpfile-fd [^borrow t :TmpFile] :Fd)

extract the file descriptor from an fs/tmpfile pair.

ttmpfile pair from fs/tmpfile

The open file descriptor as :int.

(fs/tmpfile-fd my-tmp)  ; => 5

Since: Phase B2

defn

fs/tmpfile-free

(fs/tmpfile-free [t :TmpFile])

close the fd and free the tmpfile pair.

ttmpfile pair from fs/tmpfile (may be 0)
(fs/tmpfile-free my-tmp)

Since: Phase B2

defn

fs/read-text

(fs/read-text [path :cstr])

read an entire file into a NUL-terminated heap buffer.

pathNUL-terminated path cstr

(Ok text) -- a fresh heap-allocated NUL-terminated cstr of the file contents, which the caller owns (release with free) -- or (Err e).

(match (fs/read-text "/etc/hostname")
  (Ok s)  (println s)
  (Err e) (println (io-error/message e)))

Since: Phase B2

defn

fs/write-text

(fs/write-text [path :cstr content :cstr])

write a NUL-terminated string to a file.

pathNUL-terminated destination path cstr
contentNUL-terminated string to write

(Ok nil) on success, or (Err e) carrying the errno.

(fs/write-text "/tmp/out.txt" "hello\n")  ; => (Ok nil)

Since: Phase B2

defn

fs/append-text

(fs/append-text [path :cstr content :cstr])

append a NUL-terminated string to a file.

Creates the file when it does not exist; never truncates it.

pathNUL-terminated destination path cstr
contentNUL-terminated string to append

(Ok nil) on success, or (Err e) carrying the errno.

(fs/append-text "/tmp/log.txt" "one more line\n")  ; => (Ok nil)

Since: stdlib-os-surface P0

defn

fs/read-lines

(fs/read-lines [path :cstr])

read a whole file as a vector of lines.

Each line has its newline (and a CR before it) stripped. A final line without a trailing newline counts; a trailing newline does not add an empty last line. For files too large to hold at once, open a FileHandle and call file-read-line in a loop.

pathNUL-terminated path cstr

(Ok lines) -- a (Vec cstr) of fresh heap strings; release it with fs/paths-free -- or (Err e).

(match (fs/read-lines "/etc/hosts")
  (Ok v)  (do (println (vec-len v)) (fs/paths-free v))
  (Err e) (println (io-error/message e)))

Since: stdlib-os-surface P2

defn

fs/read-dir

(fs/read-dir [dir :cstr])

the names in a directory, sorted.

Lists every entry except "." and "..", sorted by byte order so the result is stable across runs and platforms. Names only -- join them onto dir with fs/path-join for a usable path.

dirthe directory to list

(Ok names) -- a (Vec cstr) of fresh heap strings; release it with fs/paths-free -- or (Err e) when the directory cannot be opened.

(match (fs/read-dir "/tmp")
  (Ok v)  (do (println (vec-len v)) (fs/paths-free v))
  (Err e) (println (io-error/message e)))

Since: stdlib-os-surface P2

defn

fs/path-join

(fs/path-join [dir :cstr name :cstr] :cstr)

join a directory and a name with one separator.

dirthe directory part (a trailing '/' is not doubled)
namethe entry name

A fresh heap cstr "dir/name" the caller owns (release with free).

(fs/path-join "/tmp" "a.txt")  ; => "/tmp/a.txt"

Since: stdlib-os-surface P2

defn

fs/free-cstr

(fs/free-cstr [s :cstr] :void)

free a heap cstr (internal).

defn

fs/dup-cstr

(fs/dup-cstr [s :cstr] :cstr)

a fresh heap copy of a cstr (internal).

defn

fs/walk-dir?

(fs/walk-dir? [path :cstr])

is path a directory the walk descends into (internal).

defn

fs/walk-names

(fs/walk-names [dir :cstr names :(Vec cstr) i :int f :(fn [cstr bool] nil)])

visit names[i..] of dir, recursing into directories (internal).

defn

fs/walk-fn

(fs/walk-fn [root :cstr f :(fn [cstr bool] nil)])

call f on every path under root, depth first.

Visits entries in fs/read-dir order (sorted), calling (f path is-dir?) for each before descending into it, so nothing is materialized beyond one directory's names at a time. root itself is not visited. Symlinks are not followed on POSIX (no cycles). The path handed to f is freed when f returns -- copy it to keep it.

rootthe directory to walk
f(fn [path is-dir] nil), called once per entry

(Ok nil) once the whole tree was visited, or (Err e) for the first directory that could not be read (the walk stops there).

(fs/walk-fn "/tmp/proj" (fn [p : cstr d : bool] : nil (println p)))

Since: stdlib-os-surface P2

defn

fs/walk

(fs/walk [root :cstr])

every path under root, depth first, as a vector.

The convenience form of fs/walk-fn: the same order (sorted per directory, each directory before its contents), root itself excluded, symlinks not followed on POSIX.

rootthe directory to walk

(Ok paths) -- a (Vec cstr) of fresh heap paths, each starting with root; release it with fs/paths-free -- or (Err e) for the first directory that could not be read.

(match (fs/walk "/tmp/proj")
  (Ok v)  (do (println (vec-len v)) (fs/paths-free v))
  (Err e) (println (io-error/message e)))

Since: stdlib-os-surface P2

defn

fs/lstat

(fs/lstat [path :cstr])

file metadata for a path, without following a final symlink.

The same StatInfo as fs/stat, except that when path is a symlink it describes the link itself: fs/stat-kind answers KindSymlink and fs/stat-size is the length of the target path. Windows has no lstat; there this is fs/stat (use fs/symlink? to ask about a link).

pathNUL-terminated path cstr

(Ok info) -- release it with fs/stat-free -- or (Err e).

(match (fs/lstat "/tmp/link")
  (Ok s)  (do (println (fs/stat-size s)) (fs/stat-free s))
  (Err e) (println (io-error/message e)))

Since: stdlib-os-surface P3

defn

fs/chmod

(fs/chmod [path :cstr mode :Mode])

set a file's permission bits.

paththe file or directory (a symlink is followed)
modethe new permissions, e.g. (mode/with (fs/stat-perms s) (PermUser) (PermExec))

(Ok nil), or (Err e) -- EPERM when the caller does not own the file. Windows keeps only one bit: without PermWrite for PermUser the file becomes read-only; the other bits are ignored there.

(match (mode/parse "rwxr-xr-x")
  (Some m) (fs/chmod "/tmp/run.sh" m)
  (None)   (Err (io-error/of-code 22)))

Since: stdlib-os-surface P3

defn

fs/realpath

(fs/realpath [path :cstr])

the absolute, canonical form of a path.

Resolves ".", ".." and every symlink on the way; the path must exist.

patha relative or absolute path

(Ok abs) -- a fresh heap cstr the caller owns (release with free) -- or (Err e), e.g. not-found when a component is missing. On Windows this is GetFullPathName: "." and ".." are resolved, symlinks are not.

(match (fs/realpath ".")
  (Ok p)  (println p)
  (Err e) (println (io-error/message e)))

Since: stdlib-os-surface P3

defn

fs/file-dev

(fs/file-dev [path :cstr])

the volume a path lives on, for cycle checks (internal).

defn

fs/file-ino

(fs/file-ino [path :cstr])

the file's number on its volume, for cycle checks (internal).

defn

fs/walk-on-path?

(fs/walk-on-path? [anc :(Vec int) dev :int ino :int i :int] :bool)

is (dev, ino) one of the directories being walked (internal).

defn

fs/walk-follow-names

(fs/walk-follow-names [dir :cstr names :(Vec cstr) i :int f :(fn [cstr bool] nil) anc :(Vec int)])

fs/walk-names, following symlinks (internal).

defn

fs/walk-fn-follow

(fs/walk-fn-follow [root :cstr f :(fn [cstr bool] nil)])

fs/walk-fn that descends into symlinked directories.

The same visit order and callback as fs/walk-fn, but a symlink to a directory is reported with is-dir? true and walked into. A link that leads back to a directory already on the path from root (a cycle) is reported once and not entered, so the walk always ends; the same tree reached through two different links is visited twice, as find -L does.

rootthe directory to walk
f(fn [path is-dir] nil), called once per entry

(Ok nil), or (Err e) for the first directory that could not be read.

(fs/walk-fn-follow "/tmp/proj" (fn [p : cstr d : bool] : nil (println p)))

Since: stdlib-os-surface P3

defn

fs/walk-follow

(fs/walk-follow [root :cstr])

fs/walk that descends into symlinked directories.

The vector form of fs/walk-fn-follow (same order and cycle rule).

rootthe directory to walk

(Ok paths) -- a (Vec cstr) of fresh heap paths; release it with fs/paths-free -- or (Err e).

(match (fs/walk-follow "/tmp/proj")
  (Ok v)  (do (println (vec-len v)) (fs/paths-free v))
  (Err e) (println (io-error/message e)))

Since: stdlib-os-surface P3

defn

fs/touch

(fs/touch [path :cstr])

create a file if missing, else set its access and modification times to now.

Never truncates. Works on a directory too (times only).

paththe file to touch

(Ok nil), or (Err e) -- not-found when the parent directory is missing.

(fs/touch "/tmp/stamp")  ; => (Ok nil)

Since: stdlib-os-surface P3