Skip to content

Commit beb6937

Browse files
committed
fix symlink test on windows
1 parent 1849b41 commit beb6937

File tree

1 file changed

+42
-39
lines changed

1 file changed

+42
-39
lines changed

library/std/src/sys/fs/windows.rs

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,53 +1198,56 @@ impl Dir {
11981198
io::const_error!(io::ErrorKind::InvalidFilename, "File name is too long");
11991199
let mut opts = OpenOptions::new();
12001200
opts.write(true);
1201-
let linkfile = File::open(link, &opts)?;
1202-
let utf16: Vec<u16> = original.iter().chain(original).copied().collect();
1203-
let file_name_len = u16::try_from(original.len()).or(Err(TOO_LONG_ERR))?;
1204-
let sym_buffer = c::SYMBOLIC_LINK_REPARSE_BUFFER {
1205-
SubstituteNameOffset: 0,
1206-
SubstituteNameLength: file_name_len,
1207-
PrintNameOffset: file_name_len,
1208-
PrintNameLength: file_name_len,
1209-
Flags: if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 },
1210-
PathBuffer: 0,
1211-
};
1212-
let layout = Layout::new::<c::REPARSE_DATA_BUFFER>();
1213-
let layout = layout
1214-
.extend(Layout::new::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1215-
.or(Err(TOO_LONG_ERR))?
1216-
.0;
1217-
let layout = Layout::array::<u16>(original.len() * 2)
1218-
.and_then(|arr| layout.extend(arr))
1219-
.or(Err(TOO_LONG_ERR))?
1220-
.0;
1201+
opts.create(true);
1202+
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
1203+
opts.attributes(c::FILE_ATTRIBUTE_REPARSE_POINT);
1204+
let linkfile = self.open_with(link, &opts)?;
1205+
let original_name_byte_len =
1206+
u16::try_from(size_of::<u16>() * original.len()).or(Err(TOO_LONG_ERR))?;
1207+
let layout = Layout::from_size_align(
1208+
size_of::<c::REPARSE_DATA_BUFFER>()
1209+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1210+
+ size_of::<u16>() * (original.len() - 1),
1211+
align_of::<c::REPARSE_DATA_BUFFER>()
1212+
.max(align_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1213+
.max(align_of::<u16>()),
1214+
)
1215+
.or(Err(TOO_LONG_ERR))?;
12211216
let buffer = unsafe { alloc(layout) }.cast::<c::REPARSE_DATA_BUFFER>();
1217+
if buffer.is_null() {
1218+
return Err(io::ErrorKind::OutOfMemory.into());
1219+
}
12221220
unsafe {
1223-
buffer.write(c::REPARSE_DATA_BUFFER {
1224-
ReparseTag: c::IO_REPARSE_TAG_SYMLINK,
1225-
ReparseDataLength: u16::try_from(size_of_val(&sym_buffer)).or(Err(TOO_LONG_ERR))?,
1226-
Reserved: 0,
1227-
rest: (),
1228-
});
1229-
buffer
1230-
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
1231-
.cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1232-
.write(sym_buffer);
1233-
ptr::copy_nonoverlapping(
1234-
utf16.as_ptr(),
1235-
buffer
1236-
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
1237-
.add(offset_of!(c::SYMBOLIC_LINK_REPARSE_BUFFER, PathBuffer))
1238-
.cast::<u16>(),
1239-
original.len() * 2,
1221+
(&raw mut (*buffer).ReparseTag).write(c::IO_REPARSE_TAG_SYMLINK);
1222+
(&raw mut (*buffer).ReparseDataLength).write(
1223+
u16::try_from(
1224+
size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1225+
+ size_of::<u16>() * (original.len() - 1),
1226+
)
1227+
.or(Err(TOO_LONG_ERR))?,
12401228
);
1229+
(&raw mut (*buffer).Reserved).write(0);
1230+
let rest = (&raw mut (*buffer).rest).cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>();
1231+
1232+
(&raw mut (*rest).SubstituteNameOffset).write(0);
1233+
(&raw mut (*rest).SubstituteNameLength).write(original_name_byte_len);
1234+
(&raw mut (*rest).PrintNameOffset).write(0);
1235+
(&raw mut (*rest).PrintNameLength).write(original_name_byte_len);
1236+
(&raw mut (*rest).Flags).write(if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 });
1237+
1238+
original.as_ptr().copy_to_nonoverlapping(&raw mut (*rest).PathBuffer, original.len());
12411239
};
12421240
let result = unsafe {
12431241
c::DeviceIoControl(
12441242
linkfile.handle.as_raw_handle(),
12451243
c::FSCTL_SET_REPARSE_POINT,
1246-
&raw const buffer as *const c_void,
1247-
u32::try_from(size_of_val(&buffer)).or(Err(TOO_LONG_ERR))?,
1244+
buffer as *mut c_void as *const c_void,
1245+
u32::try_from(
1246+
size_of::<c::REPARSE_DATA_BUFFER>()
1247+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1248+
+ size_of::<u16>() * (original.len() - 1),
1249+
)
1250+
.or(Err(TOO_LONG_ERR))?,
12481251
ptr::null_mut(),
12491252
0,
12501253
ptr::null_mut(),

0 commit comments

Comments
 (0)