Skip to content

Commit 242af00

Browse files
authored
[WASMFS] Fix remaining TODO items with wasmfs + noderawfs (#23617)
In order make sure this gets tested I added the combination of wasmfs and rawfs to `@with_all_fs`. Fixes: #23618
1 parent b68ddc9 commit 242af00

File tree

9 files changed

+127
-17
lines changed

9 files changed

+127
-17
lines changed

Diff for: src/lib/libsigs.js

+5
Original file line numberDiff line numberDiff line change
@@ -402,14 +402,19 @@ sigs = {
402402
_wasmfs_jsimpl_write__sig: 'ippppj',
403403
_wasmfs_node_close__sig: 'ii',
404404
_wasmfs_node_fstat_size__sig: 'iip',
405+
_wasmfs_node_ftruncate__sig: 'iij',
405406
_wasmfs_node_get_mode__sig: 'ipp',
406407
_wasmfs_node_insert_directory__sig: 'ipi',
407408
_wasmfs_node_insert_file__sig: 'ipi',
408409
_wasmfs_node_open__sig: 'ipp',
409410
_wasmfs_node_read__sig: 'iipiip',
410411
_wasmfs_node_readdir__sig: 'ipp',
412+
_wasmfs_node_readlink__sig: 'ippi',
413+
_wasmfs_node_rename__sig: 'ipp',
411414
_wasmfs_node_rmdir__sig: 'ip',
412415
_wasmfs_node_stat_size__sig: 'ipp',
416+
_wasmfs_node_symlink__sig: 'ipp',
417+
_wasmfs_node_truncate__sig: 'ipj',
413418
_wasmfs_node_unlink__sig: 'ip',
414419
_wasmfs_node_write__sig: 'iipiip',
415420
_wasmfs_opfs_close_access__sig: 'vpip',

Diff for: src/lib/libwasmfs_node.js

+32-3
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,39 @@ addToLibrary({
156156
});
157157
},
158158

159+
_wasmfs_node_truncate__i53abi: true,
160+
_wasmfs_node_truncate__deps : ['$wasmfsTry'],
161+
_wasmfs_node_truncate : (path_p, len) => {
162+
return wasmfsTry(() => fs.truncateSync(UTF8ToString(path_p), len));
163+
},
164+
165+
_wasmfs_node_ftruncate__i53abi: true,
166+
_wasmfs_node_ftruncate__deps : ['$wasmfsTry'],
167+
_wasmfs_node_ftruncate : (fd, len) => {
168+
return wasmfsTry(() => fs.ftruncateSync(fd, len));
169+
},
170+
159171
_wasmfs_node_open__deps: ['$wasmfsTry'],
160172
_wasmfs_node_open: (path_p, mode_p) => {
161-
return wasmfsTry(() =>
162-
fs.openSync(UTF8ToString(path_p), UTF8ToString(mode_p))
163-
);
173+
return wasmfsTry(() => fs.openSync(UTF8ToString(path_p), UTF8ToString(mode_p)));
174+
},
175+
176+
_wasmfs_node_rename__deps: ['$wasmfsTry'],
177+
_wasmfs_node_rename: (from_path_p, to_path_p) => {
178+
return wasmfsTry(() => fs.renameSync(UTF8ToString(from_path_p), UTF8ToString(to_path_p)));
179+
},
180+
181+
_wasmfs_node_symlink__deps: ['$wasmfsTry'],
182+
_wasmfs_node_symlink: (target_path_p, linkpath_path_p) => {
183+
return wasmfsTry(() => fs.symlinkSync(UTF8ToString(target_path_p), UTF8ToString(linkpath_path_p)));
184+
},
185+
186+
_wasmfs_node_readlink__deps: ['$wasmfsTry'],
187+
_wasmfs_node_readlink: (path_p, target_p, bufsize) => {
188+
return wasmfsTry(() => {
189+
var target = fs.readlinkSync(UTF8ToString(path_p));
190+
return stringToUTF8(target, target_p, bufsize);
191+
});
164192
},
165193

166194
_wasmfs_node_close__deps: [],
@@ -192,4 +220,5 @@ addToLibrary({
192220
// implicitly return 0
193221
});
194222
},
223+
195224
});

