Skip to content

Commit

Permalink
std: net: Add function to get the system hostname
Browse files Browse the repository at this point in the history
  • Loading branch information
orowith2os committed Jan 6, 2025
1 parent b3b368a commit 9761a27
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
40 changes: 40 additions & 0 deletions library/std/src/net/hostname.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#[cfg(not(target_family = "windows" ))]
use libc::gethostname;
use crate::ffi::CStr;
use crate::ffi::OsString;
use crate::os::raw::c_char;

/// Returns the system hostname.
///
/// The returned result will, on success, return the same result [`libc::gethostname`] would return
/// (as it is implemented using the very same function), and on error, what `errno` contains, also
/// set by [`libc::gethostname`].
#[unstable(feature = "gethostname", issue = "135142")]
pub fn hostname() -> crate::io::Result<OsString> {
// 255 bytes is the maximum allowable length for a hostname (as per the DNS spec),
// so we shouldn't ever have problems with this. I (@orowith2os) considered using a constant
// and letting the platform set the length, but it was determined after some discussion that
// this could break things if the platform changes their length. Possible alternative is to
// read the sysconf setting for the max hostname length, but that might be a bit too much work.
// The 256 byte length is to allow for the NUL terminator.
let mut temp_buffer: [c_char; 256] = [0; 256];
// 0 = no problem, and there isn't any other relevant error code to check for. Only stuff for
// sethostname, and ENAMETOOLONG, which is only relevant for glibc 2.1 or newer. With the
// previous information given in mind, we shouldn't ever encounter any error other than the
// fact that the system *somehow* failed to get the hostname.
// SAFETY: should never be unsafe, as we're passing in a valid (0-initialized) buffer, and the
// length of said buffer.
#[cfg(not(target_family = "windows" ))]
let gethostname_result = unsafe { gethostname(&mut temp_buffer as _, temp_buffer.len()) };
#[cfg(target_family = "windows" )]
let gethostname_result = { println!("gethostname impl for the Rust stdlib isn't done on Windows yet, so here's an error instead!"); return -1; }

match gethostname_result {
0 => {
// SAFETY: we already know the pointer here is valid, we made it from safe Rust earlier.
let cstring = unsafe { CStr::from_ptr(&mut temp_buffer as _) };
return Ok(OsString::from(cstring.to_string_lossy().as_ref()));
}
_ => Err(crate::io::Error::last_os_error()),
}
}
6 changes: 5 additions & 1 deletion library/std/src/net/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Networking primitives for TCP/UDP communication.
//!
//! This module provides networking functionality for the Transmission Control and User
//! Datagram Protocols, as well as types for IP and socket addresses.
//! Datagram Protocols, as well as types for IP and socket addresses, and functions related
//! to network properties.
//!
//! # Organization
//!
Expand Down Expand Up @@ -35,13 +36,16 @@ pub use self::tcp::{Incoming, TcpListener, TcpStream};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::udp::UdpSocket;
use crate::io::{self, ErrorKind};
#[unstable(feature = "gethostname", issue = "135142")]
pub use self::hostname::hostname;

mod ip_addr;
mod socket_addr;
mod tcp;
#[cfg(test)]
pub(crate) mod test;
mod udp;
mod hostname;

/// Possible values which can be passed to the [`TcpStream::shutdown`] method.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
Expand Down

0 comments on commit 9761a27

Please sign in to comment.