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 .open(path)?;
17 Ok(Flock::lock(file, mode).map_err(|(_, errno)| Error::Lock(errno))?)
18}
19
20/// Recursively searches upwards for a directory
21pub fn find_parent_with_dir(
22 dir: PathBuf,
23 searching_for: impl AsRef<Path>,
24) -> Result<Option<PathBuf>> {
25 // Create a new pathbuf to modify, we slap a segment onto the end but then pop it off right
26 // away
27 let mut d = dir.join(&searching_for);
28 while d.pop() {
29 let check = d.join(&searching_for);
30 if check.exists() {
31 if fs::metadata(&check)?.dev() != fs::metadata(&dir)?.dev() {
32 // we hit a filesystem boundary
33 return Ok(None);
34 }
35 return Ok(Some(check));
36 }
37 }
38 Ok(None)
39}