Skip to content

Commit

Permalink
unistd: document and change implementation of gethostname
Browse files Browse the repository at this point in the history
Previously gethostname just mutated a buffer.  We now provide
a slightly more usable (but still allocation free) API that ensures
that the returned buffer is NUL-terminated.  We give back a `&CStr`
instead of requiring that the user do all of the conversions from
`&[u8]` when we know we are dealing with a `&CStr`.

Signed-off-by: Paul Osborne <osbpau@gmail.com>
  • Loading branch information
posborne committed Jan 16, 2017
1 parent d324991 commit 2d4c44a
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#410](https://github.com/nix-rust/nix/pull/410))
- `sethostname` now takes a `&str` instead of a `&[u8]` as this provides an API
that makes more sense in normal, correct usage of the API.
- `gethostname` previously did not expose the actual length of the hostname
written from the underlying system call at all. This has been updated to
return a `&CStr` within the provided buffer that is always properly
NUL-terminated (this is not guaranteed by the call with all platforms/libc
implementations).

### Fixed
- Fixed using kqueue with `EVFILT_USER` on FreeBSD
Expand Down
31 changes: 27 additions & 4 deletions src/unistd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,12 +473,35 @@ pub fn sethostname(name: &str) -> Result<()> {
Errno::result(res).map(drop)
}

pub fn gethostname(name: &mut [u8]) -> Result<()> {
let ptr = name.as_mut_ptr() as *mut c_char;
let len = name.len() as size_t;
/// Get the host name and store it in the provided buffer, returning a pointer
/// the CStr in that buffer on success (see
/// [gethostname(2)](http://man7.org/linux/man-pages/man2/gethostname.2.html)).
///
/// This function call attempts to get the host name for the running system and
/// store it in a provided buffer. The buffer will be populated with bytes up
/// to the length of the provided slice including a NUL terminating byte. If
/// the hostname is longer than the length provided, no error will be provided.
/// The posix specification does not specify whether implementations will
/// null-terminate in this case, but the nix implementation will ensure that the
/// buffer is null terminated in this case.
///
/// ```no_run
/// use nix::unistd;
///
/// let mut buf = [0u8; 64];
/// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname");
/// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8");
/// println!("Hostname: {}", hostname);
/// ```
pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr> {
let ptr = buffer.as_mut_ptr() as *mut c_char;
let len = buffer.len() as size_t;

let res = unsafe { libc::gethostname(ptr, len) };
Errno::result(res).map(drop)
Errno::result(res).map(|_| {
buffer[len - 1] = 0; // ensure always null-terminated
unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }
})
}

pub fn close(fd: RawFd) -> Result<()> {
Expand Down

0 comments on commit 2d4c44a

Please sign in to comment.