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}