fs builtin (highly experimental and potentially dangerous)
This commit is contained in:
parent
0388b6a2a4
commit
f1a7cc1fb7
31
packages/plugos-syscall/fs.ts
Normal file
31
packages/plugos-syscall/fs.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { syscall } from "./syscall";
|
||||||
|
|
||||||
|
export type FileMeta = {
|
||||||
|
name: string;
|
||||||
|
lastModified: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function readFile(
|
||||||
|
path: string
|
||||||
|
): Promise<{ text: string; meta: FileMeta }> {
|
||||||
|
return syscall("fs.readFile", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getFileMeta(path: string): Promise<FileMeta> {
|
||||||
|
return syscall("fs.getFileMeta", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function writeFile(path: string, text: string): Promise<FileMeta> {
|
||||||
|
return syscall("fs.writeFile", path, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteFile(path: string): Promise<void> {
|
||||||
|
return syscall("fs.deleteFile", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function listFiles(
|
||||||
|
dirName: string,
|
||||||
|
recursive = false
|
||||||
|
): Promise<FileMeta[]> {
|
||||||
|
return syscall("fs.listFiles", dirName, recursive);
|
||||||
|
}
|
87
packages/plugos/syscalls/fs.node.ts
Normal file
87
packages/plugos/syscalls/fs.node.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import { readdir, readFile, stat, writeFile, unlink } from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
import type { SysCallMapping } from "../system";
|
||||||
|
|
||||||
|
export type FileMeta = {
|
||||||
|
name: string;
|
||||||
|
lastModified: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function fileSystemSyscalls(root: string = "/"): SysCallMapping {
|
||||||
|
function resolvedPath(p: string): string {
|
||||||
|
p = path.resolve(root, p);
|
||||||
|
if (!p.startsWith(root)) {
|
||||||
|
throw Error("Path outside root, not allowed");
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"fs.readFile": async (
|
||||||
|
ctx,
|
||||||
|
filePath: string
|
||||||
|
): Promise<{ text: string; meta: FileMeta }> => {
|
||||||
|
let p = resolvedPath(filePath);
|
||||||
|
let text = await readFile(p, "utf8");
|
||||||
|
let s = await stat(p);
|
||||||
|
return {
|
||||||
|
text,
|
||||||
|
meta: {
|
||||||
|
name: filePath,
|
||||||
|
lastModified: s.mtime.getTime(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
"fs.getFileMeta": async (ctx, filePath: string): Promise<FileMeta> => {
|
||||||
|
let p = resolvedPath(filePath);
|
||||||
|
let s = await stat(p);
|
||||||
|
return {
|
||||||
|
name: filePath,
|
||||||
|
lastModified: s.mtime.getTime(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
"fs.writeFile": async (
|
||||||
|
ctx,
|
||||||
|
filePath: string,
|
||||||
|
text: string
|
||||||
|
): Promise<FileMeta> => {
|
||||||
|
let p = resolvedPath(filePath);
|
||||||
|
await writeFile(p, text);
|
||||||
|
let s = await stat(p);
|
||||||
|
return {
|
||||||
|
name: filePath,
|
||||||
|
lastModified: s.mtime.getTime(),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
"fs.deleteFile": async (ctx, filePath: string): Promise<void> => {
|
||||||
|
let p = resolvedPath(filePath);
|
||||||
|
await unlink(p);
|
||||||
|
},
|
||||||
|
"fs.listFiles": async (
|
||||||
|
ctx,
|
||||||
|
dirPath: string,
|
||||||
|
recursive: boolean
|
||||||
|
): Promise<FileMeta[]> => {
|
||||||
|
dirPath = resolvedPath(dirPath);
|
||||||
|
let allFiles: FileMeta[] = [];
|
||||||
|
|
||||||
|
async function walkPath(dir: string) {
|
||||||
|
let files = await readdir(dir);
|
||||||
|
for (let file of files) {
|
||||||
|
const fullPath = path.join(dir, file);
|
||||||
|
let s = await stat(fullPath);
|
||||||
|
if (s.isDirectory() && recursive) {
|
||||||
|
await walkPath(fullPath);
|
||||||
|
} else {
|
||||||
|
allFiles.push({
|
||||||
|
name: fullPath.substring(dirPath.length + 1),
|
||||||
|
lastModified: s.mtime.getTime(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await walkPath(dirPath);
|
||||||
|
return allFiles;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
@ -49,6 +49,7 @@ import {
|
|||||||
import { PlugSpacePrimitives } from "./hooks/plug_space_primitives";
|
import { PlugSpacePrimitives } from "./hooks/plug_space_primitives";
|
||||||
import { PageNamespaceHook } from "./hooks/page_namespace";
|
import { PageNamespaceHook } from "./hooks/page_namespace";
|
||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
|
import fileSystemSyscalls from "@plugos/plugos/syscalls/fs.node";
|
||||||
|
|
||||||
const safeFilename = /^[a-zA-Z0-9_\-\.]+$/;
|
const safeFilename = /^[a-zA-Z0-9_\-\.]+$/;
|
||||||
|
|
||||||
@ -115,6 +116,8 @@ export class ExpressServer {
|
|||||||
|
|
||||||
// Register syscalls available on the server sid
|
// Register syscalls available on the server sid
|
||||||
this.system.registerSyscalls(["shell"], shellSyscalls(options.pagesPath));
|
this.system.registerSyscalls(["shell"], shellSyscalls(options.pagesPath));
|
||||||
|
// YOLO
|
||||||
|
this.system.registerSyscalls([], fileSystemSyscalls("/"));
|
||||||
this.system.registerSyscalls(
|
this.system.registerSyscalls(
|
||||||
[],
|
[],
|
||||||
pageIndexSyscalls(this.db),
|
pageIndexSyscalls(this.db),
|
||||||
|
Loading…
Reference in New Issue
Block a user