diff options
author | Jakob Borg <jakob@kastelo.net> | 2022-10-16 17:04:28 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-16 17:04:28 +0200 |
commit | d3f50637d2e818c2b6ad516e4811fe2192b9b305 (patch) | |
tree | dbe0757e766d4ac234301c6bee91ecd2ae69775b | |
parent | ed588ce335877b31f864581bd130d9fa528fd36e (diff) |
lib/model, lib/protocol: Fix file comparisons (fixes #8594) (#8603)
-rw-r--r-- | lib/model/folder.go | 17 | ||||
-rw-r--r-- | lib/protocol/bep_extensions.go | 49 |
2 files changed, 41 insertions, 25 deletions
diff --git a/lib/model/folder.go b/lib/model/folder.go index 555de4ac69..52638a2dfb 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -601,14 +601,15 @@ func (b *scanBatch) Update(fi protocol.FileInfo, snap *db.Snapshot) bool { b.Remove(fi.Name) return true } - case gf.IsEquivalentOptional(fi, protocol.FileInfoComparison{ - ModTimeWindow: b.f.modTimeWindow, - IgnorePerms: b.f.IgnorePerms, - IgnoreBlocks: true, - IgnoreFlags: protocol.FlagLocalReceiveOnly, - IgnoreOwnership: !b.f.SyncOwnership, - IgnoreXattrs: !b.f.SyncXattrs, - }): + case (b.f.Type == config.FolderTypeReceiveOnly || b.f.Type == config.FolderTypeReceiveEncrypted) && + gf.IsEquivalentOptional(fi, protocol.FileInfoComparison{ + ModTimeWindow: b.f.modTimeWindow, + IgnorePerms: b.f.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: protocol.FlagLocalReceiveOnly, + IgnoreOwnership: !b.f.SyncOwnership && !b.f.SendOwnership, + IgnoreXattrs: !b.f.SyncXattrs && !b.f.SendXattrs, + }): // What we have locally is equivalent to the global file. l.Debugf("%v scanning: Merging identical locally changed item with global", b.f, fi) fi = gf diff --git a/lib/protocol/bep_extensions.go b/lib/protocol/bep_extensions.go index d2a0cad35c..3d3eb437c3 100644 --- a/lib/protocol/bep_extensions.go +++ b/lib/protocol/bep_extensions.go @@ -246,7 +246,7 @@ func (f FileInfo) isEquivalent(other FileInfo, comp FileInfoComparison) bool { // If we are recording inode change times and it changed, they are not // equal. - if f.InodeChangeNs != 0 && other.InodeChangeNs != 0 && f.InodeChangeNs != other.InodeChangeNs { + if (f.InodeChangeNs != 0 && other.InodeChangeNs != 0) && f.InodeChangeNs != other.InodeChangeNs { return false } @@ -258,21 +258,12 @@ func (f FileInfo) isEquivalent(other FileInfo, comp FileInfoComparison) bool { return false } - // OS data comparison is special: we consider a difference only if an - // entry for the same OS exists on both sides and they are different. - // Otherwise a file would become different as soon as it's synced from - // Windows to Linux, as Linux would add a new POSIX entry for the file. if !comp.IgnoreOwnership && f.Platform != other.Platform { - if f.Platform.Unix != nil && other.Platform.Unix != nil { - if *f.Platform.Unix != *other.Platform.Unix { - return false - } + if !unixOwnershipEqual(f.Platform.Unix, other.Platform.Unix) { + return false } - if f.Platform.Windows != nil && other.Platform.Windows != nil { - if f.Platform.Windows.OwnerName != other.Platform.Windows.OwnerName || - f.Platform.Windows.OwnerIsGroup != other.Platform.Windows.OwnerIsGroup { - return false - } + if !windowsOwnershipEqual(f.Platform.Windows, other.Platform.Windows) { + return false } } if !comp.IgnoreXattrs && f.Platform != other.Platform { @@ -542,11 +533,15 @@ func (x *FileInfoType) UnmarshalJSON(data []byte) error { } func xattrsEqual(a, b *XattrData) bool { - if a == nil || b == nil { - // Having no data on either side means we have nothing to compare - // to, and we consider that equal. + aEmpty := a == nil || len(a.Xattrs) == 0 + bEmpty := b == nil || len(b.Xattrs) == 0 + if aEmpty && bEmpty { return true } + if aEmpty || bEmpty { + // Only one side is empty, so they can't be equal. + return false + } if len(a.Xattrs) != len(b.Xattrs) { return false } @@ -560,3 +555,23 @@ func xattrsEqual(a, b *XattrData) bool { } return true } + +func unixOwnershipEqual(a, b *UnixData) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + return a.UID == b.UID && a.GID == b.GID && a.OwnerName == b.OwnerName && a.GroupName == b.GroupName +} + +func windowsOwnershipEqual(a, b *WindowsData) bool { + if a == nil && b == nil { + return true + } + if a == nil || b == nil { + return false + } + return a.OwnerName == b.OwnerName && a.OwnerIsGroup == b.OwnerIsGroup +} |