Skip to content

Commit 825f687

Browse files
gzcxxalimpfard
authored andcommitted
runtime: Detect symlinked directories in DirectoryIterator
DirectoryIterator::next() only sets `is_directory` when `dirent.d_type == DT_DIR`. For entries whose `d_type` is `DT_LNK` (a symlink pointing at a directory) or `DT_UNKNOWN` (returned by file systems that don't populate `d_type`), a directory is misclassified as a regular file. This breaks `install()` in selfhost/main.jakt: it takes the file-copy path for such an entry, opens it, and `read()`s it, which fails with `EISDIR`. It reproduces during a normal SerenityOS toolchain build. runtime/CMakeLists.txt populates runtime/AK by symlinking every entry of SerenityOS' AK/ directory, so the AK/Math subdirectory becomes a symlink-to-directory. Environment: Linux (Fedora 44), reproduced via `Meta/serenity.sh build`. Note: this surfaced after commit d4c79a3 : file(COPY ...) -> create_symlink. Alternatively reverting to copying AK would also resolve it. Glad to take whichever direction you'd prefer.
1 parent ec3f4d3 commit 825f687

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

runtime/jaktlib/platform/posix_fs.jakt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,21 @@ class DirectoryIterator implements(ThrowingIterable<(Path, bool)>) {
9292

9393
mut builder = StringBuilder::create()
9494
mut is_directory = false
95+
let dir_handle = .dir_fd
9596

9697
unsafe {
9798
builder.append_c_string((*file).d_name)
9899

99100
// FIXME: Extern constant support
100101
cpp {
101-
"if ((*file).d_type == DT_DIR)"
102-
"is_directory = true;"
102+
"struct stat st;"
103+
"if ((*file).d_type == DT_DIR) {"
104+
" is_directory = true;"
105+
"} else if (((*file).d_type == DT_LNK || (*file).d_type == DT_UNKNOWN)"
106+
" && fstatat(dirfd(dir_handle), (*file).d_name, &st, 0) == 0"
107+
" && S_ISDIR(st.st_mode)) {"
108+
" is_directory = true;"
109+
"}"
103110
}
104111
}
105112

0 commit comments

Comments
 (0)