Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit beb6937

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

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
@@ -1198,53 +1198,56 @@ 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))?;
1204-
let sym_buffer = c::SYMBOLIC_LINK_REPARSE_BUFFER {
1205-
SubstituteNameOffset: 0,
1206-
SubstituteNameLength: file_name_len,
1207-
PrintNameOffset: file_name_len,
1208-
PrintNameLength: file_name_len,
1209-
Flags: if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 },
1210-
PathBuffer: 0,
1211-
};
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;
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))?;
1207+
let layout = Layout::from_size_align(
1208+
size_of::<c::REPARSE_DATA_BUFFER>()
1209+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1210+
+ size_of::<u16>() * (original.len() - 1),
1211+
align_of::<c::REPARSE_DATA_BUFFER>()
1212+
.max(align_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>())
1213+
.max(align_of::<u16>()),
1214+
)
1215+
.or(Err(TOO_LONG_ERR))?;
12211216
let buffer = unsafe { alloc(layout) }.cast::<c::REPARSE_DATA_BUFFER>();
1217+
if buffer.is_null() {
1218+
return Err(io::ErrorKind::OutOfMemory.into());
1219+
}
12221220
unsafe {
1223-
buffer.write(c::REPARSE_DATA_BUFFER {
1224-
ReparseTag: c::IO_REPARSE_TAG_SYMLINK,
1225-
ReparseDataLength: u16::try_from(size_of_val(&sym_buffer)).or(Err(TOO_LONG_ERR))?,
1226-
Reserved: 0,
1227-
rest: (),
1228-
});
1229-
buffer
1230-
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
1231-
.cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1232-
.write(sym_buffer);
1233-
ptr::copy_nonoverlapping(
1234-
utf16.as_ptr(),
1235-
buffer
1236-
.add(offset_of!(c::REPARSE_DATA_BUFFER, rest))
1237-
.add(offset_of!(c::SYMBOLIC_LINK_REPARSE_BUFFER, PathBuffer))
1238-
.cast::<u16>(),
1239-
original.len() * 2,
1221+
(&raw mut (*buffer).ReparseTag).write(c::IO_REPARSE_TAG_SYMLINK);
1222+
(&raw mut (*buffer).ReparseDataLength).write(
1223+
u16::try_from(
1224+
size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1225+
+ size_of::<u16>() * (original.len() - 1),
1226+
)
1227+
.or(Err(TOO_LONG_ERR))?,
12401228
);
1229+
(&raw mut (*buffer).Reserved).write(0);
1230+
let rest = (&raw mut (*buffer).rest).cast::<c::SYMBOLIC_LINK_REPARSE_BUFFER>();
1231+
1232+
(&raw mut (*rest).SubstituteNameOffset).write(0);
1233+
(&raw mut (*rest).SubstituteNameLength).write(original_name_byte_len);
1234+
(&raw mut (*rest).PrintNameOffset).write(0);
1235+
(&raw mut (*rest).PrintNameLength).write(original_name_byte_len);
1236+
(&raw mut (*rest).Flags).write(if relative { c::SYMLINK_FLAG_RELATIVE } else { 0 });
1237+
1238+
original.as_ptr().copy_to_nonoverlapping(&raw mut (*rest).PathBuffer, original.len());
12411239
};
12421240
let result = unsafe {
12431241
c::DeviceIoControl(
12441242
linkfile.handle.as_raw_handle(),
12451243
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))?,
1244+
buffer as *mut c_void as *const c_void,
1245+
u32::try_from(
1246+
size_of::<c::REPARSE_DATA_BUFFER>()
1247+
+ size_of::<c::SYMBOLIC_LINK_REPARSE_BUFFER>()
1248+
+ size_of::<u16>() * (original.len() - 1),
1249+
)
1250+
.or(Err(TOO_LONG_ERR))?,
12481251
ptr::null_mut(),
12491252
0,
12501253
ptr::null_mut(),

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /