@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
87 lines • 4.03 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 { usageHint } from "../../../../commands/spec/usage.js";
import { encodeText } from "../../../../shell/bytes.js";
import { MountMode } from "../../../../types.js";
import { pathVisible } from "../../../../utils/hidden.js";
import { compareCodePoints } from "../../../../utils/sort.js";
import { fail, ok, parseLine } from "../shared.js";
// The mount options a mode reads as: the ladder's READ cannot write and only
// EXEC lets the interpreters run a script, which is what ro, rw and noexec say
// about a Linux mount.
const MODE_OPTIONS = {
[MountMode.READ]: 'ro,noexec',
[MountMode.WRITE]: 'rw,noexec',
[MountMode.EXEC]: 'rw',
};
// The flags that ask for a mount, which with no operand is a bad usage rather
// than the listing.
const MOUNTING = ['bind', 'move', 'rbind', 'read_only', 'rw'];
const BAD_USAGE = `mount: bad usage\n${usageHint('mount')}\n`;
function superuser(target) {
return (`mount: ${target}: must be superuser to use mount.\n` +
' dmesg(1) may have more information after failed mount system call.\n');
}
/**
* Whether a filesystem type passes `-t`, as util-linux mount reads the list. A
* comma list, case-insensitive; a leading `no` negates the whole list
* (`-t nofoo,bar` is neither), and a `no` on a later item refuses that one
* type.
*/
function matchType(name, pattern) {
const negated = pattern.startsWith('no');
const body = negated ? pattern.slice(2) : pattern;
const wanted = name.toLowerCase();
for (const item of body.split(',')) {
const lower = item.toLowerCase();
if (lower.startsWith('no') && lower.slice(2) === wanted)
return false;
if (lower === wanted)
return !negated;
}
return negated;
}
/**
* mount [-l] [-t TYPES]: list the mounts the session sees, util-linux 2.41.5's
* way, with the session's mode as the options (`MODE_OPTIONS`). Mounting is an
* unprivileged user's refusal, since mounts come from the configuration, a
* mounting flag with no operand is a bad usage, and `-a` mounts the empty
* fstab.
*/
export function handleMount(registry, session, args) {
const [parsed, fl, refused] = parseLine('mount', args, session.cwd);
if (refused !== null)
return refused;
const words = parsed.texts;
const last = words.at(-1);
if (words.length >= 2 && last !== undefined)
return fail('mount', superuser(last), 32);
const only = words[0];
if (only !== undefined)
return fail('mount', `mount: ${only}: can't find in /etc/fstab.\n`);
if (fl.asBool('all'))
return ok('mount');
if (fl.asStr('options') !== undefined || MOUNTING.some((dest) => fl.asBool(dest))) {
return fail('mount', BAD_USAGE);
}
const types = fl.asStr('types');
const lines = [...registry.visibleMounts()]
.sort((a, b) => compareCodePoints(a.prefix, b.prefix))
.filter((m) => pathVisible(session.visibility, m.prefix.replace(/\/+$/, '') || '/'))
.filter((m) => types === undefined || matchType(m.vfs.name, types))
.map((m) => `${m.vfs.name} on ${m.prefix.replace(/\/+$/, '') || '/'} type ${m.vfs.name} ` +
`(${MODE_OPTIONS[m.effectiveMode(session)]})\n`);
return ok('mount', lines.length > 0 ? encodeText(lines.join('')) : null);
}
//# sourceMappingURL=mount.js.map