1
0

fs builtin (highly experimental and potentially dangerous)

This commit is contained in:
Zef Hemel 2022-07-06 12:17:42 +02:00
parent 0388b6a2a4
commit f1a7cc1fb7
3 changed files with 121 additions and 0 deletions

View 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);
}

View 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;
},
};
}

View File

@ -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),