Skip to content

Commit adca2e7

Browse files
authored
WasmFS JS API: Implement write (#19508)
1 parent 4339c66 commit adca2e7

File tree

6 files changed

+59
-1
lines changed

6 files changed

+59
-1
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ jobs:
516516
wasmfs.test_unistd_truncate
517517
wasmfs.test_readdir
518518
wasmfs.test_unistd_pipe
519+
wasmfs.test_fs_write
519520
wasmfs.test_webidl
520521
wasmfs.test_dlfcn_self
521522
wasmfs.test_dlfcn_unique_sig

emcc.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2318,6 +2318,8 @@ def phase_linker_setup(options, state, newargs):
23182318
'_wasmfs_write_file',
23192319
'_wasmfs_open',
23202320
'_wasmfs_close',
2321+
'_wasmfs_write',
2322+
'_wasmfs_pwrite',
23212323
'_wasmfs_rename',
23222324
'_wasmfs_mkdir',
23232325
'_wasmfs_unlink',

src/library_wasmfs.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,26 @@ FS.createPreloadedFile = FS_createPreloadedFile;
162162
_free(dataBuffer);
163163
return bytesRead;
164164
},
165-
// TODO: write
165+
// Note that canOwn is an optimization that we ignore for now in WasmFS.
166+
write: (fd, buffer, offset, length, position, canOwn) => {
167+
var seeking = typeof position != 'undefined';
168+
169+
var dataBuffer = _malloc(length);
170+
for (var i = 0; i < length; i++) {
171+
{{{ makeSetValue('dataBuffer', 'i', 'buffer[offset + i]', 'i8') }}};
172+
}
173+
174+
var bytesRead;
175+
if (seeking) {
176+
bytesRead = __wasmfs_pwrite(fd, dataBuffer, length, position);
177+
} else {
178+
bytesRead = __wasmfs_write(fd, dataBuffer, length);
179+
}
180+
bytesRead = FS.handleError(bytesRead);
181+
_free(dataBuffer);
182+
183+
return bytesRead;
184+
},
166185
// TODO: allocate
167186
// TODO: mmap
168187
// TODO: msync

system/lib/wasmfs/js_api.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,32 @@ int _wasmfs_symlink(char* old_path, char* new_path) {
143143
return __syscall_symlink((intptr_t)old_path, (intptr_t)new_path);
144144
}
145145

146+
int _wasmfs_write(int fd, void *buf, size_t count) {
147+
__wasi_ciovec_t iovs[1];
148+
iovs[0].buf = (uint8_t*)buf;
149+
iovs[0].buf_len = count;
150+
151+
__wasi_size_t numBytes;
152+
__wasi_errno_t err = __wasi_fd_write(fd, iovs, 1, &numBytes);
153+
if (err) {
154+
return -err;
155+
}
156+
return numBytes;
157+
}
158+
159+
int _wasmfs_pwrite(int fd, void *buf, size_t count, off_t offset) {
160+
__wasi_ciovec_t iovs[1];
161+
iovs[0].buf = (uint8_t*)buf;
162+
iovs[0].buf_len = count;
163+
164+
__wasi_size_t numBytes;
165+
__wasi_errno_t err = __wasi_fd_pwrite(fd, iovs, 1, offset, &numBytes);
166+
if (err) {
167+
return -err;
168+
}
169+
return numBytes;
170+
}
171+
146172
int _wasmfs_chmod(char* path, mode_t mode) {
147173
return __syscall_chmod((intptr_t)path, mode);
148174
}

test/fs/test_write.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ int main()
2929
FS.write(stream, data, 0, lengthBytesUTF8(str)+1, pos, /*canOwn=*/false);
3030

3131
FS.close(stream);
32+
33+
var ex;
34+
try {
35+
FS.write(stream, data, 0, lengthBytesUTF8(str)+1, pos, /*canOwn=*/false);
36+
} catch (err) {
37+
ex = err;
38+
}
39+
assert(ex.name === 'ErrnoError' && ex.errno === 8 /* EBADF */)
3240
);
3341

3442
std::ifstream file("testfile");

test/test_core.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6022,6 +6022,8 @@ def test_fs_js_api(self):
60226022
self.do_runf(test_file('fs/test_fs_js_api.c'), 'success')
60236023

60246024
def test_fs_write(self):
6025+
if self.get_setting('WASMFS'):
6026+
self.set_setting("FORCE_FILESYSTEM")
60256027
self.do_run_in_out_file_test('fs/test_write.cpp')
60266028

60276029
@also_with_noderawfs

0 commit comments

Comments
 (0)