Fs.FsLayer
Definitions
Resolves path to an absolute, normalized form and checks that it matches
at least one of the given glob patterns. Returns Ok(resolvedPath) if allowed,
or Err(PermissionDenied) if the path does not match any pattern.
Resolves path to an absolute, normalized form and checks that it falls within
at least one of the allowedDirs. Returns Ok(resolvedPath) if allowed,
or Err(PermissionDenied) if the path is outside every allowed directory.
def atomicWrite(file: String, doWrite: String -> Result[IoError, Unit] \ ef, doMoveAtomic: String -> (String -> Result[IoError, Unit] \ ef), doDelete: String -> Result[IoError, Unit] \ ef): Result[IoError, Unit] \ ef§ SourcePerforms an atomic write to file by writing to a temporary sibling path
first, then atomically moving it into place.
doWrite(tmp)writes data to the temporary path.doMoveAtomic(tmp, file)atomically moves the temp file to the target.doDelete(tmp)cleans up the temp file on failure.
The caller supplies these as effect operations so that this helper works
with any effect (FileWrite, FileSystem, etc.).
def backup(file: String, suffix: String, doCopy: String -> (String -> Result[IoError, Unit] \ ef), doAction: Unit -> Result[IoError, a] \ ef): Result[IoError, a] \ ef§ SourcePerforms a backup of file to file + suffix before executing doAction.
doCopy(file, bak)copies the file to the backup path.- If the copy succeeds,
doAction()is executed. - If the copy fails with
NotFound, the file doesn't exist yet, sodoAction()proceeds without backup. - If the copy fails with any other error, the operation is aborted.
Checks that actualSize does not exceed maxSize.
Returns Ok(()) if within the limit, or Err(TransferLimitExceeded) otherwise.
def checksumAfterDelete(file: String, sidecar: String, deleteResult: Result[IoError, Unit], doDeleteSidecar: String -> Result[IoError, Unit] \ ef): Result[IoError, Unit] \ ef§ SourceDeletes the checksum sidecar after a successful delete.
If the sidecar does not exist, the delete result is returned unchanged. Sidecar delete errors are discarded.
def checksumAfterMove(src: String, dst: String, sidecar: String, moveResult: Result[IoError, Unit], doMoveSidecar: String -> (String -> Result[IoError, Unit] \ ef)): Result[IoError, Unit] \ ef§ SourceMoves the checksum sidecar after a successful moveWith.
If the source sidecar does not exist, the move result is returned unchanged. Sidecar move errors are discarded.
def checksumAfterWrite(file: String, doWrite: Unit -> Result[IoError, Unit] \ ef1, doUpdateSidecar: String -> Result[IoError, Unit] \ ef2): Result[IoError, Unit] \ ef1 + ef2§ SourcePerforms doWrite, then computes and writes a checksum sidecar for file.
doUpdateSidecar(file) should read the file bytes, hash them, and
write the hex digest to the sidecar path.
def checksumOnRead(file: String, sidecar: String, computeHex: Vector[Int8] -> String, readResult: Result[IoError, a], doReadBytes: String -> Result[IoError, Vector[Int8]] \ ef, doReadSidecar: String -> Result[IoError, String] \ ef): Result[IoError, a] \ ef§ SourceVerifies a read or readLines result against a checksum sidecar.
Since the result type (String or List[String]) does not preserve
raw bytes, doReadBytes is called to obtain the on-disk bytes for
hashing. If no sidecar exists, the result passes through.
def checksumOnReadBytes(file: String, sidecar: String, computeHex: Vector[Int8] -> String, readResult: Result[IoError, Vector[Int8]], doReadSidecar: String -> Result[IoError, String] \ ef): Result[IoError, Vector[Int8]] \ ef§ SourceVerifies a readBytes result against a checksum sidecar.
The returned bytes are hashed via computeHex and compared against
the sidecar. If no sidecar exists, the result passes through.
Resolves path against chrootDir and validates that the resolved result
stays within the chroot directory. Symlinks are resolved to their real
filesystem targets before the boundary check.
Returns Ok(resolvedPath) if the path is within bounds,
or Err(PermissionDenied) if the path escapes the chroot.
def conflictCheck(file: String, snapshots: MutMap[String, Int64, r], getModTime: String -> Result[IoError, Int64] \ ef): Result[IoError, Unit] \ ef + r§ SourceChecks whether file was modified externally since last snapshot.
- No snapshot →
Ok()(file was never read, nothing to conflict with). - Mod time matches snapshot →
Ok(). - Mod time differs →
Err(Conflict(...)). - File deleted (
NotFound) →Ok()(file gone, proceed). - Other
getModTimeerror → propagated.
Resolves path to an absolute, normalized form and checks that it does not match
any of the given glob patterns. Returns Ok(resolvedPath) if permitted,
or Err(PermissionDenied) if the path matches a denied pattern.
Resolves path to an absolute, normalized form and checks that it does not fall
within any of the deniedDirs. Returns Ok(resolvedPath) if permitted,
or Err(PermissionDenied) if the path is within a denied directory.
def ensureParentDirs(file: String, doMkDirs: String -> Result[IoError, Unit] \ ef, doAction: Unit -> Result[IoError, a] \ ef): Result[IoError, a] \ ef§ SourceEnsures the parent directory of file exists before executing doAction.
- If
filehas no parent (bare filename),doAction()proceeds directly. - If
doMkDirs(parent)succeeds,doAction()proceeds. - If
doMkDirs(parent)fails, the error is returned anddoActionis not performed.
Estimates the UTF-8 byte size of a string by multiplying the character count by 4 (the maximum bytes per character in UTF-8).
Estimates the UTF-8 byte size of a list of strings by multiplying the total character count by 4 (the maximum bytes per character in UTF-8).
def logPost(op: String, path: String, describe: a -> String, result: Result[IoError, a]): Unit \ Logger§ SourceLogs a post-operation message: Debug on success, Warn on error.
def logPost2(op: String, src: String, dst: String, result: Result[IoError, Unit]): Unit \ Logger§ SourceLogs a post-operation message for two-path operations (copy/move).
Logs a pre-operation message at Debug level.
Logs a pre-operation message for two-path operations (copy/move) at Debug level.
Returns the parent directory of path, or None if the path has no parent
(e.g., a bare filename like "test.txt").
Resolves path against baseDir using Java's Path.resolve semantics:
- If
pathis absolute, it is returned as-is. - If
pathis relative, it is joined tobaseDir.
Resolves path to its real filesystem target by following all symlinks.
Returns Ok(realPath) if the path exists, or an appropriate IoError if the
path is invalid, does not exist, or cannot be resolved.
Resolves path to its real filesystem target by following all symlinks.
Falls back to the original path if resolution fails (e.g., the file does not
exist yet). Useful for write/create operations where the target may not exist.
def rotateIfNeeded(file: String, maxSize: Size, maxFiles: Int32, doSize: String -> Result[IoError, Size] \ ef1, doMove: String -> (String -> Result[IoError, Unit] \ ef2), doDelete: String -> Result[IoError, Unit] \ ef2, doAction: Unit -> Result[IoError, a] \ ef2): Result[IoError, a] \ ef1 + ef2§ SourceRotates file if its size meets or exceeds maxSize, then executes doAction.
Rotation shifts existing numbered files (file.1 … file.{maxFiles})
upward by one, deletes the oldest (file.{maxFiles}), and moves file
to file.1. The doAction then writes to the now-absent original path.
If the file does not exist (NotFound), rotation is skipped and
doAction proceeds directly (append will create it).
def snapshotModTime(file: String, snapshots: MutMap[String, Int64, r], getModTime: String -> Result[IoError, Int64] \ ef): Unit \ ef + r§ SourceSnapshots the modification time of file into snapshots.
If getModTime fails (file deleted, etc.), silently skips.
def updateSidecar(file: String, sidecar: String, computeHex: Vector[Int8] -> String, doReadBytes: String -> Result[IoError, Vector[Int8]] \ ef1, doWriteSidecar: String -> (String -> Result[IoError, Unit] \ ef2)): Result[IoError, Unit] \ ef1 + ef2§ SourceReads the bytes of file, hashes them with computeHex, and writes
the hex digest to the sidecar path file + sidecar.
def verifyChecksum(file: String, sidecar: String, actual: String, doReadSidecar: String -> Result[IoError, String] \ ef): Result[IoError, Unit] \ ef§ SourceVerifies actual (a hex digest string) against the checksum stored in
the sidecar file file + sidecar.
- If the sidecar does not exist (
NotFound), returnsOk(()). - If the sidecar exists and matches, returns
Ok(()). - If the sidecar exists and does not match, returns
Err(IoError(ChecksumMismatch, ...)).