use crate::process::PidError;
use libc::pid_t;
use log::{debug, info};
use std::fs::File;
use std::io::{BufRead, BufReader, BufWriter, Write};
use std::path::PathBuf;
use std::process;
pub fn get_pid_file_path(app_file_path: &PathBuf) -> PathBuf {
let mut pid_file_path = app_file_path.clone();
pid_file_path.set_extension("pid");
pid_file_path
}
pub fn read_pid(pid_file_path: &PathBuf) -> Result<Option<pid_t>, PidError> {
debug!("Reading PID from {pid_file_path:?}...");
let path = pid_file_path
.to_str()
.ok_or(PidError::InvalidPidFilePath(pid_file_path.clone()))?;
if !pid_file_path.exists() {
return Ok(None);
}
let pid_file = File::open(path).map_err(|_| PidError::OpenPidFile(path.to_string()))?;
let reader = BufReader::new(pid_file);
let pid = reader
.lines()
.next()
.ok_or(PidError::ReadPidFile(path.to_string()))?
.map_err(|_| PidError::ReadPidFile(path.to_string()))?
.trim()
.parse::<pid_t>()
.map_err(|_| PidError::ParsePidFileContent(path.to_string()))?;
Ok(Some(pid))
}
pub fn write_pid(pid_file_path: &PathBuf) -> Result<(), PidError> {
let pid = process::id();
debug!("Writing PID {pid} to {pid_file_path:?}...");
let path = pid_file_path
.to_str()
.ok_or(PidError::InvalidPidFilePath(pid_file_path.clone()))?;
let pid_file = File::create(path).map_err(|_| PidError::CreatePidFile(path.to_string()))?;
let mut writer = BufWriter::new(pid_file);
writer
.write_all(pid.to_string().as_bytes())
.map_err(|_| PidError::WritePidFile(path.to_string()))?;
Ok(())
}
pub fn delete_pid_file(pid_file_path: &PathBuf) -> Result<(), PidError> {
info!("Deleting PID file: {pid_file_path:?} ...");
let path = pid_file_path
.to_str()
.ok_or(PidError::InvalidPidFilePath(pid_file_path.clone()))?;
std::fs::remove_file(pid_file_path).map_err(|_| PidError::DeletePidFile(path.to_string()))?;
Ok(())
}
pub fn delete_pid_file_if_my_process(pid_file_path: &PathBuf) -> Result<(), PidError> {
if let Ok(Some(pid)) = read_pid(pid_file_path)
&& pid == process::id() as pid_t
{
delete_pid_file(pid_file_path)?;
}
Ok(())
}