@@ -3521,25 +3521,13 @@ file_status status(path const& p, error_code* ec)
3521
3521
3522
3522
#else // defined(BOOST_POSIX_API)
3523
3523
3524
- DWORD attrs = ::GetFileAttributesW (p.c_str ());
3525
- if (attrs == INVALID_FILE_ATTRIBUTES)
3524
+ // We should first test if the file is a symlink or a reparse point. Resolving some reparse
3525
+ // points by opening the file may fail, and status() should return file_status(reparse_file) in this case.
3526
+ // Which is what symlink_status() returns.
3527
+ fs::file_status st (detail::symlink_status (p, ec));
3528
+ if (st.type () == symlink_file)
3526
3529
{
3527
- return process_status_failure (p, ec);
3528
- }
3529
-
3530
- perms permissions = make_permissions (p, attrs);
3531
-
3532
- // reparse point handling;
3533
- // since GetFileAttributesW does not resolve symlinks, try to open a file
3534
- // handle to discover if the file exists
3535
- if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
3536
- {
3537
- if (!is_reparse_point_a_symlink (p))
3538
- {
3539
- return file_status (reparse_file, permissions);
3540
- }
3541
-
3542
- // try to resolve symlink
3530
+ // Resolve the symlink
3543
3531
handle_wrapper h (
3544
3532
create_file_handle (
3545
3533
p.c_str (),
@@ -3551,20 +3539,36 @@ file_status status(path const& p, error_code* ec)
3551
3539
3552
3540
if (h.handle == INVALID_HANDLE_VALUE)
3553
3541
{
3542
+ return_status_failure:
3554
3543
return process_status_failure (p, ec);
3555
3544
}
3556
3545
3557
- // take attributes of target
3558
- BY_HANDLE_FILE_INFORMATION info ;
3559
- if (!:: GetFileInformationByHandle (h. handle , &info ))
3546
+ DWORD attrs;
3547
+ GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed (get_file_information_by_handle_ex_api) ;
3548
+ if (BOOST_LIKELY (get_file_information_by_handle_ex != NULL ))
3560
3549
{
3561
- return process_status_failure (p, ec);
3550
+ file_attribute_tag_info info;
3551
+ BOOL res = get_file_information_by_handle_ex (h.handle , file_attribute_tag_info_class, &info, sizeof (info));
3552
+ if (BOOST_UNLIKELY (!res))
3553
+ goto return_status_failure;
3554
+
3555
+ attrs = info.FileAttributes ;
3562
3556
}
3557
+ else
3558
+ {
3559
+ BY_HANDLE_FILE_INFORMATION info;
3560
+ BOOL res = ::GetFileInformationByHandle (h.handle , &info);
3561
+ if (BOOST_UNLIKELY (!res))
3562
+ goto return_status_failure;
3563
3563
3564
- attrs = info.dwFileAttributes ;
3564
+ attrs = info.dwFileAttributes ;
3565
+ }
3566
+
3567
+ st.permissions (make_permissions (p, attrs));
3568
+ st.type ((attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::directory_file : fs::regular_file);
3565
3569
}
3566
3570
3567
- return (attrs & FILE_ATTRIBUTE_DIRECTORY) ? file_status (directory_file, permissions) : file_status (regular_file, permissions) ;
3571
+ return st ;
3568
3572
3569
3573
#endif // defined(BOOST_POSIX_API)
3570
3574
}
@@ -3627,18 +3631,52 @@ file_status symlink_status(path const& p, error_code* ec)
3627
3631
3628
3632
#else // defined(BOOST_POSIX_API)
3629
3633
3630
- DWORD attrs = ::GetFileAttributesW (p.c_str ());
3631
- if (attrs == INVALID_FILE_ATTRIBUTES)
3634
+ handle_wrapper h (
3635
+ create_file_handle (
3636
+ p.c_str (),
3637
+ 0u , // dwDesiredAccess; attributes only
3638
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
3639
+ NULL , // lpSecurityAttributes
3640
+ OPEN_EXISTING,
3641
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT));
3642
+
3643
+ if (h.handle == INVALID_HANDLE_VALUE)
3632
3644
{
3645
+ return_status_failure:
3633
3646
return process_status_failure (p, ec);
3634
3647
}
3635
3648
3636
- perms permissions = make_permissions (p, attrs);
3649
+ DWORD attrs;
3650
+ fs::perms permissions;
3651
+ GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed (get_file_information_by_handle_ex_api);
3652
+ if (BOOST_LIKELY (get_file_information_by_handle_ex != NULL ))
3653
+ {
3654
+ file_attribute_tag_info info;
3655
+ BOOL res = get_file_information_by_handle_ex (h.handle , file_attribute_tag_info_class, &info, sizeof (info));
3656
+ if (BOOST_UNLIKELY (!res))
3657
+ goto return_status_failure;
3658
+
3659
+ attrs = info.FileAttributes ;
3660
+ permissions = make_permissions (p, attrs);
3637
3661
3638
- if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
3639
- return is_reparse_point_a_symlink (p) ? file_status (symlink_file, permissions) : file_status (reparse_file, permissions);
3662
+ if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
3663
+ return is_reparse_point_tag_a_symlink (info.ReparseTag ) ? fs::file_status (fs::symlink_file, permissions) : fs::file_status (fs::reparse_file, permissions);
3664
+ }
3665
+ else
3666
+ {
3667
+ BY_HANDLE_FILE_INFORMATION info;
3668
+ BOOL res = ::GetFileInformationByHandle (h.handle , &info);
3669
+ if (BOOST_UNLIKELY (!res))
3670
+ goto return_status_failure;
3671
+
3672
+ attrs = info.dwFileAttributes ;
3673
+ permissions = make_permissions (p, attrs);
3674
+
3675
+ if (attrs & FILE_ATTRIBUTE_REPARSE_POINT)
3676
+ return is_reparse_point_a_symlink_ioctl (h.handle ) ? fs::file_status (fs::symlink_file, permissions) : fs::file_status (fs::reparse_file, permissions);
3677
+ }
3640
3678
3641
- return (attrs & FILE_ATTRIBUTE_DIRECTORY) ? file_status (directory_file, permissions) : file_status (regular_file, permissions);
3679
+ return (attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs:: file_status (fs:: directory_file, permissions) : fs:: file_status (fs:: regular_file, permissions);
3642
3680
3643
3681
#endif // defined(BOOST_POSIX_API)
3644
3682
}
0 commit comments