From cf0bf159abbf8505fab84327c29fe2a24e361ae2 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 8 Oct 2022 11:27:17 +0100 Subject: [PATCH] s3: try to keep the maximum precision in ModTime with --user-server-modtime Before this change if --user-server-modtime was in use the ModTime could change for an object as we receive it accurate to the nearest ms in listings, but only accurate to the nearest second in HEAD and GET requests. Normally AWS returns the milliseconds as .000 in listings, but if versions are in use it may not. Storj S3 also seems to return milliseconds. This patch tries to keep the maximum precision in the last modified time, so it doesn't update a last modified time with a truncated version if the times were the same to the nearest second. See: https://forum.rclone.org/t/cache-fingerprint-miss-behavior-leading-to-false-positive-stalen-cache/33404/ --- backend/s3/s3.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/s3/s3.go b/backend/s3/s3.go index 6abfd541c..9aba03a3f 100644 --- a/backend/s3/s3.go +++ b/backend/s3/s3.go @@ -4507,7 +4507,15 @@ func (o *Object) setMetaData(resp *s3.HeadObjectOutput) { o.lastModified = time.Now() fs.Logf(o, "Failed to read last modified") } else { - o.lastModified = *resp.LastModified + // Try to keep the maximum precision in lastModified. If we read + // it from listings then it may have millisecond precision, but + // if we read it from a HEAD/GET request then it will have + // second precision. + equalToWithinOneSecond := o.lastModified.Truncate(time.Second).Equal((*resp.LastModified).Truncate(time.Second)) + newHasNs := (*resp.LastModified).Nanosecond() != 0 + if !equalToWithinOneSecond || newHasNs { + o.lastModified = *resp.LastModified + } } o.mimeType = aws.StringValue(resp.ContentType)