@@ -73,12 +73,26 @@ pub struct SizeConflictError<Size> {
7373 pub detected : Size ,
7474}
7575
76+ /// Error that occurs when a different [`nlink`][nlink] was detected for the same [`ino`][ino].
77+ ///
78+ /// <!-- Should have been `std::os::unix::fs::MetadataExt::ino` but it would error on Windows -->
79+ /// [nlink]: https://doc.rust-lang.org/std/os/unix/fs/trait.MetadataExt.html#tymethod.nlink
80+ /// [ino]: https://doc.rust-lang.org/std/os/unix/fs/trait.MetadataExt.html#tymethod.ino
81+ #[ derive( Debug , Display , Error ) ]
82+ #[ display( "Number of links of inode {ino} changed from {recorded:?} to {detected:?}" ) ]
83+ pub struct NumberOfLinksConflictError {
84+ pub ino : InodeNumber ,
85+ pub recorded : u64 ,
86+ pub detected : u64 ,
87+ }
88+
7689/// Error that occurs when it fails to add an item to [`HardlinkList`].
7790#[ derive( Debug , Display , Error ) ]
7891#[ display( bound( Size : Debug ) ) ]
7992#[ non_exhaustive]
8093pub enum AddError < Size > {
8194 SizeConflict ( SizeConflictError < Size > ) ,
95+ NumberOfLinksConflict ( NumberOfLinksConflictError ) ,
8296}
8397
8498impl < Size > HardlinkList < Size >
@@ -94,25 +108,37 @@ where
94108 links : u64 ,
95109 path : & Path ,
96110 ) -> Result < ( ) , AddError < Size > > {
97- let mut size_assertion = Ok ( ( ) ) ;
111+ let mut assertions = Ok ( ( ) ) ;
98112 self . 0
99113 . entry ( ino)
100114 . and_modify ( |recorded| {
101- if size == recorded. size {
102- recorded. paths . add ( path. to_path_buf ( ) ) ;
103- } else {
104- size_assertion = Err ( SizeConflictError {
115+ if size != recorded. size {
116+ assertions = Err ( AddError :: SizeConflict ( SizeConflictError {
105117 ino,
106118 recorded : recorded. size ,
107119 detected : size,
108- } ) ;
120+ } ) ) ;
121+ return ;
109122 }
123+
124+ if links != recorded. links {
125+ assertions = Err ( AddError :: NumberOfLinksConflict (
126+ NumberOfLinksConflictError {
127+ ino,
128+ recorded : recorded. links ,
129+ detected : links,
130+ } ,
131+ ) ) ;
132+ return ;
133+ }
134+
135+ recorded. paths . add ( path. to_path_buf ( ) ) ;
110136 } )
111137 . or_insert_with ( || {
112138 let paths = path. to_path_buf ( ) . pipe ( LinkPathList :: single) ;
113139 Value { size, links, paths }
114140 } ) ;
115- size_assertion . map_err ( AddError :: SizeConflict )
141+ assertions
116142 }
117143}
118144
0 commit comments