pub fn write_pid_file_raw(path: &std::ffi::CStr) -> Result<(), i32> {
unsafe {
let pid = libc::getpid();
let mut buf = [0u8; 16];
let len = format_pid_to_buffer(pid, &mut buf);
let fd = libc::open(
path.as_ptr(),
libc::O_WRONLY | libc::O_CREAT | libc::O_TRUNC,
0o644 as libc::c_uint,
);
if fd < 0 {
return Err(super::get_errno());
}
let written = libc::write(fd, buf.as_ptr() as *const libc::c_void, len);
let write_errno = if written < 0 {
Some(super::get_errno())
} else {
None
};
libc::close(fd);
if let Some(errno) = write_errno {
return Err(errno);
}
Ok(())
}
}
#[inline]
fn format_pid_to_buffer(mut pid: i32, buf: &mut [u8; 16]) -> usize {
if pid == 0 {
buf[0] = b'0';
buf[1] = b'\n';
return 2;
}
let negative = pid < 0;
if negative {
pid = -pid;
}
let mut len = 0;
let mut tmp = [0u8; 16];
while pid > 0 {
tmp[len] = b'0' + (pid % 10) as u8;
pid /= 10;
len += 1;
}
let mut pos = 0;
if negative {
buf[pos] = b'-';
pos += 1;
}
for i in 0..len {
buf[pos] = tmp[len - 1 - i];
pos += 1;
}
buf[pos] = b'\n';
pos += 1;
pos
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::CString;
#[test]
fn test_format_pid_to_buffer() {
let mut buf = [0u8; 16];
let len = format_pid_to_buffer(12345, &mut buf);
assert_eq!(&buf[..len], b"12345\n");
let len = format_pid_to_buffer(7, &mut buf);
assert_eq!(&buf[..len], b"7\n");
let len = format_pid_to_buffer(0, &mut buf);
assert_eq!(&buf[..len], b"0\n");
let len = format_pid_to_buffer(1234567890, &mut buf);
assert_eq!(&buf[..len], b"1234567890\n");
}
#[test]
fn test_write_pid_file_raw() {
use std::io::Read;
let temp_dir = std::env::temp_dir();
let pid_file = temp_dir.join("test_pid_file.pid");
let path = CString::new(pid_file.to_string_lossy().as_bytes()).unwrap();
write_pid_file_raw(&path).expect("Should write PID file");
let mut content = String::new();
std::fs::File::open(&pid_file)
.expect("Should open file")
.read_to_string(&mut content)
.expect("Should read file");
let expected_pid = std::process::id();
let file_pid: u32 = content.trim().parse().expect("Should parse PID");
assert_eq!(file_pid, expected_pid);
let _ = std::fs::remove_file(&pid_file);
}
}