Skip to content

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

Description

@kylo5aby

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].

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    fsIssues and PRs related to file-system APIs and the fs module.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions