emscripten-core / emscripten-core/emscripten

File-related syscalls, like readdir, can not handle empty directories properly

Open
#21,604 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

Please include the following in your bug report:

**Version of emscripten/emsdk:**
I'm using emcc 3.1.54, node version v20.11.0.

**Failing command line in full:**
```
emcc test_emptydir.cpp --preload-file ./dir@./dir -o test_emptydir.js
node test_emptydir.js
```

**Full link command and output with `-v` appended:**
Even for runtime issues it helps a lot if you can include the full link command.
Adding `-v` to the link command will show all of the sub-commands run which
can help us diagnose your issue.

**The description of issue**

I'm trying to print all the files and directories under the `./dir` directory using `readdir`. Here inside the `./dir` I have a empty directory with path `./dir/empty_dir`. It seems this empty directory is not captured and handled by `readdir`.

Here's the `test_emptydir.cpp`
```
#include
#include

int main() {
dirent* _entry;
DIR* _dir = ::opendir("./dir");
if(!_dir) {
std::cout << "dir is null" << std::endl;
}
while((_entry = ::readdir(_dir)) != nullptr) {
std::cout << _entry->d_name << std::endl;
}
return 0;
}

```

Here's the content inside the `./dir` directory:
```
./dir/test.txt
./dir/empty_dir/
./dir/non_empty_dir/
./dir/non_empty_dir/test_2.txt

```
Where `./dir/test.txt` is an empty file, `./dir/empty_dir/` is an empty directory, and `./dir/non_empty_dir/` is an non-empty directory

By compiling with `emcc test_emptydir.cpp --preload-file ./dir@./dir -o test_emptydir.js` and run `node test_emptydir.js`, I get the result:

```
.
..
non_empty_dir
test.txt
```

As the result shows, the empty directory `./dir/empty_dir` is not printed.

**Similar problem** happens on other file-related syscalls like `lstat`. For example, if I compile and run the following code with the same command line `emcc test_lstat.cpp --preload-file ./dir@./dir -o test_lstat.js` and `node test_lstat.js`:
```
#include
#include
#include

int main() {
struct ::stat st;
auto result = ::lstat("./dir/empty_dir", &st);
std::cout << "is dir?: " << S_ISDIR(st.st_mode) << std::endl;
return 0;
}
```
I get the result:

```
is dir?: 0
```

Actually, it seems emscripten `--preload-file` cannot solely load an empty directory. For example, if I run following command:
```emcc test_emptydir.cpp --preload-file ./dir/empty_dir/@./dir/empty_dir -o test_emptydir.js```
I get compilation error:
```
Nothing to do!
emcc: error: '/data/emsdk/upstream/emscripten/tools/file_packager test_emptydir.data --from-emcc --preload ./dir/empty_dir/@./dir/empty_dir' failed (returned 1)
```
So it seems the problem could be derived from the strategy that emscripten does not preload empty directories during compilation time, and such operation will be restricted.

However, if we load an empty directory within a non-empty directory (or just preload it together with other non-empty files/directories), then it will cause bugs during runtime like mentioned above.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.