Skip to content

Commit f2cca1a

Browse files
authored
[WasmFS] Gracefully error when moving OPFS directory (#19320)
The OPFS API does not yet support moving directories. When user code tried to move a directory using the OPFS backend, we previously crashed because the backend implementation incorrectly assumed that the moved file was a data file. Fix the crash by returning EBUSY instead in that case.
1 parent 75c7902 commit f2cca1a

File tree

4 files changed

+47
-14
lines changed

4 files changed

+47
-14
lines changed

src/library_wasmfs_opfs.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,14 @@ mergeInto(LibraryManager.library, {
189189
wasmfsOPFSProxyFinish(ctx);
190190
},
191191

192-
_wasmfs_opfs_move__sig: 'vpiipp',
193-
_wasmfs_opfs_move__deps: ['$wasmfsOPFSFileHandles',
194-
'$wasmfsOPFSDirectoryHandles', '$wasmfsOPFSProxyFinish'],
195-
_wasmfs_opfs_move: async function(ctx, fileID, newDirID, namePtr, errPtr) {
192+
_wasmfs_opfs_move_file__sig: 'vpiipp',
193+
_wasmfs_opfs_move_file__deps: ['$wasmfsOPFSFileHandles',
194+
'$wasmfsOPFSDirectoryHandles',
195+
'$wasmfsOPFSProxyFinish'],
196+
_wasmfs_opfs_move_file: async function(ctx, fileID, newParentID, namePtr, errPtr) {
196197
let name = UTF8ToString(namePtr);
197198
let fileHandle = wasmfsOPFSFileHandles.get(fileID);
198-
let newDirHandle = wasmfsOPFSDirectoryHandles.get(newDirID);
199+
let newDirHandle = wasmfsOPFSDirectoryHandles.get(newParentID);
199200
try {
200201
await fileHandle.move(newDirHandle, name);
201202
} catch {

system/lib/wasmfs/backends/opfs_backend.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ void _wasmfs_opfs_insert_directory(em_proxying_ctx* ctx,
4141
const char* name,
4242
int* child_id);
4343

44-
void _wasmfs_opfs_move(em_proxying_ctx* ctx,
45-
int file_id,
46-
int new_dir_id,
47-
const char* name,
48-
int* err);
44+
void _wasmfs_opfs_move_file(em_proxying_ctx* ctx,
45+
int file_id,
46+
int new_parent_id,
47+
const char* name,
48+
int* err);
4949

5050
void _wasmfs_opfs_remove_child(em_proxying_ctx* ctx,
5151
int dir_id,
@@ -431,11 +431,19 @@ class OPFSDirectory : public Directory {
431431
}
432432

433433
int insertMove(const std::string& name, std::shared_ptr<File> file) override {
434-
auto old_file = std::static_pointer_cast<OPFSFile>(file);
435434
int err = 0;
436-
proxy([&](auto ctx) {
437-
_wasmfs_opfs_move(ctx.ctx, old_file->fileID, dirID, name.c_str(), &err);
438-
});
435+
if (file->is<DataFile>()) {
436+
auto opfsFile = std::static_pointer_cast<OPFSFile>(file);
437+
proxy([&](auto ctx) {
438+
_wasmfs_opfs_move_file(
439+
ctx.ctx, opfsFile->fileID, dirID, name.c_str(), &err);
440+
});
441+
} else {
442+
// TODO: Support moving directories once OPFS supports that.
443+
// EBUSY can be returned when the directory is "in use by the system,"
444+
// which can mean whatever we want.
445+
err = -EBUSY;
446+
}
439447
return err;
440448
}
441449

test/wasmfs/wasmfs_opfs_errors.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <emscripten/wasmfs.h>
55
#include <errno.h>
66
#include <fcntl.h>
7+
#include <stdio.h>
78
#include <stdlib.h>
89
#include <string.h>
910
#include <unistd.h>
@@ -121,6 +122,25 @@ int try_oob_write(void) {
121122
return 2;
122123
}
123124

125+
EMSCRIPTEN_KEEPALIVE
126+
int try_rename_dir(void) {
127+
int err = mkdir("/opfs/dir1", 0666);
128+
if (err != 0) {
129+
return 2;
130+
}
131+
err = rename("/opfs/dir1", "/opfs/dir2");
132+
if (err == 0) {
133+
return 1;
134+
}
135+
if (errno == EBUSY) {
136+
rmdir("/opfs/dir1");
137+
return 0;
138+
}
139+
emscripten_console_error(strerror(errno));
140+
rmdir("/opfs/dir1");
141+
return 2;
142+
}
143+
124144
EMSCRIPTEN_KEEPALIVE
125145
void report_result(int result) {
126146
EM_ASM({ console.log(new Error().stack); });

test/wasmfs/wasmfs_opfs_errors_post.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,9 @@ async function run_test() {
6666
"nothing prevents it)";
6767
}
6868

69+
if (Module._try_rename_dir() != 0) {
70+
throw "Did not get expected EBUSY while renaming directory";
71+
}
72+
6973
Module._report_result(0);
7074
}

0 commit comments

Comments
 (0)