UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

161 lines • 6.7 kB
// ========= 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