1use std::io;
7use std::path::PathBuf;
8
9const SOCKET_NAME: &str = "debugger-cli";
11
12#[cfg(unix)]
18pub fn socket_path() -> PathBuf {
19 if let Ok(runtime_dir) = std::env::var("XDG_RUNTIME_DIR") {
21 return PathBuf::from(runtime_dir)
22 .join(SOCKET_NAME)
23 .join("daemon.sock");
24 }
25
26 let uid = unsafe { libc::getuid() };
28 PathBuf::from(format!("/tmp/{}-{}", SOCKET_NAME, uid)).join("daemon.sock")
29}
30
31#[cfg(windows)]
32pub fn socket_path() -> PathBuf {
33 let username = std::env::var("USERNAME").unwrap_or_else(|_| "default".to_string());
36 PathBuf::from(format!("{}-{}", SOCKET_NAME, username))
37}
38
39#[cfg(unix)]
43pub fn socket_name() -> String {
44 socket_path().to_string_lossy().into_owned()
45}
46
47#[cfg(windows)]
48pub fn socket_name() -> String {
49 let username = std::env::var("USERNAME").unwrap_or_else(|_| "default".to_string());
50 format!("{}-{}", SOCKET_NAME, username)
51}
52
53#[cfg(unix)]
57pub fn ensure_socket_dir() -> io::Result<PathBuf> {
58 let socket = socket_path();
59 let dir = socket.parent().ok_or_else(|| {
60 io::Error::new(io::ErrorKind::InvalidInput, "Invalid socket path")
61 })?;
62
63 if !dir.exists() {
64 std::fs::create_dir_all(dir)?;
65 use std::os::unix::fs::PermissionsExt;
67 std::fs::set_permissions(dir, std::fs::Permissions::from_mode(0o700))?;
68 }
69
70 Ok(dir.to_path_buf())
71}
72
73#[cfg(windows)]
74pub fn ensure_socket_dir() -> io::Result<PathBuf> {
75 Ok(PathBuf::new())
77}
78
79#[cfg(unix)]
81pub fn remove_socket() -> io::Result<()> {
82 let path = socket_path();
83 if path.exists() {
84 std::fs::remove_file(&path)?;
85 }
86 Ok(())
87}
88
89#[cfg(windows)]
90pub fn remove_socket() -> io::Result<()> {
91 Ok(())
93}
94
95pub fn config_dir() -> Option<PathBuf> {
102 directories::ProjectDirs::from("", "", SOCKET_NAME)
103 .map(|dirs| dirs.config_dir().to_path_buf())
104}
105
106pub fn config_path() -> Option<PathBuf> {
108 config_dir().map(|dir| dir.join("config.toml"))
109}
110
111pub fn log_dir() -> Option<PathBuf> {
113 directories::ProjectDirs::from("", "", SOCKET_NAME)
114 .map(|dirs| dirs.data_dir().join("logs"))
115}
116
117pub fn ensure_config_dir() -> io::Result<Option<PathBuf>> {
119 if let Some(dir) = config_dir() {
120 if !dir.exists() {
121 std::fs::create_dir_all(&dir)?;
122 }
123 Ok(Some(dir))
124 } else {
125 Ok(None)
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_socket_path_is_valid() {
135 let path = socket_path();
136 assert!(!path.as_os_str().is_empty());
137 }
138
139 #[test]
140 fn test_config_dir_is_valid() {
141 let dir = config_dir();
142 assert!(dir.is_some());
143 }
144}