diff --git a/lib/protocol/protocol.go b/lib/protocol/protocol.go index 03ec3e138..9204ef35b 100644 --- a/lib/protocol/protocol.go +++ b/lib/protocol/protocol.go @@ -640,8 +640,12 @@ func checkFileInfoConsistency(f FileInfo) error { // Only files should have blocks return errNonFileHasBlocks - case f.Type != FileInfoTypeFile && f.Size != 0: - // Only files should have a size + case f.IsDirectory() && f.Size != 0 && f.Size != SyntheticDirectorySize: + // Directories should be size zero or the synthetic directory size + return errNonFileHasSize + + case f.IsSymlink() && f.Size != 0: + // Symlinks should be size zero return errNonFileHasSize case !f.Deleted && !f.IsInvalid() && f.Type == FileInfoTypeFile && len(f.Blocks) == 0: diff --git a/lib/protocol/protocol_test.go b/lib/protocol/protocol_test.go index dda4ba86a..1bba358b3 100644 --- a/lib/protocol/protocol_test.go +++ b/lib/protocol/protocol_test.go @@ -451,6 +451,61 @@ func TestCheckConsistency(t *testing.T) { }, ok: false, }, + { + // directory with zero size + fi: FileInfo{ + Name: "foo", + Type: FileInfoTypeDirectory, + }, + ok: true, + }, + { + // directory with synthetic size + fi: FileInfo{ + Name: "foo", + Type: FileInfoTypeDirectory, + Size: SyntheticDirectorySize, + }, + ok: true, + }, + { + // directory with arbitrary size + fi: FileInfo{ + Name: "foo", + Type: FileInfoTypeDirectory, + Size: 42, + }, + ok: false, + }, + { + // symlink with zero size + fi: FileInfo{ + Name: "foo", + Type: FileInfoTypeSymlink, + SymlinkTarget: []byte("bar"), + }, + ok: true, + }, + { + // symlink with synthetic directory size (not permitted) + fi: FileInfo{ + Name: "foo", + Type: FileInfoTypeSymlink, + SymlinkTarget: []byte("bar"), + Size: SyntheticDirectorySize, + }, + ok: false, + }, + { + // symlink with arbitrary size + fi: FileInfo{ + Name: "foo", + Type: FileInfoTypeSymlink, + SymlinkTarget: []byte("bar"), + Size: 42, + }, + ok: false, + }, } for _, tc := range cases {