fix inconsistent use of symlink mtimes in database;

on upload, dupes are by default handled by symlinking to the existing
copy on disk, writing the uploader's local mtime into the symlink mtime,
which is also what gets indexed in the db

this worked as intended, however during an -e2dsa rescan on startup the
symlink destination timestamps would be used instead, causing a reindex
and the resulting loss of uploader metadata (ip, timestamp)

will now always use the symlink's mtime;
worst-case 1% slower startup (no dhash)

this change will cause a reindex of incorrectly indexed files, however
as this has already happened at least once due to the bug being fixed,
there will be no additional loss of metadata
This commit is contained in:
ed 2023-09-01 20:29:55 +00:00
parent a50d0563c3
commit c1efd227b7

View file

@ -1050,7 +1050,7 @@ class Up2k(object):
if WINDOWS: if WINDOWS:
rd = rd.replace("\\", "/").strip("/") rd = rd.replace("\\", "/").strip("/")
g = statdir(self.log_func, not self.args.no_scandir, False, cdir) g = statdir(self.log_func, not self.args.no_scandir, True, cdir)
gl = sorted(g) gl = sorted(g)
partials = set([x[0] for x in gl if "PARTIAL" in x[0]]) partials = set([x[0] for x in gl if "PARTIAL" in x[0]])
for iname, inf in gl: for iname, inf in gl:
@ -1065,6 +1065,12 @@ class Up2k(object):
continue continue
lmod = int(inf.st_mtime) lmod = int(inf.st_mtime)
if stat.S_ISLNK(inf.st_mode):
try:
inf = bos.stat(abspath)
except:
continue
sz = inf.st_size sz = inf.st_size
if fat32 and not ffat and inf.st_mtime % 2: if fat32 and not ffat and inf.st_mtime % 2:
fat32 = False fat32 = False
@ -1445,9 +1451,11 @@ class Up2k(object):
pf = "v{}, {:.0f}+".format(n_left, b_left / 1024 / 1024) pf = "v{}, {:.0f}+".format(n_left, b_left / 1024 / 1024)
self.pp.msg = pf + abspath self.pp.msg = pf + abspath
st = bos.stat(abspath) # throws on broken symlinks (always did)
stl = bos.lstat(abspath)
st = bos.stat(abspath) if stat.S_ISLNK(stl.st_mode) else stl
mt2 = int(stl.st_mtime)
sz2 = st.st_size sz2 = st.st_size
mt2 = int(st.st_mtime)
if nohash or not sz2: if nohash or not sz2:
w2 = up2k_wark_from_metadata(self.salt, sz2, mt2, rd, fn) w2 = up2k_wark_from_metadata(self.salt, sz2, mt2, rd, fn)
@ -1469,6 +1477,13 @@ class Up2k(object):
if w == w2: if w == w2:
continue continue
# symlink mtime was inconsistent before v1.9.4; check if that's it
if st != stl and (nohash or not sz2):
mt2b = int(st.st_mtime)
w2b = up2k_wark_from_metadata(self.salt, sz2, mt2b, rd, fn)
if w == w2b:
continue
rewark.append((drd, dfn, w2, sz2, mt2)) rewark.append((drd, dfn, w2, sz2, mt2))
t = "hash mismatch: {}\n db: {} ({} byte, {})\n fs: {} ({} byte, {})" t = "hash mismatch: {}\n db: {} ({} byte, {})\n fs: {} ({} byte, {})"