crypt4ghfs/
regular_file.rs1use std::collections::HashMap;
2use std::fs::File;
3use std::io::{Read, Seek, SeekFrom, Write};
4use std::os::unix::io::AsRawFd;
5use std::path::Path;
6
7use crate::egafile::EgaFile;
8use crate::error::{Crypt4GHFSError, Result};
9use crate::utils;
10
11pub struct RegularFile {
12 pub opened_files: HashMap<u64, Box<File>>,
13 pub path: Box<Path>,
14 pub only_read: bool,
15}
16
17impl EgaFile for RegularFile {
18 fn fh(&self) -> Vec<u64> {
19 self.opened_files.iter().map(|(&fh, _)| fh).collect()
20 }
21
22 fn path(&self) -> Box<Path> {
23 self.path.clone()
24 }
25
26 fn open(&mut self, flags: i32) -> Result<i32> {
27 let path = self.path();
28 let file = utils::open(&path, flags)?;
29 let fh = file.as_raw_fd();
30 self.opened_files.insert(fh as u64, Box::new(file));
31 Ok(fh)
32 }
33
34 fn read(&mut self, fh: u64, offset: i64, size: u32) -> Result<Vec<u8>> {
35 let f = self.opened_files.get_mut(&fh).ok_or(Crypt4GHFSError::FileNotOpened)?;
36 let mut data = Vec::new();
37 f.seek(SeekFrom::Start(offset as u64))?;
38 f.as_ref().take(u64::from(size)).read_to_end(&mut data)?;
39 Ok(data)
40 }
41
42 fn flush(&mut self, fh: u64) -> Result<()> {
43 let f = self.opened_files.get_mut(&fh).ok_or(Crypt4GHFSError::FileNotOpened)?;
44 f.flush()?;
45 Ok(())
46 }
47
48 fn write(&mut self, fh: u64, data: &[u8]) -> Result<usize> {
49 self.only_read = false;
50 let f = self.opened_files.get_mut(&fh).ok_or(Crypt4GHFSError::FileNotOpened)?;
51
52 f.write_all(data)?;
54 Ok(data.len())
55 }
56
57 fn truncate(&mut self, fh: Option<u64>, size: u64) -> Result<()> {
58 log::debug!("Truncate: size = {}", size);
59 self.opened_files
60 .iter_mut()
61 .filter(|(&ffh, _)| fh.is_none() || fh == Some(ffh))
62 .try_for_each(|(_, f)| f.set_len(size))?;
63 Ok(())
64 }
65
66 fn close(&mut self, fh: u64) -> Result<()> {
67 let f = self.opened_files.get(&fh).ok_or(Crypt4GHFSError::FileNotOpened)?;
68 assert_eq!(f.as_raw_fd(), fh as i32);
69 self.opened_files.remove(&fh);
70 self.only_read = true;
71 Ok(())
72 }
73
74 fn rename(&mut self, new_path: &Path) {
75 self.path = new_path.into();
76 }
77
78 fn attrs(&self, uid: u32, gid: u32) -> Result<fuser::FileAttr> {
79 let stat = utils::lstat(&self.path)?;
80 Ok(utils::stat_to_fileatr(stat, uid, gid))
81 }
82}
83
84impl RegularFile {
85 pub fn new(file: Option<Box<File>>, path: Box<Path>) -> Self {
86 let mut opened_files = HashMap::new();
88 if let Some(f) = file {
89 opened_files.insert(f.as_raw_fd() as u64, f);
90 }
91
92 Self {
94 opened_files,
95 path,
96 only_read: true,
97 }
98 }
99}