Skip to content

Commit f62937b

Browse files
committed
fix symlink test on windows
1 parent ced0e20 commit f62937b

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

0 commit comments

Comments
 (0)