Skip to content

fts: refactor to use fd-relative operations internally#2278

Open
Jeetubhati wants to merge 2 commits into
freebsd:mainfrom
Jeetubhati:jbhati/fts-refactor
Open

fts: refactor to use fd-relative operations internally#2278
Jeetubhati wants to merge 2 commits into
freebsd:mainfrom
Jeetubhati:jbhati/fts-refactor

Conversation

@Jeetubhati

Copy link
Copy Markdown
Contributor

Replace all _open(".", O_RDONLY|O_CLOEXEC) calls with _openat(ROOTFD(sp), ".", O_RDONLY|O_CLOEXEC) in __fts_open(), fts_read(), and fts_children().

Add ftsp_rootfd to struct _fts_private to hold the root file descriptor, and FTSP()/ROOTFD() macros for clean access to it. fts_open() initialises ftsp_rootfd to AT_FDCWD which preserves existing behaviour.

This is a preparatory change for fts_openat() which will allow callers to provide a pre-opened directory fd, enabling fts(3) traversal inside Capsicum capability mode.

Sponsored by: Google LLC (GSoC 2026)

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

Thank you for taking the time to contribute to FreeBSD!

There is an issue that needs to be resolved:

Note

Please review CONTRIBUTING.md, then update and push your branch again.

Replace all _open(".", O_RDONLY|O_CLOEXEC) calls with
_openat(ROOTFD(sp), ".", O_RDONLY|O_CLOEXEC) in __fts_open(),
fts_read(), and fts_children().

Add ftsp_rootfd to struct _fts_private to hold the root file
descriptor, and FTSP()/ROOTFD() macros for clean access to it.
fts_open() initialises ftsp_rootfd to AT_FDCWD which preserves
existing behaviour.

This is a preparatory change for fts_openat() which will allow
callers to provide a pre-opened directory fd, enabling fts(3)
traversal inside Capsicum capability mode.

Sponsored by: Google LLC (GSoC 2026)

@asomers asomers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the _open in fts_safe_changedir? I think that instead of changing directories, it would be better to open the child directory, and use that for future openat calls. But since the child directory is already opened, there might not be anything to do. In fact, we might be able to remove fts_safe_changedir altogether.

Comment thread lib/libc/gen/fts.c
/* Allocate/initialize the stream. */
if ((priv = calloc(1, sizeof(*priv))) == NULL)
return (NULL);
priv->ftsp_rootfd = AT_FDCWD;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only going to work for small directory trees. For larger ones, fts might internally chdir. Then AT_FDCWD would be pointing to the wrong place. So it would be better to use an actual file descriptor. Like fts_rfd. Why can't you just use that?

Comment thread lib/libc/gen/fts.c
struct statfs ftsp_statfs;
dev_t ftsp_dev;
int ftsp_linksreliable;
int ftsp_rootfd;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add a new file descriptor, instead of reusing fts_rfd?

Comment thread lib/libc/gen/fts.c Outdated
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
if ((p->fts_symfd = _open(".", O_RDONLY | O_CLOEXEC,
0)) < 0) {
if ((p->fts_symfd = _openat(ROOTFD(sp), ".",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we've already changed directories, then ROOTFD(sp) will be the wrong thing to use here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed ROOTFD(sp) to AT_FDCWD for the mid-traversal CWD saves in fts_read() and fts_children().

Comment thread lib/libc/gen/fts.c Outdated
if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
if ((p->fts_symfd =
_open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) {
_openat(ROOTFD(sp), ".", O_RDONLY |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as above, ROOTFD(sp) will be wrong if we've already changed directories.

Comment thread lib/libc/gen/fts.c Outdated
return (sp->fts_child = fts_build(sp, instr));

if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
if ((fd = _openat(ROOTFD(sp), ".", O_RDONLY | O_CLOEXEC, 0)) < 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, too, ROOTFD(sp) might be wrong.

@Jeetubhati

Copy link
Copy Markdown
Contributor Author

What about the _open in fts_safe_changedir? I think that instead of changing directories, it would be better to open the child directory, and use that for future openat calls. But since the child directory is already opened, there might not be anything to do. In fact, we might be able to remove fts_safe_changedir altogether.

if the child directory is already opened via fts_safe_changedir, we might not need path-based opens at all.
I need to think through whether fts_safe_changedir can be removed or simplified. Will look at this more carefully.

@Jeetubhati Jeetubhati force-pushed the jbhati/fts-refactor branch from 6098548 to 6cf9dd9 Compare June 13, 2026 05:22
ROOTFD(sp) is only correct for the initial open in __fts_open().
After fts has internally chdir'd, ROOTFD(sp) points to the wrong
directory. Use AT_FDCWD for the mid-traversal CWD saves in
fts_read() and fts_children() which is equivalent to the original
_open('.', ...) behaviour.

Sponsored by: Google LLC (GSoC 2026)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants