summaryrefslogtreecommitdiff
path: root/init/src/host/set.rs
diff options
context:
space:
mode:
Diffstat (limited to 'init/src/host/set.rs')
-rw-r--r--init/src/host/set.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/init/src/host/set.rs b/init/src/host/set.rs
new file mode 100644
index 0000000..9550b29
--- /dev/null
+++ b/init/src/host/set.rs
@@ -0,0 +1,53 @@
+use crate::log::log_warning;
+use libc::{c_char, sethostname, size_t};
+use std::{ffi::CString, fs, io};
+
+pub fn set_hostname() -> Result<(), Box<dyn std::error::Error>> {
+ let content = fs::read_to_string("/etc/hostname")
+ .map(|s| s.trim().to_string())
+ .unwrap_or_else(|_| "localhost".to_string());
+
+ if let Err(e) = perform_set_hostname(&content) {
+ match perform_set_hostname("localhost") {
+ Ok(_) => Err(format!(
+ "Failed to set hostname: \"{}\": {}. Fell back to localhost successfully.",
+ content, e
+ )
+ .into()),
+
+ Err(fallback_error) => {
+ log_warning(&format!(
+ "Failed to set hostname to '{}': {}. Also failed to set localhost: {}.",
+ content, e, fallback_error
+ ));
+ Err(format!(
+ "Failed to set hostname '{}' and failed to fall back to localhost: {}.",
+ content, e
+ )
+ .into())
+ }
+ }
+ } else {
+ Ok(())
+ }
+}
+
+fn perform_set_hostname(name: &str) -> io::Result<()> {
+ if name.len() > 64 {
+ return Err(io::Error::new(
+ io::ErrorKind::InvalidInput,
+ "Hostname too long",
+ ));
+ }
+
+ let c_str = CString::new(name)
+ .map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "Hostname contains null byte"))?;
+
+ let res = unsafe { sethostname(c_str.as_ptr() as *const c_char, name.len() as size_t) };
+
+ if res != 0 {
+ return Err(io::Error::last_os_error());
+ }
+
+ Ok(())
+}