Diff for: system/lib/wasmfs/backends/node_backend.cpp

+45-7
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,13 @@ class NodeState {
4545
result = _wasmfs_node_open(path.c_str(), "r");
4646
break;
4747
case O_WRONLY:
48-
result = _wasmfs_node_open(path.c_str(), "w");
49-
break;
48+
// TODO(sbc): Specific handling of O_WRONLY.
49+
// There is no simple way to map O_WRONLY to an fopen-style
50+
// mode string since the only two modes that are write only
51+
// are `w` and `a`. The problem with the former is that it
52+
// truncates to file. The problem with the latter is that it
53+
// opens for appending. For now simply opening in O_RDWR
54+
// mode is enough to pass all our tests.
5055
case O_RDWR:
5156
result = _wasmfs_node_open(path.c_str(), "r+");
5257
break;
@@ -118,7 +123,10 @@ class NodeFile : public DataFile {
118123
}
119124

120125
int setSize(off_t size) override {
121-
WASMFS_UNREACHABLE("TODO: implement NodeFile::setSize");
126+
if (state.isOpen()) {
127+
return _wasmfs_node_ftruncate(state.getFD(), size);
128+
}
129+
return _wasmfs_node_truncate(state.path.c_str(), size);
122130
}
123131

124132
int open(oflags_t flags) override { return state.open(flags); }
@@ -147,6 +155,22 @@ class NodeFile : public DataFile {
147155
}
148156
};
149157

