Files
Ilya Zlobintsev e5a3eb1509 chore: update to rust 2024 edition (#889)
* chore: bump rust edition to 2024

* chore: another chunk of clippy fixes

* chore: fix warning in bindings

* chore: restructure awkward unsafe blocks

* chore: reformat

* chore: clippy fix

* chore: bump rust release in docker build
2026-01-31 23:43:43 +02:00

109 lines
2.9 KiB
Rust

use anyhow::{Context, anyhow};
use nix::{
sys::stat::{Mode, umask},
unistd::{Gid, Group, User, chown, getuid},
};
use std::{
env, fs,
path::{Path, PathBuf},
str::FromStr,
};
use tokio::net::UnixListener;
use tracing::{debug, info};
use crate::{
config,
system::{IS_FLATBOX, run_command},
};
pub fn get_socket_path() -> PathBuf {
let uid = getuid();
if let Ok(path) = env::var("LACT_DAEMON_SOCKET_PATH") {
PathBuf::from_str(&path).unwrap()
} else if uid.is_root() {
PathBuf::from_str("/run/lactd.sock").unwrap()
} else {
PathBuf::from_str(&format!("/run/user/{uid}/lactd.sock")).unwrap()
}
}
pub fn cleanup() {
let socket_path = get_socket_path();
if socket_path.exists() {
fs::remove_file(socket_path).expect("failed to remove socket");
}
debug!("removed socket");
}
pub fn listen() -> anyhow::Result<(UnixListener, PathBuf)> {
let socket_path = get_socket_path();
if socket_path.exists() {
return Err(anyhow!(
"Socket {} already exists. \
This probably means that another instance of lact-daemon is currently running. \
If you are sure that this is not the case, please remove the file",
socket_path.display()
));
}
let socket_mask = Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IRWXO;
umask(socket_mask);
let listener = UnixListener::bind(&socket_path)?;
info!("listening on {socket_path:?}");
Ok((listener, socket_path))
}
pub async fn set_permissions(
socket_path: &Path,
daemon_config: &config::Daemon,
) -> anyhow::Result<()> {
let group = daemon_config
.admin_group
.as_ref()
.map(|name| {
Group::from_name(name)
.context("Could not get group")?
.with_context(|| format!("Group {name} does not exist"))
})
.transpose()?
.map_or_else(Gid::current, |group| group.gid);
let user = daemon_config
.admin_user
.as_ref()
.map(|name| {
User::from_name(name)
.context("Could not get group")?
.with_context(|| format!("Group {name} does not exist"))
})
.transpose()?
.map(|user| user.uid);
debug!("using gid {group} uid {user:?} for socket");
if *IS_FLATBOX {
let owner_arg = match user {
Some(user) => format!("{}:{}", user.as_raw(), group.as_raw()),
None => format!(":{}", group.as_raw()),
};
let path = socket_path
.to_str()
.expect("Invalid socket path")
.trim_start_matches("/run/host/root");
run_command("chown", &[&owner_arg, path])
.await
.context("Could not set socket permissions")?;
} else {
chown(socket_path, user, Some(group)).context("Could not set socket permissions")?;
}
Ok(())
}