// https://github.com/svartalf/hostname/blob/master/src/nix.rs use std::ffi::CStr; use std::fmt::Debug; use std::fmt::Formatter; #[cfg(not(miri))] use std::os::unix::ffi::OsStrExt; const _POSIX_HOST_NAME_MAX: libc::c_long = 255; pub struct NickName {} impl Debug for NickName { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { f.debug_struct("NickName").finish() } } impl NickName { pub fn new() -> crate::Result { Ok(Self {}) } pub fn get(&self) -> crate::Result { // ホスト名を格納するバッファのサイズを指定 // https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html #[cfg(not(miri))] let limit = unsafe { libc::sysconf(libc::_SC_HOST_NAME_MAX) }; #[cfg(miri)] let limit = 64; let size = libc::c_long::max(limit, _POSIX_HOST_NAME_MAX) as usize; #[cfg_attr(miri, allow(unused_mut))] let mut hostname_buffer: Vec = vec![0; size + 1]; // libcのgethostname関数を呼び出し、ホスト名を取得 #[cfg(not(miri))] let result = unsafe { libc::gethostname(hostname_buffer.as_mut_ptr() as *mut libc::c_char, size) }; #[cfg(miri)] let result = 0; if result != 0 { return Err(std::io::Error::last_os_error().into()); } // ヌル終端されたC文字列をRustの文字列に変換 let hostname_cstr = unsafe { CStr::from_ptr(hostname_buffer.as_ptr() as *const libc::c_char) }; match hostname_cstr.to_str() { Ok(v) => Ok(v.into()), Err(e) => Err(crate::Error::Other(Box::new(e))), } } #[cfg(not(miri))] // https://github.com/svartalf/hostname/blob/master/src/nix.rs pub fn set>(&self, nickname: S) -> crate::Result<()> { let nickname: String = nickname.into(); let nickname = std::ffi::OsStr::new(&nickname); #[cfg(not(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "solarish", target_os = "illumos", )))] #[allow(non_camel_case_types)] type nickname_len_t = libc::size_t; #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "solarish", target_os = "illumos", ))] #[allow(non_camel_case_types)] type nickname_len_t = libc::c_int; #[cfg(not(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "solarish", target_os = "illumos", )))] #[allow(clippy::absurd_extreme_comparisons)] if nickname.len() > nickname_len_t::MAX { return Err(std::io::Error::new(std::io::ErrorKind::Other, "nickname too long").into()); } #[cfg(any( target_os = "dragonfly", target_os = "freebsd", target_os = "ios", target_os = "macos", target_os = "solarish", target_os = "illumos", ))] if nickname.len() > nickname_len_t::MAX as usize { return Err(std::io::Error::new(std::io::ErrorKind::Other, "nickname too long").into()); } let size = nickname.len() as nickname_len_t; let result = unsafe { libc::sethostname(nickname.as_bytes().as_ptr() as *const libc::c_char, size) }; if result != 0 { Err(std::io::Error::last_os_error().into()) } else { Ok(()) } } #[cfg(miri)] pub fn set>(&self, _nickname: S) -> crate::Result<()> { Ok(()) } }