Skip to content

Commit e9bd439

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

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

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

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,31 +1198,38 @@ 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))?;
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))?;
12041207
let sym_buffer = c::SYMBOLIC_LINK_REPARSE_BUFFER {
12051208
SubstituteNameOffset: 0,
1206-
SubstituteNameLength: file_name_len,
1207-
PrintNameOffset: file_name_len,
1208-
PrintNameLength: file_name_len,
1209+
SubstituteNameLength: original_name_byte_len,
1210+
PrintNameOffset: 0,
1211+
PrintNameLength: original_name_byte_len,
12091212
Flags: if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 },
12101213
PathBuffer: 0,
12111214
};
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;
1215+
let layout = Layout::from_size_align(
1216+
size_of::<c::REPARSE_DATA_BUFFER>()
1217+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1218+
+ size_of::<u16>() * (original.len() - 1),
1219+
align_of::<c::REPARSE_DATA_BUFFER>()
1220+
.max(align_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1221+
.max(align_of::<u16>()),
1222+
)
1223+
.or(Err(TOO_LONG_ERR))?;
12211224
let buffer = unsafe { alloc(layout) }.cast::<c::REPARSE_DATA_BUFFER>();
12221225
unsafe {
12231226
buffer.write(c::REPARSE_DATA_BUFFER {
12241227
ReparseTag: c::IO_REPARSE_TAG_SYMLINK,
1225-
ReparseDataLength: u16::try_from(size_of_val(&sym_buffer)).or(Err(TOO_LONG_ERR))?,
1228+
ReparseDataLength: u16::try_from(
1229+
size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1230+
+ size_of::<u16>() * (original.len() - 1),
1231+
)
1232+
.or(Err(TOO_LONG_ERR))?,
12261233
Reserved: 0,
12271234
rest: (),
12281235
});
@@ -1231,20 +1238,25 @@ impl Dir {
12311238
.cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
12321239
.write(sym_buffer);
12331240
ptr::copy_nonoverlapping(
1234-
utf16.as_ptr(),
1241+
original.as_ptr(),
12351242
buffer
12361243
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
12371244
.add(offset_of!(c::SYMBOLIC_LINK_REPARSE_BUFFER, PathBuffer))
12381245
.cast::<u16>(),
1239-
original.len() * 2,
1246+
original.len(),
12401247
);
12411248
};
12421249
let result = unsafe {
12431250
c::DeviceIoControl(
12441251
linkfile.handle.as_raw_handle(),
12451252
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))?,
1253+
buffer as *mut c_void as *const c_void,
1254+
u32::try_from(
1255+
size_of::<c::REPARSE_DATA_BUFFER>()
1256+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1257+
+ size_of::<u16>() * (original.len() - 1),
1258+
)
1259+
.or(Err(TOO_LONG_ERR))?,
12481260
ptr::null_mut(),
12491261
0,
12501262
ptr::null_mut(),

0 commit comments

Comments
 (0)