158+
class NodeSymlink : public Symlink {
159+
public:
160+
std::string path;
161+
162+
NodeSymlink(backend_t backend, std::string path)
163+
: Symlink(backend), path(path) {}
164+
165+
virtual std::string getTarget() const {
166+
char buf[PATH_MAX];
167+
if (_wasmfs_node_readlink(path.c_str(), buf, PATH_MAX) < 0) {
168+
WASMFS_UNREACHABLE("getTarget cannot fail");
169+
}
170+
return std::string(buf);
171+
}
172+
};
173+
150174
class NodeDirectory : public Directory {
151175
public:
152176
NodeState state;
@@ -172,8 +196,7 @@ class NodeDirectory : public Directory {
172196
} else if (S_ISDIR(mode)) {
173197
return std::make_shared<NodeDirectory>(mode, getBackend(), childPath);
174198
} else if (S_ISLNK(mode)) {
175-
// return std::make_shared<NodeSymlink>(mode, getBackend(), childPath);
176-
return nullptr;
199+
return std::make_shared<NodeSymlink>(getBackend(), childPath);
177200
} else {
178201
// Unrecognized file kind not made visible to WasmFS.
179202
return nullptr;
@@ -212,11 +235,26 @@ class NodeDirectory : public Directory {
212235

213236
std::shared_ptr<Symlink> insertSymlink(const std::string& name,
214237
const std::string& target) override {
215-
WASMFS_UNREACHABLE("TODO: implement NodeDirectory::insertSymlink");
238+
auto childPath = getChildPath(name);
239+
if (_wasmfs_node_symlink(target.c_str(), childPath.c_str())) {
240+
return nullptr;
241+
}
242+
return std::make_shared<NodeSymlink>(getBackend(), childPath);
216243
}
217244

218245
int insertMove(const std::string& name, std::shared_ptr<File> file) override {
219-
WASMFS_UNREACHABLE("TODO: implement NodeDirectory::insertMove");
246+
std::string fromPath;
247+
248+
if (file->is<DataFile>()) {
249+
auto nodeFile = std::static_pointer_cast<NodeFile>(file);
250+
fromPath = nodeFile->state.path;
251+
} else {
252+
auto nodeDir = std::static_pointer_cast<NodeDirectory>(file);
253+
fromPath = nodeDir->state.path;
254+
}
255+
256+
auto childPath = getChildPath(name);
257+
return _wasmfs_node_rename(fromPath.c_str(), childPath.c_str());
220258
}
221259

222260
ssize_t getNumEntries() override {

Diff for: system/lib/wasmfs/backends/node_backend.h

+11-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ int _wasmfs_node_insert_directory(const char* path, mode_t mode);
2727
int _wasmfs_node_unlink(const char* path);
2828
int _wasmfs_node_rmdir(const char* path);
2929

30+
int _wasmfs_node_truncate(const char* path, off_t len);
31+
int _wasmfs_node_ftruncate(int fd, off_t len);
32+
33+
int _wasmfs_node_rename(const char* oldpath, const char* newpath);
34+
35+
int _wasmfs_node_symlink(const char *target, const char *linkpath);
36+
37+
int _wasmfs_node_readlink(const char *path, const char *buf, int bufsize);
38+
3039
// Open the file and return the underlying file descriptor.
3140
[[nodiscard]] int _wasmfs_node_open(const char* path, const char* mode);
3241

@@ -42,4 +51,5 @@ int _wasmfs_node_read(
4251
// the number of bytes written to `nread`. Return 0 on success or an error code.
4352
int _wasmfs_node_write(
4453
int fd, const void* buf, uint32_t len, uint32_t pos, uint32_t* nwritten);
45-
}
54+
55+
} // extern "C"

Diff for: test/common.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ def metafunc(self, fs, *args, **kwargs):
448448
self.setup_noderawfs_test()
449449
elif fs == 'wasmfs':
450450
self.setup_wasmfs_test()
451+
elif fs == 'wasmfs_rawfs':
452+
self.setup_wasmfs_test()
453+
self.setup_noderawfs_test()
451454
else:
452455
self.emcc_args += ['-DMEMFS']
453456
assert fs is None
@@ -458,7 +461,8 @@ def metafunc(self, fs, *args, **kwargs):
458461
parameterize(metafunc, {'': (None,),
459462
'nodefs': ('nodefs',),
460463
'rawfs': ('rawfs',),
461-
'wasmfs': ('wasmfs',)})
464+
'wasmfs': ('wasmfs',),
465+
'wasmfs_rawfs': ('wasmfs_rawfs',)})
462466
return metafunc
463467

464468

Diff for: test/fs/test_stat_unnamed_file_descriptor.c

+5
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ int main() {
88
int fd = open("file.txt", O_RDWR | O_CREAT, 0666);
99
unlink("file.txt");
1010
int res;
11+
1112
struct stat buf;
1213
res = fstat(fd, &buf);
1314
assert(res == 0);
1415
assert(buf.st_atime > 1000000000);
16+
printf("done stat: %d\n", res);
17+
1518
res = fchmod(fd, 0777);
1619
assert(res == 0);
20+
1721
res = ftruncate(fd, 10);
1822
assert(res == 0);
23+
1924
printf("success\n");
2025
}

Diff for: test/test_core.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5922,7 +5922,7 @@ def test_unistd_access(self):
59225922
# We also report all files as executable since there is no x bit
59235923
# recorded there.
59245924
# See https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/chmod-wchmod?view=msvc-170#remarks
5925-
if WINDOWS and '-DNODERAWFS' in self.emcc_args:
5925+
if WINDOWS and '-DNODERAWFS' in self.emcc_args and not self.get_setting('WASMFS'):
59265926
out_suffix = '.win'
59275927
else:
59285928
out_suffix = ''

Diff for: test/unistd/truncate.c

+22-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* found in the LICENSE file.
66
*/
77

8+
#include <assert.h>
89
#include <stdio.h>
910
#include <errno.h>
1011
#include <unistd.h>
@@ -13,26 +14,35 @@
1314
#include <string.h>
1415

1516
void setup() {
17+
int rtn;
18+
1619
FILE* f = fopen("towrite", "w");
17-
fwrite("abcdef", 6, 1, f);
20+
assert(f);
21+
rtn = fwrite("abcdef", 6, 1, f);
22+
assert(rtn = 6);
1823
fclose(f);
24+
1925
f = fopen("toread", "w");
20-
fwrite("abcdef", 6, 1, f);
26+
assert(f);
27+
rtn = fwrite("abcdef", 6, 1, f);
28+
assert(rtn = 6);
2129
fclose(f);
2230

23-
chmod("toread", 0444);
31+
assert(chmod("toread", 0444) == 0);
2432
}
2533

2634
int main() {
2735
setup();
2836

2937
struct stat s;
3038
int f = open("towrite", O_WRONLY);
39+
assert(f);
3140
int f2 = open("toread", O_RDONLY);
32-
printf("f2: %d\n", f2);
41+
assert(f2);
3342

3443
fstat(f, &s);
3544
printf("st_size: %lld\n", s.st_size);
45+
assert(s.st_size == 6);
3646
memset(&s, 0, sizeof s);
3747
errno = 0;
3848
printf("\n");
@@ -41,6 +51,7 @@ int main() {
4151
printf("errno: %s\n", strerror(errno));
4252
fstat(f, &s);
4353
printf("st_size: %lld\n", s.st_size);
54+
assert(s.st_size == 10);
4455
memset(&s, 0, sizeof s);
4556
errno = 0;
4657
printf("\n");
@@ -49,6 +60,7 @@ int main() {
4960
printf("errno: %s\n", strerror(errno));
5061
fstat(f, &s);
5162
printf("st_size: %lld\n", s.st_size);
63+
assert(s.st_size == 4);
5264
memset(&s, 0, sizeof s);
5365
errno = 0;
5466
printf("\n");
@@ -57,6 +69,7 @@ int main() {
5769
printf("errno: %s\n", strerror(errno));
5870
fstat(f, &s);
5971
printf("st_size: %lld\n", s.st_size);
72+
assert(s.st_size == 4);
6073
memset(&s, 0, sizeof s);
6174
errno = 0;
6275
printf("\n");
@@ -65,6 +78,7 @@ int main() {
6578
printf("errno: %s\n", strerror(errno));
6679
fstat(f, &s);
6780
printf("st_size: %lld\n", s.st_size);
81+
assert(s.st_size == 2);
6882
memset(&s, 0, sizeof s);
6983
errno = 0;
7084
printf("\n");
@@ -74,6 +88,7 @@ int main() {
7488
printf("errno: %s\n", strerror(errno));
7589
fstat(f, &s);
7690
printf("st_size: %lld\n", s.st_size);
91+
assert(s.st_size == 0);
7792
memset(&s, 0, sizeof s);
7893
errno = 0;
7994
printf("\n");
@@ -82,6 +97,7 @@ int main() {
8297
printf("errno: %s\n", strerror(errno));
8398
fstat(f2, &s);
8499
printf("st_size: %lld\n", s.st_size);
100+
assert(s.st_size == 6);
85101
memset(&s, 0, sizeof s);
86102
errno = 0;
87103
printf("\n");
@@ -94,6 +110,7 @@ int main() {
94110
printf("errno: %s\n", strerror(errno));
95111
fstat(f2, &s);
96112
printf("st_size: %lld\n", s.st_size);
113+
assert(s.st_size == 6);
97114
memset(&s, 0, sizeof s);
98115
errno = 0;
99116
printf("\n");
@@ -103,6 +120,7 @@ int main() {
103120
printf("errno: %s\n", strerror(errno));
104121
fstat(f2, &s);
105122
printf("st_size: %lld\n", s.st_size);
123+
assert(s.st_size == 6);
106124
memset(&s, 0, sizeof s);
107125
errno = 0;
108126

Diff for: tools/emscripten.py

+1
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,7 @@ def create_pointer_conversion_wrappers(metadata):
10701070
'_wasmfs_get_cwd': 'p_',
10711071
'_wasmfs_identify': '_p',
10721072
'_wasmfs_read_file': 'pp',
1073+
'_wasmfs_node_record_dirent': '_pp_',
10731074
'__dl_seterr': '_pp',
10741075
'_emscripten_run_on_main_thread_js': '__p_p_',
10751076
'_emscripten_proxy_execute_task_queue': '_p',

0 commit comments

Comments
 (0)