tlc: tighten filepos privacy — 0600 permissions + reindent tests

Filepos DB reveals canonical paths of opened files. Use 0600 instead of default umask (0644) so other users cannot read it.

Reindent the HomeGuard struct / scoped_home function inside the #[cfg(test)] mod tests block (functionally correct, just hard to read before).
This commit is contained in:
2026-06-20 13:01:33 +03:00
parent 7d5b4088a6
commit 46c39c8aee
@@ -1,6 +1,8 @@
use std::env;
use std::fs;
use std::io::Write;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
/// Saved cursor line/column for a file.
@@ -75,9 +77,12 @@ pub fn save(path: &Path, pos: CursorPos) -> std::io::Result<()> {
out.push_str(&format!("{}\t{}\t{}\n", k, p.line, p.column));
}
let mut f = fs::File::create(&fp)?;
f.write_all(out.as_bytes())?;
Ok(())
}
let mut perms = f.metadata()?.permissions();
perms.set_mode(0o600);
f.set_permissions(perms)?;
f.write_all(out.as_bytes())?;
Ok(())
}
fn canonical_key(path: &Path) -> String {
std::fs::canonicalize(path)
@@ -93,41 +98,48 @@ mod tests {
static HOME_LOCK: Mutex<()> = Mutex::new(());
struct HomeGuard {
#[allow(dead_code)]
lock: std::sync::MutexGuard<'static, ()>,
prev_home: Option<std::ffi::OsString>,
prev_xdg: Option<std::ffi::OsString>,
}
struct HomeGuard {
#[allow(dead_code)]
lock: std::sync::MutexGuard<'static, ()>,
prev_home: Option<std::ffi::OsString>,
prev_xdg: Option<std::ffi::OsString>,
}
impl Drop for HomeGuard {
fn drop(&mut self) {
match &self.prev_home {
Some(v) => std::env::set_var("HOME", v),
None => std::env::remove_var("HOME"),
}
match &self.prev_xdg {
Some(v) => std::env::set_var("XDG_CONFIG_HOME", v),
None => std::env::remove_var("XDG_CONFIG_HOME"),
impl Drop for HomeGuard {
fn drop(&mut self) {
match &self.prev_home {
Some(v) => std::env::set_var("HOME", v),
None => std::env::remove_var("HOME"),
}
match &self.prev_xdg {
Some(v) => std::env::set_var("XDG_CONFIG_HOME", v),
None => std::env::remove_var("XDG_CONFIG_HOME"),
}
}
}
}
fn scoped_home(dir: &std::path::Path) -> HomeGuard {
let lock = HOME_LOCK.lock().unwrap_or_else(|e| e.into_inner());
let prev_home = std::env::var_os("HOME");
let prev_xdg = std::env::var_os("XDG_CONFIG_HOME");
std::env::set_var("HOME", dir);
std::env::remove_var("XDG_CONFIG_HOME");
HomeGuard { lock, prev_home, prev_xdg }
}
fn scoped_home(dir: &std::path::Path) -> HomeGuard {
let lock = HOME_LOCK.lock().unwrap_or_else(|e| e.into_inner());
let prev_home = std::env::var_os("HOME");
let prev_xdg = std::env::var_os("XDG_CONFIG_HOME");
std::env::set_var("HOME", dir);
std::env::remove_var("XDG_CONFIG_HOME");
HomeGuard {
lock,
prev_home,
prev_xdg,
}
}
#[test]
fn save_and_load_round_trip() {
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("hello.txt");
std::fs::write(&file, "hi\n").unwrap();
let pos = CursorPos { line: 7, column: 3 };
let pos = CursorPos {
line: 7,
column: 3,
};
let _g = scoped_home(dir.path());
save(&file, pos).unwrap();
assert_eq!(load(&file), Some(pos));
@@ -139,9 +151,29 @@ fn scoped_home(dir: &std::path::Path) -> HomeGuard {
let file = dir.path().join("hello.txt");
std::fs::write(&file, "hi\n").unwrap();
let _g = scoped_home(dir.path());
save(&file, CursorPos { line: 1, column: 0 }).unwrap();
save(&file, CursorPos { line: 9, column: 4 }).unwrap();
assert_eq!(load(&file), Some(CursorPos { line: 9, column: 4 }));
save(
&file,
CursorPos {
line: 1,
column: 0,
},
)
.unwrap();
save(
&file,
CursorPos {
line: 9,
column: 4,
},
)
.unwrap();
assert_eq!(
load(&file),
Some(CursorPos {
line: 9,
column: 4
})
);
}
#[test]