Skip to content

Commit d904bce

Browse files
committed
unistd: add {get,set}domainname
This implements `getdomainname(2)` and `setdomainname(2)`, which are common UNIX extensions not covered by POSIX. References: * http://man7.org/linux/man-pages/man2/getdomainname.2.html * http://man7.org/linux/man-pages/man2/setdomainname.2.html
1 parent e461f3c commit d904bce

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
3535
([#857](https://github.com/nix-rust/nix/pull/857))
3636
- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
3737
([#833](https://github.com/nix-rust/nix/pull/833))
38+
- Added `nix::unistd::{getdomainname, setdomainname}` for all platforms except Android.
39+
([#816](https://github.com/nix-rust/nix/pull/816))
3840

3941
### Changed
4042
- Display and Debug for SysControlAddr now includes all fields.

src/unistd.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,63 @@ pub fn gethostname() -> Result<OsString> {
774774
})
775775
}
776776

777+
cfg_if!{
778+
if #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
779+
target_os = "ios", target_os = "macos"))] {
780+
type namelen_t = c_int;
781+
} else if #[cfg(not(target_os = "android"))] {
782+
type namelen_t = size_t;
783+
}
784+
}
785+
786+
/// Set the NIS domain name (see
787+
/// [setdomainname(2)](http://man7.org/linux/man-pages/man2/setdomainname.2.html)).
788+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios",
789+
target_os = "linux", target_os = "macos"))]
790+
pub fn setdomainname<S: AsRef<OsStr>>(name: S) -> Result<()> {
791+
let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
792+
let len = name.as_ref().as_bytes().len() as namelen_t;
793+
let res = unsafe { libc::setdomainname(ptr, len) };
794+
Errno::result(res).map(drop)
795+
}
796+
797+
/// Get the NIS domain name, returning a `OsString` on success (see
798+
/// [getdomainname(2)](http://man7.org/linux/man-pages/man2/getdomainname.2.html)).
799+
///
800+
/// This function call attempts to get the NIS domain name for the
801+
/// running system.
802+
///
803+
/// # Examples
804+
///
805+
/// ```
806+
/// use nix::unistd;
807+
///
808+
/// let domainname_os = unistd::getdomainname().expect("Failed getting domain name");
809+
/// let domainname = domainname_os.into_string().expect("Domain name wasn't valid UTF-8");
810+
/// println!("Domain name: {}", domainname);
811+
/// ```
812+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios",
813+
target_os = "linux", target_os = "macos"))]
814+
pub fn getdomainname() -> Result<OsString> {
815+
// Minimum hostname maximum length as defined by POSIX,
816+
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html
817+
const _POSIX_HOST_NAME_MAX: i64 = 255;
818+
let buf_len = sysconf(SysconfVar::HOST_NAME_MAX)
819+
.unwrap_or(None).unwrap_or(_POSIX_HOST_NAME_MAX + 1);
820+
let buf = vec![0; buf_len as usize];
821+
let ptr = unsafe { CString::from_vec_unchecked(buf).into_raw() };
822+
823+
let res = unsafe { libc::getdomainname(ptr, buf_len as namelen_t) };
824+
Errno::result(res).map(|_| {
825+
let cstr = unsafe {
826+
// Ensure CString is null-terminated
827+
*ptr.offset((buf_len - 1) as isize) = 0;
828+
CString::from_raw(ptr)
829+
};
830+
OsString::from_vec(cstr.into_bytes())
831+
})
832+
}
833+
777834
/// Close a raw file descriptor
778835
///
779836
/// Be aware that many Rust types implicitly close-on-drop, including

test/test_unistd.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,11 @@ fn test_gethostname() {
463463
let hn = gethostname().expect("gethostname failed");
464464
hn.into_string().expect("hostname contains invalid data");
465465
}
466+
467+
#[test]
468+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "ios",
469+
target_os = "linux", target_os = "macos"))]
470+
fn test_getdomainname() {
471+
let dn = getdomainname().expect("getdomainname failed");
472+
dn.into_string().expect("domainname contains invalid data");
473+
}

0 commit comments

Comments
 (0)