Improve code structure

This commit is contained in:
Rafał Harabień 2018-06-07 23:07:52 +02:00
parent ccb205c906
commit 632a371b0d

View File

@ -120,7 +120,7 @@ impl <'a, 'b> Dir<'a, 'b> {
let e = self.find_entry(name, None)?; let e = self.find_entry(name, None)?;
match rest_opt { match rest_opt {
Some(rest) => e.to_dir().open_dir(rest), Some(rest) => e.to_dir().open_dir(rest),
None => Ok(e.to_dir()) None => Ok(e.to_dir()),
} }
} }
@ -130,65 +130,67 @@ impl <'a, 'b> Dir<'a, 'b> {
let e = self.find_entry(name, None)?; let e = self.find_entry(name, None)?;
match rest_opt { match rest_opt {
Some(rest) => e.to_dir().open_file(rest), Some(rest) => e.to_dir().open_file(rest),
None => Ok(e.to_file()) None => Ok(e.to_file()),
} }
} }
/// Creates new file or opens existing without truncating. /// Creates new file or opens existing without truncating.
pub fn create_file(&mut self, path: &str) -> io::Result<File<'a, 'b>> { pub fn create_file(&mut self, path: &str) -> io::Result<File<'a, 'b>> {
// traverse path
let (name, rest_opt) = split_path(path); let (name, rest_opt) = split_path(path);
match rest_opt { if let Some(rest) = rest_opt {
// path contains more than 1 component return self.find_entry(name, None)?.to_dir().create_file(rest);
Some(rest) => self.find_entry(name, None)?.to_dir().create_file(rest), }
None => { // this is final filename in the path
// this is final filename in the path let mut short_name_gen = ShortNameGenerator::new(name);
let mut short_name_gen = ShortNameGenerator::new(name); let r = self.find_entry(name, Some(&mut short_name_gen));
let r = self.find_entry(name, Some(&mut short_name_gen)); match r {
match r { // file does not exist - create it
Err(ref err) if err.kind() == ErrorKind::NotFound => { Err(ref err) if err.kind() == ErrorKind::NotFound => {
let short_name = short_name_gen.generate()?; let short_name = short_name_gen.generate()?;
let sfn_entry = self.create_sfn_entry(short_name, FileAttributes::from_bits_truncate(0), None); let sfn_entry = self.create_sfn_entry(short_name, FileAttributes::from_bits_truncate(0), None);
Ok(self.write_entry(name, sfn_entry)?.to_file()) Ok(self.write_entry(name, sfn_entry)?.to_file())
}, },
Err(err) => Err(err), // other error
Ok(e) => Ok(e.to_file()), Err(err) => Err(err),
} // file already exists - return it
} Ok(e) => Ok(e.to_file()),
} }
} }
/// Creates new directory or opens existing. /// Creates new directory or opens existing.
pub fn create_dir(&mut self, path: &str) -> io::Result<Self> { pub fn create_dir(&mut self, path: &str) -> io::Result<Self> {
// traverse path
let (name, rest_opt) = split_path(path); let (name, rest_opt) = split_path(path);
match rest_opt { if let Some(rest) = rest_opt {
// path contains more than 1 component return self.find_entry(name, None)?.to_dir().create_dir(rest);
Some(rest) => self.find_entry(name, None)?.to_dir().create_dir(rest), }
None => { // this is final filename in the path
// this is final filename in the path let mut short_name_gen = ShortNameGenerator::new(name);
let mut short_name_gen = ShortNameGenerator::new(name); let r = self.find_entry(name, Some(&mut short_name_gen));
let r = self.find_entry(name, Some(&mut short_name_gen)); match r {
match r { // directory does not exist - create it
Err(ref err) if err.kind() == ErrorKind::NotFound => { Err(ref err) if err.kind() == ErrorKind::NotFound => {
// alloc cluster for directory data // alloc cluster for directory data
let cluster = self.fs.alloc_cluster(None)?; let cluster = self.fs.alloc_cluster(None)?;
// create entry in parent directory // create entry in parent directory
let short_name = short_name_gen.generate()?; let short_name = short_name_gen.generate()?;
let sfn_entry = self.create_sfn_entry(short_name, FileAttributes::DIRECTORY, Some(cluster)); let sfn_entry = self.create_sfn_entry(short_name, FileAttributes::DIRECTORY, Some(cluster));
let entry = self.write_entry(name, sfn_entry)?; let entry = self.write_entry(name, sfn_entry)?;
let mut dir = entry.to_dir(); let mut dir = entry.to_dir();
// create special entries "." and ".." // create special entries "." and ".."
let dot_sfn = ShortNameGenerator::new(".").generate().unwrap(); let dot_sfn = ShortNameGenerator::new(".").generate().unwrap();
let sfn_entry = self.create_sfn_entry(dot_sfn, FileAttributes::DIRECTORY, entry.first_cluster()); let sfn_entry = self.create_sfn_entry(dot_sfn, FileAttributes::DIRECTORY, entry.first_cluster());
dir.write_entry(".", sfn_entry)?; dir.write_entry(".", sfn_entry)?;
let dotdot_sfn = ShortNameGenerator::new("..").generate().unwrap(); let dotdot_sfn = ShortNameGenerator::new("..").generate().unwrap();
let sfn_entry = self.create_sfn_entry(dotdot_sfn, FileAttributes::DIRECTORY, self.stream.first_cluster()); let sfn_entry = self.create_sfn_entry(dotdot_sfn, FileAttributes::DIRECTORY, self.stream.first_cluster());
dir.write_entry("..", sfn_entry)?; dir.write_entry("..", sfn_entry)?;
Ok(dir) Ok(dir)
}, },
Err(err) => Err(err), // other error
Ok(e) => Ok(e.to_dir()), Err(err) => Err(err),
} // directory already exists - return it
} Ok(e) => Ok(e.to_dir()),
} }
} }
@ -210,34 +212,33 @@ impl <'a, 'b> Dir<'a, 'b> {
/// Make sure there is no reference to this file (no File instance) or filesystem corruption /// Make sure there is no reference to this file (no File instance) or filesystem corruption
/// can happen. /// can happen.
pub fn remove(&mut self, path: &str) -> io::Result<()> { pub fn remove(&mut self, path: &str) -> io::Result<()> {
// traverse path
let (name, rest_opt) = split_path(path); let (name, rest_opt) = split_path(path);
let e = self.find_entry(name, None)?; let e = self.find_entry(name, None)?;
match rest_opt { if let Some(rest) = rest_opt {
Some(rest) => e.to_dir().remove(rest), return e.to_dir().remove(rest);
None => {
trace!("removing {}", path);
// in case of directory check if it is empty
if e.is_dir() && !e.to_dir().is_empty()? {
return Err(io::Error::new(ErrorKind::NotFound, "removing non-empty directory is denied"));
}
// free directory data
if let Some(n) = e.first_cluster() {
self.fs.free_cluster_chain(n)?;
}
// free long and short name entries
let mut stream = self.stream.clone();
stream.seek(SeekFrom::Start(e.offset_range.0 as u64))?;
let num = (e.offset_range.1 - e.offset_range.0) as usize / DIR_ENTRY_SIZE as usize;
for _ in 0..num {
let mut data = DirEntryData::deserialize(&mut stream)?;
trace!("removing dir entry {:?}", data);
data.set_free();
stream.seek(SeekFrom::Current(-(DIR_ENTRY_SIZE as i64)))?;
data.serialize(&mut stream)?;
}
Ok(())
}
} }
trace!("removing {}", path);
// in case of directory check if it is empty
if e.is_dir() && !e.to_dir().is_empty()? {
return Err(io::Error::new(ErrorKind::NotFound, "removing non-empty directory is denied"));
}
// free data
if let Some(n) = e.first_cluster() {
self.fs.free_cluster_chain(n)?;
}
// free long and short name entries
let mut stream = self.stream.clone();
stream.seek(SeekFrom::Start(e.offset_range.0 as u64))?;
let num = (e.offset_range.1 - e.offset_range.0) as usize / DIR_ENTRY_SIZE as usize;
for _ in 0..num {
let mut data = DirEntryData::deserialize(&mut stream)?;
trace!("removing dir entry {:?}", data);
data.set_free();
stream.seek(SeekFrom::Current(-(DIR_ENTRY_SIZE as i64)))?;
data.serialize(&mut stream)?;
}
Ok(())
} }
/// Renames or moves existing file or directory. /// Renames or moves existing file or directory.
@ -464,12 +465,14 @@ impl <'a, 'b> Iterator for DirIter<'a, 'b> {
} }
fn validate_long_name(name: &str) -> io::Result<()> { fn validate_long_name(name: &str) -> io::Result<()> {
// check if length is valid
if name.len() == 0 { if name.len() == 0 {
return Err(io::Error::new(ErrorKind::InvalidInput, "filename cannot be empty")); return Err(io::Error::new(ErrorKind::InvalidInput, "filename cannot be empty"));
} }
if name.len() > 255 { if name.len() > 255 {
return Err(io::Error::new(ErrorKind::InvalidInput, "filename is too long")); return Err(io::Error::new(ErrorKind::InvalidInput, "filename is too long"));
} }
// check if there are only valid characters
for c in name.chars() { for c in name.chars() {
match c { match c {
'a'...'z' | 'A'...'Z' | '0'...'9' | '\u{80}'...'\u{FFFF}' | 'a'...'z' | 'A'...'Z' | '0'...'9' | '\u{80}'...'\u{FFFF}' |