Path: blob/main/core/kernel/src/wasm/posix/stat.ts
1068 views
import { isAbsolute, join } from "path";1import constants from "./constants";2import Errno from "./errno";3import { notImplemented } from "./util";45export default function stats({ fs, process, recv, wasi }) {6function calculateAt(7dirfd: number,8path: string,9allowEmpty: boolean = false10) {11if (isAbsolute("path")) {12return path;13}1415let dir: string;16if (dirfd == constants.AT_FDCWD) {17dir = process.cwd?.() ?? "/";18} else {19// it is a file descriptor20const entry = wasi.FD_MAP.get(dirfd);21if (!entry) {22throw Errno("EBADF");23}24dir = entry.path;25}26if (path.length == 0) {27if (!allowEmpty) {28throw Errno("ENOENT");29}30return dir;31}32return join(dir, path);33}3435// because wasi's structs don't have sufficient info to deal with permissions, we make ALL of these36// chmods into stubs, below, despite having implemented them!37// This in particular totally broke libgit2 working at all.38// TODO: an alternative may be to always set the mode to 0777. I'm not sure how bad that would be.39return {40chmod: (pathPtr: number, mode: number): -1 | 0 => {41return 0; // stubbed due to wasi shortcomings42if (!mode) {43// It is impossible for stat calls by wasi to return anything except 0 at present due to this bug:44// See https://github.com/WebAssembly/wasi-filesystem/issues/3445// Thus they will often then set the mode to 0, e.g., shutil.copy in python does this to all files.46// In such cases, we silently make this a successful no-op instead of breaking everything horribly.47// This comes up a lot with using Python as part of a build process.48return 0;49}50const path = recv.string(pathPtr);51fs.chmodSync(path, mode);52return 0;53},5455_fchmod: (fd: number, mode: number): number => {56return 0; // stubbed due to wasi shortcomings57if (!mode) {58// see above.59return 0;60}61const entry = wasi.FD_MAP.get(fd);62if (!entry) {63console.warn("bad file descriptor, fchmod");64return -1;65}66fs.fchmodSync(entry.real, mode);67return 0;68},6970// int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);71fchmodat: (72dirfd: number,73pathPtr: number,74mode: number,75_flags: number76): number => {77return 0; // stubbed due to wasi shortcomings78if (!mode) {79// see above.80return 0;81}82/* "The fchmodat() system call operates in exactly the same way as chmod(2), except... If the83pathname given in pathname is relative, then it is interpreted relative to the directory referred84to by the file descriptor dirfd (rather than relative to the current working directory of the85calling process, as is done by chmod(2) for a relative pathname). If pathname is relative and86dirfd is the special value AT_FDCWD, then pathname is interpreted relative to the current87working directory of the calling process (like chmod(2)). If pathname is absolute, then dirfd88is ignored. This flag is not currently implemented."89*/90const path = recv.string(pathPtr);91const pathAt = calculateAt(dirfd, path);92fs.chmodSync(pathAt, mode);93return 0;94},9596lchmod: (pathPtr: number, mode: number): -1 | 0 => {97return 0; // stubbed due to wasi shortcomings98if (!mode) {99// see above.100return 0;101}102const path = recv.string(pathPtr);103fs.lchmodSync(path, mode);104return 0;105},106107// mode_t umask(mode_t mask);108umask: (mask: number) => {109// we return 18 when there's no process.umask function, since that's110// like umask 022, i.e., it's a reasonable default.111return process.umask?.(mask) ?? 18;112},113114// not in wasi and we haven't done it yet...115mkfifo: () => {116notImplemented("mkfifo");117},118119mknod: () => {120notImplemented("mknod");121},122};123}124125126