Skip to content

withFileTypes has different behavior in fs.readdir when reading symbolic directories  #52663

Closed
@kylo5aby

Description

Version

21.6.0

Platform

Linux 5.15.0-41-generic #44-Ubuntu x86_64 GNU/Linux

Subsystem

fs

What steps will reproduce the bug?

For the directory tree below

dir
├── dir1
│   └── 1.txt
└── dir1_s  -> dir1

When using fs.readdir or fs.readdirSync to read the contents of dir, there is a difference in the number of contents outputted by the two:

const res = fs.readdirSync('./dir', {recursive: true, withFileTypes: true});
console.log(res);
Output:
// [
//   Dirent {
//     name: 'dir1',
//     parentPath: './dir',
//     path: './dir',
//     [Symbol(type)]: 2
//   },
//   Dirent {
//     name: 'dir1_s',
//     parentPath: './dir',
//     path: './dir',
//     [Symbol(type)]: 3
//   },
//   Dirent {
//     name: '1.txt',
//     parentPath: 'dir/dir1',
//     path: 'dir/dir1',
//     [Symbol(type)]: 1
//   }
// ]
const res = fs.readdirSync('./dir', {recursive: true, withFileTypes: false});
console.log(res);
// Output:
// [ 'dir1', 'dir1_s', 'dir1/1.txt', 'dir1_s/1.txt' ]

So do fs.readdir.

How often does it reproduce? Is there a required condition?

Always

What is the expected behavior? Why is that the expected behavior?

No response

What do you see instead?

when withFileTypes: true, the directory entry dir1_s/1.txt haven't been outputted. However, I did not find any description in the documentation regarding the difference in handling symbolic directories between the two.

Additional information

I found that the reason is because the two use different conditions to determine whether to continue traversal. When {withFileTypes:true}. it use

node/lib/fs.js

Line 1420 in 91dc8c9

if (dirent.isDirectory()) {

As described by class Dirent, type "directory" and "symbolic link" of dirent are mutually exclusive.

When {withFileTypes:false}, is use

node/lib/fs.js

Line 1428 in 91dc8c9

const stat = binding.internalModuleStat(resultPath);

Contrary to {withFileTypes:true}, "directory" and "symbolic link" are compatible, and then allows traversal to continue into 1.txt after encountering the symbolic directory dir1_s.

I'm not sure if this is work as expected. If it's not, I believe maintaining consistency with the results of {withFileTypes: false} would be preferable, aligning with the result of find -L [path].

Metadata

Assignees

No one assigned

    Labels

    fsIssues and PRs related to the fs subsystem / file system.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions