Skip to content

Commit

Permalink
[WasmFS] Support file resizing in JSFiles (#22275)
Browse files Browse the repository at this point in the history
Fixes #22262
  • Loading branch information
kripken authored Jul 24, 2024
1 parent eba8702 commit 8c81cac
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 8 deletions.
1 change: 1 addition & 0 deletions src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ sigs = {
_wasmfs_jsimpl_free_file__sig: 'vpp',
_wasmfs_jsimpl_get_size__sig: 'ipp',
_wasmfs_jsimpl_read__sig: 'ippppj',
_wasmfs_jsimpl_set_size__sig: 'ippj',
_wasmfs_jsimpl_write__sig: 'ippppj',
_wasmfs_node_close__sig: 'ii',
_wasmfs_node_fstat_size__sig: 'iip',
Expand Down
2 changes: 2 additions & 0 deletions src/library_wasmfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ FS.init();
wasmFSDeviceStreams[file] = undefined;
},
getSize: (file) => {},
// Devices cannot be resized.
setSize: (file, size) => 0,
read: (file, buffer, length, offset) => {
var bufferArray = Module.HEAP8.subarray(buffer, buffer + length);
try {
Expand Down
12 changes: 11 additions & 1 deletion src/library_wasmfs_js_file.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,17 @@ addToLibrary({
HEAPU8.set(fileData.subarray(offset, offset + length), buffer);
return length;
},
getSize: (file) => wasmFS$JSMemoryFiles[file] ? wasmFS$JSMemoryFiles[file].length : 0,
getSize: (file) => wasmFS$JSMemoryFiles[file]?.length || 0,
setSize: (file, size) => {
// Allocate a new array of the proper size, and copy as much data as
// possible.
var old = wasmFS$JSMemoryFiles[file];
var new_ = wasmFS$JSMemoryFiles[file] = new Uint8Array(size);
if (old) {
new_.set(old.subarray(0, size));
}
return 0;
}
};
},
});
7 changes: 7 additions & 0 deletions src/library_wasmfs_jsimpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ addToLibrary({
return wasmFS$backends[backend].getSize(file);
},

_wasmfs_jsimpl_set_size: (backend, file, size) => {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
return wasmFS$backends[backend].setSize(file, size);
},

// ProxiedAsyncJSImpl. Each function receives a function pointer and a
// parameter. We convert those into a convenient Promise API for the
// implementors of backends: the hooks we call should return Promises, which
Expand Down
3 changes: 2 additions & 1 deletion system/lib/wasmfs/js_impl_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ int _wasmfs_jsimpl_read(js_index_t backend,
size_t length,
off_t offset);
int _wasmfs_jsimpl_get_size(js_index_t backend, js_index_t index);
int _wasmfs_jsimpl_set_size(js_index_t backend, js_index_t index, off_t size);
}

namespace wasmfs {
Expand Down Expand Up @@ -101,7 +102,7 @@ class JSImplFile : public DataFile {
}

int setSize(off_t size) override {
WASMFS_UNREACHABLE("TODO: JSImpl setSize");
return _wasmfs_jsimpl_set_size(getBackendIndex(), getFileIndex(), size);
}

public:
Expand Down
6 changes: 0 additions & 6 deletions test/fs/test_writev_partial_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,7 @@ void test_writev_direct(void) {
// and is included here as this code most closely matches the original bug
// report
void test_via_stdio(void) {
// XXX: We open in append mode because truncating JS based files is not
// supported yet. See #22262
#ifdef WASMFS
FILE* f = fopen("/device", "a");
#else
FILE* f = fopen("/device", "w");
#endif
assert(f);
// Use line buffering. The bug is exposed with line buffering because with
// line buffering two entries in __stdio_write's iovs are used.
Expand Down
25 changes: 25 additions & 0 deletions test/wasmfs/wasmfs_jsfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,31 @@ int main() {
lseek(fd4, 0, SEEK_SET);
assert(errno == 0);
int bytesRead = read(fd4, buf, sizeof(buf));
for (ssize_t i = 0; i < bytesRead; i++) {
if (buf[i] == 0) {
printf("\\0");
} else {
printf("%c", buf[i]);
}
}
printf("\n");

// Check the size.
int result = lseek(fd4, 0, SEEK_END);
assert(result != -1);
printf("size: %lld\n", lseek(fd4, 0, SEEK_CUR));

// Resize.
result = ftruncate(fd4, 42);
assert(!result);
result = lseek(fd4, 0, SEEK_END);
assert(result != -1);
printf("resize: %lld\n", lseek(fd4, 0, SEEK_CUR));

// Check the contents remain after the resize (but are a tad shorter).
lseek(fd4, 0, SEEK_SET);
assert(errno == 0);
bytesRead = read(fd4, buf, sizeof(buf));
for (ssize_t i = 0; i < bytesRead; i++) {
if (buf[i] == 0) {
printf("\\0");
Expand All @@ -120,5 +144,6 @@ int main() {
}
printf("\n");

puts("\ndone.");
return 0;
}
6 changes: 6 additions & 0 deletions test/wasmfs/wasmfs_jsfile.out
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
\0\0\0\0\0\0\0\0\0\0Test with a backend file created under root

size: 54
resize: 42
\0\0\0\0\0\0\0\0\0\0Test with a backend file created

done.

0 comments on commit 8c81cac

Please sign in to comment.