| 2107 | } |
| 2108 | |
| 2109 | func (m *model) recheckFile(deviceID protocol.DeviceID, folder, name string, offset int64, hash []byte) { |
| 2110 | cf, ok, err := m.CurrentFolderFile(folder, name) |
| 2111 | if err != nil { |
| 2112 | l.Debugf("%v recheckFile: %s: %q / %q: current file error: %v", m, deviceID, folder, name, err) |
| 2113 | return |
| 2114 | } |
| 2115 | if !ok { |
| 2116 | l.Debugf("%v recheckFile: %s: %q / %q: no current file", m, deviceID, folder, name) |
| 2117 | return |
| 2118 | } |
| 2119 | |
| 2120 | if cf.IsDeleted() || cf.IsInvalid() || cf.IsSymlink() || cf.IsDirectory() { |
| 2121 | l.Debugf("%v recheckFile: %s: %q / %q: not a regular file", m, deviceID, folder, name) |
| 2122 | return |
| 2123 | } |
| 2124 | |
| 2125 | blockIndex := int(offset / int64(cf.BlockSize())) |
| 2126 | if blockIndex >= len(cf.Blocks) { |
| 2127 | l.Debugf("%v recheckFile: %s: %q / %q i=%d: block index too far", m, deviceID, folder, name, blockIndex) |
| 2128 | return |
| 2129 | } |
| 2130 | |
| 2131 | block := cf.Blocks[blockIndex] |
| 2132 | |
| 2133 | // Seems to want a different version of the file, whatever. |
| 2134 | if !bytes.Equal(block.Hash, hash) { |
| 2135 | l.Debugf("%v recheckFile: %s: %q / %q i=%d: hash mismatch %x != %x", m, deviceID, folder, name, blockIndex, block.Hash, hash) |
| 2136 | return |
| 2137 | } |
| 2138 | |
| 2139 | // The hashes provided part of the request match what we expect to find according |
| 2140 | // to what we have in the database, yet the content we've read off the filesystem doesn't |
| 2141 | // Something is fishy, invalidate the file and rescan it. |
| 2142 | // The file will temporarily become invalid, which is ok as the content is messed up. |
| 2143 | m.mut.RLock() |
| 2144 | runner, ok := m.folderRunners.Get(folder) |
| 2145 | m.mut.RUnlock() |
| 2146 | if !ok { |
| 2147 | l.Debugf("%v recheckFile: %s: %q / %q: Folder stopped before rescan could be scheduled", m, deviceID, folder, name) |
| 2148 | return |
| 2149 | } |
| 2150 | |
| 2151 | runner.ScheduleForceRescan(name) |
| 2152 | |
| 2153 | l.Debugf("%v recheckFile: %s: %q / %q", m, deviceID, folder, name) |
| 2154 | } |
| 2155 | |
| 2156 | func (m *model) CurrentFolderFile(folder string, file string) (protocol.FileInfo, bool, error) { |
| 2157 | return m.sdb.GetDeviceFile(folder, protocol.LocalDeviceID, file) |