UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

87 lines (86 loc) • 3.2 kB
import { a as asOptionalRecord } from "./record-coerce-TIsquoVR.mjs"; import { a as openRootFile } from "./boundary-file-read-CCth2Hwg.mjs"; import "./string-coerce-runtime-50qKeWeL.mjs"; import "./file-access-runtime-BMp89X4Y.mjs"; import { n as matchesFileIdentity, r as readPathBinding, t as fileIdentity } from "./path-binding-C8xt74EN.mjs"; import { a as resolveCanonicalReadPath, n as readAbsolutePath, r as rejectCanonicalPathChange, t as classifyFsSafeReadError } from "./path-errors-C4umvZFT.mjs"; import fs from "node:fs"; import path from "node:path"; //#region extensions/file-transfer/src/node-host/file-stat.ts function classifyError(error) { const safeCode = classifyFsSafeReadError(error); if (safeCode) return safeCode; const code = asOptionalRecord(error)?.code; if (code === "ENOENT" || code === "ENOTDIR") return "NOT_FOUND"; return code === "EACCES" || code === "EPERM" ? "PERMISSION_DENIED" : "READ_ERROR"; } async function handleFileStat(params) { const requestedPath = readAbsolutePath(params.path); if (typeof requestedPath !== "string") return requestedPath; const canonicalPath = await resolveCanonicalReadPath({ requestedPath, followSymlinks: params.followSymlinks === true, classifyError, notFoundMessage: "path not found" }); if (typeof canonicalPath !== "string") return canonicalPath; const changed = rejectCanonicalPathChange(params.expectedCanonicalPath, canonicalPath); if (changed) return changed; try { const candidate = await fs.promises.lstat(canonicalPath); if (!candidate.isFile() && !candidate.isDirectory()) return { ok: false, code: "UNSUPPORTED_FILE_TYPE", message: "only regular files and directories are supported", canonicalPath }; const opened = await openRootFile({ absolutePath: canonicalPath, rootPath: path.dirname(canonicalPath), boundaryLabel: "file.stat", allowedType: candidate.isDirectory() ? "directory" : "file", rejectHardlinks: false }); if (!opened.ok) return { ok: false, code: classifyError(opened.error), message: "could not open the metadata target", canonicalPath }; try { const openedPathChange = rejectCanonicalPathChange(canonicalPath, opened.path); if (openedPathChange) return openedPathChange; const stats = fs.fstatSync(opened.fd, { bigint: true }); const expected = readPathBinding(params.expectedBinding); if (params.expectedBinding !== void 0 && (expected?.kind !== "existing" || !matchesFileIdentity(stats, expected))) return { ok: false, code: "CANONICAL_PATH_CHANGED", message: "filesystem identity differs from the authorized target", canonicalPath }; return { ok: true, path: opened.path, type: stats.isDirectory() ? "directory" : "file", size: Number(stats.size), mtimeMs: Number(stats.mtimeNs) / 1e6, binding: { kind: "existing", ...fileIdentity(stats) }, ...params.preflightOnly === true ? { preflightOnly: true } : {} }; } finally { fs.closeSync(opened.fd); } } catch (error) { return { ok: false, code: classifyError(error), message: "could not read file metadata", canonicalPath }; } } //#endregion export { handleFileStat };