use crate::fs::{manually, OpenOptions};
use std::ffi::OsStr;
use std::path::Path;
use std::{fs, io};
use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND;
pub(crate) fn open_impl(
start: &fs::File,
path: &Path,
options: &OpenOptions,
) -> io::Result<fs::File> {
if let Some(stem) = file_prefix(path) {
if let Some(stemstr) = stem.to_str() {
match stemstr.trim_end().to_uppercase().as_str() {
"CON" | "PRN" | "AUX" | "NUL" | "COM0" | "COM1" | "COM2" | "COM3" | "COM4"
| "COM5" | "COM6" | "COM7" | "COM8" | "COM9" | "COM¹" | "COM²" | "COM³"
| "LPT0" | "LPT1" | "LPT2" | "LPT3" | "LPT4" | "LPT5" | "LPT6" | "LPT7"
| "LPT8" | "LPT9" | "LPT¹" | "LPT²" | "LPT³" => {
return Err(io::Error::from_raw_os_error(ERROR_FILE_NOT_FOUND as i32));
}
_ => {}
}
}
}
manually::open(start, path, options)
}
fn file_prefix(path: &Path) -> Option<&OsStr> {
path.file_name()
.map(split_file_at_dot)
.and_then(|(before, _after)| Some(before))
}
#[allow(unsafe_code)]
fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {
let slice = file.as_encoded_bytes();
if slice == b".." {
return (file, None);
}
let i = match slice[1..].iter().position(|b| *b == b'.') {
Some(i) => i + 1,
None => return (file, None),
};
let before = &slice[..i];
let after = &slice[i + 1..];
unsafe {
(
OsStr::from_encoded_bytes_unchecked(before),
Some(OsStr::from_encoded_bytes_unchecked(after)),
)
}
}