optimizePath(): Detect some .links corruption
If automatic store optimisation is enabled, and a hard-linked file in the store gets corrupted, then the corresponding .links entry will also be corrupted. In that case, trying to repair with --repair or --repair-path won't work, because the new "good" file will be replaced by a hard link to the corrupted file. We can catch most of these cases by doing a sanity-check on the file sizes.
This commit is contained in:
		
							parent
							
								
									7759a56bed
								
							
						
					
					
						commit
						4384bbd2e1
					
				
					 1 changed files with 9 additions and 2 deletions
				
			
		|  | @ -120,9 +120,9 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     /* This can still happen on top-level files */ | ||||
|     /* This can still happen on top-level files. */ | ||||
|     if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) { | ||||
|         printMsg(lvlDebug, format("‘%1%’ is already linked, with %2% other file(s).") % path % (st.st_nlink - 2)); | ||||
|         printMsg(lvlDebug, format("‘%1%’ is already linked, with %2% other file(s)") % path % (st.st_nlink - 2)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|  | @ -141,6 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa | |||
|     /* Check if this is a known hash. */ | ||||
|     Path linkPath = linksDir + "/" + printHash32(hash); | ||||
| 
 | ||||
|  retry: | ||||
|     if (!pathExists(linkPath)) { | ||||
|         /* Nope, create a hard link in the links directory. */ | ||||
|         if (link(path.c_str(), linkPath.c_str()) == 0) { | ||||
|  | @ -164,6 +165,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (st.st_size != stLink.st_size) { | ||||
|         printMsg(lvlError, format("removing corrupted link ‘%1%’") % linkPath); | ||||
|         unlink(linkPath.c_str()); | ||||
|         goto retry; | ||||
|     } | ||||
| 
 | ||||
|     printMsg(lvlTalkative, format("linking ‘%1%’ to ‘%2%’") % path % linkPath); | ||||
| 
 | ||||
|     /* Make the containing directory writable, but only if it's not
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue