Open
Description
Please include the following in your bug report:
Version of emscripten/emsdk:
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.6 (1ddaae4)
clang version 21.0.0git (https:/github.com/llvm/llvm-project 4775e6d9099467df9363e1a3cd5950cc3d2fde05)
Target: wasm32-unknown-emscripten
Thread model: posix
Failing command line in full:
Full link command and output with -v
appended:
emcc -g -s WASMFS -pthread -s PROXY_TO_PTHREAD=1 -s EXPORTED_FUNCTIONS="_malloc,_free" -v wasmfs_links.c -o test.html
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/bin/clang -target wasm32-unknown-emscripten -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --sysroot=/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot -D__EMSCRIPTEN_SHARED_MEMORY__=1 -DEMSCRIPTEN -Xclang -iwithsysroot/include/fakesdl -Xclang -iwithsysroot/include/compat -g3 -pthread -v -c wasmfs_links.c -o /var/folders/d8/08bv2b6s2b50q04__ln3cmbh0000gp/T/emscripten_temp_61hwxnjn/wasmfs_links_0.o
clang version 21.0.0git (https:/github.com/llvm/llvm-project 4775e6d9099467df9363e1a3cd5950cc3d2fde05)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /Users/richardgillaspy/GitHubOpen/emsdk/upstream/bin
(in-process)
"/Users/richardgillaspy/GitHubOpen/emsdk/upstream/bin/clang-21" -cc1 -triple wasm32-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name wasmfs_links.c -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-feature +atomics -target-feature +bulk-memory -target-feature +mutable-globals -target-feature +sign-ext -target-cpu generic -fvisibility=hidden -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/test -v -fcoverage-compilation-dir=/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/test -resource-dir /Users/richardgillaspy/GitHubOpen/emsdk/upstream/lib/clang/21 -D __EMSCRIPTEN_SHARED_MEMORY__=1 -D EMSCRIPTEN -isysroot /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot -internal-isystem /Users/richardgillaspy/GitHubOpen/emsdk/upstream/lib/clang/21/include -internal-isystem /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten -internal-isystem /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/include -ferror-limit 19 -pthread -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fignore-exceptions -fcolor-diagnostics -iwithsysroot/include/fakesdl -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /var/folders/d8/08bv2b6s2b50q04__ln3cmbh0000gp/T/emscripten_temp_61hwxnjn/wasmfs_links_0.o -x c wasmfs_links.c
clang -cc1 version 21.0.0git based upon LLVM 21.0.0git default target x86_64-apple-darwin23.6.0
ignoring nonexistent directory "/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten"
#include "..." search starts here:
#include <...> search starts here:
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/include/fakesdl
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/include/compat
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/lib/clang/21/include
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/include
End of search list.
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/bin/clang --version
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/bin/wasm-ld -o test.wasm /var/folders/d8/08bv2b6s2b50q04__ln3cmbh0000gp/T/emscripten_temp_61hwxnjn/wasmfs_links_0.o -L/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten -L/Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/src/lib /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/crtbegin.o /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/crt1_proxy_main.o -lGL-mt-getprocaddr -lal -lhtml5 -lstubs-debug -lnoexit -lc-mt-debug -ldlmalloc-mt-debug -lcompiler_rt-mt -lc++-mt-noexcept -lc++abi-debug-mt-noexcept -lsockets-mt -lwasmfs_no_fs -lwasmfs-mt-debug -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr /var/folders/d8/08bv2b6s2b50q04__ln3cmbh0000gp/T/tmpg0r0_o6vlibemscripten_js_symbols.so --import-memory --shared-memory --export=malloc --export=free --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_get_current --export=emscripten_stack_init --export=wasmfs_flush --export=_emscripten_stack_alloc --export=_emscripten_thread_free_data --export=_emscripten_thread_crashed --export=__wasm_call_ctors --export=_emscripten_tls_init --export=_emscripten_thread_init --export=_emscripten_stack_restore --export=emscripten_stack_set_limits --export=_emscripten_thread_exit --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --no-growable-memory --initial-memory=16777216 --entry=_emscripten_proxy_main --stack-first --table-base=1
/Users/richardgillaspy/GitHubOpen/emsdk/upstream/bin/llvm-objcopy test.wasm test.wasm --remove-section=producers
emcc: warning: `main` is defined in the input files, but `_main` is not in `EXPORTED_FUNCTIONS`. Add it to this list if you want `main` to run. [-Wunused-main]
/Users/richardgillaspy/GitHubOpen/emsdk/node/20.18.0_64bit/bin/node /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/tools/compiler.mjs -
/Users/richardgillaspy/GitHubOpen/emsdk/node/20.18.0_64bit/bin/node /Users/richardgillaspy/GitHubOpen/emsdk/upstream/emscripten/tools/preprocessor.mjs - shell.html
I just modified the unistd/link.c test to use WASMFS and it fails.
/*
* Copyright 2011 The Emscripten Authors. All rights reserved.
* Emscripten is available under two separate licenses, the MIT license and the
* University of Illinois/NCSA Open Source License. Both these licenses can be
* found in the LICENSE file.
*/
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <emscripten/wasmfs.h>
#include <emscripten/console.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endif
void makedir(const char *dir) {
int rtn = mkdir(dir, 0777);
assert(rtn == 0);
}
void makefile(const char *file, const char *content) {
int fd = open(file, O_RDWR | O_CREAT, 0777);
assert(fd >= 0);
int rtn = write(fd, content, strlen(content));
assert(rtn == strlen(content));
close(fd);
}
void makelink(const char *link, const char *path) {
int rtn = symlink(link, path);
assert(rtn == 0);
}
void changedir(const char *dir) {
int rtn = chdir(dir);
assert(rtn == 0);
}
void setup() {
// makedir("/working");
#if defined(__EMSCRIPTEN__) && defined(NODEFS)
EM_ASM(FS.mount(NODEFS, { root: '.' }, '/working'));
#endif
changedir("/working");
makelink("../test/../there!", "link");
makefile("file", "test");
makedir("directory");
makedir("directory/subdirectory");
makefile("directory/subdirectory/file", "Subdirectory");
makedir("relative");
makedir("relative/subrelative");
makefile("relative/file", "Relative");
makefile("relative/subrelative/file", "Subrelative");
makelink("../relative/file", "directory/relative");
makelink("../../relative/subrelative/file", "directory/subdirectory/subrelative");
makelink("directory/subdirectory/file", "subdirectoryrelative");
makedir("absolute");
makedir("absolute/subabsolute");
makefile("absolute/file", "Absolute");
makefile("absolute/subabsolute/file", "Subabsolute");
makelink("/working/absolute/file", "/working/directory/absolute");
makelink("/working/absolute/subabsolute/file", "/working/directory/subdirectory/subabsolute");
makelink("/working/directory/subdirectory/file", "/working/subdirectoryabsolute");
}
void test_reading_existing_symlinks() {
char* files[] = {"link", "file", "directory"};
for (int i = 0; i < sizeof files / sizeof files[0]; i++) {
char buffer[256] = {0};
int rtn = readlink(files[i], buffer, 256);
printf("readlink: '%s'\n", files[i]);
printf("errno: %s\n\n", strerror(errno));
if (rtn < 0) {
continue;
}
assert(strcmp(buffer, "../test/../there!") == 0);
assert(strlen(buffer) == rtn);
errno = 0;
}
}
void test_overwriting_symlink() {
int rtn = symlink("new-nonexistent-path", "link");
assert(rtn == -1);
assert(errno == EEXIST);
errno = 0;
}
void test_creating_symlink() {
int rtn = symlink("new-nonexistent-path", "directory/link");
assert(rtn == 0);
assert(errno == 0);
errno = 0;
char buffer[256] = {0};
rtn = readlink("directory/link", buffer, 256);
assert(errno == 0);
assert(strcmp(buffer, "new-nonexistent-path") == 0);
assert(strlen(buffer) == rtn);
errno = 0;
}
void test_reading_shortened_symlink() {
char buffer[256] = {0};
readlink("directory/link", buffer, 256);
buffer[0] = buffer[1] = buffer[2] = buffer[3] = buffer[4] = buffer[5] = '*';
int rtn = readlink("link", buffer, 4);
assert(errno == 0);
assert(rtn == 4);
assert(strcmp(buffer, "../t**nexistent-path") == 0);
errno = 0;
}
void test_noticing_loop_in_symlink() {
// FS.lookupPath should notice the symlink loop and return ELOOP, not go into
// an infinite recurse.
//
// This test doesn't work in wasmfs -- probably because access sees the
// symlink and returns true without bothering to chase the symlink
symlink("./loop-link/inside", "./loop-link");
int rtn = access("loop-link", F_OK);
assert(rtn == -1);
assert(errno == ELOOP);
errno = 0;
}
void test_relative_path_symlinks() {
char* parents[] = {
"/working/directory/",
"/working/directory/subdirectory/",
"/working/"
};
char* links[] = {
"relative",
"subrelative",
"subdirectoryrelative",
};
for (int i = 0; i < sizeof links / sizeof links[0]; i++) {
int rtn = chdir(parents[i]);
assert(rtn == 0);
char symlink[256] = {0};
strcat(strcpy(symlink, parents[i]), links[i]);
printf("symlink: '%s'\n", symlink);
char buf[256] = {0};
rtn = readlink(links[i], buf, 256);
FILE *fd = fopen(buf, "r");
assert(fd);
char buffer[13] = {0};
rtn = fread(buffer, 1, 13, fd);
assert(rtn <= 13);
printf("buffer: '%s'\n\n", buffer);
fclose(fd);
}
}
void test_absolute_path_symlinks() {
char* links[] = {
"/working/directory/absolute",
"/working/directory/subdirectory/subabsolute",
"/working/subdirectoryabsolute"
};
for (int i = 0; i < sizeof links / sizeof links[0]; i++) {
printf("symlink: '%s'\n", links[i]);
char buf[256] = {0};
readlink(links[i], buf, 256);
FILE *fd = fopen(buf, "r");
assert(fd);
char buffer[13] = {0};
int rtn = fread(buffer, 1, 13, fd);
assert(rtn <= 13);
printf("buffer: '%s'\n\n", buffer);
fclose(fd);
}
}
int main() {
backend_t opfs = wasmfs_create_opfs_backend();
emscripten_console_log("created OPFS backend");
int err = wasmfs_create_directory("/working", 0777, opfs);
assert(err == 0);
emscripten_console_log("mounted OPFS root directory");
setup();
test_reading_existing_symlinks();
test_overwriting_symlink();
test_creating_symlink();
test_reading_shortened_symlink();
test_noticing_loop_in_symlink();
test_relative_path_symlinks();
test_absolute_path_symlinks();
return 0;
}
Metadata
Metadata
Assignees
Labels
No labels