forked from M-Labs/rust-fatfs
Do not remove source file in Dir::rename if destination already exists
Previous code removed source file before returning an error. It also caused a clusters leak. Now it returns error before doing any modifications on the partition.
This commit is contained in:
parent
4afd38a150
commit
8c1dae9f0c
12
src/dir.rs
12
src/dir.rs
@ -298,6 +298,12 @@ impl <'a, T: ReadWriteSeek + 'a> Dir<'a, T> {
|
||||
trace!("moving {} to {}", src_name, dst_name);
|
||||
// find existing file
|
||||
let e = self.find_entry(src_name, None, None)?;
|
||||
// check if destionation filename is unused
|
||||
let mut short_name_gen = ShortNameGenerator::new(dst_name);
|
||||
let r = dst_dir.find_entry(dst_name, None, Some(&mut short_name_gen));
|
||||
if r.is_ok() {
|
||||
return Err(io::Error::new(ErrorKind::AlreadyExists, "destination file already exists"))
|
||||
}
|
||||
// free long and short name entries
|
||||
let mut stream = self.stream.clone();
|
||||
stream.seek(SeekFrom::Start(e.offset_range.0 as u64))?;
|
||||
@ -309,12 +315,6 @@ impl <'a, T: ReadWriteSeek + 'a> Dir<'a, T> {
|
||||
stream.seek(SeekFrom::Current(-(DIR_ENTRY_SIZE as i64)))?;
|
||||
data.serialize(&mut stream)?;
|
||||
}
|
||||
// check if destionation filename is unused
|
||||
let mut short_name_gen = ShortNameGenerator::new(dst_name);
|
||||
let r = dst_dir.find_entry(dst_name, None, Some(&mut short_name_gen));
|
||||
if r.is_ok() {
|
||||
return Err(io::Error::new(ErrorKind::AlreadyExists, "destination file already exists"))
|
||||
}
|
||||
// save new directory entry
|
||||
let short_name = short_name_gen.generate()?;
|
||||
let sfn_entry = e.data.renamed(short_name);
|
||||
|
@ -271,6 +271,11 @@ fn test_rename_file(fs: FileSystem) {
|
||||
file.read_to_end(&mut buf).unwrap();
|
||||
assert_eq!(str::from_utf8(&buf).unwrap(), TEST_STR2);
|
||||
|
||||
assert!(root_dir.rename("moved-file.txt", &root_dir, "short.txt").is_err());
|
||||
let entries = root_dir.iter().map(|r| r.unwrap()).collect::<Vec<_>>();
|
||||
let names = entries.iter().map(|r| r.file_name()).collect::<Vec<_>>();
|
||||
assert_eq!(names, ["long.txt", "short.txt", "very", "very-long-dir-name", "moved-file.txt"]);
|
||||
|
||||
let new_stats = fs.stats().unwrap();
|
||||
assert_eq!(new_stats.free_clusters(), stats.free_clusters());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user