util.rs

 1use std::{
 2    io::{Error, ErrorKind, Result},
 3    path::Path,
 4    sync::Once,
 5};
 6
 7use windows::Win32::Networking::WinSock::{
 8    ADDRESS_FAMILY, AF_UNIX, SOCKADDR_UN, SOCKET_ERROR, WSAGetLastError, WSAStartup,
 9};
10
11pub(crate) fn init() {
12    static ONCE: Once = Once::new();
13
14    ONCE.call_once(|| unsafe {
15        let mut wsa_data = std::mem::zeroed();
16        let result = WSAStartup(0x202, &mut wsa_data);
17        if result != 0 {
18            panic!("WSAStartup failed: {}", result);
19        }
20    });
21}
22
23// https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/
24pub(crate) fn sockaddr_un<P: AsRef<Path>>(path: P) -> Result<(SOCKADDR_UN, usize)> {
25    let mut addr = SOCKADDR_UN::default();
26    addr.sun_family = ADDRESS_FAMILY(AF_UNIX);
27
28    let bytes = path
29        .as_ref()
30        .to_str()
31        .map(|s| s.as_bytes())
32        .ok_or(ErrorKind::InvalidInput)?;
33
34    if bytes.contains(&0) {
35        return Err(Error::new(
36            ErrorKind::InvalidInput,
37            "paths may not contain interior null bytes",
38        ));
39    }
40    if bytes.len() >= addr.sun_path.len() {
41        return Err(Error::new(
42            ErrorKind::InvalidInput,
43            "path must be shorter than SUN_LEN",
44        ));
45    }
46
47    unsafe {
48        std::ptr::copy_nonoverlapping(
49            bytes.as_ptr(),
50            addr.sun_path.as_mut_ptr().cast(),
51            bytes.len(),
52        );
53    }
54
55    let mut len = sun_path_offset(&addr) + bytes.len();
56    match bytes.first() {
57        Some(&0) | None => {}
58        Some(_) => len += 1,
59    }
60    Ok((addr, len))
61}
62
63pub(crate) fn map_ret(ret: i32) -> Result<usize> {
64    if ret == SOCKET_ERROR {
65        Err(Error::from_raw_os_error(unsafe { WSAGetLastError().0 }))
66    } else {
67        Ok(ret as usize)
68    }
69}
70
71fn sun_path_offset(addr: &SOCKADDR_UN) -> usize {
72    // Work with an actual instance of the type since using a null pointer is UB
73    let base = addr as *const _ as usize;
74    let path = &addr.sun_path as *const _ as usize;
75    path - base
76}