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}