chj_unix_util/
file_util.rs

1use std::{
2    fmt::Debug,
3    fs::{File, OpenOptions},
4    io::ErrorKind,
5    path::Path,
6    sync::Arc,
7};
8
9use anyhow::{anyhow, Context};
10
11use crate::daemon::InOutError;
12
13/// Open a file for reading and writing, without truncating it if it
14/// exists, but creating it if it doesn't exist. The filehandle is in
15/// append mode (XX is it?, only on Unix?). You can use this to open a
16/// file that you intend to mutate, but need to flock first
17/// (i.e. can't truncate before you've got the lock).
18pub fn open_rw<P: AsRef<Path> + Debug>(path: P) -> anyhow::Result<File> {
19    // Can`t use `File::create` since that
20    // truncates before we have the lock.
21    OpenOptions::new()
22        .read(true)
23        .create(true)
24        .append(true)
25        .open(path.as_ref())
26        .with_context(|| anyhow!("opening {path:?} for updating"))
27}
28
29/// Open a file for writing in append mode, without truncating it if it
30/// exists, but creating it if it doesn't exist. E.g. for writing logs.
31pub fn open_append<P: AsRef<Path> + Debug>(path: P) -> anyhow::Result<File> {
32    // Can`t use `File::create` since that
33    // truncates before we have the lock.
34    OpenOptions::new()
35        .create(true)
36        .append(true)
37        .open(path.as_ref())
38        .with_context(|| anyhow!("opening {path:?} for appending"))
39}
40
41#[derive(thiserror::Error, Debug)]
42#[error("could not {what} at {path:?}: {error}")]
43pub struct PathIOError {
44    what: &'static str,
45    path: Arc<Path>,
46    error: InOutError,
47}
48
49pub fn create_dir_if_not_exists(path: &Arc<Path>) -> Result<(), PathIOError> {
50    match std::fs::create_dir(path) {
51        Ok(()) => Ok(()),
52        Err(error) => match error.kind() {
53            ErrorKind::AlreadyExists => Ok(()),
54            _ => Err(PathIOError {
55                what: "create dir",
56                path: path.clone(),
57                error: error.into(),
58            }),
59        },
60    }
61}