win,fs: handle AppExecLink reparse points in fstat
Currently, libuv throws EACCES when trying to fstat AppExecLink reparse points, because Win32's CreateFileW can't resolve them on its own.
Use fs__readlink_handle as a fallback for reparse points that CreateFileW can't handle.
Fixes this nodejs issue: https://github.com/nodejs/node/issues/36790
This was already attempted (https://github.com/libuv/libuv/pull/4663) but the author of that pr stopped working on it. I believe this is what was intended in https://github.com/libuv/libuv/pull/4663#pullrequestreview-2524405802 and https://github.com/libuv/libuv/pull/4663#pullrequestreview-2573143548 but correct me if im wrong.
There are still fixes to be made, will add soon
Should be fine now, I changed readlink to accept a preallocated buffer (to reduce unnecessary allocations), but i can put that in another pr if that is preferred.
Claude also wrote a test for you (apply with caution since it is AI generated):
--- a/test/test-fs.c
+++ b/test/test-fs.c
@@ -2738,7 +2738,23 @@ TEST_IMPL(fs_lstat_windows_store_apps) {
dirent.name) < 0) {
continue;
}
- ASSERT_OK(uv_fs_lstat(loop, &stat_req, file_path, NULL));
+ /* lstat should work on AppExecLink reparse points */
+ ASSERT_OK(uv_fs_lstat(loop, &stat_req, file_path, NULL));
+ uv_fs_req_cleanup(&stat_req);
+
+ /* stat should also work - this is what PR #4936 fixes */
+ r = uv_fs_stat(loop, &stat_req, file_path, NULL);
+ ASSERT_OK(r);
+ uv_fs_req_cleanup(&stat_req);
+
+ /* readlink should return the target path */
+ r = uv_fs_readlink(loop, &stat_req, file_path, NULL);
+ ASSERT_OK(r);
+ ASSERT_NOT_NULL(stat_req.ptr);
+ /* Target should be an absolute path starting with a drive letter */
+ ASSERT_GE(strlen(stat_req.ptr), 3);
+ uv_fs_req_cleanup(&stat_req);
+ break; /* One successful test is enough */
}
MAKE_VALGRIND_HAPPY(loop);
return 0;
I added the suggested changes + made a small change in fs__create_file (line 439 + 460) to skip an unreachable if statement.
Also added the test, which turned out to be a oneliner.