Skip to content

Commit

Permalink
Replace libc with rustix
Browse files Browse the repository at this point in the history
We no longer need to concern ourselves with buffer sizes and unsafe code.

See #10, closes #16
  • Loading branch information
swsnr committed Jul 6, 2024
1 parent c31b57e commit 0d2bd4e
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 48 deletions.
29 changes: 26 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
# Changelog

All notable changes to this project will be documented in this file.

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).
and this project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

- On Unix, use `rustix` to provide a simple implementation of `gethostname`
without `unsafe` (see [GH-10] and [GH-17]).

[GH-10]: https://github.com/swsnr/gethostname.rs/pull/10
[GH-17]: https://github.com/swsnr/gethostname.rs/pull/17

## [0.4.3] – 2023-05-13

### Changed
- Removed the `windows` dependency in favor of using embedded bindings, see [GH-11].

- Removed the `windows` dependency in favor of using embedded bindings, see
[GH-11].

[GH-11]: https://github.com/swsnr/gethostname.rs/pull/11

## [0.4.2] – 2023-04-13

### Changed

- Update dependencies.

## [0.4.1] – 2022-12-01
Expand All @@ -27,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.4.0] – 2022-10-28

### Changed

- Replace `winapi` with windows-rs, see [GH-7].
- Bump MSRV to 1.64 as required by windows-rs, see [GH-7].

Expand All @@ -35,30 +49,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.3.0] – 2022-10-09

### Changed

- Bump MSRV to 1.56.

## [0.2.3] – 2022-03-12

### Changed
- Limit `gethostname()` to `cfg(unix)` and `cfg(windows)` to provide more useful build failures on other platforms.

- Limit `gethostname()` to `cfg(unix)` and `cfg(windows)` to provide more useful
build failures on other platforms.

## [0.2.2] – 2022-01-14

## [0.2.1] – 2019-12-18

### Changed

- Consolidate documetation.
- Update crates.io metadata.

## [0.2.0] – 2019-01-22

### Added

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

[GH-1]: https://github.com/swsnr/gethostname.rs/pull/1

### Changed

- Pin supported Rust version to 1.31

## 0.1.0 – 2019-01-20

Initial release.

### Added
Expand Down
46 changes: 45 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ categories = ["os", "api-bindings"]
rust-version = "1.64"

[target.'cfg(not(windows))'.dependencies]
libc = "0.2.141"
rustix = { version = "0.38.34", default-features = false, features = [
"system",
] }

[target.'cfg(windows)'.dependencies]
windows-targets = "0.52.4"
55 changes: 12 additions & 43 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,61 +28,30 @@ use std::ffi::OsString;

/// Get the standard host name for the current machine.
///
/// On Unix simply wrap POSIX [gethostname] in a safe interface. On Windows
/// return the DNS host name of the local computer, as returned by
/// [GetComputerNameExW] with `ComputerNamePhysicalDnsHostname` as `NameType`.
///
/// This function panics if the buffer allocated for the hostname result of the
/// operating system is too small; however we take great care to allocate a
/// buffer of sufficient size:
/// On Unix call [`rustix::system::uname`] to obtain the node name, see
/// [`rustix::system::Uname::nodename`].
///
/// * On Unix we allocate the buffer using the maximum permitted hostname size,
/// as returned by [sysconf] via `sysconf(_SC_HOST_NAME_MAX)`, plus an extra
/// byte for the trailing NUL byte. A hostname cannot exceed this limit, so
/// this function can't realistically panic.
/// * On Windows we call `GetComputerNameExW` with a NULL buffer first, which
/// makes it return the length of the current host name. We then use this
/// length to allocate a buffer for the actual result; this leaves a tiny
/// tiny race condition in case the hostname changes to a longer name right
/// in between those two calls but that's a risk we don't consider of any
/// practical relevance.
/// On Windows return the DNS host name of the local computer, as returned by
/// [GetComputerNameExW] with `ComputerNamePhysicalDnsHostname` as `NameType`.
/// We call this function twice to obtain the appropriate buffer size; there is
/// a race condition window between these two calls where a change to the node
/// name would result in a wrong buffer size which could cause this function to
/// panic.
///
/// Hence _if_ this function does panic please [report an issue][new].
/// Note that this host name does not have a well-defined meaning in terms of
/// network name resolution. Specifically, it's not guaranteed that the
/// returned name can be resolved in any particular way, e.g. DNS.
///
/// [gethostname]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html
/// [sysconf]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html
/// [GetComputerNameExW]: https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getcomputernameexw
/// [new]: https://github.com/swsnr/gethostname.rs/issues/new
pub fn gethostname() -> OsString {
gethostname_impl()
}

#[cfg(unix)]
#[inline]
fn gethostname_impl() -> OsString {
use libc::{c_char, sysconf, _SC_HOST_NAME_MAX};
use std::os::unix::ffi::OsStringExt;
// Get the maximum size of host names on this system, and account for the
// trailing NUL byte.
let hostname_max = unsafe { sysconf(_SC_HOST_NAME_MAX) };
let mut buffer = vec![0; (hostname_max as usize) + 1];
let returncode = unsafe { libc::gethostname(buffer.as_mut_ptr() as *mut c_char, buffer.len()) };
if returncode != 0 {
// There are no reasonable failures, so lets panic
panic!(
"gethostname failed: {}
Please report an issue to <https://github.com/swsnr/gethostname.rs/issues>!",
std::io::Error::last_os_error()
);
}
// We explicitly search for the trailing NUL byte and cap at the buffer
// length: If the buffer's too small (which shouldn't happen since we
// explicitly use the max hostname size above but just in case) POSIX
// doesn't specify whether there's a NUL byte at the end, so if we didn't
// check we might read from memory that's not ours.
let end = buffer.iter().position(|&b| b == 0).unwrap_or(buffer.len());
buffer.truncate(end);
OsString::from_vec(buffer)
OsString::from_vec(rustix::system::uname().nodename().to_bytes().to_vec())
}

#[cfg(windows)]
Expand Down

0 comments on commit 0d2bd4e

Please sign in to comment.