crypt4ghfs/
regular_file.rs

1use 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		// Write data
53		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		// Build open files
87		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		// Build RegularFile object
93		Self {
94			opened_files,
95			path,
96			only_read: true,
97		}
98	}
99}