From 90858c8abefd5a5a23d5242df5ffc6d80a09716f Mon Sep 17 00:00:00 2001 From: jameshu15869 <55058507+jameshu15869@users.noreply.github.com> Date: Tue, 13 Jun 2023 19:57:49 -0400 Subject: [PATCH] WasmFS JS API: Implement truncate (#19543) --- emcc.py | 2 ++ src/library_wasmfs.js | 8 +++-- system/lib/wasmfs/js_api.cpp | 8 +++++ test/fs/test_fs_js_api.c | 66 ++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/emcc.py b/emcc.py index 83aa005da0ca7..549eea562a647 100755 --- a/emcc.py +++ b/emcc.py @@ -2338,6 +2338,8 @@ def phase_linker_setup(options, state, newargs): '_wasmfs_read', '_wasmfs_pread', '_wasmfs_symlink', + '_wasmfs_truncate', + '_wasmfs_ftruncate', '_wasmfs_stat', '_wasmfs_lstat', '_wasmfs_chmod', diff --git a/src/library_wasmfs.js b/src/library_wasmfs.js index fc9766e95c4bd..48bb8cf00557a 100644 --- a/src/library_wasmfs.js +++ b/src/library_wasmfs.js @@ -279,8 +279,12 @@ FS.createPreloadedFile = FS_createPreloadedFile; // TDOO: chown // TODO: lchown // TODO: fchown - // TODO: truncate - // TODO: ftruncate + truncate: (path, len) => { + return FS.handleError(withStackSave(() => (__wasmfs_truncate(stringToUTF8OnStack(path), {{{ splitI64('len') }}})))); + }, + ftruncate: (fd, len) => { + return FS.handleError(__wasmfs_ftruncate(fd, {{{ splitI64('len') }}})); + }, // TODO: utime findObject: (path) => { var result = __wasmfs_identify(path); diff --git a/system/lib/wasmfs/js_api.cpp b/system/lib/wasmfs/js_api.cpp index cdc9dbebdbd9a..8c58589f234c4 100644 --- a/system/lib/wasmfs/js_api.cpp +++ b/system/lib/wasmfs/js_api.cpp @@ -220,6 +220,14 @@ int _wasmfs_pread(int fd, void *buf, size_t count, off_t offset) { return numBytes; } +int _wasmfs_truncate(char* path, off_t length) { + return __syscall_truncate64((intptr_t)path, length); +} + +int _wasmfs_ftruncate(int fd, off_t length) { + return __syscall_ftruncate64(fd, length); +} + int _wasmfs_close(int fd) { return __wasi_fd_close(fd); } diff --git a/test/fs/test_fs_js_api.c b/test/fs/test_fs_js_api.c index 5503be3611fec..dae0daa0875ad 100644 --- a/test/fs/test_fs_js_api.c +++ b/test/fs/test_fs_js_api.c @@ -4,6 +4,70 @@ #include #include +void test_fs_truncate() { + EM_ASM( + FS.writeFile('truncatetest', 'a=1\nb=2\n'); + ); + + struct stat s; + stat("truncatetest", &s); + assert(s.st_size == 8); + + EM_ASM( + FS.truncate('truncatetest', 2); + ); + stat("truncatetest", &s); + assert(s.st_size == 2); + + EM_ASM( + FS.truncate('truncatetest', 10); + ); + stat("truncatetest", &s); + assert(s.st_size == 10); + + EM_ASM( + var truncateStream = FS.open('truncatetest', 'w'); + FS.ftruncate(truncateStream.fd, 4); + ); + stat("truncatetest", &s); + assert(s.st_size == 4); + + EM_ASM( + var ex; + try { + FS.truncate('truncatetest', -10); + } catch(err) { + ex = err; + } + assert(ex.name === "ErrnoError" && ex.errno === 28 /* EINVAL */); + + try { + var truncateStream = FS.open('truncatetest', 'w'); + FS.ftruncate(truncateStream.fd, -10); + } catch(err) { + ex = err; + } + assert(ex.name === "ErrnoError" && ex.errno === 28 /* EINVAL */); + + try { + FS.truncate('nonexistent', 10); + } catch(err) { + ex = err; + } + assert(ex.name === "ErrnoError" && ex.errno === 44 /* ENOENT */); + + var ex; + try { + FS.ftruncate(99, 10); + } catch(err) { + ex = err; + } + assert(ex.name === "ErrnoError" && ex.errno === 8 /* EBADF */); + ); + + remove("truncatetest"); +} + int main() { /********** test FS.open() **********/ EM_ASM( @@ -201,6 +265,8 @@ int main() { assert(S_ISREG(stats.st_mode)); assert(stats.st_mode & 0400); + test_fs_truncate(); + remove("mknodtest"); remove("createtest"); remove("testfile");