Skip to content

Commit b3b0a58

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

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

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

Lines changed: 22 additions & 12 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

@@ -1193,18 +1193,17 @@ impl Dir {
11931193
.io_result()
11941194
}
11951195

1196-
fn symlink_native(&self, original: &[u16], link: &Path, relative: bool) -> io::Result<()> {
1196+
fn symlink_native(&self, original: &Path, link: &[u16], relative: bool) -> io::Result<()> {
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();
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))?;
1201+
let linkfile = self.open_with(original, &opts)?;
1202+
let file_name_len = u16::try_from(link.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,
@@ -1214,15 +1213,21 @@ impl Dir {
12141213
.extend(Layout::new::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
12151214
.or(Err(TOO_LONG_ERR))?
12161215
.0;
1217-
let layout = Layout::array::<u16>(original.len() * 2)
1216+
let layout = Layout::array::<u16>(link.len())
12181217
.and_then(|arr| layout.extend(arr))
12191218
.or(Err(TOO_LONG_ERR))?
12201219
.0;
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::REPARSE_DATA_BUFFER>()
1226+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1227+
+ usize::from(file_name_len)
1228+
- offset_of!(c::REPARSE_DATA_BUFFER, Reserved),
1229+
)
1230+
.or(Err(TOO_LONG_ERR))?,
12261231
Reserved: 0,
12271232
rest: (),
12281233
});
@@ -1231,20 +1236,25 @@ impl Dir {
12311236
.cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
12321237
.write(sym_buffer);
12331238
ptr::copy_nonoverlapping(
1234-
utf16.as_ptr(),
1239+
link.as_ptr(),
12351240
buffer
12361241
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
12371242
.add(offset_of!(c::SYMBOLIC_LINK_REPARSE_BUFFER, PathBuffer))
12381243
.cast::<u16>(),
1239-
original.len() * 2,
1244+
link.len(),
12401245
);
12411246
};
12421247
let result = unsafe {
12431248
c::DeviceIoControl(
12441249
linkfile.handle.as_raw_handle(),
12451250
c::FSCTL_SET_REPARSE_POINT,
12461251
&raw const buffer as *const c_void,
1247-
u32::try_from(size_of_val(&buffer)).or(Err(TOO_LONG_ERR))?,
1252+
u32::try_from(
1253+
size_of::<c::REPARSE_DATA_BUFFER>()
1254+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1255+
+ usize::from(file_name_len),
1256+
)
1257+
.or(Err(TOO_LONG_ERR))?,
12481258
ptr::null_mut(),
12491259
0,
12501260
ptr::null_mut(),

0 commit comments

Comments
 (0)