@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
161 lines • 6.7 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import { FileType } from "../types.js";
import { isoTimestamp } from "./dates.js";
// The one spelling of "a directory looks like drwxr-xr-x and a file
// like -rw-r--r--" for every stat translator (FUSE attrs, guest
// st_mode); mirrors mirage/utils/stat_view.py.
export const S_IFMT = 0o170000;
export const S_IFDIR = 0o040000;
export const S_IFCHR = 0o020000;
export const S_IFREG = 0o100000;
export const S_IFLNK = 0o120000;
export const CHAR_MODE = S_IFCHR | 0o666;
export const DIR_MODE = S_IFDIR | 0o755;
export const FILE_MODE = S_IFREG | 0o644;
// S_IFIFO; a pipe is created rw------- (GNU: `stat -L -c %A <(true)`).
export const FIFO_MODE = 0o010000 | 0o600;
// A link is always lrwxrwxrwx: the bits on a symlink are not consulted
// by any POSIX system, so this is the one mode every translator reports
// for one (the FUSE attr fold, find's -type l row, a guest's lstat).
export const LINK_MODE = S_IFLNK | 0o777;
// A directory is one ext4 block, the st_size GNU tools show for one,
// whatever aggregate a backend reports; ls, stat, find and FUSE all
// report this, so find -size agrees with what the listing shows.
export const DIR_SIZE = 4096;
// The block size every stat translator reports: a backend has none of its
// own, and 4 KiB is what the kernel adapters answer. st_blocks counts in
// BLOCK_UNIT whatever the block size, as POSIX has it.
export const BLKSIZE = 4096;
export const BLOCK_UNIT = 512;
// The bits chmod sets: permissions plus setuid, setgid and sticky,
// everything but the file type.
export const ALL_MODE_BITS = 0o7777;
// FNV-1a, 64-bit: the same arithmetic on both hosts and in every runtime,
// so one path reports one inode whoever asks.
const FNV_OFFSET = 0xcbf29ce484222325n;
const FNV_PRIME = 0x100000001b3n;
const FNV_MASK = 0xffffffffffffffffn;
const ENC = new TextEncoder();
/**
* A stable, distinct id for one name, as a stat's ino and dev: derived
* from the name rather than counted, so two processes reading the same
* workspace agree and a repeated stat of one path does not move. The top
* 48 bits of the hash, which a number holds exactly. Mirrors Python's
* `ident`.
*/
export function ident(text) {
let value = FNV_OFFSET;
for (const byte of ENC.encode(text))
value = ((value ^ BigInt(byte)) * FNV_PRIME) & FNV_MASK;
return Number(value >> 16n);
}
/**
* A FileStat's mtime as epoch milliseconds, null when unknown.
*
* Delegates to `isoTimestamp` rather than re-parsing, which is the
* whole point: an offset-less stamp is read as UTC so every translator
* (the FUSE attr fold, the runtime bridge, python's twins) answers the
* same epoch, instead of drifting by the host's UTC offset the way a
* bare `Date.parse`/`new Date` does. Null (missing or unparseable
* stamp) is distinct from 0, which is the real answer for
* 1970-01-01T00:00:00Z; a wire with no validity channel collapses the
* two at its own boundary.
*/
export function mtimeMs(st) {
const seconds = isoTimestamp(st.modified);
return seconds === null ? null : seconds * 1000;
}
/** A FileStat's atime as epoch milliseconds, null when unknown. */
export function atimeMs(st) {
const seconds = isoTimestamp(st.atime);
return seconds === null ? null : seconds * 1000;
}
/** Whether a FileStat describes a directory. */
export function isDir(st) {
return st.type === FileType.DIRECTORY;
}
/** Whether a FileStat describes a symlink. */
export function isLink(st) {
return st.type === FileType.SYMLINK;
}
/** Whether a FileStat describes a character device. */
export function isCharDevice(st) {
return st.type === FileType.CHAR_DEVICE;
}
/** Whether a FileStat describes a FIFO. */
export function isFifo(st) {
return st.type === FileType.FIFO;
}
/** Encode a character device's logical major:minor for guest stat. */
export function deviceRdev(st) {
const values = st.extra.device_numbers;
if (!Array.isArray(values) ||
values.length !== 2 ||
!values.every((value) => Number.isInteger(value))) {
return 0;
}
return (Number(values[0]) << 8) | Number(values[1]);
}
/**
* The st_mode a stat consumer should report for one FileStat.
*
* The type bits come from the entry's kind and the permission bits from
* the namespace overlay when a chmod put one there, which is what makes
* a metadata write visible to a guest and to a mount alike. A backend
* that reports no mode keeps the default rw-r--r-- / rwxr-xr-x pair
* (rw------- for a FIFO); there are no permissions to read on an object
* store.
*
* A link is the exception in both halves: its type bits are S_IFLNK and
* its permission bits are always 0777, because no POSIX system consults
* the bits on a symlink. An overlay mode a `chmod -h` wrote is
* therefore not reported here (ownership is, since `chown -h` does
* change what `ls -l` shows). Mirrors python's posix_mode.
*/
export function posixMode(st) {
if (isLink(st))
return LINK_MODE;
const base = isCharDevice(st)
? CHAR_MODE
: isFifo(st)
? FIFO_MODE
: isDir(st)
? DIR_MODE
: FILE_MODE;
if (st.mode === null)
return base;
return (base & ~ALL_MODE_BITS) | (st.mode & ALL_MODE_BITS);
}
/**
* The byte size a stat consumer should report, 0 when unknown.
*
* A directory is always `DIR_SIZE`, whatever aggregate a backend put in
* `size` (Graph folders report a subtree total there); an unknown file
* size is 0 and rides the unknown-size machinery above.
*/
export function contentSize(st) {
if (isDir(st))
return DIR_SIZE;
return st.size ?? 0;
}
/**
* Whether a listing has no size to show for one FileStat. A directory shows
* `DIR_SIZE` and a FIFO, which stores nothing, 0 (as GNU's `stat` and `ls -l`
* do); any other entry its rendered length. Mirrors python's size_unknown.
*/
export function sizeUnknown(st) {
return st.size === null && !isDir(st) && !isFifo(st);
}
//# sourceMappingURL=stat_view.js.map