Skip to content

Commit 917568d

Browse files
authored
Make WASMFS FS.createPath match the FS version behavior on EEXIST (#23603)
Both now continue if a path already exists (but not on other errors). Fixes #23602.
1 parent b20e0d3 commit 917568d

File tree

5 files changed

+84
-2
lines changed

5 files changed

+84
-2
lines changed

src/lib/libfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,7 @@ FS.staticInit();
16261626
try {
16271627
FS.mkdir(current);
16281628
} catch (e) {
1629-
// ignore EEXIST
1629+
if (e.errno != {{{ cDefs.EEXIST }}}) throw e;
16301630
}
16311631
parent = current;
16321632
}

src/lib/libwasmfs.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ FS.init();
111111
if (!wasmFSPreloadingFlushed) {
112112
wasmFSPreloadedDirs.push({parentPath: parent, childName: part});
113113
} else {
114-
FS.mkdir(current);
114+
try {
115+
FS.mkdir(current);
116+
} catch (e) {
117+
if (e.errno != {{{ cDefs.EEXIST }}}) throw e;
118+
}
115119
}
116120
parent = current;
117121
}

test/fs/test_fs_js_api.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,21 @@ EM_JS(void, test_fs_open, (), {
3838
assert(createFileNotHere && createFileNotHere.fd >= 0);
3939
});
4040

41+
// createPath should succeed when called on existing paths ( https://github.com/emscripten-core/emscripten/issues/23602 )
42+
EM_JS(void, test_fs_createPath, (), {
43+
FS.createPath('/', 'home', true, true);
44+
FS.createPath('/home', 'nested1', true, true);
45+
FS.createPath('/home', 'nested2', true, true);
46+
FS.writeFile('/home/nested1/test.txt', 'a=1\nb=2\n');
47+
FS.writeFile('/home/nested2/test.txt', 'a=2\nb=4\n');
48+
var read1 = FS.readFile('/home/nested1/test.txt',{encoding:'utf8'});
49+
var read2 = FS.readFile('/home/nested2/test.txt',{encoding:'utf8'});
50+
console.log("r1",read1);
51+
console.log("r2",read2);
52+
assert(read1 == 'a=1\nb=2\n');
53+
assert(read2 == 'a=2\nb=4\n');
54+
});
55+
4156
EM_JS(void, test_fs_rename, (), {
4257
FS.mkdir('renamedir');
4358
FS.writeFile('renamedir/renametestfile', "");
@@ -456,6 +471,7 @@ void cleanup() {
456471

457472
int main() {
458473
test_fs_open();
474+
test_fs_createPath();
459475
test_fs_rename();
460476
test_fs_readlink();
461477
test_fs_read();

test/test_browser.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,6 +1873,22 @@ def setup():
18731873
shutil.copy(Path('sub/test.data'), '.')
18741874
self.btest_exit('test_emscripten_async_load_script.c', args=['-sFORCE_FILESYSTEM'])
18751875

1876+
@also_with_wasmfs
1877+
def test_emscripten_overlapped_package(self):
1878+
# test that a program that loads multiple file_packager.py packages has a correctly initialized filesystem.
1879+
# this exercises https://github.com/emscripten-core/emscripten/issues/23602 whose root cause was a difference
1880+
# between JS FS and WASMFS behavior.
1881+
def setup():
1882+
ensure_dir('sub')
1883+
create_file('sub/file1.txt', 'first')
1884+
create_file('sub/file2.txt', 'second')
1885+
1886+
setup()
1887+
self.run_process([FILE_PACKAGER, 'test.data', '--preload', 'sub/file1.txt@/target/file1.txt'], stdout=open('script1.js', 'w'))
1888+
self.run_process([FILE_PACKAGER, 'test2.data', '--preload', 'sub/file2.txt@/target/file2.txt'], stdout=open('script2.js', 'w'))
1889+
self.btest_exit('test_emscripten_overlapped_package.c', args=['-sFORCE_FILESYSTEM'])
1890+
self.clear()
1891+
18761892
def test_emscripten_api_infloop(self):
18771893
self.btest_exit('emscripten_api_browser_infloop.cpp')
18781894

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2025 The Emscripten Authors. All rights reserved.
2+
// Emscripten is available under two separate licenses, the MIT license and the
3+
// University of Illinois/NCSA Open Source License. Both these licenses can be
4+
// found in the LICENSE file.
5+
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <string.h>
9+
#include <assert.h>
10+
11+
#include <emscripten.h>
12+
13+
void error2() {
14+
printf("fail2\n");
15+
}
16+
17+
void load2() {
18+
char buffer[10];
19+
memset(buffer, 0, 10);
20+
FILE *f = fopen("/target/file1.txt", "r");
21+
assert(f);
22+
fread(buffer, 1, 5, f);
23+
fclose(f);
24+
assert(strcmp(buffer, "first") == 0);
25+
26+
memset(buffer, 0, 10);
27+
f = fopen("/target/file2.txt", "r");
28+
assert(f);
29+
fread(buffer, 1, 6, f);
30+
fclose(f);
31+
assert(strcmp(buffer, "second") == 0);
32+
exit(0);
33+
}
34+
35+
void load1() {
36+
emscripten_async_load_script("script2.js", load2, error2);
37+
}
38+
39+
void error1() {
40+
printf("fail1\n");
41+
}
42+
43+
int main() {
44+
emscripten_async_load_script("script1.js", load1, error1);
45+
return 99;
46+
}

0 commit comments

Comments
 (0)