Skip to content

Commit e7725e6

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

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

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

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,8 +1033,8 @@ impl Dir {
10331033
}
10341034

10351035
pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(&self, original: P, link: Q) -> io::Result<()> {
1036-
run_path_with_utf16(original.as_ref(), &|orig| {
1037-
self.symlink_native(orig, link.as_ref(), original.as_ref().is_relative())
1036+
run_path_with_utf16(link.as_ref(), &|l| {
1037+
self.symlink_native(original.as_ref(), l.as_ref(), link.as_ref().is_relative())
10381038
})
10391039
}
10401040

@@ -1197,32 +1197,34 @@ impl Dir {
11971197
const TOO_LONG_ERR: io::Error =
11981198
io::const_error!(io::ErrorKind::InvalidFilename, "File name is too long");
11991199
let mut opts = OpenOptions::new();
1200-
opts.write(true);
1201-
let linkfile = File::open(link, &opts)?;
1202-
let utf16: Vec<u16> = original.iter().chain(original).copied().collect();
1200+
opts.create(true);
1201+
let linkfile = self.open_with(link, &opts)?;
12031202
let file_name_len = u16::try_from(original.len()).or(Err(TOO_LONG_ERR))?;
12041203
let sym_buffer = c::SYMBOLIC_LINK_REPARSE_BUFFER {
12051204
SubstituteNameOffset: 0,
12061205
SubstituteNameLength: file_name_len,
1207-
PrintNameOffset: file_name_len,
1206+
PrintNameOffset: 0,
12081207
PrintNameLength: file_name_len,
12091208
Flags: if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 },
12101209
PathBuffer: 0,
12111210
};
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;
1211+
let layout = Layout::from_size_align(
1212+
size_of::<c::REPARSE_DATA_BUFFER>()
1213+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1214+
+ size_of::<u16>() * (original.len() - 1),
1215+
align_of::<c::REPARSE_DATA_BUFFER>()
1216+
.max(align_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1217+
.max(align_of::<u16>()),
1218+
)
1219+
.or(Err(TOO_LONG_ERR))?;
12211220
let buffer = unsafe { alloc(layout) }.cast::<c::REPARSE_DATA_BUFFER>();
12221221
unsafe {
12231222
buffer.write(c::REPARSE_DATA_BUFFER {
12241223
ReparseTag: c::IO_REPARSE_TAG_SYMLINK,
1225-
ReparseDataLength: u16::try_from(size_of_val(&sym_buffer)).or(Err(TOO_LONG_ERR))?,
1224+
ReparseDataLength: u16::try_from(
1225+
size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>() + usize::from(file_name_len),
1226+
)
1227+
.or(Err(TOO_LONG_ERR))?,
12261228
Reserved: 0,
12271229
rest: (),
12281230
});
@@ -1231,20 +1233,23 @@ impl Dir {
12311233
.cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
12321234
.write(sym_buffer);
12331235
ptr::copy_nonoverlapping(
1234-
utf16.as_ptr(),
1236+
original.as_ptr(),
12351237
buffer
12361238
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
12371239
.add(offset_of!(c::SYMBOLIC_LINK_REPARSE_BUFFER, PathBuffer))
12381240
.cast::<u16>(),
1239-
original.len() * 2,
1241+
original.len(),
12401242
);
12411243
};
12421244
let result = unsafe {
12431245
c::DeviceIoControl(
12441246
linkfile.handle.as_raw_handle(),
12451247
c::FSCTL_SET_REPARSE_POINT,
12461248
&raw const buffer as *const c_void,
1247-
u32::try_from(size_of_val(&buffer)).or(Err(TOO_LONG_ERR))?,
1249+
u32::try_from(
1250+
size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>() + usize::from(file_name_len),
1251+
)
1252+
.or(Err(TOO_LONG_ERR))?,
12481253
ptr::null_mut(),
12491254
0,
12501255
ptr::null_mut(),

0 commit comments

Comments
 (0)