zonename/
lib.rs

1#![deny(warnings)]
2#![deny(missing_docs)]
3
4//! # rust-zonename
5//!
6//! The `rust-zonename` crate provides a rust abstraction over the illumos `getzoneid`,
7//! `getzoneidbyname`, and `getzonenamebyid` C library functions.
8
9extern crate libc;
10
11use std::ffi::CString;
12use std::io;
13
14mod ffi;
15
16/// Max length of a zone name.
17pub const ZONENAME_MAX: usize = 64;
18
19/// Returns the zone ID of the calling process.
20///
21/// # Example
22/// ```
23/// let zoneid = zonename::getzoneid().expect("failed to get zoneid");
24/// ```
25pub fn getzoneid() -> io::Result<i32> {
26    let zoneid = unsafe { ffi::getzoneid() };
27
28    match zoneid {
29        -1 => Err(io::Error::last_os_error()),
30        _ => Ok(zoneid),
31    }
32}
33
34/// Returns the zone ID corresponding to the named zone.
35///
36/// # Example
37/// ```
38/// # let zid = zonename::getzoneid().expect("failed to get zoneid");
39/// # let zonename = zonename::getzonenamebyid(zid).expect("failed to get zonename");
40/// let zoneid = zonename::getzoneidbyname(&zonename).expect("failed to get zoneid");
41/// ```
42pub fn getzoneidbyname(zonename: &str) -> io::Result<i32> {
43    let c_zonename = CString::new(zonename)?;
44    let zoneid = unsafe { ffi::getzoneidbyname(c_zonename.as_ptr()) };
45
46    match zoneid {
47        -1 => Err(io::Error::last_os_error()),
48        _ => Ok(zoneid),
49    }
50}
51
52/// Returns the zone name for the corresponding zone ID.
53///
54/// # Example
55/// ```
56/// # let zoneid = zonename::getzoneid().expect("failed to get zoneid");
57/// let zonename = zonename::getzonenamebyid(zoneid).expect("failed to get zonename");
58/// ```
59pub fn getzonenamebyid(id: i32) -> io::Result<String> {
60    // since `CString::from_raw` is only supposed to be called after calling `into_raw` on a
61    // CString, we make a bogus buffer here that the ffi function will fill in for us
62    let c_string = CString::new(" ".repeat(ZONENAME_MAX)).unwrap();
63    let ptr = c_string.into_raw();
64
65    let len = unsafe { ffi::getzonenamebyid(id, ptr, ZONENAME_MAX) };
66    if len < 0 {
67        return Err(io::Error::last_os_error());
68    }
69
70    assert!(len >= 0);
71
72    // Attempt to force unwrap cstring because the kernel really shouldn't be giving us back
73    // invalid utf8 characters
74    let cstring = unsafe {
75        CString::from_raw(ptr)
76            .into_string()
77            .expect("found invalid UTF-8 converting from CString to String")
78    };
79
80    Ok(cstring)
81}
82
83/// Returns the current zones name for the calling process.
84///
85/// # Example
86/// ```
87/// let zid = zonename::getzoneid().expect("failed to get zoneid");
88/// let zname = zonename::getzonenamebyid(zid).expect("failed to get zonename");
89/// let zonename = zonename::getzonename().expect("failed to get zonename");
90/// assert_eq!(zname, zonename);
91/// ```
92pub fn getzonename() -> io::Result<String> {
93    let id = getzoneid()?;
94    getzonenamebyid(id)
95}