Skip to content

fix: lstat on unlinked symlink returns ENOENT#248

Merged
atoomic merged 1 commit intocpanel:masterfrom
atoomic:koan.atoomic/fix-stat-unlinked-symlink
Feb 28, 2026
Merged

fix: lstat on unlinked symlink returns ENOENT#248
atoomic merged 1 commit intocpanel:masterfrom
atoomic:koan.atoomic/fix-stat-unlinked-symlink

Conversation

@Koan-Bot
Copy link
Contributor

What

lstat() on an unlinked symlink now correctly returns ENOENT instead of stale stat data.

Why

After unlink($symlink), _mock_stat was skipping the "file not present" check for symlinks because the condition !$file_data->is_link excluded them. An unlinked symlink still has is_link() true (it's still a symlink object), but exists() is false — which is the correct predicate.

How

Replaced !$file_data->is_link && !defined $file_data->contents() with the canonical !$file_data->exists() check, which handles files, dirs, and symlinks uniformly.

Testing

Added 5 tests in t/symlink.t covering lstat/stat behavior before and after symlink unlink.

🤖 Generated with Claude Code

_mock_stat used `!$file_data->is_link && !defined $file_data->contents()`
to detect non-existent mocks. This excluded ALL symlinks — even deleted
ones (readlink=undef after unlink). After unlink, lstat would still
return a valid stat array instead of failing.

Replace with `!$file_data->exists()` which correctly handles all three
types: files (contents=undef), dirs (has_content=0), and unlinked
symlinks (readlink=undef).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@atoomic atoomic marked this pull request as ready for review February 28, 2026 01:05
@atoomic atoomic merged commit 16afb01 into cpanel:master Feb 28, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants