Skip to content

Commit 8c81cac

Browse files
authored
[WasmFS] Support file resizing in JSFiles (#22275)
Fixes #22262
1 parent eba8702 commit 8c81cac

8 files changed

+54
-8
lines changed

src/library_sigs.js

+1
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ sigs = {
404404
_wasmfs_jsimpl_free_file__sig: 'vpp',
405405
_wasmfs_jsimpl_get_size__sig: 'ipp',
406406
_wasmfs_jsimpl_read__sig: 'ippppj',
407+
_wasmfs_jsimpl_set_size__sig: 'ippj',
407408
_wasmfs_jsimpl_write__sig: 'ippppj',
408409
_wasmfs_node_close__sig: 'ii',
409410
_wasmfs_node_fstat_size__sig: 'iip',

src/library_wasmfs.js

+2
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@ FS.init();
375375
wasmFSDeviceStreams[file] = undefined;
376376
},
377377
getSize: (file) => {},
378+
// Devices cannot be resized.
379+
setSize: (file, size) => 0,
378380
read: (file, buffer, length, offset) => {
379381
var bufferArray = Module.HEAP8.subarray(buffer, buffer + length);
380382
try {

src/library_wasmfs_js_file.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,17 @@ addToLibrary({
4444
HEAPU8.set(fileData.subarray(offset, offset + length), buffer);
4545
return length;
4646
},
47-
getSize: (file) => wasmFS$JSMemoryFiles[file] ? wasmFS$JSMemoryFiles[file].length : 0,
47+
getSize: (file) => wasmFS$JSMemoryFiles[file]?.length || 0,
48+
setSize: (file, size) => {
49+
// Allocate a new array of the proper size, and copy as much data as
50+
// possible.
51+
var old = wasmFS$JSMemoryFiles[file];
52+
var new_ = wasmFS$JSMemoryFiles[file] = new Uint8Array(size);
53+
if (old) {
54+
new_.set(old.subarray(0, size));
55+
}
56+
return 0;
57+
}
4858
};
4959
},
5060
});

src/library_wasmfs_jsimpl.js

+7
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ addToLibrary({
5353
return wasmFS$backends[backend].getSize(file);
5454
},
5555

56+
_wasmfs_jsimpl_set_size: (backend, file, size) => {
57+
#if ASSERTIONS
58+
assert(wasmFS$backends[backend]);
59+
#endif
60+
return wasmFS$backends[backend].setSize(file, size);
61+
},
62+
5663
// ProxiedAsyncJSImpl. Each function receives a function pointer and a
5764
// parameter. We convert those into a convenient Promise API for the
5865
// implementors of backends: the hooks we call should return Promises, which

system/lib/wasmfs/js_impl_backend.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ int _wasmfs_jsimpl_read(js_index_t backend,
6565
size_t length,
6666
off_t offset);
6767
int _wasmfs_jsimpl_get_size(js_index_t backend, js_index_t index);
68+
int _wasmfs_jsimpl_set_size(js_index_t backend, js_index_t index, off_t size);
6869
}
6970

7071
namespace wasmfs {
@@ -101,7 +102,7 @@ class JSImplFile : public DataFile {
101102
}
102103

103104
int setSize(off_t size) override {
104-
WASMFS_UNREACHABLE("TODO: JSImpl setSize");
105+
return _wasmfs_jsimpl_set_size(getBackendIndex(), getFileIndex(), size);
105106
}
106107

107108
public:

test/fs/test_writev_partial_write.c

-6
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,7 @@ void test_writev_direct(void) {
6868
// and is included here as this code most closely matches the original bug
6969
// report
7070
void test_via_stdio(void) {
71-
// XXX: We open in append mode because truncating JS based files is not
72-
// supported yet. See #22262
73-
#ifdef WASMFS
74-
FILE* f = fopen("/device", "a");
75-
#else
7671
FILE* f = fopen("/device", "w");
77-
#endif
7872
assert(f);
7973
// Use line buffering. The bug is exposed with line buffering because with
8074
// line buffering two entries in __stdio_write's iovs are used.

test/wasmfs/wasmfs_jsfile.c

+25
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,31 @@ int main() {
110110
lseek(fd4, 0, SEEK_SET);
111111
assert(errno == 0);
112112
int bytesRead = read(fd4, buf, sizeof(buf));
113+
for (ssize_t i = 0; i < bytesRead; i++) {
114+
if (buf[i] == 0) {
115+
printf("\\0");
116+
} else {
117+
printf("%c", buf[i]);
118+
}
119+
}
120+
printf("\n");
121+
122+
// Check the size.
123+
int result = lseek(fd4, 0, SEEK_END);
124+
assert(result != -1);
125+
printf("size: %lld\n", lseek(fd4, 0, SEEK_CUR));
113126

127+
// Resize.
128+
result = ftruncate(fd4, 42);
129+
assert(!result);
130+
result = lseek(fd4, 0, SEEK_END);
131+
assert(result != -1);
132+
printf("resize: %lld\n", lseek(fd4, 0, SEEK_CUR));
133+
134+
// Check the contents remain after the resize (but are a tad shorter).
135+
lseek(fd4, 0, SEEK_SET);
136+
assert(errno == 0);
137+
bytesRead = read(fd4, buf, sizeof(buf));
114138
for (ssize_t i = 0; i < bytesRead; i++) {
115139
if (buf[i] == 0) {
116140
printf("\\0");
@@ -120,5 +144,6 @@ int main() {
120144
}
121145
printf("\n");
122146

147+
puts("\ndone.");
123148
return 0;
124149
}

test/wasmfs/wasmfs_jsfile.out

+6
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
\0\0\0\0\0\0\0\0\0\0Test with a backend file created under root
2+
3+
size: 54
4+
resize: 42
5+
\0\0\0\0\0\0\0\0\0\0Test with a backend file created
6+
7+
done.

0 commit comments

Comments
 (0)