Skip to content

Commit

Permalink
Use FILE_ATTRIBUTE_TAG_INFO to get reparse tag
Browse files Browse the repository at this point in the history
This avoid unnecessarily getting the full reparse data when all we need is the tag.
  • Loading branch information
ChrisDenton committed Sep 1, 2022
1 parent 3892b70 commit 630f831
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
6 changes: 6 additions & 0 deletions library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,12 @@ pub enum FILE_INFO_BY_HANDLE_CLASS {
MaximumFileInfoByHandlesClass,
}

#[repr(C)]
pub struct FILE_ATTRIBUTE_TAG_INFO {
pub FileAttributes: DWORD,
pub ReparseTag: DWORD,
}

#[repr(C)]
pub struct FILE_DISPOSITION_INFO {
pub DeleteFile: BOOLEAN,
Expand Down
26 changes: 18 additions & 8 deletions library/std/src/sys/windows/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,15 @@ impl File {
cvt(c::GetFileInformationByHandle(self.handle.as_raw_handle(), &mut info))?;
let mut reparse_tag = 0;
if info.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
let mut b =
Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
if let Ok((_, buf)) = self.reparse_point(&mut b) {
reparse_tag = (*buf).ReparseTag;
let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
cvt(c::GetFileInformationByHandleEx(
self.handle.as_raw_handle(),
c::FileAttributeTagInfo,
ptr::addr_of_mut!(attr_tag).cast(),
mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
))?;
if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
reparse_tag = attr_tag.ReparseTag;
}
}
Ok(FileAttr {
Expand Down Expand Up @@ -390,10 +395,15 @@ impl File {
attr.file_size = info.AllocationSize as u64;
attr.number_of_links = Some(info.NumberOfLinks);
if attr.file_type().is_reparse_point() {
let mut b =
Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
if let Ok((_, buf)) = self.reparse_point(&mut b) {
attr.reparse_tag = (*buf).ReparseTag;
let mut attr_tag: c::FILE_ATTRIBUTE_TAG_INFO = mem::zeroed();
cvt(c::GetFileInformationByHandleEx(
self.handle.as_raw_handle(),
c::FileAttributeTagInfo,
ptr::addr_of_mut!(attr_tag).cast(),
mem::size_of::<c::FILE_ATTRIBUTE_TAG_INFO>().try_into().unwrap(),
))?;
if attr_tag.FileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
reparse_tag = attr_tag.ReparseTag;
}
}
Ok(attr)
Expand Down

0 comments on commit 630f831

Please sign in to comment.