Skip to content

Commit

Permalink
Merge pull request #1 from lunaryorn/windows
Browse files Browse the repository at this point in the history
Add Windows implementation
  • Loading branch information
swsnr committed Jan 22, 2019
2 parents be9be63 + 613c0dc commit 8e2fd69
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
8 changes: 8 additions & 0 deletions .travis.yml
Expand Up @@ -20,6 +20,9 @@ jobs:
- stage: test
os: osx
rust: stable
- stage: test
os: windows
rust: stable

- stage: test
os: linux
Expand All @@ -33,3 +36,8 @@ jobs:
rust: stable
before_script: rustup component add clippy
script: cargo clippy --all-targets
- stage: lint
os: windows
rust: stable
before_script: rustup component add clippy
script: cargo clippy --all-targets
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Add Windows implementation (see [GH-1]).

[Gh-1]: https://github.com/lunaryorn/gethostname.rs/pull/1

## 0.1.0 – 2019-01-20
Initial release.

Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Expand Up @@ -17,3 +17,6 @@ pretty_assertions = "^0.5"

[target.'cfg(not(windows))'.dependencies]
libc = "^0.2"

[target.'cfg(windows)'.dependencies]
winapi = {version = "^0.3", features = ["sysinfoapi"]}
60 changes: 55 additions & 5 deletions src/lib.rs
Expand Up @@ -23,10 +23,10 @@ use std::io::Error;

/// Get the standard host name for the current machine.
///
/// Wraps POSIX [gethostname] in a safe interface. The function doesn’t fail but
/// it may `panic!` if the internal buffer for the hostname is too small, but we
/// use a buffer large enough to hold the maximum hostname, so we consider any
/// panics from this function as bug which you should report.
/// Wraps POSIX [gethostname] in a safe interface. The function may `panic!` if
/// the internal buffer for the hostname is too small, but we use a buffer large
/// enough to hold the maximum hostname, so we consider any panics from this
/// function as bug which you should report.
///
/// [gethostname]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html
#[cfg(not(windows))]
Expand Down Expand Up @@ -59,13 +59,63 @@ pub fn gethostname() -> OsString {
OsString::from_vec(buffer)
}

/// Get the standard hostname for the current machine.
///
/// Returns the DNS host name of the local computer, as returned by
/// [GetComputerNameExW] with `ComputerNamePhysicalDnsHostname` flag has name
/// type. This function may `panic!` if the internal buffer for the hostname is
/// too small. Since we try to allocate a buffer large enough to hold the host
/// name we consider panics a bug which you should report.
///
/// [GetComputerNameExW]: https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getcomputernameexw
#[cfg(windows)]
pub fn gethostname() -> OsString {
use std::os::windows::ffi::OsStringExt;
use winapi::ctypes::{c_ulong, wchar_t};
use winapi::um::sysinfoapi::{ComputerNamePhysicalDnsHostname, GetComputerNameExW};

let mut buffer_size: c_ulong = 0;

unsafe {
// This call always fails with ERROR_MORE_DATA, because we pass NULL to
// get the required buffer size.
GetComputerNameExW(
ComputerNamePhysicalDnsHostname,
std::ptr::null_mut(),
&mut buffer_size,
)
};

let mut buffer = vec![0 as wchar_t; buffer_size as usize];
let returncode = unsafe {
GetComputerNameExW(
ComputerNamePhysicalDnsHostname,
buffer.as_mut_ptr() as *mut wchar_t,
&mut buffer_size,
)
};
// GetComputerNameExW returns a non-zero value on success!
if returncode == 0 {
panic!(
"GetComputerNameExW failed to read hostname: {}
Please report this issue to <https://github.com/lunaryorn/gethostname.rs/issues>!",
Error::last_os_error()
);
}

let end = buffer
.iter()
.position(|&b| b == 0)
.unwrap_or_else(|| buffer.len());
OsString::from_wide(&buffer[0..end])
}

#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use std::process::Command;

#[test]
#[cfg(not(windows))]
fn gethostname_matches_system_hostname() {
let output = Command::new("hostname")
.output()
Expand Down

0 comments on commit 8e2fd69

Please sign in to comment.