diff --git a/src/lib/libwasmfs.js b/src/lib/libwasmfs.js index 63a14510767bd..a665f431b56b8 100644 --- a/src/lib/libwasmfs.js +++ b/src/lib/libwasmfs.js @@ -348,7 +348,7 @@ addToLibrary({ } #endif var backendPointer = type.createBackend(opts); - return FS.handleError(withStackSave(() => __wasmfs_mount(stringToUTF8OnStack(mountpoint), backendPointer))); + return FS.handleError(withStackSave(() => _wasmfs_mount(stringToUTF8OnStack(mountpoint), backendPointer))); }, unmount: (mountpoint) => ( FS.handleError(withStackSave(() => _wasmfs_unmount(stringToUTF8OnStack(mountpoint)))) diff --git a/system/include/emscripten/wasmfs.h b/system/include/emscripten/wasmfs.h index f7025dc6eb6cb..b3839e26d1dda 100644 --- a/system/include/emscripten/wasmfs.h +++ b/system/include/emscripten/wasmfs.h @@ -29,11 +29,13 @@ backend_t wasmfs_get_backend_by_fd(int fd); // TODO: Remove this function so that only directories can be mounted. int wasmfs_create_file(const char* pathname __attribute__((nonnull)), mode_t mode, backend_t backend); -// Creates a new directory using a specific backend. -// Returns 0 on success like `mkdir`, or a negative value on error. -// TODO: Add an alias with wasmfs_mount. +// Legacy function. This function works like `mkdir` + `wasmfs_mount`. int wasmfs_create_directory(const char* path __attribute__((nonnull)), mode_t mode, backend_t backend); +// Mount a backend at a given location in the filesystem +// `path` must be an existing directory. +int wasmfs_mount(const char* path __attribute__((nonnull)), backend_t backend); + // Unmounts the directory (Which must be a valid mountpoint) at a specific path. // Returns 0 on success, or a negative value on error. int wasmfs_unmount(const char* path __attribute__((nonnull))); diff --git a/system/lib/wasmfs/js_api.cpp b/system/lib/wasmfs/js_api.cpp index bcf3be01c5c9f..08b605a86d7ab 100644 --- a/system/lib/wasmfs/js_api.cpp +++ b/system/lib/wasmfs/js_api.cpp @@ -277,21 +277,6 @@ int _wasmfs_lstat(const char* path, struct stat* statBuf) { return __syscall_lstat64((intptr_t)path, (intptr_t)statBuf); } -// The legacy JS API requires a mountpoint to already exist, so WasmFS will -// attempt to remove the target directory if it exists before replacing it with -// a mounted directory. -int _wasmfs_mount(const char* path, ::backend_t created_backend) { - int err = __syscall_rmdir((intptr_t)path); - - // The legacy JS API mount requires the directory to already exist, but we - // will also allow it to be missing. - if (err && err != -ENOENT) { - return err; - } - - return wasmfs_create_directory(path, 0777, created_backend); -} - // Helper method that identifies what a path is: // ENOENT - if nothing exists there // EISDIR - if it is a directory diff --git a/system/lib/wasmfs/syscalls.cpp b/system/lib/wasmfs/syscalls.cpp index 64932128d19ad..c5de6fcedaceb 100644 --- a/system/lib/wasmfs/syscalls.cpp +++ b/system/lib/wasmfs/syscalls.cpp @@ -597,8 +597,7 @@ int __syscall_mknodat(int dirfd, intptr_t path, int mode, int dev) { OpenReturnMode::Nothing); } -static int -doMkdir(path::ParsedParent parsed, int mode, backend_t backend = NullBackend) { +static int doMkdir(path::ParsedParent parsed, int mode) { if (auto err = parsed.getError()) { return err; } @@ -624,41 +623,57 @@ doMkdir(path::ParsedParent parsed, int mode, backend_t backend = NullBackend) { return -EACCES; } - // By default, the backend that the directory is created in is the same as - // the parent directory. However, if a backend is passed as a parameter, - // then that backend is used. - if (!backend) { - backend = parent->getBackend(); + if (!lockedParent.insertDirectory(childName, mode)) { + // TODO Receive a specific error code, and report it here. For now, report + // a generic error. + return -EIO; } - if (backend == parent->getBackend()) { - if (!lockedParent.insertDirectory(childName, mode)) { - // TODO Receive a specific error code, and report it here. For now, report - // a generic error. - return -EIO; - } - } else { - auto created = backend->createDirectory(mode); - if (!created) { - // TODO Receive a specific error code, and report it here. For now, report - // a generic error. - return -EIO; - } - [[maybe_unused]] bool mounted = lockedParent.mountChild(childName, created); - assert(mounted); + // TODO: Check that the insertion is successful. + + return 0; +} + +int wasmfs_mount(const char* path, backend_t backend) { + path::ParsedParent parsed = path::parseParent(path); + if (auto err = parsed.getError()) { + return err; } + auto& [parent, childNameView] = parsed.getParentChild(); + auto lockedParent = parent->locked(); + std::string childName(childNameView); - // TODO: Check that the insertion is successful. + // Child must exist and must be directory + auto child = lockedParent.getChild(childName); + if (!child) { + return -EEXIST; + } + if (!child->dynCast()) { + return -ENOTDIR; + } + + auto created = backend->createDirectory(0777); + if (!created) { + // TODO Receive a specific error code, and report it here. For now, report + // a generic error. + return -EIO; + } + [[maybe_unused]] bool mounted = lockedParent.mountChild(childName, created); + assert(mounted); return 0; } -// This function is exposed to users and allows users to specify a particular -// backend that a directory should be created within. -int wasmfs_create_directory(char* path, int mode, backend_t backend) { - static_assert(std::is_same_v, +// Legacy function, use wasmfs_mount instead. +int wasmfs_create_directory(const char* path, int mode, backend_t backend) { + static_assert(std::is_same_v, "unexpected conversion from result of doMkdir to int"); - return doMkdir(path::parseParent(path), mode, backend); + int rtn = doMkdir(path::parseParent(path), mode); + if (rtn != 0) { + return rtn; + } + + return wasmfs_mount(path, backend); } // TODO: Test this. diff --git a/tools/link.py b/tools/link.py index 9440e8908a858..314a3b70895cb 100644 --- a/tools/link.py +++ b/tools/link.py @@ -1265,7 +1265,7 @@ def phase_linker_setup(options, linker_args): # noqa: C901, PLR0912, PLR0915 'emscripten_builtin_memalign', 'wasmfs_create_file', 'wasmfs_unmount', - '_wasmfs_mount', + 'wasmfs_mount', '_wasmfs_read_file', '_wasmfs_write_file', '_wasmfs_open',