A file-based task manager
1use crate::errors::{Error, Result};
2use std::fs;
3use std::os::unix::fs::MetadataExt;
4use std::{
5 fs::{File, OpenOptions},
6 path::{Path, PathBuf},
7};
8
9use nix::fcntl::{Flock, FlockArg};
10
11pub fn flopen(path: PathBuf, mode: FlockArg) -> Result<Flock<File>> {
12 let file = OpenOptions::new()
13 .read(true)
14 .write(true)
15 .create(true)
16 .truncate(false)
17 .open(path)?;
18 Flock::lock(file, mode).map_err(|(_, errno)| Error::Lock(errno))
19}
20
21/// Recursively searches upwards for a directory
22pub fn find_parent_with_dir(
23 dir: PathBuf,
24 searching_for: impl AsRef<Path>,
25) -> Result<Option<PathBuf>> {
26 // Create a new pathbuf to modify, we slap a segment onto the end but then pop it off right
27 // away
28 let mut d = dir.join(&searching_for);
29 while d.pop() {
30 let check = d.join(&searching_for);
31 if check.exists() {
32 if fs::metadata(&check)?.dev() != fs::metadata(&dir)?.dev() {
33 // we hit a filesystem boundary
34 return Ok(None);
35 }
36 return Ok(Some(check));
37 }
38 }
39 Ok(None)
40}