summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hurst <tom@hur.st>2020-06-30 15:16:31 +0000
committerSebastian Thiel <sebastian.thiel@icloud.com>2020-07-01 14:21:07 +0800
commitc37ee449f32ed3af0fc222f669ae3f40859d8a39 (patch)
tree179d59f8c662a564e6af1d1a3a574ffded1ca259
parent0ee7e06589baace8fd453e67ac78db5ca3e1553d (diff)
Fix inode filtering with multiple devices
Inodes are only unique per device, so include device in the lookup. Also replace a conditional with an additional pattern match, makes it a bit tidier I think.
-rw-r--r--src/inodefilter.rs43
1 files changed, 24 insertions, 19 deletions
diff --git a/src/inodefilter.rs b/src/inodefilter.rs
index 7182044..ec72d4a 100644
--- a/src/inodefilter.rs
+++ b/src/inodefilter.rs
@@ -2,7 +2,7 @@ use std::collections::HashMap;
#[derive(Debug, Default, Clone)]
pub struct InodeFilter {
- inner: HashMap<u64, u64>,
+ inner: HashMap<(u64, u64), u64>,
}
impl InodeFilter {
@@ -10,15 +10,19 @@ impl InodeFilter {
pub fn add(&mut self, metadata: &std::fs::Metadata) -> bool {
use std::os::unix::fs::MetadataExt;
- self.add_inode(metadata.ino(), metadata.nlink())
+ self.add_dev_inode((metadata.dev(), metadata.ino()), metadata.nlink())
}
#[cfg(windows)]
pub fn add(&mut self, metadata: &std::fs::Metadata) -> bool {
use std::os::windows::fs::MetadataExt;
- if let (Some(inode), Some(nlinks)) = (metadata.file_index(), metadata.number_of_links()) {
- self.add_inode(inode, nlinks as u64)
+ if let (Some(dev), Some(inode), Some(nlinks)) = (
+ metadata.volume_serial_number(),
+ metadata.file_index(),
+ metadata.number_of_links(),
+ ) {
+ self.add_dev_inode((dev as u64, inode), nlinks as u64)
} else {
true
}
@@ -29,23 +33,22 @@ impl InodeFilter {
true
}
- pub fn add_inode(&mut self, inode: u64, nlinks: u64) -> bool {
+ pub fn add_dev_inode(&mut self, dev_inode: (u64, u64), nlinks: u64) -> bool {
if nlinks <= 1 {
return true;
}
- match self.inner.get_mut(&inode) {
+ match self.inner.get_mut(&dev_inode) {
+ Some(1) => {
+ self.inner.remove(&dev_inode);
+ false
+ }
Some(count) => {
*count -= 1;
-
- if *count == 0 {
- self.inner.remove(&inode);
- }
-
false
}
None => {
- self.inner.insert(inode, nlinks - 1);
+ self.inner.insert(dev_inode, nlinks - 1);
true
}
}
@@ -60,14 +63,16 @@ mod tests {
fn it_filters_inodes() {
let mut inodes = InodeFilter::default();
- assert!(inodes.add_inode(1, 2));
- assert!(!inodes.add_inode(1, 2));
+ assert!(inodes.add_dev_inode((1, 1), 2));
+ assert!(inodes.add_dev_inode((2, 1), 2));
+ assert!(!inodes.add_dev_inode((1, 1), 2));
+ assert!(!inodes.add_dev_inode((2, 1), 2));
- assert!(inodes.add_inode(1, 3));
- assert!(!inodes.add_inode(1, 3));
- assert!(!inodes.add_inode(1, 3));
+ assert!(inodes.add_dev_inode((1, 1), 3));
+ assert!(!inodes.add_dev_inode((1, 1), 3));
+ assert!(!inodes.add_dev_inode((1, 1), 3));
- assert!(inodes.add_inode(1, 1));
- assert!(inodes.add_inode(1, 1));
+ assert!(inodes.add_dev_inode((1, 1), 1));
+ assert!(inodes.add_dev_inode((1, 1), 1));
}
}