forked from M-Labs/rust-fatfs
Fix detection of short name collisions for very short names
This commit is contained in:
parent
0b22cfa0b3
commit
b53882a2ad
67
src/dir.rs
67
src/dir.rs
@ -657,19 +657,24 @@ impl ShortNameGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn add_existing(&mut self, short_name: &[u8; 11]) {
|
fn add_existing(&mut self, short_name: &[u8; 11]) {
|
||||||
|
// check for exact match collision
|
||||||
if short_name == &self.short_name {
|
if short_name == &self.short_name {
|
||||||
self.exact_match = true;
|
self.exact_match = true;
|
||||||
}
|
}
|
||||||
let num_suffix = if short_name[6] as char == '~' { (short_name[7] as char).to_digit(10) } else { None };
|
// check for long prefix form collision (TEXTFI~1.TXT)
|
||||||
|
let prefix_len = cmp::min(self.basename_len, 6) as usize;
|
||||||
|
let num_suffix = if short_name[prefix_len] as char == '~' { (short_name[prefix_len+1] as char).to_digit(10) } else { None };
|
||||||
let ext_matches = short_name[8..] == self.short_name[8..];
|
let ext_matches = short_name[8..] == self.short_name[8..];
|
||||||
if short_name[..6] == self.short_name[..6] && num_suffix.is_some() && ext_matches {
|
if short_name[..prefix_len] == self.short_name[..prefix_len] && num_suffix.is_some() && ext_matches {
|
||||||
// prefix6-number form (TEXTFI~1.TXT)
|
|
||||||
let num = num_suffix.unwrap(); // SAFE
|
let num = num_suffix.unwrap(); // SAFE
|
||||||
self.long_prefix_bitmap |= 1 << num;
|
self.long_prefix_bitmap |= 1 << num;
|
||||||
}
|
}
|
||||||
if short_name[..2] == self.short_name[..2] && num_suffix.is_some() && ext_matches {
|
|
||||||
// prefix2-chsum-number form (TE021F~1.TXT)
|
// check for short prefix + checksum form collision (TE021F~1.TXT)
|
||||||
let chksum_res = str::from_utf8(&short_name[2..6]).map(|s| u16::from_str_radix(s, 16));
|
let prefix_len = cmp::min(self.basename_len, 2) as usize;
|
||||||
|
let num_suffix = if short_name[prefix_len+4] as char == '~' { (short_name[prefix_len+4+1] as char).to_digit(10) } else { None };
|
||||||
|
if short_name[..prefix_len] == self.short_name[..prefix_len] && num_suffix.is_some() && ext_matches {
|
||||||
|
let chksum_res = str::from_utf8(&short_name[prefix_len..prefix_len+4]).map(|s| u16::from_str_radix(s, 16));
|
||||||
if chksum_res == Ok(Ok(self.chksum)) {
|
if chksum_res == Ok(Ok(self.chksum)) {
|
||||||
let num = num_suffix.unwrap(); // SAFE
|
let num = num_suffix.unwrap(); // SAFE
|
||||||
self.prefix_chksum_bitmap |= 1 << num;
|
self.prefix_chksum_bitmap |= 1 << num;
|
||||||
@ -759,19 +764,51 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_generate_short_name_collisions() {
|
fn test_generate_short_name_collisions_long() {
|
||||||
let mut buf = [0u8; 11];
|
let mut buf: [u8; 11];
|
||||||
let mut gen = ShortNameGenerator::new("TextFile.Mine.txt");
|
let mut gen = ShortNameGenerator::new("TextFile.Mine.txt");
|
||||||
assert_eq!(&gen.generate().unwrap(), "TEXTFI~1TXT".as_bytes());
|
buf = gen.generate().unwrap();
|
||||||
buf.copy_from_slice("TEXTFI~1TXT".as_bytes());
|
assert_eq!(&buf, "TEXTFI~1TXT".as_bytes());
|
||||||
gen.add_existing(&buf);
|
gen.add_existing(&buf);
|
||||||
assert_eq!(&gen.generate().unwrap(), "TEXTFI~2TXT".as_bytes());
|
buf = gen.generate().unwrap();
|
||||||
buf.copy_from_slice("TEXTFI~2TXT".as_bytes());
|
assert_eq!(&buf, "TEXTFI~2TXT".as_bytes());
|
||||||
gen.add_existing(&buf);
|
gen.add_existing(&buf);
|
||||||
buf.copy_from_slice("TEXTFI~3TXT".as_bytes());
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "TEXTFI~3TXT".as_bytes());
|
||||||
gen.add_existing(&buf);
|
gen.add_existing(&buf);
|
||||||
buf.copy_from_slice("TEXTFI~4TXT".as_bytes());
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "TEXTFI~4TXT".as_bytes());
|
||||||
gen.add_existing(&buf);
|
gen.add_existing(&buf);
|
||||||
assert_eq!(&gen.generate().unwrap(), "TE527D~1TXT".as_bytes());
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "TE527D~1TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "TE527D~2TXT".as_bytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_generate_short_name_collisions_short() {
|
||||||
|
let mut buf: [u8; 11];
|
||||||
|
let mut gen = ShortNameGenerator::new("x.txt");
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X~1 TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X~2 TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X~3 TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X~4 TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X40DA~1 TXT".as_bytes());
|
||||||
|
gen.add_existing(&buf);
|
||||||
|
buf = gen.generate().unwrap();
|
||||||
|
assert_eq!(&buf, "X40DA~2 TXT".as_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user