Skip to content

Commit 6759de5

Browse files
committed
fix symlink test on windows
1 parent b1332e7 commit 6759de5

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
@@ -1204,53 +1204,56 @@ impl Dir {
12041204
io::const_error!(io::ErrorKind::InvalidFilename, "File name is too long");
12051205
let mut opts = OpenOptions::new();
12061206
opts.write(true);
1207-
let linkfile = File::open(link, &opts)?;
1208-
let utf16: Vec<u16> = original.iter().chain(original).copied().collect();
1209-
let file_name_len = u16::try_from(original.len()).or(Err(TOO_LONG_ERR))?;
1210-
let sym_buffer = c::SYMBOLIC_LINK_REPARSE_BUFFER {
1211-
SubstituteNameOffset: 0,
1212-
SubstituteNameLength: file_name_len,
1213-
PrintNameOffset: file_name_len,
1214-
PrintNameLength: file_name_len,
1215-
Flags: if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 },
1216-
PathBuffer: 0,
1217-
};
1218-
let layout = Layout::new::<c::REPARSE_DATA_BUFFER>();
1219-
let layout = layout
1220-
.extend(Layout::new::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1221-
.or(Err(TOO_LONG_ERR))?
1222-
.0;
1223-
let layout = Layout::array::<u16>(original.len() * 2)
1224-
.and_then(|arr| layout.extend(arr))
1225-
.or(Err(TOO_LONG_ERR))?
1226-
.0;
1207+
opts.create(true);
1208+
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
1209+
opts.attributes(c::FILE_ATTRIBUTE_REPARSE_POINT);
1210+
let linkfile = self.open_with(link, &opts)?;
1211+
let original_name_byte_len =
1212+
u16::try_from(size_of::<u16>() * original.len()).or(Err(TOO_LONG_ERR))?;
1213+
let layout = Layout::from_size_align(
1214+
size_of::<c::REPARSE_DATA_BUFFER>()
1215+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1216+
+ size_of::<u16>() * (original.len() - 1),
1217+
align_of::<c::REPARSE_DATA_BUFFER>()
1218+
.max(align_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1219+
.max(align_of::<u16>()),
1220+
)
1221+
.or(Err(TOO_LONG_ERR))?;
12271222
let buffer = unsafe { alloc(layout) }.cast::<c::REPARSE_DATA_BUFFER>();
1223+
if buffer.is_null() {
1224+
return Err(io::ErrorKind::OutOfMemory.into());
1225+
}
12281226
unsafe {
1229-
buffer.write(c::REPARSE_DATA_BUFFER {
1230-
ReparseTag: c::IO_REPARSE_TAG_SYMLINK,
1231-
ReparseDataLength: u16::try_from(size_of_val(&sym_buffer)).or(Err(TOO_LONG_ERR))?,
1232-
Reserved: 0,
1233-
rest: (),
1234-
});
1235-
buffer
1236-
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
1237-
.cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1238-
.write(sym_buffer);
1239-
ptr::copy_nonoverlapping(
1240-
utf16.as_ptr(),
1241-
buffer
1242-
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
1243-
.add(offset_of!(c::SYMBOLIC_LINK_REPARSE_BUFFER, PathBuffer))
1244-
.cast::<u16>(),
1245-
original.len() * 2,
1227+
(&raw mut (*buffer).ReparseTag).write(c::IO_REPARSE_TAG_SYMLINK);
1228+
(&raw mut (*buffer).ReparseDataLength).write(
1229+
u16::try_from(
1230+
size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1231+
+ size_of::<u16>() * (original.len() - 1),
1232+
)
1233+
.or(Err(TOO_LONG_ERR))?,
12461234
);
1235+
(&raw mut (*buffer).Reserved).write(0);
1236+
let rest = (&raw mut (*buffer).rest).cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>();
1237+
1238+
(&raw mut (*rest).SubstituteNameOffset).write(0);
1239+
(&raw mut (*rest).SubstituteNameLength).write(original_name_byte_len);
1240+
(&raw mut (*rest).PrintNameOffset).write(0);
1241+
(&raw mut (*rest).PrintNameLength).write(original_name_byte_len);
1242+
(&raw mut (*rest).Flags).write(if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 });
1243+
1244+
original.as_ptr().copy_to_nonoverlapping(&raw mut (*rest).PathBuffer, original.len());
12471245
};
12481246
let result = unsafe {
12491247
c::DeviceIoControl(
12501248
linkfile.handle.as_raw_handle(),
12511249
c::FSCTL_SET_REPARSE_POINT,
1252-
&raw const buffer as *const c_void,
1253-
u32::try_from(size_of_val(&buffer)).or(Err(TOO_LONG_ERR))?,
1250+
buffer as *mut c_void as *const c_void,
1251+
u32::try_from(
1252+
size_of::<c::REPARSE_DATA_BUFFER>()
1253+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1254+
+ size_of::<u16>() * (original.len() - 1),
1255+
)
1256+
.or(Err(TOO_LONG_ERR))?,
12541257
ptr::null_mut(),
12551258
0,
12561259
ptr::null_mut(),

0 commit comments

Comments
 (0)