From adce6fa473557e921cb01d7c892181a8f9c11b0b Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Tue, 26 Jul 2022 08:24:58 +0200 Subject: [PATCH] all: Support syncing ownership (fixes #1329) (#8434) This adds support for syncing ownership on Unixes and on Windows. The scanner always picks up ownership information, but it is not applied unless the new folder option "Sync Ownership" is set. Ownership data is stored in a new FileInfo field called "platform data". This is intended to hold further platform-specific data in the future (specifically, extended attributes), which is why the whole design is a bit overkill for just ownership. --- go.mod | 2 +- go.sum | 3 +- lib/config/config.pb.go | 5 +- lib/config/folderconfiguration.pb.go | 296 +++--- lib/db/db_test.go | 4 +- lib/db/structs.pb.go | 256 +++-- lib/fs/basicfs.go | 8 - lib/fs/basicfs_platformdata_unix.go | 18 + lib/fs/basicfs_platformdata_windows.go | 69 ++ lib/fs/basicfs_test.go | 3 +- lib/fs/basicfs_unix.go | 17 + lib/fs/basicfs_windows.go | 38 + lib/fs/casefs.go | 2 +- lib/fs/errorfs.go | 7 +- lib/fs/fakefs.go | 31 +- lib/fs/fakefs_test.go | 2 +- lib/fs/filesystem.go | 5 +- lib/fs/mtimefs.go | 2 +- lib/fs/platform_common.go | 55 + lib/model/folder.go | 9 +- lib/model/folder_recvonly.go | 6 +- lib/model/folder_sendonly.go | 6 +- lib/model/folder_sendrecv.go | 62 +- lib/model/folder_sendrecv_test.go | 3 +- lib/model/folder_sendrecv_unix.go | 45 + lib/model/folder_sendrecv_windows.go | 82 ++ lib/protocol/bep.pb.go | 1102 ++++++++++++++++---- lib/protocol/bep_extensions.go | 75 +- lib/protocol/protocol_test.go | 4 +- lib/scanner/virtualfs_test.go | 9 + lib/scanner/walk.go | 71 +- lib/scanner/walk_test.go | 73 ++ proto/lib/config/folderconfiguration.proto | 1 + proto/lib/db/structs.proto | 1 + proto/lib/protocol/bep.proto | 24 + 35 files changed, 1896 insertions(+), 500 deletions(-) create mode 100644 lib/fs/basicfs_platformdata_unix.go create mode 100644 lib/fs/basicfs_platformdata_windows.go create mode 100644 lib/fs/platform_common.go create mode 100644 lib/model/folder_sendrecv_unix.go create mode 100644 lib/model/folder_sendrecv_windows.go diff --git a/go.mod b/go.mod index da7382c24..275b1251f 100644 --- a/go.mod +++ b/go.mod @@ -52,7 +52,7 @@ require ( golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 golang.org/x/mod v0.5.1 // indirect golang.org/x/net v0.0.0-20220607020251-c690dde0001d - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a + golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac golang.org/x/tools v0.1.7 diff --git a/go.sum b/go.sum index 2ea520cea..d912a1bf4 100644 --- a/go.sum +++ b/go.sum @@ -603,8 +603,9 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/lib/config/config.pb.go b/lib/config/config.pb.go index 12a65df0d..57a3e9b38 100644 --- a/lib/config/config.pb.go +++ b/lib/config/config.pb.go @@ -972,10 +972,7 @@ func (m *Defaults) Unmarshal(dAtA []byte) error { if err != nil { return err } - if skippy < 0 { - return ErrInvalidLengthConfig - } - if (iNdEx + skippy) < 0 { + if (skippy < 0) || (iNdEx+skippy) < 0 { return ErrInvalidLengthConfig } if (iNdEx + skippy) > l { diff --git a/lib/config/folderconfiguration.pb.go b/lib/config/folderconfiguration.pb.go index bcbc2a240..2989b8c41 100644 --- a/lib/config/folderconfiguration.pb.go +++ b/lib/config/folderconfiguration.pb.go @@ -100,6 +100,7 @@ type FolderConfiguration struct { CopyRangeMethod fs.CopyRangeMethod `protobuf:"varint,32,opt,name=copy_range_method,json=copyRangeMethod,proto3,enum=fs.CopyRangeMethod" json:"copyRangeMethod" xml:"copyRangeMethod" default:"standard"` CaseSensitiveFS bool `protobuf:"varint,33,opt,name=case_sensitive_fs,json=caseSensitiveFs,proto3" json:"caseSensitiveFS" xml:"caseSensitiveFS"` JunctionsAsDirs bool `protobuf:"varint,34,opt,name=follow_junctions,json=followJunctions,proto3" json:"junctionsAsDirs" xml:"junctionsAsDirs"` + SyncOwnership bool `protobuf:"varint,35,opt,name=sync_ownership,json=syncOwnership,proto3" json:"syncOwnership" xml:"syncOwnership"` // Legacy deprecated DeprecatedReadOnly bool `protobuf:"varint,9000,opt,name=read_only,json=readOnly,proto3" json:"-" xml:"ro,attr,omitempty"` // Deprecated: Do not use. DeprecatedMinDiskFreePct float64 `protobuf:"fixed64,9001,opt,name=min_disk_free_pct,json=minDiskFreePct,proto3" json:"-" xml:"minDiskFreePct,omitempty"` // Deprecated: Do not use. @@ -149,135 +150,137 @@ func init() { } var fileDescriptor_44a9785876ed3afa = []byte{ - // 2043 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x6f, 0x24, 0x47, - 0x15, 0x77, 0x7b, 0xbf, 0xec, 0xf2, 0x77, 0x79, 0xbd, 0xdb, 0xf1, 0x26, 0x53, 0x93, 0x66, 0x36, - 0x38, 0x51, 0xe2, 0xdd, 0x75, 0x10, 0x12, 0x2b, 0x16, 0xc8, 0xd8, 0xb1, 0x58, 0x16, 0x67, 0x47, - 0xed, 0x85, 0x15, 0x01, 0xa9, 0xe9, 0xe9, 0xae, 0x99, 0xa9, 0xb8, 0xbf, 0xa8, 0xea, 0x59, 0x7b, - 0xf6, 0x10, 0x2d, 0x17, 0x04, 0x22, 0x07, 0x64, 0x0e, 0xdc, 0x50, 0x24, 0x10, 0x82, 0xfc, 0x03, - 0x48, 0xfc, 0x05, 0x7b, 0x41, 0x9e, 0x13, 0x42, 0x1c, 0x4a, 0x8a, 0xf7, 0x36, 0xc7, 0x3e, 0xfa, - 0x84, 0xaa, 0xaa, 0xbb, 0xa7, 0xbb, 0x67, 0x22, 0x21, 0x71, 0x9b, 0xfa, 0xfd, 0x5e, 0xbd, 0xf7, - 0xeb, 0x57, 0xaf, 0x5e, 0xbf, 0x1e, 0xd0, 0xf0, 0x48, 0xfb, 0x8e, 0x13, 0x06, 0x1d, 0xd2, 0xbd, - 0xd3, 0x09, 0x3d, 0x17, 0x53, 0xb5, 0xe8, 0x53, 0x3b, 0x26, 0x61, 0xb0, 0x1d, 0xd1, 0x30, 0x0e, - 0xe1, 0x55, 0x05, 0x6e, 0xde, 0x9a, 0xb0, 0x8e, 0x07, 0x11, 0x56, 0x46, 0x9b, 0x1b, 0x05, 0x92, - 0x91, 0xe7, 0x19, 0xbc, 0x59, 0x80, 0xa3, 0xbe, 0xe7, 0x85, 0xd4, 0xc5, 0x34, 0xe5, 0xb6, 0x0a, - 0xdc, 0x33, 0x4c, 0x19, 0x09, 0x03, 0x12, 0x74, 0xa7, 0x28, 0xd8, 0x44, 0x05, 0xcb, 0xb6, 0x17, - 0x3a, 0x47, 0x55, 0x57, 0x50, 0x18, 0x74, 0xd8, 0x1d, 0x21, 0x88, 0xa5, 0xd8, 0xeb, 0x29, 0xe6, - 0x84, 0xd1, 0x80, 0xda, 0x41, 0x17, 0xfb, 0x38, 0xee, 0x85, 0x6e, 0xca, 0xce, 0xe3, 0x93, 0x58, - 0xfd, 0x34, 0xfe, 0x75, 0x09, 0xbc, 0xb6, 0x2f, 0x9f, 0x67, 0x0f, 0x3f, 0x23, 0x0e, 0xde, 0x2d, - 0x2a, 0x80, 0x5f, 0x68, 0x60, 0xde, 0x95, 0xb8, 0x45, 0x5c, 0x5d, 0xab, 0x6b, 0x5b, 0x8b, 0xcd, - 0xcf, 0xb4, 0x97, 0x1c, 0xcd, 0xfc, 0x87, 0xa3, 0x6f, 0x74, 0x49, 0xdc, 0xeb, 0xb7, 0xb7, 0x9d, - 0xd0, 0xbf, 0xc3, 0x06, 0x81, 0x13, 0xf7, 0x48, 0xd0, 0x2d, 0xfc, 0x12, 0x12, 0x64, 0x10, 0x27, - 0xf4, 0xb6, 0x95, 0xf7, 0x87, 0x7b, 0xe7, 0x1c, 0xcd, 0x65, 0xbf, 0x47, 0x1c, 0xcd, 0xb9, 0xe9, - 0xef, 0x84, 0xa3, 0xa5, 0x13, 0xdf, 0xbb, 0x6f, 0x10, 0xf7, 0x5d, 0x3b, 0x8e, 0xa9, 0x31, 0x3a, - 0x6b, 0x5c, 0x4b, 0x7f, 0x27, 0x67, 0x8d, 0xdc, 0xee, 0xd7, 0xc3, 0x86, 0x76, 0x3a, 0x6c, 0xe4, - 0x3e, 0xcc, 0x8c, 0x71, 0xe1, 0x5f, 0x34, 0xb0, 0x44, 0x82, 0x98, 0x86, 0x6e, 0xdf, 0xc1, 0xae, - 0xd5, 0x1e, 0xe8, 0xb3, 0x52, 0xf0, 0x8b, 0xff, 0x4b, 0xf0, 0x88, 0xa3, 0xc5, 0xb1, 0xd7, 0xe6, - 0x20, 0xe1, 0xe8, 0xa6, 0x12, 0x5a, 0x00, 0x73, 0xc9, 0x6b, 0x13, 0xa8, 0x10, 0x6c, 0x96, 0x3c, - 0x40, 0x07, 0xac, 0xe3, 0xc0, 0xa1, 0x83, 0x48, 0xe4, 0xd8, 0x8a, 0x6c, 0xc6, 0x8e, 0x43, 0xea, - 0xea, 0x97, 0xea, 0xda, 0xd6, 0x7c, 0x73, 0x67, 0xc4, 0x11, 0x1c, 0xd3, 0xad, 0x94, 0x4d, 0x38, - 0xd2, 0x65, 0xd8, 0x49, 0xca, 0x30, 0xa7, 0xd8, 0x1b, 0x7f, 0xac, 0x83, 0x75, 0x75, 0xb0, 0xe5, - 0x23, 0x3d, 0x04, 0xb3, 0xe9, 0x51, 0xce, 0x37, 0x77, 0xcf, 0x39, 0x9a, 0x95, 0x8f, 0x38, 0x4b, - 0x44, 0x84, 0x5a, 0xe9, 0x04, 0xea, 0x41, 0xe8, 0xe2, 0x8e, 0xdd, 0xf7, 0xe2, 0xfb, 0x46, 0x4c, - 0xfb, 0xb8, 0x78, 0x24, 0xa7, 0xc3, 0xc6, 0xec, 0xc3, 0xbd, 0xcf, 0xc5, 0xb3, 0xcd, 0x12, 0x17, - 0xfe, 0x08, 0x5c, 0xf1, 0xec, 0x36, 0xf6, 0x64, 0xc6, 0xe7, 0x9b, 0xdf, 0x1d, 0x71, 0xa4, 0x80, - 0x84, 0xa3, 0xba, 0x74, 0x2a, 0x57, 0xa9, 0x5f, 0x8a, 0x59, 0x6c, 0xd3, 0xf8, 0xbe, 0xd1, 0xb1, - 0x3d, 0x26, 0xdd, 0x82, 0x31, 0xfd, 0x62, 0xd8, 0x98, 0x31, 0xd5, 0x66, 0xd8, 0x05, 0x2b, 0x1d, - 0xe2, 0x61, 0x36, 0x60, 0x31, 0xf6, 0x2d, 0x51, 0xdf, 0x32, 0x49, 0xcb, 0x3b, 0x70, 0xbb, 0xc3, - 0xb6, 0xf7, 0x73, 0xea, 0xc9, 0x20, 0xc2, 0xcd, 0x77, 0x46, 0x1c, 0x2d, 0x77, 0x4a, 0x58, 0xc2, - 0xd1, 0x75, 0x19, 0xbd, 0x0c, 0x1b, 0x66, 0xc5, 0x0e, 0x1e, 0x80, 0xcb, 0x91, 0x1d, 0xf7, 0xf4, - 0xcb, 0x52, 0xfe, 0xb7, 0x46, 0x1c, 0xc9, 0x75, 0xc2, 0xd1, 0x2d, 0xb9, 0x5f, 0x2c, 0x52, 0xf1, - 0x79, 0x4a, 0x3e, 0x15, 0xc2, 0xe7, 0x73, 0xe6, 0xe2, 0xac, 0xa1, 0x7d, 0x6a, 0xca, 0x6d, 0xb0, - 0x05, 0x2e, 0x4b, 0xb1, 0x57, 0x52, 0xb1, 0xea, 0xf6, 0x6e, 0xab, 0xe3, 0x90, 0x62, 0xb7, 0x44, - 0x88, 0x58, 0x49, 0x5c, 0x91, 0x21, 0xc4, 0x22, 0x2f, 0xa3, 0xf9, 0x7c, 0x65, 0x4a, 0x2b, 0xf8, - 0x33, 0x70, 0x4d, 0xd5, 0x39, 0xd3, 0xaf, 0xd6, 0x2f, 0x6d, 0x2d, 0xec, 0xbc, 0x59, 0x76, 0x3a, - 0xe5, 0xf2, 0x36, 0x91, 0x28, 0xfb, 0x11, 0x47, 0xd9, 0xce, 0x84, 0xa3, 0x45, 0x19, 0x4a, 0xad, - 0x0d, 0x33, 0x23, 0xe0, 0xef, 0x35, 0xb0, 0x46, 0x31, 0x73, 0xec, 0xc0, 0x22, 0x41, 0x8c, 0xe9, - 0x33, 0xdb, 0xb3, 0x98, 0x7e, 0xad, 0xae, 0x6d, 0x5d, 0x69, 0x76, 0x47, 0x1c, 0xad, 0x28, 0xf2, - 0x61, 0xca, 0x1d, 0x26, 0x1c, 0xbd, 0x2d, 0x3d, 0x55, 0xf0, 0x6a, 0x8a, 0xde, 0xff, 0xe6, 0xdd, - 0xbb, 0xc6, 0x05, 0x47, 0x97, 0x48, 0x10, 0x8f, 0xce, 0x1a, 0xd7, 0xa7, 0x99, 0x5f, 0x9c, 0x35, - 0x2e, 0x0b, 0x3b, 0xb3, 0x1a, 0x04, 0xfe, 0x43, 0x03, 0xb0, 0xc3, 0xac, 0x63, 0x3b, 0x76, 0x7a, - 0x98, 0x5a, 0x38, 0xb0, 0xdb, 0x1e, 0x76, 0xf5, 0xb9, 0xba, 0xb6, 0x35, 0xd7, 0xfc, 0xad, 0x76, - 0xce, 0xd1, 0xea, 0xfe, 0xe1, 0x53, 0xc5, 0x7e, 0xa8, 0xc8, 0x11, 0x47, 0xab, 0x1d, 0x56, 0xc6, - 0x12, 0x8e, 0xde, 0x51, 0x45, 0x50, 0x21, 0xaa, 0x6a, 0xb3, 0x1a, 0xdf, 0x98, 0x6a, 0x28, 0x74, - 0x0a, 0x8b, 0xd3, 0x61, 0x63, 0x22, 0xac, 0x39, 0x11, 0x14, 0xfe, 0xbd, 0x2c, 0xde, 0xc5, 0x9e, - 0x3d, 0xb0, 0x98, 0x3e, 0x2f, 0x73, 0xfa, 0x1b, 0x21, 0x7e, 0x25, 0xf7, 0xb2, 0x27, 0xc8, 0x43, - 0x91, 0xe7, 0xdc, 0x8d, 0x82, 0x12, 0x8e, 0xbe, 0x5e, 0x96, 0xae, 0xf0, 0xaa, 0xf2, 0x7b, 0xa5, - 0x2c, 0x4f, 0x33, 0xbe, 0x38, 0x6b, 0xcc, 0xde, 0xbb, 0x7b, 0x3a, 0x6c, 0x54, 0xa3, 0x9a, 0xd5, - 0x98, 0xf0, 0xe7, 0x60, 0x91, 0x74, 0x83, 0x90, 0x62, 0x2b, 0xc2, 0xd4, 0x67, 0x3a, 0x90, 0xf9, - 0x7e, 0x30, 0xe2, 0x68, 0x41, 0xe1, 0x2d, 0x01, 0x27, 0x1c, 0xdd, 0x50, 0xdd, 0x62, 0x8c, 0xe5, - 0xe5, 0xbb, 0x5a, 0x05, 0xcd, 0xe2, 0x56, 0xf8, 0x4b, 0x0d, 0x2c, 0xdb, 0xfd, 0x38, 0xb4, 0x82, - 0x90, 0xfa, 0xb6, 0x47, 0x9e, 0x63, 0x7d, 0x41, 0x06, 0xf9, 0x78, 0xc4, 0xd1, 0x92, 0x60, 0x3e, - 0xca, 0x88, 0x3c, 0x03, 0x25, 0xf4, 0xab, 0x4e, 0x0e, 0x4e, 0x5a, 0x65, 0xc7, 0x66, 0x96, 0xfd, - 0xc2, 0x10, 0x2c, 0xf9, 0x24, 0xb0, 0x5c, 0xc2, 0x8e, 0xac, 0x0e, 0xc5, 0x58, 0x5f, 0xac, 0x6b, - 0x5b, 0x0b, 0x3b, 0x8b, 0xd9, 0xb5, 0x3a, 0x24, 0xcf, 0x71, 0xf3, 0x41, 0x7a, 0x83, 0x16, 0x7c, - 0x12, 0xec, 0x11, 0x76, 0xb4, 0x4f, 0xb1, 0x50, 0x84, 0xa4, 0xa2, 0x02, 0x56, 0x3c, 0x8a, 0xfa, - 0x6d, 0xe3, 0xe2, 0xac, 0x71, 0xe9, 0x5e, 0xfd, 0xb6, 0x59, 0xdc, 0x06, 0xbb, 0x00, 0x8c, 0xdf, - 0xf3, 0xfa, 0x92, 0x8c, 0x86, 0xb2, 0x68, 0x3f, 0xce, 0x99, 0xf2, 0x15, 0x7e, 0x2b, 0x15, 0x50, - 0xd8, 0x9a, 0x70, 0xb4, 0x2a, 0xe3, 0x8f, 0x21, 0xc3, 0x2c, 0xf0, 0xf0, 0x01, 0xb8, 0xe6, 0x84, - 0x11, 0xc1, 0x94, 0xe9, 0xcb, 0xb2, 0xda, 0xbe, 0x26, 0x7a, 0x40, 0x0a, 0xe5, 0xaf, 0xd9, 0x74, - 0x9d, 0xd5, 0x8d, 0x99, 0x19, 0xc0, 0x7f, 0x6a, 0xe0, 0x86, 0x98, 0x30, 0x30, 0xb5, 0x7c, 0xfb, - 0xc4, 0x8a, 0x70, 0xe0, 0x92, 0xa0, 0x6b, 0x1d, 0x91, 0xb6, 0xbe, 0x22, 0xdd, 0xfd, 0x41, 0x14, - 0xef, 0x7a, 0x4b, 0x9a, 0x1c, 0xd8, 0x27, 0x2d, 0x65, 0xf0, 0x88, 0x34, 0x47, 0x1c, 0xad, 0x47, - 0x93, 0x70, 0xc2, 0xd1, 0x6b, 0xaa, 0x89, 0x4e, 0x72, 0x85, 0xb2, 0x9d, 0xba, 0x75, 0x3a, 0x7c, - 0x3a, 0x6c, 0x4c, 0x8b, 0x6f, 0x4e, 0xb1, 0x6d, 0x8b, 0x74, 0xf4, 0x6c, 0xd6, 0x13, 0xe9, 0x58, - 0x1d, 0xa7, 0x23, 0x85, 0xf2, 0x74, 0xa4, 0xeb, 0x71, 0x3a, 0x52, 0x00, 0x7e, 0x00, 0xae, 0xc8, - 0x59, 0x4b, 0x5f, 0x93, 0xbd, 0x7c, 0x2d, 0x3b, 0x31, 0x11, 0xff, 0xb1, 0x20, 0x9a, 0xba, 0x78, - 0xd9, 0x49, 0x9b, 0x84, 0xa3, 0x05, 0xe9, 0x4d, 0xae, 0x0c, 0x53, 0xa1, 0xf0, 0x11, 0x58, 0x4a, - 0x2f, 0x94, 0x8b, 0x3d, 0x1c, 0x63, 0x1d, 0xca, 0x62, 0x7f, 0x4b, 0x4e, 0x16, 0x92, 0xd8, 0x93, - 0x78, 0xc2, 0x11, 0x2c, 0x5c, 0x29, 0x05, 0x1a, 0x66, 0xc9, 0x06, 0x9e, 0x00, 0x5d, 0xf6, 0xe9, - 0x88, 0x86, 0x5d, 0x8a, 0x19, 0x2b, 0x36, 0xec, 0x75, 0xf9, 0x7c, 0xe2, 0xe5, 0xbb, 0x21, 0x6c, - 0x5a, 0xa9, 0x49, 0xb1, 0x6d, 0xab, 0xd7, 0xd9, 0x54, 0x36, 0x7f, 0xf6, 0xe9, 0x9b, 0xe1, 0x21, - 0x58, 0x4e, 0xeb, 0x22, 0xb2, 0xfb, 0x0c, 0x5b, 0x4c, 0xbf, 0x2e, 0xe3, 0xbd, 0x27, 0x9e, 0x43, - 0x31, 0x2d, 0x41, 0x1c, 0xe6, 0xcf, 0x51, 0x04, 0x73, 0xef, 0x25, 0x53, 0x88, 0xc1, 0x92, 0xa8, - 0x32, 0x91, 0x54, 0x8f, 0x38, 0x31, 0xd3, 0x37, 0xa4, 0xcf, 0xef, 0x09, 0x9f, 0xbe, 0x7d, 0xb2, - 0x9b, 0xe1, 0xe3, 0x5b, 0x57, 0x00, 0xa7, 0x76, 0x40, 0xd5, 0xe9, 0xcc, 0xd2, 0x6e, 0xe8, 0x82, - 0xeb, 0x2e, 0x61, 0xa2, 0x33, 0x5b, 0x2c, 0xb2, 0x29, 0xc3, 0x96, 0x1c, 0x00, 0xf4, 0x1b, 0xf2, - 0x24, 0xe4, 0xc8, 0x95, 0xf2, 0x87, 0x92, 0x96, 0xa3, 0x45, 0x3e, 0x72, 0x4d, 0x52, 0x86, 0x39, - 0xc5, 0xbe, 0x18, 0x25, 0xc6, 0x7e, 0x64, 0x91, 0xc0, 0xc5, 0x27, 0x98, 0xe9, 0x37, 0x27, 0xa2, - 0x3c, 0xc1, 0x7e, 0xf4, 0x50, 0xb1, 0xd5, 0x28, 0x05, 0x6a, 0x1c, 0xa5, 0x00, 0xc2, 0x1d, 0x70, - 0x55, 0x1e, 0x80, 0xab, 0xeb, 0xd2, 0xef, 0xe6, 0x88, 0xa3, 0x14, 0xc9, 0xdf, 0xf0, 0x6a, 0x69, - 0x98, 0x29, 0x0e, 0x63, 0x70, 0xf3, 0x18, 0xdb, 0x47, 0x96, 0xa8, 0x6a, 0x2b, 0xee, 0x51, 0xcc, - 0x7a, 0xa1, 0xe7, 0x5a, 0x91, 0x13, 0xeb, 0xaf, 0xc9, 0x84, 0x8b, 0xf6, 0x7e, 0x5d, 0x98, 0x7c, - 0xdf, 0x66, 0xbd, 0x27, 0x99, 0x41, 0xcb, 0x89, 0x13, 0x8e, 0x36, 0xa5, 0xcb, 0x69, 0x64, 0x7e, - 0xa8, 0x53, 0xb7, 0xc2, 0x5d, 0xb0, 0xe0, 0xdb, 0xf4, 0x08, 0x53, 0x2b, 0xb0, 0x7d, 0xac, 0x6f, - 0xca, 0xe1, 0xca, 0x10, 0xed, 0x4c, 0xc1, 0x1f, 0xd9, 0x3e, 0xce, 0xdb, 0xd9, 0x18, 0x32, 0xcc, - 0x02, 0x0f, 0x07, 0x60, 0x53, 0x7c, 0xc4, 0x58, 0xe1, 0x71, 0x80, 0x29, 0xeb, 0x91, 0xc8, 0xea, - 0xd0, 0xd0, 0xb7, 0x22, 0x9b, 0xe2, 0x20, 0xd6, 0x6f, 0xc9, 0x14, 0x7c, 0x7b, 0xc4, 0xd1, 0x4d, - 0x61, 0xf5, 0x38, 0x33, 0xda, 0xa7, 0xa1, 0xdf, 0x92, 0x26, 0x09, 0x47, 0x6f, 0x64, 0x1d, 0x6f, - 0x1a, 0x6f, 0x98, 0x5f, 0xb5, 0x13, 0xfe, 0x4a, 0x03, 0x6b, 0x7e, 0xe8, 0x5a, 0x31, 0xf1, 0xb1, - 0x75, 0x4c, 0x02, 0x37, 0x3c, 0xb6, 0x98, 0xfe, 0xba, 0x4c, 0xd8, 0x4f, 0xcf, 0x39, 0x5a, 0x33, - 0xed, 0xe3, 0x83, 0xd0, 0x7d, 0x42, 0x7c, 0xfc, 0x54, 0xb2, 0xe2, 0x1d, 0xbe, 0xec, 0x97, 0x90, - 0x7c, 0x04, 0x2d, 0xc3, 0x59, 0xe6, 0x4e, 0x87, 0x8d, 0x49, 0x2f, 0x66, 0xc5, 0x07, 0x7c, 0xa1, - 0x81, 0x8d, 0xf4, 0x9a, 0x38, 0x7d, 0x2a, 0xb4, 0x59, 0xc7, 0x94, 0xc4, 0x98, 0xe9, 0x6f, 0x48, - 0x31, 0x3f, 0x14, 0xad, 0x57, 0x15, 0x7c, 0xca, 0x3f, 0x95, 0x74, 0xc2, 0xd1, 0xed, 0xc2, 0xad, - 0x29, 0x71, 0x85, 0xcb, 0xb3, 0x53, 0xb8, 0x3b, 0xda, 0x8e, 0x39, 0xcd, 0x93, 0x68, 0x62, 0x59, - 0x6d, 0x77, 0xc4, 0x17, 0x93, 0x5e, 0x1b, 0x37, 0xb1, 0x94, 0xd8, 0x17, 0x78, 0x7e, 0xf9, 0x8b, - 0xa0, 0x61, 0x96, 0x6c, 0xa0, 0x07, 0x56, 0xe5, 0x97, 0xac, 0x25, 0x7a, 0x81, 0xa5, 0xfa, 0x2b, - 0x92, 0xfd, 0xf5, 0x46, 0xd6, 0x5f, 0x9b, 0x82, 0x1f, 0x37, 0x59, 0x39, 0xdc, 0xb7, 0x4b, 0x58, - 0x9e, 0xd9, 0x32, 0x6c, 0x98, 0x15, 0x3b, 0xf8, 0x99, 0x06, 0xd6, 0x64, 0x09, 0xc9, 0x0f, 0x61, - 0x4b, 0x7d, 0x09, 0xeb, 0x75, 0x19, 0x6f, 0x5d, 0x7c, 0x48, 0xec, 0x86, 0xd1, 0xc0, 0x14, 0xdc, - 0x81, 0xa4, 0x9a, 0x8f, 0xc4, 0x28, 0xe6, 0x94, 0xc1, 0x84, 0xa3, 0xad, 0xbc, 0x8c, 0x0a, 0x78, - 0x21, 0x8d, 0x2c, 0xb6, 0x03, 0xd7, 0xa6, 0xae, 0x78, 0xff, 0xcf, 0x65, 0x0b, 0xb3, 0xea, 0x08, - 0xfe, 0x59, 0xc8, 0xb1, 0x45, 0x03, 0xc5, 0x01, 0x23, 0x31, 0x79, 0x26, 0x32, 0xaa, 0xbf, 0x29, - 0xd3, 0x79, 0x22, 0xe6, 0xc2, 0x5d, 0x9b, 0xe1, 0xc3, 0x8c, 0xdb, 0x97, 0x73, 0xa1, 0x53, 0x86, - 0x12, 0x8e, 0x36, 0x94, 0x98, 0x32, 0x2e, 0x66, 0xa0, 0x09, 0xdb, 0x49, 0x48, 0x8c, 0x81, 0x95, - 0x20, 0x66, 0xc5, 0x86, 0xc1, 0x3f, 0x69, 0x60, 0xb5, 0x13, 0x7a, 0x5e, 0x78, 0x6c, 0x7d, 0xd2, - 0x0f, 0x1c, 0x31, 0x8e, 0x30, 0xdd, 0x18, 0xab, 0xfc, 0x41, 0x06, 0x7e, 0xc0, 0xf6, 0x08, 0x65, - 0x42, 0xe5, 0x27, 0x65, 0x28, 0x57, 0x59, 0xc1, 0xa5, 0xca, 0xaa, 0xed, 0x24, 0x24, 0x54, 0x56, - 0x82, 0x98, 0x2b, 0x4a, 0x51, 0x0e, 0xc3, 0x23, 0x30, 0x4f, 0xb1, 0xed, 0x5a, 0x61, 0xe0, 0x0d, - 0xf4, 0xbf, 0xee, 0x4b, 0x79, 0x07, 0xe7, 0x1c, 0xc1, 0x3d, 0x1c, 0x51, 0xec, 0xd8, 0x31, 0x76, - 0x4d, 0x6c, 0xbb, 0x8f, 0x03, 0x6f, 0x30, 0xe2, 0x48, 0x7b, 0x2f, 0xff, 0x7a, 0xa7, 0xa1, 0x1c, - 0x0f, 0xdf, 0x0d, 0x7d, 0x22, 0x7a, 0x75, 0x3c, 0x90, 0x5f, 0xef, 0x13, 0xa8, 0xae, 0x99, 0x73, - 0x34, 0x75, 0x00, 0x7f, 0x01, 0xd6, 0x4a, 0x33, 0xa3, 0xec, 0x9f, 0x7f, 0x13, 0x41, 0xb5, 0xe6, - 0x87, 0xe7, 0x1c, 0xe9, 0xe3, 0xa0, 0x07, 0xe3, 0xc9, 0xaf, 0xe5, 0xc4, 0x59, 0xe8, 0x5a, 0x75, - 0x70, 0x6c, 0x39, 0x71, 0x41, 0x81, 0xae, 0x99, 0xcb, 0x65, 0x12, 0xfe, 0x04, 0x5c, 0x53, 0xef, - 0x4b, 0xa6, 0x7f, 0xb1, 0x2f, 0xef, 0xfa, 0x77, 0x44, 0xe3, 0x19, 0x07, 0x52, 0x73, 0x10, 0x2b, - 0x3f, 0x5c, 0xba, 0xa5, 0xe0, 0x3a, 0xbd, 0xe0, 0xba, 0x66, 0x66, 0xfe, 0x9a, 0x8f, 0x5e, 0x7e, - 0x59, 0x9b, 0x19, 0x7e, 0x59, 0x9b, 0x79, 0x79, 0x5e, 0xd3, 0x86, 0xe7, 0x35, 0xed, 0x77, 0xaf, - 0x6a, 0x33, 0x9f, 0xbf, 0xaa, 0x69, 0xc3, 0x57, 0xb5, 0x99, 0x7f, 0xbf, 0xaa, 0xcd, 0x7c, 0xfc, - 0xf6, 0xff, 0xf0, 0x7f, 0x89, 0xba, 0xae, 0xed, 0xab, 0xf2, 0x7f, 0x93, 0xf7, 0xff, 0x1b, 0x00, - 0x00, 0xff, 0xff, 0x3e, 0xb6, 0x85, 0xe6, 0x55, 0x13, 0x00, 0x00, + // 2074 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x6f, 0xdc, 0xc6, + 0x15, 0x17, 0xe5, 0x2f, 0x69, 0xf4, 0x3d, 0xb2, 0xec, 0xb1, 0x9c, 0xec, 0x6c, 0x98, 0x75, 0xaa, + 0x04, 0x89, 0x6c, 0x2b, 0x45, 0x81, 0x1a, 0x75, 0xdb, 0xac, 0x14, 0xa1, 0xae, 0xab, 0x78, 0x41, + 0xb9, 0x35, 0x9a, 0x16, 0x60, 0xb9, 0xe4, 0xec, 0x2e, 0x23, 0x7e, 0x75, 0x86, 0x6b, 0x69, 0x7d, + 0x08, 0xdc, 0x4b, 0xd1, 0xa2, 0x39, 0x14, 0xea, 0xa1, 0xd7, 0x00, 0x2d, 0x8a, 0x36, 0xff, 0x40, + 0x81, 0xfe, 0x05, 0xbe, 0x14, 0xda, 0x53, 0x51, 0xf4, 0x30, 0x40, 0xe4, 0xdb, 0x5e, 0x0a, 0xf0, + 0xe8, 0x53, 0x31, 0x33, 0x24, 0x97, 0xe4, 0x6e, 0x80, 0x02, 0xb9, 0xed, 0xfc, 0x7e, 0x6f, 0xde, + 0xfb, 0xf1, 0xcd, 0x9b, 0xc7, 0xc7, 0x05, 0x0d, 0xcf, 0x6d, 0xdf, 0xb6, 0xc3, 0xa0, 0xe3, 0x76, + 0x6f, 0x77, 0x42, 0xcf, 0x21, 0x54, 0x2d, 0xfa, 0xd4, 0x8a, 0xdd, 0x30, 0xd8, 0x8e, 0x68, 0x18, + 0x87, 0xf0, 0xb2, 0x02, 0x37, 0x6f, 0x4e, 0x58, 0xc7, 0x83, 0x88, 0x28, 0xa3, 0xcd, 0x8d, 0x02, + 0xc9, 0xdc, 0x67, 0x19, 0xbc, 0x59, 0x80, 0xa3, 0xbe, 0xe7, 0x85, 0xd4, 0x21, 0x34, 0xe5, 0xb6, + 0x0a, 0xdc, 0x53, 0x42, 0x99, 0x1b, 0x06, 0x6e, 0xd0, 0x9d, 0xa2, 0x60, 0x13, 0x17, 0x2c, 0xdb, + 0x5e, 0x68, 0x1f, 0x55, 0x5d, 0x41, 0x61, 0xd0, 0x61, 0xb7, 0x85, 0x20, 0x96, 0x62, 0xaf, 0xa5, + 0x98, 0x1d, 0x46, 0x03, 0x6a, 0x05, 0x5d, 0xe2, 0x93, 0xb8, 0x17, 0x3a, 0x29, 0x3b, 0x4f, 0x4e, + 0x62, 0xf5, 0x53, 0xff, 0xd7, 0x05, 0x70, 0x63, 0x5f, 0x3e, 0xcf, 0x1e, 0x79, 0xea, 0xda, 0x64, + 0xb7, 0xa8, 0x00, 0x7e, 0xa1, 0x81, 0x79, 0x47, 0xe2, 0xa6, 0xeb, 0x20, 0xad, 0xae, 0x6d, 0x2d, + 0x36, 0x3f, 0xd3, 0x5e, 0x70, 0x3c, 0xf3, 0x1f, 0x8e, 0xbf, 0xd9, 0x75, 0xe3, 0x5e, 0xbf, 0xbd, + 0x6d, 0x87, 0xfe, 0x6d, 0x36, 0x08, 0xec, 0xb8, 0xe7, 0x06, 0xdd, 0xc2, 0x2f, 0x21, 0x41, 0x06, + 0xb1, 0x43, 0x6f, 0x5b, 0x79, 0x7f, 0xb0, 0x77, 0xce, 0xf1, 0x5c, 0xf6, 0x7b, 0xc4, 0xf1, 0x9c, + 0x93, 0xfe, 0x4e, 0x38, 0x5e, 0x3a, 0xf1, 0xbd, 0x7b, 0xba, 0xeb, 0xbc, 0x6b, 0xc5, 0x31, 0xd5, + 0x47, 0x67, 0x8d, 0x2b, 0xe9, 0xef, 0xe4, 0xac, 0x91, 0xdb, 0xfd, 0x66, 0xd8, 0xd0, 0x4e, 0x87, + 0x8d, 0xdc, 0x87, 0x91, 0x31, 0x0e, 0xfc, 0x8b, 0x06, 0x96, 0xdc, 0x20, 0xa6, 0xa1, 0xd3, 0xb7, + 0x89, 0x63, 0xb6, 0x07, 0x68, 0x56, 0x0a, 0x7e, 0xfe, 0xb5, 0x04, 0x8f, 0x38, 0x5e, 0x1c, 0x7b, + 0x6d, 0x0e, 0x12, 0x8e, 0xaf, 0x2b, 0xa1, 0x05, 0x30, 0x97, 0xbc, 0x36, 0x81, 0x0a, 0xc1, 0x46, + 0xc9, 0x03, 0xb4, 0xc1, 0x3a, 0x09, 0x6c, 0x3a, 0x88, 0x44, 0x8e, 0xcd, 0xc8, 0x62, 0xec, 0x38, + 0xa4, 0x0e, 0xba, 0x50, 0xd7, 0xb6, 0xe6, 0x9b, 0x3b, 0x23, 0x8e, 0xe1, 0x98, 0x6e, 0xa5, 0x6c, + 0xc2, 0x31, 0x92, 0x61, 0x27, 0x29, 0xdd, 0x98, 0x62, 0xaf, 0xff, 0xb7, 0x0e, 0xd6, 0xd5, 0xc1, + 0x96, 0x8f, 0xf4, 0x10, 0xcc, 0xa6, 0x47, 0x39, 0xdf, 0xdc, 0x3d, 0xe7, 0x78, 0x56, 0x3e, 0xe2, + 0xac, 0x2b, 0x22, 0xd4, 0x4a, 0x27, 0x50, 0x0f, 0x42, 0x87, 0x74, 0xac, 0xbe, 0x17, 0xdf, 0xd3, + 0x63, 0xda, 0x27, 0xc5, 0x23, 0x39, 0x1d, 0x36, 0x66, 0x1f, 0xec, 0x7d, 0x2e, 0x9e, 0x6d, 0xd6, + 0x75, 0xe0, 0x8f, 0xc1, 0x25, 0xcf, 0x6a, 0x13, 0x4f, 0x66, 0x7c, 0xbe, 0xf9, 0xbd, 0x11, 0xc7, + 0x0a, 0x48, 0x38, 0xae, 0x4b, 0xa7, 0x72, 0x95, 0xfa, 0xa5, 0x84, 0xc5, 0x16, 0x8d, 0xef, 0xe9, + 0x1d, 0xcb, 0x63, 0xd2, 0x2d, 0x18, 0xd3, 0xcf, 0x87, 0x8d, 0x19, 0x43, 0x6d, 0x86, 0x5d, 0xb0, + 0xd2, 0x71, 0x3d, 0xc2, 0x06, 0x2c, 0x26, 0xbe, 0x29, 0xea, 0x5b, 0x26, 0x69, 0x79, 0x07, 0x6e, + 0x77, 0xd8, 0xf6, 0x7e, 0x4e, 0x3d, 0x1e, 0x44, 0xa4, 0xf9, 0xce, 0x88, 0xe3, 0xe5, 0x4e, 0x09, + 0x4b, 0x38, 0xbe, 0x2a, 0xa3, 0x97, 0x61, 0xdd, 0xa8, 0xd8, 0xc1, 0x03, 0x70, 0x31, 0xb2, 0xe2, + 0x1e, 0xba, 0x28, 0xe5, 0x7f, 0x7b, 0xc4, 0xb1, 0x5c, 0x27, 0x1c, 0xdf, 0x94, 0xfb, 0xc5, 0x22, + 0x15, 0x9f, 0xa7, 0xe4, 0x53, 0x21, 0x7c, 0x3e, 0x67, 0x5e, 0x9d, 0x35, 0xb4, 0x4f, 0x0d, 0xb9, + 0x0d, 0xb6, 0xc0, 0x45, 0x29, 0xf6, 0x52, 0x2a, 0x56, 0xdd, 0xde, 0x6d, 0x75, 0x1c, 0x52, 0xec, + 0x96, 0x08, 0x11, 0x2b, 0x89, 0x2b, 0x32, 0x84, 0x58, 0xe4, 0x65, 0x34, 0x9f, 0xaf, 0x0c, 0x69, + 0x05, 0x7f, 0x0e, 0xae, 0xa8, 0x3a, 0x67, 0xe8, 0x72, 0xfd, 0xc2, 0xd6, 0xc2, 0xce, 0x1b, 0x65, + 0xa7, 0x53, 0x2e, 0x6f, 0x13, 0x8b, 0xb2, 0x1f, 0x71, 0x9c, 0xed, 0x4c, 0x38, 0x5e, 0x94, 0xa1, + 0xd4, 0x5a, 0x37, 0x32, 0x02, 0xfe, 0x41, 0x03, 0x6b, 0x94, 0x30, 0xdb, 0x0a, 0x4c, 0x37, 0x88, + 0x09, 0x7d, 0x6a, 0x79, 0x26, 0x43, 0x57, 0xea, 0xda, 0xd6, 0xa5, 0x66, 0x77, 0xc4, 0xf1, 0x8a, + 0x22, 0x1f, 0xa4, 0xdc, 0x61, 0xc2, 0xf1, 0xdb, 0xd2, 0x53, 0x05, 0xaf, 0xa6, 0xe8, 0xfd, 0x6f, + 0xdd, 0xb9, 0xa3, 0xbf, 0xe2, 0xf8, 0x82, 0x1b, 0xc4, 0xa3, 0xb3, 0xc6, 0xd5, 0x69, 0xe6, 0xaf, + 0xce, 0x1a, 0x17, 0x85, 0x9d, 0x51, 0x0d, 0x02, 0xff, 0xa1, 0x01, 0xd8, 0x61, 0xe6, 0xb1, 0x15, + 0xdb, 0x3d, 0x42, 0x4d, 0x12, 0x58, 0x6d, 0x8f, 0x38, 0x68, 0xae, 0xae, 0x6d, 0xcd, 0x35, 0x7f, + 0xa7, 0x9d, 0x73, 0xbc, 0xba, 0x7f, 0xf8, 0x44, 0xb1, 0x1f, 0x2a, 0x72, 0xc4, 0xf1, 0x6a, 0x87, + 0x95, 0xb1, 0x84, 0xe3, 0x77, 0x54, 0x11, 0x54, 0x88, 0xaa, 0xda, 0xac, 0xc6, 0x37, 0xa6, 0x1a, + 0x0a, 0x9d, 0xc2, 0xe2, 0x74, 0xd8, 0x98, 0x08, 0x6b, 0x4c, 0x04, 0x85, 0x7f, 0x2f, 0x8b, 0x77, + 0x88, 0x67, 0x0d, 0x4c, 0x86, 0xe6, 0x65, 0x4e, 0x7f, 0x2b, 0xc4, 0xaf, 0xe4, 0x5e, 0xf6, 0x04, + 0x79, 0x28, 0xf2, 0x9c, 0xbb, 0x51, 0x50, 0xc2, 0xf1, 0x37, 0xca, 0xd2, 0x15, 0x5e, 0x55, 0x7e, + 0xb7, 0x94, 0xe5, 0x69, 0xc6, 0xaf, 0xce, 0x1a, 0xb3, 0x77, 0xef, 0x9c, 0x0e, 0x1b, 0xd5, 0xa8, + 0x46, 0x35, 0x26, 0xfc, 0x05, 0x58, 0x74, 0xbb, 0x41, 0x48, 0x89, 0x19, 0x11, 0xea, 0x33, 0x04, + 0x64, 0xbe, 0xef, 0x8f, 0x38, 0x5e, 0x50, 0x78, 0x4b, 0xc0, 0x09, 0xc7, 0xd7, 0x54, 0xb7, 0x18, + 0x63, 0x79, 0xf9, 0xae, 0x56, 0x41, 0xa3, 0xb8, 0x15, 0xfe, 0x4a, 0x03, 0xcb, 0x56, 0x3f, 0x0e, + 0xcd, 0x20, 0xa4, 0xbe, 0xe5, 0xb9, 0xcf, 0x08, 0x5a, 0x90, 0x41, 0x3e, 0x1e, 0x71, 0xbc, 0x24, + 0x98, 0x8f, 0x32, 0x22, 0xcf, 0x40, 0x09, 0xfd, 0xaa, 0x93, 0x83, 0x93, 0x56, 0xd9, 0xb1, 0x19, + 0x65, 0xbf, 0x30, 0x04, 0x4b, 0xbe, 0x1b, 0x98, 0x8e, 0xcb, 0x8e, 0xcc, 0x0e, 0x25, 0x04, 0x2d, + 0xd6, 0xb5, 0xad, 0x85, 0x9d, 0xc5, 0xec, 0x5a, 0x1d, 0xba, 0xcf, 0x48, 0xf3, 0x7e, 0x7a, 0x83, + 0x16, 0x7c, 0x37, 0xd8, 0x73, 0xd9, 0xd1, 0x3e, 0x25, 0x42, 0x11, 0x96, 0x8a, 0x0a, 0x58, 0xf1, + 0x28, 0xea, 0xb7, 0xf4, 0x57, 0x67, 0x8d, 0x0b, 0x77, 0xeb, 0xb7, 0x8c, 0xe2, 0x36, 0xd8, 0x05, + 0x60, 0xfc, 0x9e, 0x47, 0x4b, 0x32, 0x1a, 0xce, 0xa2, 0xfd, 0x24, 0x67, 0xca, 0x57, 0xf8, 0xad, + 0x54, 0x40, 0x61, 0x6b, 0xc2, 0xf1, 0xaa, 0x8c, 0x3f, 0x86, 0x74, 0xa3, 0xc0, 0xc3, 0xfb, 0xe0, + 0x8a, 0x1d, 0x46, 0x2e, 0xa1, 0x0c, 0x2d, 0xcb, 0x6a, 0x7b, 0x53, 0xf4, 0x80, 0x14, 0xca, 0x5f, + 0xb3, 0xe9, 0x3a, 0xab, 0x1b, 0x23, 0x33, 0x80, 0xff, 0xd4, 0xc0, 0x35, 0x31, 0x61, 0x10, 0x6a, + 0xfa, 0xd6, 0x89, 0x19, 0x91, 0xc0, 0x71, 0x83, 0xae, 0x79, 0xe4, 0xb6, 0xd1, 0x8a, 0x74, 0xf7, + 0x47, 0x51, 0xbc, 0xeb, 0x2d, 0x69, 0x72, 0x60, 0x9d, 0xb4, 0x94, 0xc1, 0x43, 0xb7, 0x39, 0xe2, + 0x78, 0x3d, 0x9a, 0x84, 0x13, 0x8e, 0x6f, 0xa8, 0x26, 0x3a, 0xc9, 0x15, 0xca, 0x76, 0xea, 0xd6, + 0xe9, 0xf0, 0xe9, 0xb0, 0x31, 0x2d, 0xbe, 0x31, 0xc5, 0xb6, 0x2d, 0xd2, 0xd1, 0xb3, 0x58, 0x4f, + 0xa4, 0x63, 0x75, 0x9c, 0x8e, 0x14, 0xca, 0xd3, 0x91, 0xae, 0xc7, 0xe9, 0x48, 0x01, 0xf8, 0x01, + 0xb8, 0x24, 0x67, 0x2d, 0xb4, 0x26, 0x7b, 0xf9, 0x5a, 0x76, 0x62, 0x22, 0xfe, 0x23, 0x41, 0x34, + 0x91, 0x78, 0xd9, 0x49, 0x9b, 0x84, 0xe3, 0x05, 0xe9, 0x4d, 0xae, 0x74, 0x43, 0xa1, 0xf0, 0x21, + 0x58, 0x4a, 0x2f, 0x94, 0x43, 0x3c, 0x12, 0x13, 0x04, 0x65, 0xb1, 0xbf, 0x25, 0x27, 0x0b, 0x49, + 0xec, 0x49, 0x3c, 0xe1, 0x18, 0x16, 0xae, 0x94, 0x02, 0x75, 0xa3, 0x64, 0x03, 0x4f, 0x00, 0x92, + 0x7d, 0x3a, 0xa2, 0x61, 0x97, 0x12, 0xc6, 0x8a, 0x0d, 0x7b, 0x5d, 0x3e, 0x9f, 0x78, 0xf9, 0x6e, + 0x08, 0x9b, 0x56, 0x6a, 0x52, 0x6c, 0xdb, 0xea, 0x75, 0x36, 0x95, 0xcd, 0x9f, 0x7d, 0xfa, 0x66, + 0x78, 0x08, 0x96, 0xd3, 0xba, 0x88, 0xac, 0x3e, 0x23, 0x26, 0x43, 0x57, 0x65, 0xbc, 0xf7, 0xc4, + 0x73, 0x28, 0xa6, 0x25, 0x88, 0xc3, 0xfc, 0x39, 0x8a, 0x60, 0xee, 0xbd, 0x64, 0x0a, 0x09, 0x58, + 0x12, 0x55, 0x26, 0x92, 0xea, 0xb9, 0x76, 0xcc, 0xd0, 0x86, 0xf4, 0xf9, 0x7d, 0xe1, 0xd3, 0xb7, + 0x4e, 0x76, 0x33, 0x7c, 0x7c, 0xeb, 0x0a, 0xe0, 0xd4, 0x0e, 0xa8, 0x3a, 0x9d, 0x51, 0xda, 0x0d, + 0x1d, 0x70, 0xd5, 0x71, 0x99, 0xe8, 0xcc, 0x26, 0x8b, 0x2c, 0xca, 0x88, 0x29, 0x07, 0x00, 0x74, + 0x4d, 0x9e, 0x84, 0x1c, 0xb9, 0x52, 0xfe, 0x50, 0xd2, 0x72, 0xb4, 0xc8, 0x47, 0xae, 0x49, 0x4a, + 0x37, 0xa6, 0xd8, 0x17, 0xa3, 0xc4, 0xc4, 0x8f, 0x4c, 0x37, 0x70, 0xc8, 0x09, 0x61, 0xe8, 0xfa, + 0x44, 0x94, 0xc7, 0xc4, 0x8f, 0x1e, 0x28, 0xb6, 0x1a, 0xa5, 0x40, 0x8d, 0xa3, 0x14, 0x40, 0xb8, + 0x03, 0x2e, 0xcb, 0x03, 0x70, 0x10, 0x92, 0x7e, 0x37, 0x47, 0x1c, 0xa7, 0x48, 0xfe, 0x86, 0x57, + 0x4b, 0xdd, 0x48, 0x71, 0x18, 0x83, 0xeb, 0xc7, 0xc4, 0x3a, 0x32, 0x45, 0x55, 0x9b, 0x71, 0x8f, + 0x12, 0xd6, 0x0b, 0x3d, 0xc7, 0x8c, 0xec, 0x18, 0xdd, 0x90, 0x09, 0x17, 0xed, 0xfd, 0xaa, 0x30, + 0xf9, 0x81, 0xc5, 0x7a, 0x8f, 0x33, 0x83, 0x96, 0x1d, 0x27, 0x1c, 0x6f, 0x4a, 0x97, 0xd3, 0xc8, + 0xfc, 0x50, 0xa7, 0x6e, 0x85, 0xbb, 0x60, 0xc1, 0xb7, 0xe8, 0x11, 0xa1, 0x66, 0x60, 0xf9, 0x04, + 0x6d, 0xca, 0xe1, 0x4a, 0x17, 0xed, 0x4c, 0xc1, 0x1f, 0x59, 0x3e, 0xc9, 0xdb, 0xd9, 0x18, 0xd2, + 0x8d, 0x02, 0x0f, 0x07, 0x60, 0x53, 0x7c, 0xc4, 0x98, 0xe1, 0x71, 0x40, 0x28, 0xeb, 0xb9, 0x91, + 0xd9, 0xa1, 0xa1, 0x6f, 0x46, 0x16, 0x25, 0x41, 0x8c, 0x6e, 0xca, 0x14, 0x7c, 0x67, 0xc4, 0xf1, + 0x75, 0x61, 0xf5, 0x28, 0x33, 0xda, 0xa7, 0xa1, 0xdf, 0x92, 0x26, 0x09, 0xc7, 0xaf, 0x67, 0x1d, + 0x6f, 0x1a, 0xaf, 0x1b, 0x5f, 0xb5, 0x13, 0xfe, 0x5a, 0x03, 0x6b, 0x7e, 0xe8, 0x98, 0xb1, 0xeb, + 0x13, 0xf3, 0xd8, 0x0d, 0x9c, 0xf0, 0xd8, 0x64, 0xe8, 0x35, 0x99, 0xb0, 0x9f, 0x9d, 0x73, 0xbc, + 0x66, 0x58, 0xc7, 0x07, 0xa1, 0xf3, 0xd8, 0xf5, 0xc9, 0x13, 0xc9, 0x8a, 0x77, 0xf8, 0xb2, 0x5f, + 0x42, 0xf2, 0x11, 0xb4, 0x0c, 0x67, 0x99, 0x3b, 0x1d, 0x36, 0x26, 0xbd, 0x18, 0x15, 0x1f, 0xf0, + 0xb9, 0x06, 0x36, 0xd2, 0x6b, 0x62, 0xf7, 0xa9, 0xd0, 0x66, 0x1e, 0x53, 0x37, 0x26, 0x0c, 0xbd, + 0x2e, 0xc5, 0xfc, 0x48, 0xb4, 0x5e, 0x55, 0xf0, 0x29, 0xff, 0x44, 0xd2, 0x09, 0xc7, 0xb7, 0x0a, + 0xb7, 0xa6, 0xc4, 0x15, 0x2e, 0xcf, 0x4e, 0xe1, 0xee, 0x68, 0x3b, 0xc6, 0x34, 0x4f, 0xa2, 0x89, + 0x65, 0xb5, 0xdd, 0x11, 0x5f, 0x4c, 0xa8, 0x36, 0x6e, 0x62, 0x29, 0xb1, 0x2f, 0xf0, 0xfc, 0xf2, + 0x17, 0x41, 0xdd, 0x28, 0xd9, 0x40, 0x0f, 0xac, 0xca, 0x2f, 0x59, 0x53, 0xf4, 0x02, 0x53, 0xf5, + 0x57, 0x2c, 0xfb, 0xeb, 0xb5, 0xac, 0xbf, 0x36, 0x05, 0x3f, 0x6e, 0xb2, 0x72, 0xb8, 0x6f, 0x97, + 0xb0, 0x3c, 0xb3, 0x65, 0x58, 0x37, 0x2a, 0x76, 0xf0, 0x33, 0x0d, 0xac, 0xc9, 0x12, 0x92, 0x1f, + 0xc2, 0xa6, 0xfa, 0x12, 0x46, 0x75, 0x19, 0x6f, 0x5d, 0x7c, 0x48, 0xec, 0x86, 0xd1, 0xc0, 0x10, + 0xdc, 0x81, 0xa4, 0x9a, 0x0f, 0xc5, 0x28, 0x66, 0x97, 0xc1, 0x84, 0xe3, 0xad, 0xbc, 0x8c, 0x0a, + 0x78, 0x21, 0x8d, 0x2c, 0xb6, 0x02, 0xc7, 0xa2, 0x8e, 0x78, 0xff, 0xcf, 0x65, 0x0b, 0xa3, 0xea, + 0x08, 0xfe, 0x59, 0xc8, 0xb1, 0x44, 0x03, 0x25, 0x01, 0x73, 0x63, 0xf7, 0xa9, 0xc8, 0x28, 0x7a, + 0x43, 0xa6, 0xf3, 0x44, 0xcc, 0x85, 0xbb, 0x16, 0x23, 0x87, 0x19, 0xb7, 0x2f, 0xe7, 0x42, 0xbb, + 0x0c, 0x25, 0x1c, 0x6f, 0x28, 0x31, 0x65, 0x5c, 0xcc, 0x40, 0x13, 0xb6, 0x93, 0x90, 0x18, 0x03, + 0x2b, 0x41, 0x8c, 0x8a, 0x0d, 0x83, 0x7f, 0xd2, 0xc0, 0x6a, 0x27, 0xf4, 0xbc, 0xf0, 0xd8, 0xfc, + 0xa4, 0x1f, 0xd8, 0x62, 0x1c, 0x61, 0x48, 0x1f, 0xab, 0xfc, 0x61, 0x06, 0x7e, 0xc0, 0xf6, 0x5c, + 0xca, 0x84, 0xca, 0x4f, 0xca, 0x50, 0xae, 0xb2, 0x82, 0x4b, 0x95, 0x55, 0xdb, 0x49, 0x48, 0xa8, + 0xac, 0x04, 0x31, 0x56, 0x94, 0xa2, 0x1c, 0x86, 0x8f, 0xc0, 0xb2, 0xa8, 0xa8, 0x71, 0x77, 0x40, + 0x6f, 0x4a, 0x89, 0xe2, 0xfb, 0x6a, 0x49, 0x30, 0xf9, 0xbd, 0x4e, 0x38, 0x5e, 0x57, 0x2f, 0xbf, + 0x22, 0xaa, 0x1b, 0x65, 0x2b, 0x78, 0x04, 0xe6, 0x29, 0xb1, 0x1c, 0x33, 0x0c, 0xbc, 0x01, 0xfa, + 0xeb, 0xbe, 0x74, 0x76, 0x70, 0xce, 0x31, 0xdc, 0x23, 0x11, 0x25, 0xb6, 0x15, 0x13, 0xc7, 0x20, + 0x96, 0xf3, 0x28, 0xf0, 0x06, 0x23, 0x8e, 0xb5, 0xf7, 0xf2, 0xbf, 0x03, 0x68, 0x28, 0xe7, 0xcd, + 0x77, 0x43, 0xdf, 0x15, 0xcd, 0x3f, 0x1e, 0xc8, 0xbf, 0x03, 0x26, 0x50, 0xa4, 0x19, 0x73, 0x34, + 0x75, 0x00, 0x7f, 0x09, 0xd6, 0x4a, 0x43, 0xa8, 0x6c, 0xc8, 0x7f, 0x13, 0x41, 0xb5, 0xe6, 0x87, + 0xe7, 0x1c, 0xa3, 0x71, 0xd0, 0x83, 0xf1, 0x28, 0xd9, 0xb2, 0xe3, 0x2c, 0x74, 0xad, 0x3a, 0x89, + 0xb6, 0xec, 0xb8, 0xa0, 0x00, 0x69, 0xc6, 0x72, 0x99, 0x84, 0x3f, 0x05, 0x57, 0xd4, 0x0b, 0x98, + 0xa1, 0x2f, 0xf6, 0x65, 0xf3, 0xf8, 0xae, 0xe8, 0x64, 0xe3, 0x40, 0x6a, 0xb0, 0x62, 0xe5, 0x87, + 0x4b, 0xb7, 0x14, 0x5c, 0xa7, 0x1d, 0x03, 0x69, 0x46, 0xe6, 0xaf, 0xf9, 0xf0, 0xc5, 0x97, 0xb5, + 0x99, 0xe1, 0x97, 0xb5, 0x99, 0x17, 0xe7, 0x35, 0x6d, 0x78, 0x5e, 0xd3, 0x7e, 0xff, 0xb2, 0x36, + 0xf3, 0xf9, 0xcb, 0x9a, 0x36, 0x7c, 0x59, 0x9b, 0xf9, 0xf7, 0xcb, 0xda, 0xcc, 0xc7, 0x6f, 0xff, + 0x1f, 0x7f, 0xc0, 0xa8, 0xfb, 0xdf, 0xbe, 0x2c, 0xff, 0x88, 0x79, 0xff, 0x7f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0x16, 0x42, 0xde, 0x46, 0xa6, 0x13, 0x00, 0x00, } func (m *FolderDeviceConfiguration) Marshal() (dAtA []byte, err error) { @@ -383,6 +386,18 @@ func (m *FolderConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0xc0 } + if m.SyncOwnership { + i-- + if m.SyncOwnership { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x2 + i-- + dAtA[i] = 0x98 + } if m.JunctionsAsDirs { i-- if m.JunctionsAsDirs { @@ -817,6 +832,9 @@ func (m *FolderConfiguration) ProtoSize() (n int) { if m.JunctionsAsDirs { n += 3 } + if m.SyncOwnership { + n += 3 + } if m.DeprecatedReadOnly { n += 4 } @@ -1764,6 +1782,26 @@ func (m *FolderConfiguration) Unmarshal(dAtA []byte) error { } } m.JunctionsAsDirs = bool(v != 0) + case 35: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field SyncOwnership", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowFolderconfiguration + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.SyncOwnership = bool(v != 0) case 9000: if wireType != 0 { return fmt.Errorf("proto: wrong wireType = %d for field DeprecatedReadOnly", wireType) diff --git a/lib/db/db_test.go b/lib/db/db_test.go index b76bb1c50..947188c20 100644 --- a/lib/db/db_test.go +++ b/lib/db/db_test.go @@ -212,7 +212,7 @@ func TestUpdate0to3(t *testing.T) { t.Error("Unexpected additional file via sequence", f.FileName()) return true } - if e := haveUpdate0to3[protocol.LocalDeviceID][0]; f.IsEquivalentOptional(e, 0, true, true, 0) { + if e := haveUpdate0to3[protocol.LocalDeviceID][0]; f.IsEquivalentOptional(e, protocol.FileInfoComparison{IgnorePerms: true, IgnoreBlocks: true}) { found = true } else { t.Errorf("Wrong file via sequence, got %v, expected %v", f, e) @@ -281,7 +281,7 @@ func TestUpdate0to3(t *testing.T) { } f := fi.(protocol.FileInfo) delete(need, f.Name) - if !f.IsEquivalentOptional(e, 0, true, true, 0) { + if !f.IsEquivalentOptional(e, protocol.FileInfoComparison{IgnorePerms: true, IgnoreBlocks: true}) { t.Errorf("Wrong needed file, got %v, expected %v", f, e) } } diff --git a/lib/db/structs.pb.go b/lib/db/structs.pb.go index a72e3756b..8703708c4 100644 --- a/lib/db/structs.pb.go +++ b/lib/db/structs.pb.go @@ -122,6 +122,7 @@ type FileInfoTruncated struct { Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions" xml:"permissions"` ModifiedNs int `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3,casttype=int" json:"modifiedNs" xml:"modifiedNs"` RawBlockSize int `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3,casttype=int" json:"blockSize" xml:"blockSize"` + Platform protocol.PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform" xml:"platform"` // see bep.proto LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"localFlags" xml:"localFlags"` VersionHash []byte `protobuf:"bytes,1001,opt,name=version_hash,json=versionHash,proto3" json:"versionHash" xml:"versionHash"` @@ -495,100 +496,102 @@ func init() { func init() { proto.RegisterFile("lib/db/structs.proto", fileDescriptor_5465d80e8cba02e3) } var fileDescriptor_5465d80e8cba02e3 = []byte{ - // 1476 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x4d, 0x6f, 0xdb, 0x46, - 0x13, 0x36, 0x2d, 0xf9, 0x43, 0x2b, 0xf9, 0x8b, 0x79, 0x6d, 0xe8, 0xf5, 0xfb, 0x56, 0xab, 0x6e, - 0x1c, 0x40, 0xfd, 0x80, 0x0c, 0x38, 0x88, 0x51, 0x04, 0x68, 0x83, 0x30, 0xae, 0x13, 0x07, 0x69, - 0x52, 0xac, 0x83, 0xa4, 0x68, 0x0f, 0x82, 0x48, 0xae, 0x65, 0x22, 0x14, 0xa9, 0x72, 0x69, 0x3b, - 0xca, 0xad, 0x97, 0x02, 0xbd, 0x05, 0x41, 0x0f, 0x45, 0x51, 0x14, 0x39, 0xf5, 0x27, 0xf4, 0x17, - 0x14, 0x45, 0x8e, 0x3e, 0x16, 0x3d, 0xb0, 0x88, 0x7d, 0x69, 0x75, 0xd4, 0xa9, 0xe8, 0xa9, 0xd8, - 0xd9, 0xe5, 0x92, 0xb2, 0x91, 0x22, 0x49, 0x7d, 0xd3, 0x3c, 0xf3, 0xcc, 0x88, 0x9c, 0x7d, 0x66, - 0x76, 0x88, 0xfe, 0xe3, 0x7b, 0xf6, 0xaa, 0x6b, 0xaf, 0xf2, 0x38, 0xda, 0x73, 0x62, 0xde, 0xec, - 0x45, 0x61, 0x1c, 0x9a, 0xe3, 0xae, 0xbd, 0x7c, 0x3e, 0x62, 0xbd, 0x90, 0xaf, 0x02, 0x60, 0xef, - 0xed, 0xac, 0x76, 0xc2, 0x4e, 0x08, 0x06, 0xfc, 0x92, 0xc4, 0x65, 0xdc, 0x09, 0xc3, 0x8e, 0xcf, - 0x32, 0x56, 0xec, 0x75, 0x19, 0x8f, 0xdb, 0xdd, 0x9e, 0x22, 0x2c, 0x89, 0xfc, 0xf0, 0xd3, 0x09, - 0xfd, 0x55, 0x9b, 0xa5, 0x78, 0x89, 0x3d, 0x8c, 0xe5, 0x4f, 0xf2, 0xfd, 0x38, 0x2a, 0x6f, 0x7a, - 0x3e, 0xbb, 0xc7, 0x22, 0xee, 0x85, 0x81, 0x79, 0x0b, 0x4d, 0xed, 0xcb, 0x9f, 0x55, 0xa3, 0x6e, - 0x34, 0xca, 0x6b, 0xf3, 0xcd, 0x34, 0x41, 0xf3, 0x1e, 0x73, 0xe2, 0x30, 0xb2, 0xea, 0xcf, 0x12, - 0x3c, 0x36, 0x48, 0x70, 0x4a, 0x1c, 0x26, 0x78, 0xe6, 0x61, 0xd7, 0xbf, 0x4c, 0x94, 0x4d, 0x68, - 0xea, 0x31, 0xd7, 0xd1, 0x94, 0xcb, 0x7c, 0x16, 0x33, 0xb7, 0x3a, 0x5e, 0x37, 0x1a, 0xd3, 0xd6, - 0xff, 0x45, 0x9c, 0x82, 0x74, 0x9c, 0xb2, 0x09, 0x4d, 0x3d, 0xe6, 0x25, 0x11, 0xb7, 0xef, 0x39, - 0x8c, 0x57, 0x0b, 0xf5, 0x42, 0xa3, 0x62, 0xfd, 0x4f, 0xc6, 0x01, 0x34, 0x4c, 0x70, 0x45, 0xc5, - 0x09, 0x1b, 0xc2, 0xc0, 0x61, 0x52, 0x34, 0xe7, 0x05, 0xfb, 0x6d, 0xdf, 0x73, 0x5b, 0x69, 0x78, - 0x11, 0xc2, 0xdf, 0x1a, 0x24, 0x78, 0x56, 0xb9, 0x36, 0x74, 0x96, 0x73, 0x90, 0x65, 0x04, 0x26, - 0xf4, 0x04, 0x8d, 0x7c, 0x61, 0xa0, 0xb2, 0x2a, 0xce, 0x2d, 0x8f, 0xc7, 0xa6, 0x8f, 0xa6, 0xd5, - 0xdb, 0xf1, 0xaa, 0x51, 0x2f, 0x34, 0xca, 0x6b, 0x73, 0x4d, 0xd7, 0x6e, 0xe6, 0x6a, 0x68, 0x5d, - 0x11, 0x05, 0x3a, 0x4a, 0x70, 0x99, 0xb6, 0x0f, 0x14, 0xc6, 0x07, 0x09, 0xd6, 0x71, 0xa7, 0x0a, - 0xf6, 0xe4, 0x70, 0x25, 0xcf, 0xa5, 0x9a, 0x79, 0xb9, 0xf8, 0xcd, 0x53, 0x3c, 0x46, 0xfe, 0x44, - 0x68, 0x41, 0xfc, 0xc1, 0x56, 0xb0, 0x13, 0xde, 0x8d, 0xf6, 0x02, 0xa7, 0x2d, 0x8a, 0xf4, 0x36, - 0x2a, 0x06, 0xed, 0x2e, 0x83, 0x73, 0x2a, 0x59, 0x4b, 0x83, 0x04, 0x83, 0x3d, 0x4c, 0x30, 0x82, - 0xec, 0xc2, 0x20, 0x14, 0x30, 0xc1, 0xe5, 0xde, 0x23, 0x56, 0x2d, 0xd4, 0x8d, 0x46, 0x41, 0x72, - 0x85, 0xad, 0xb9, 0xc2, 0x20, 0x14, 0x30, 0xf3, 0x0a, 0x42, 0xdd, 0xd0, 0xf5, 0x76, 0x3c, 0xe6, - 0xb6, 0x78, 0x75, 0x02, 0x22, 0xea, 0x83, 0x04, 0x97, 0x52, 0x74, 0x7b, 0x98, 0xe0, 0x39, 0x08, - 0xd3, 0x08, 0xa1, 0x99, 0xd7, 0xfc, 0xd1, 0x40, 0x65, 0x9d, 0xc1, 0xee, 0x57, 0x2b, 0x75, 0xa3, - 0x51, 0xb4, 0xbe, 0x36, 0x44, 0x59, 0x7e, 0x4d, 0xf0, 0xc5, 0x8e, 0x17, 0xef, 0xee, 0xd9, 0x4d, - 0x27, 0xec, 0xae, 0xf2, 0x7e, 0xe0, 0xc4, 0xbb, 0x5e, 0xd0, 0xc9, 0xfd, 0xca, 0x8b, 0xb6, 0xb9, - 0xbd, 0x1b, 0x46, 0xf1, 0xd6, 0xc6, 0x20, 0xc1, 0xfa, 0xa1, 0xac, 0xfe, 0x30, 0xc1, 0xf3, 0x23, - 0xff, 0x6f, 0xf5, 0xc9, 0xb7, 0x87, 0x2b, 0xaf, 0x93, 0x98, 0xe6, 0xd2, 0xe6, 0xc5, 0x5f, 0xfa, - 0xf7, 0xe2, 0xbf, 0x8c, 0xa6, 0x39, 0xfb, 0x7c, 0x8f, 0x05, 0x0e, 0xab, 0x22, 0xa8, 0x62, 0x4d, - 0xa8, 0x20, 0xc5, 0x86, 0x09, 0x9e, 0x95, 0xb5, 0x57, 0x00, 0xa1, 0xda, 0x67, 0xde, 0x41, 0xb3, - 0xbc, 0xdf, 0xf5, 0xbd, 0xe0, 0x41, 0x2b, 0x6e, 0x47, 0x1d, 0x16, 0x57, 0x17, 0xe0, 0x94, 0x1b, - 0x83, 0x04, 0xcf, 0x28, 0xcf, 0x5d, 0x70, 0x68, 0x1d, 0x8f, 0xa0, 0x84, 0x8e, 0xb2, 0xcc, 0x6b, - 0xa8, 0x6c, 0xfb, 0xa1, 0xf3, 0x80, 0xb7, 0x76, 0xdb, 0x7c, 0xb7, 0x6a, 0xd6, 0x8d, 0x46, 0xc5, - 0x22, 0xa2, 0xac, 0x12, 0xbe, 0xd1, 0xe6, 0xbb, 0xba, 0xac, 0x19, 0x44, 0x68, 0xce, 0x6f, 0x7e, - 0x80, 0x4a, 0x2c, 0x70, 0xa2, 0x7e, 0x4f, 0x34, 0xf4, 0x39, 0x48, 0x01, 0xc2, 0xd0, 0xa0, 0x16, - 0x86, 0x46, 0x08, 0xcd, 0xbc, 0xa6, 0x85, 0x8a, 0x71, 0xbf, 0xc7, 0x60, 0x16, 0xcc, 0xae, 0x2d, - 0x65, 0xc5, 0xd5, 0xe2, 0xee, 0xf7, 0x98, 0x54, 0xa7, 0xe0, 0x69, 0x75, 0x0a, 0x83, 0x50, 0xc0, - 0xcc, 0x4d, 0x54, 0xee, 0xb1, 0xa8, 0xeb, 0x71, 0xd9, 0x82, 0xc5, 0xba, 0xd1, 0x98, 0xb1, 0x56, - 0x06, 0x09, 0xce, 0xc3, 0xc3, 0x04, 0x2f, 0x40, 0x64, 0x0e, 0x23, 0x34, 0xcf, 0x30, 0x6f, 0xe6, - 0x34, 0x1a, 0xf0, 0x6a, 0xb9, 0x6e, 0x34, 0x26, 0x60, 0x4e, 0x68, 0x41, 0xdc, 0xe6, 0xa7, 0x74, - 0x76, 0x9b, 0x93, 0xbf, 0x12, 0x5c, 0xf0, 0x82, 0x98, 0xe6, 0x68, 0xe6, 0x0e, 0x92, 0x55, 0x6a, - 0x41, 0x8f, 0xcd, 0x40, 0xaa, 0xeb, 0x47, 0x09, 0xae, 0xd0, 0xf6, 0x81, 0x25, 0x1c, 0xdb, 0xde, - 0x23, 0x26, 0x0a, 0x65, 0xa7, 0x86, 0x2e, 0x94, 0x46, 0xd2, 0xc4, 0x4f, 0x0e, 0x57, 0x46, 0xc2, - 0x68, 0x16, 0x64, 0x6e, 0xa0, 0xb2, 0x1f, 0x3a, 0x6d, 0xbf, 0xb5, 0xe3, 0xb7, 0x3b, 0xbc, 0xfa, - 0xfb, 0x14, 0xbc, 0x3c, 0x9c, 0x22, 0xe0, 0x9b, 0x02, 0xd6, 0x0f, 0x9d, 0x41, 0x84, 0xe6, 0xfc, - 0xe6, 0x0d, 0x54, 0x51, 0x12, 0x95, 0x5a, 0xf8, 0x63, 0x0a, 0x4e, 0x12, 0x6a, 0xa8, 0x1c, 0x4a, - 0x0d, 0x0b, 0x79, 0x65, 0x4b, 0x39, 0xe4, 0x19, 0xf9, 0xf1, 0x3e, 0xf9, 0x2a, 0xe3, 0x9d, 0xa2, - 0x29, 0x35, 0x65, 0xab, 0x53, 0x10, 0xf7, 0xde, 0x51, 0x82, 0x11, 0x6d, 0x1f, 0x6c, 0x49, 0x54, - 0x64, 0x51, 0x04, 0x9d, 0x45, 0xd9, 0x62, 0x56, 0xe6, 0x98, 0x34, 0xe5, 0x89, 0x8e, 0x09, 0xc2, - 0x56, 0x5e, 0x1a, 0xd3, 0x90, 0x1a, 0x3a, 0x26, 0x08, 0x3f, 0x1e, 0x11, 0x87, 0xec, 0x98, 0x11, - 0x94, 0xd0, 0x51, 0x96, 0x1a, 0xbd, 0xf7, 0x51, 0x09, 0x8e, 0x02, 0x66, 0xff, 0x4d, 0x34, 0x29, - 0xbb, 0x41, 0x4d, 0xfe, 0x73, 0x99, 0x82, 0x81, 0x24, 0x24, 0x6c, 0xbd, 0xa1, 0x26, 0x84, 0xa2, - 0x0e, 0x13, 0x5c, 0xce, 0x4e, 0x9a, 0x50, 0x05, 0x93, 0x1f, 0x0c, 0xb4, 0xb8, 0x15, 0xb8, 0x5e, - 0xc4, 0x9c, 0x58, 0xd5, 0x93, 0xf1, 0x3b, 0x81, 0xdf, 0x3f, 0x9b, 0x56, 0x3d, 0xb3, 0x43, 0x26, - 0xdf, 0x15, 0xd1, 0xe4, 0xb5, 0x70, 0x2f, 0x88, 0xb9, 0x79, 0x09, 0x4d, 0xec, 0x78, 0x3e, 0xe3, - 0x70, 0xe5, 0x4c, 0x58, 0x78, 0x90, 0x60, 0x09, 0xe8, 0x97, 0x04, 0x4b, 0xf7, 0x88, 0x74, 0x9a, - 0x1f, 0xa1, 0xb2, 0x7c, 0xcf, 0x30, 0xf2, 0x18, 0x87, 0xee, 0x9f, 0xb0, 0xde, 0x11, 0x4f, 0x92, - 0x83, 0xf5, 0x93, 0xe4, 0x30, 0x9d, 0x28, 0x4f, 0x34, 0xaf, 0xa2, 0x69, 0x35, 0xdb, 0x38, 0xdc, - 0x67, 0x13, 0xd6, 0x05, 0x98, 0xab, 0x0a, 0xcb, 0xe6, 0xaa, 0x02, 0x74, 0x16, 0x4d, 0x31, 0xdf, - 0xcf, 0x84, 0x5b, 0x84, 0x0c, 0xe7, 0xff, 0x49, 0xb8, 0x69, 0xbc, 0xd6, 0x6f, 0x13, 0x4d, 0xd8, - 0xfd, 0x98, 0xa5, 0x97, 0x63, 0x55, 0xd4, 0x01, 0x80, 0xec, 0xb0, 0x85, 0x45, 0xa8, 0x44, 0x47, - 0x6e, 0x82, 0xc9, 0x57, 0xbc, 0x09, 0xb6, 0x51, 0x49, 0xee, 0x32, 0x2d, 0xcf, 0x85, 0x4b, 0xa0, - 0x62, 0xad, 0x1f, 0x25, 0x78, 0x5a, 0xee, 0x27, 0x70, 0x33, 0x4e, 0x4b, 0xc2, 0x96, 0xab, 0x13, - 0xa5, 0x80, 0xe8, 0x16, 0xcd, 0xa4, 0x9a, 0x27, 0x24, 0x96, 0x1f, 0x24, 0xe6, 0xeb, 0xcc, 0x11, - 0xd5, 0x20, 0x5f, 0x1a, 0xa8, 0x24, 0xe5, 0xb1, 0xcd, 0x62, 0xf3, 0x2a, 0x9a, 0x74, 0xc0, 0x50, - 0x1d, 0x82, 0xc4, 0x6e, 0x24, 0xdd, 0x59, 0x63, 0x48, 0x86, 0xae, 0x15, 0x98, 0x84, 0x2a, 0x58, - 0x0c, 0x15, 0x27, 0x62, 0xed, 0x74, 0x67, 0x2c, 0xc8, 0xa1, 0xa2, 0x20, 0x7d, 0x36, 0xca, 0x26, - 0x34, 0xf5, 0x90, 0xaf, 0xc6, 0xd1, 0x62, 0x6e, 0x0b, 0xdb, 0x60, 0xbd, 0x88, 0xc9, 0x45, 0xe9, - 0x6c, 0x77, 0xda, 0x35, 0x34, 0x29, 0xeb, 0x08, 0x8f, 0x57, 0xb1, 0x96, 0xc5, 0x2b, 0x49, 0xe4, - 0xd4, 0x66, 0xaa, 0x70, 0xf1, 0x4e, 0xe9, 0xc0, 0x2b, 0x64, 0x83, 0xf2, 0x45, 0x23, 0x2e, 0x1b, - 0x6a, 0xeb, 0xa3, 0x3a, 0x7d, 0xd9, 0x01, 0x4b, 0x0e, 0xd0, 0x62, 0x6e, 0x67, 0xcd, 0x95, 0xe2, - 0x93, 0x53, 0xdb, 0xeb, 0x7f, 0x4f, 0x6c, 0xaf, 0x19, 0xd9, 0x7a, 0x53, 0x15, 0xe5, 0xc5, 0x8b, - 0xeb, 0xa9, 0x4d, 0xf5, 0xe7, 0x71, 0x34, 0x7b, 0xc7, 0xe6, 0x2c, 0xda, 0x67, 0xee, 0x66, 0xe8, - 0xbb, 0x2c, 0x32, 0x6f, 0xa3, 0xa2, 0xf8, 0x2e, 0x51, 0xa5, 0x5f, 0x6e, 0xca, 0x8f, 0x96, 0x66, - 0xfa, 0xd1, 0xd2, 0xbc, 0x9b, 0x7e, 0xb4, 0x58, 0x35, 0xf5, 0x7f, 0xc0, 0xcf, 0x2e, 0x7f, 0xaf, - 0xcb, 0xc8, 0xe3, 0xdf, 0xb0, 0x41, 0x01, 0x17, 0xcd, 0xe7, 0xb7, 0x6d, 0xe6, 0x43, 0xf9, 0x4b, - 0xb2, 0xf9, 0x00, 0xd0, 0x82, 0x02, 0x8b, 0x50, 0x89, 0x9a, 0x9f, 0xa1, 0x85, 0x88, 0x39, 0xcc, - 0xdb, 0x67, 0xad, 0x6c, 0x79, 0x91, 0xa7, 0xd0, 0x1c, 0x24, 0x78, 0x5e, 0x39, 0x3f, 0xcc, 0xed, - 0x30, 0x4b, 0x90, 0xe6, 0xa4, 0x83, 0xd0, 0x53, 0x5c, 0xf3, 0x3e, 0x9a, 0x8f, 0x58, 0x37, 0x8c, - 0xf3, 0xb9, 0xe5, 0x49, 0xbd, 0x3b, 0x48, 0xf0, 0x9c, 0xf4, 0xe5, 0x53, 0x2f, 0xaa, 0xd4, 0x23, - 0x38, 0xa1, 0x27, 0x99, 0xe4, 0x27, 0x23, 0x2b, 0xa4, 0x6c, 0xe0, 0x33, 0x2f, 0x64, 0xfa, 0xfd, - 0x30, 0xfe, 0x12, 0xdf, 0x0f, 0xeb, 0x68, 0xaa, 0xed, 0xba, 0x11, 0xe3, 0x72, 0xe4, 0x96, 0xa4, - 0x10, 0x15, 0xa4, 0x65, 0xa1, 0x6c, 0x42, 0x53, 0x8f, 0x75, 0xfd, 0xd9, 0xf3, 0xda, 0xd8, 0xe1, - 0xf3, 0xda, 0xd8, 0xb3, 0xa3, 0x9a, 0x71, 0x78, 0x54, 0x33, 0x1e, 0x1f, 0xd7, 0xc6, 0x9e, 0x1e, - 0xd7, 0x8c, 0xc3, 0xe3, 0xda, 0xd8, 0x2f, 0xc7, 0xb5, 0xb1, 0x4f, 0x2f, 0xbc, 0xc4, 0xd2, 0xee, - 0xda, 0xf6, 0x24, 0xbc, 0xe6, 0xc5, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb3, 0xa4, 0xea, 0xfc, - 0x33, 0x0f, 0x00, 0x00, + // 1510 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6f, 0xdb, 0x46, + 0x16, 0x37, 0x2d, 0xd9, 0x96, 0x46, 0xf2, 0x17, 0xb3, 0x36, 0xb8, 0xde, 0x5d, 0x8d, 0x76, 0xe2, + 0x00, 0xda, 0x0f, 0xc8, 0x80, 0x83, 0x18, 0x8b, 0x00, 0xdb, 0x20, 0x8c, 0xeb, 0xc4, 0x41, 0x9a, + 0x04, 0xe3, 0x20, 0x29, 0xda, 0x83, 0xc0, 0x8f, 0xb1, 0x4c, 0x84, 0x22, 0x55, 0x92, 0xb6, 0xa3, + 0xdc, 0x7a, 0x29, 0xd0, 0x5b, 0x10, 0xf4, 0x50, 0x14, 0x45, 0x91, 0x53, 0xff, 0x84, 0xfe, 0x05, + 0x45, 0x91, 0xa3, 0x8f, 0x45, 0x0f, 0x2c, 0x62, 0x5f, 0x5a, 0x1d, 0x75, 0xec, 0xa9, 0x98, 0x37, + 0xc3, 0x21, 0x65, 0x23, 0x45, 0x92, 0xfa, 0xc6, 0xf7, 0x7b, 0xbf, 0xf7, 0x24, 0xbe, 0xf9, 0xbd, + 0x37, 0x8f, 0xe8, 0x2f, 0xbe, 0x67, 0xaf, 0xb9, 0xf6, 0x5a, 0x9c, 0x44, 0xfb, 0x4e, 0x12, 0xb7, + 0xfb, 0x51, 0x98, 0x84, 0xfa, 0xa4, 0x6b, 0xaf, 0x5c, 0x8c, 0x58, 0x3f, 0x8c, 0xd7, 0x00, 0xb0, + 0xf7, 0x77, 0xd7, 0xba, 0x61, 0x37, 0x04, 0x03, 0x9e, 0x04, 0x71, 0x05, 0x77, 0xc3, 0xb0, 0xeb, + 0xb3, 0x9c, 0x95, 0x78, 0x3d, 0x16, 0x27, 0x56, 0xaf, 0x2f, 0x09, 0xcb, 0x3c, 0x3f, 0x3c, 0x3a, + 0xa1, 0xbf, 0x66, 0xb3, 0x0c, 0xaf, 0xb2, 0x27, 0x89, 0x78, 0x24, 0xdf, 0x4c, 0xa2, 0xda, 0x96, + 0xe7, 0xb3, 0x87, 0x2c, 0x8a, 0xbd, 0x30, 0xd0, 0xef, 0xa0, 0x99, 0x03, 0xf1, 0x68, 0x68, 0x4d, + 0xad, 0x55, 0x5b, 0x5f, 0x68, 0x67, 0x09, 0xda, 0x0f, 0x99, 0x93, 0x84, 0x91, 0xd9, 0x7c, 0x99, + 0xe2, 0x89, 0x61, 0x8a, 0x33, 0xe2, 0x28, 0xc5, 0xb3, 0x4f, 0x7a, 0xfe, 0x55, 0x22, 0x6d, 0x42, + 0x33, 0x8f, 0xbe, 0x81, 0x66, 0x5c, 0xe6, 0xb3, 0x84, 0xb9, 0xc6, 0x64, 0x53, 0x6b, 0x55, 0xcc, + 0xbf, 0xf3, 0x38, 0x09, 0xa9, 0x38, 0x69, 0x13, 0x9a, 0x79, 0xf4, 0x2b, 0x3c, 0xee, 0xc0, 0x73, + 0x58, 0x6c, 0x94, 0x9a, 0xa5, 0x56, 0xdd, 0xfc, 0x9b, 0x88, 0x03, 0x68, 0x94, 0xe2, 0xba, 0x8c, + 0xe3, 0x36, 0x84, 0x81, 0x43, 0xa7, 0x68, 0xde, 0x0b, 0x0e, 0x2c, 0xdf, 0x73, 0x3b, 0x59, 0x78, + 0x19, 0xc2, 0xff, 0x35, 0x4c, 0xf1, 0x9c, 0x74, 0x6d, 0xaa, 0x2c, 0x17, 0x20, 0xcb, 0x18, 0x4c, + 0xe8, 0x29, 0x1a, 0xf9, 0x54, 0x43, 0x35, 0x59, 0x9c, 0x3b, 0x5e, 0x9c, 0xe8, 0x3e, 0xaa, 0xc8, + 0xb7, 0x8b, 0x0d, 0xad, 0x59, 0x6a, 0xd5, 0xd6, 0xe7, 0xdb, 0xae, 0xdd, 0x2e, 0xd4, 0xd0, 0xbc, + 0xc6, 0x0b, 0x74, 0x9c, 0xe2, 0x1a, 0xb5, 0x0e, 0x25, 0x16, 0x0f, 0x53, 0xac, 0xe2, 0xce, 0x14, + 0xec, 0xf9, 0xd1, 0x6a, 0x91, 0x4b, 0x15, 0xf3, 0x6a, 0xf9, 0xcb, 0x17, 0x78, 0x82, 0x1c, 0xd5, + 0xd0, 0x22, 0xff, 0x81, 0xed, 0x60, 0x37, 0x7c, 0x10, 0xed, 0x07, 0x8e, 0xc5, 0x8b, 0xf4, 0x6f, + 0x54, 0x0e, 0xac, 0x1e, 0x83, 0x73, 0xaa, 0x9a, 0xcb, 0xc3, 0x14, 0x83, 0x3d, 0x4a, 0x31, 0x82, + 0xec, 0xdc, 0x20, 0x14, 0x30, 0xce, 0x8d, 0xbd, 0xa7, 0xcc, 0x28, 0x35, 0xb5, 0x56, 0x49, 0x70, + 0xb9, 0xad, 0xb8, 0xdc, 0x20, 0x14, 0x30, 0xfd, 0x1a, 0x42, 0xbd, 0xd0, 0xf5, 0x76, 0x3d, 0xe6, + 0x76, 0x62, 0x63, 0x0a, 0x22, 0x9a, 0xc3, 0x14, 0x57, 0x33, 0x74, 0x67, 0x94, 0xe2, 0x79, 0x08, + 0x53, 0x08, 0xa1, 0xb9, 0x57, 0xff, 0x4e, 0x43, 0x35, 0x95, 0xc1, 0x1e, 0x18, 0xf5, 0xa6, 0xd6, + 0x2a, 0x9b, 0x5f, 0x68, 0xbc, 0x2c, 0x3f, 0xa5, 0xf8, 0x72, 0xd7, 0x4b, 0xf6, 0xf6, 0xed, 0xb6, + 0x13, 0xf6, 0xd6, 0xe2, 0x41, 0xe0, 0x24, 0x7b, 0x5e, 0xd0, 0x2d, 0x3c, 0x15, 0x45, 0xdb, 0xde, + 0xd9, 0x0b, 0xa3, 0x64, 0x7b, 0x73, 0x98, 0x62, 0xf5, 0xa7, 0xcc, 0xc1, 0x28, 0xc5, 0x0b, 0x63, + 0xbf, 0x6f, 0x0e, 0xc8, 0x57, 0x47, 0xab, 0xef, 0x92, 0x98, 0x16, 0xd2, 0x16, 0xc5, 0x5f, 0xfd, + 0xf3, 0xe2, 0xbf, 0x8a, 0x2a, 0x31, 0xfb, 0x64, 0x9f, 0x05, 0x0e, 0x33, 0x10, 0x54, 0xb1, 0xc1, + 0x55, 0x90, 0x61, 0xa3, 0x14, 0xcf, 0x89, 0xda, 0x4b, 0x80, 0x50, 0xe5, 0xd3, 0xef, 0xa1, 0xb9, + 0x78, 0xd0, 0xf3, 0xbd, 0xe0, 0x71, 0x27, 0xb1, 0xa2, 0x2e, 0x4b, 0x8c, 0x45, 0x38, 0xe5, 0xd6, + 0x30, 0xc5, 0xb3, 0xd2, 0xf3, 0x00, 0x1c, 0x4a, 0xc7, 0x63, 0x28, 0xa1, 0xe3, 0x2c, 0xfd, 0x06, + 0xaa, 0xd9, 0x7e, 0xe8, 0x3c, 0x8e, 0x3b, 0x7b, 0x56, 0xbc, 0x67, 0xe8, 0x4d, 0xad, 0x55, 0x37, + 0x09, 0x2f, 0xab, 0x80, 0x6f, 0x59, 0xf1, 0x9e, 0x2a, 0x6b, 0x0e, 0x11, 0x5a, 0xf0, 0xeb, 0xef, + 0xa1, 0x2a, 0x0b, 0x9c, 0x68, 0xd0, 0xe7, 0x0d, 0x7d, 0x01, 0x52, 0x80, 0x30, 0x14, 0xa8, 0x84, + 0xa1, 0x10, 0x42, 0x73, 0xaf, 0x6e, 0xa2, 0x72, 0x32, 0xe8, 0x33, 0x98, 0x05, 0x73, 0xeb, 0xcb, + 0x79, 0x71, 0x95, 0xb8, 0x07, 0x7d, 0x26, 0xd4, 0xc9, 0x79, 0x4a, 0x9d, 0xdc, 0x20, 0x14, 0x30, + 0x7d, 0x0b, 0xd5, 0xfa, 0x2c, 0xea, 0x79, 0xb1, 0x68, 0xc1, 0x72, 0x53, 0x6b, 0xcd, 0x9a, 0xab, + 0xc3, 0x14, 0x17, 0xe1, 0x51, 0x8a, 0x17, 0x21, 0xb2, 0x80, 0x11, 0x5a, 0x64, 0xe8, 0xb7, 0x0b, + 0x1a, 0x0d, 0x62, 0xa3, 0xd6, 0xd4, 0x5a, 0x53, 0x30, 0x27, 0x94, 0x20, 0xee, 0xc6, 0x67, 0x74, + 0x76, 0x37, 0x26, 0xbf, 0xa5, 0xb8, 0xe4, 0x05, 0x09, 0x2d, 0xd0, 0xf4, 0x5d, 0x24, 0xaa, 0xd4, + 0x81, 0x1e, 0x9b, 0x85, 0x54, 0x37, 0x8f, 0x53, 0x5c, 0xa7, 0xd6, 0xa1, 0xc9, 0x1d, 0x3b, 0xde, + 0x53, 0xc6, 0x0b, 0x65, 0x67, 0x86, 0x2a, 0x94, 0x42, 0xb2, 0xc4, 0xcf, 0x8f, 0x56, 0xc7, 0xc2, + 0x68, 0x1e, 0xa4, 0x3f, 0x44, 0x95, 0xbe, 0x6f, 0x25, 0xbb, 0x61, 0xd4, 0x33, 0xe6, 0x40, 0xa0, + 0x85, 0x1a, 0xde, 0x97, 0x9e, 0x4d, 0x2b, 0xb1, 0x4c, 0x22, 0x65, 0xaa, 0xf8, 0x4a, 0x6d, 0x19, + 0x40, 0xa8, 0xf2, 0xe9, 0x9b, 0xa8, 0xe6, 0x87, 0x8e, 0xe5, 0x77, 0x76, 0x7d, 0xab, 0x1b, 0x1b, + 0xbf, 0xcc, 0x40, 0x51, 0x41, 0x1d, 0x80, 0x6f, 0x71, 0x58, 0x15, 0x23, 0x87, 0x08, 0x2d, 0xf8, + 0xf5, 0x5b, 0xa8, 0x2e, 0xa5, 0x2f, 0x34, 0xf6, 0xeb, 0x0c, 0x28, 0x04, 0xce, 0x46, 0x3a, 0xa4, + 0xca, 0x16, 0x8b, 0x1d, 0x23, 0x64, 0x56, 0x64, 0x14, 0xaf, 0x8d, 0xe9, 0xb7, 0xb9, 0x36, 0x28, + 0x9a, 0x91, 0xd3, 0xdb, 0x98, 0x81, 0xb8, 0xff, 0x1d, 0xa7, 0x18, 0x51, 0xeb, 0x70, 0x5b, 0xa0, + 0x3c, 0x8b, 0x24, 0xa8, 0x2c, 0xd2, 0xe6, 0x33, 0xb8, 0xc0, 0xa4, 0x19, 0x8f, 0x77, 0x62, 0x10, + 0x76, 0x8a, 0x92, 0xab, 0x40, 0x6a, 0xe8, 0xc4, 0x20, 0xbc, 0x3f, 0x26, 0x3a, 0xd1, 0x89, 0x63, + 0x28, 0xa1, 0xe3, 0x2c, 0x39, 0xd2, 0x1f, 0xa1, 0x2a, 0x1c, 0x31, 0xdc, 0x29, 0xb7, 0xd1, 0xb4, + 0xe8, 0x32, 0x79, 0xa3, 0x5c, 0xc8, 0x4f, 0x15, 0x48, 0xbc, 0x35, 0xcc, 0x7f, 0xc8, 0x23, 0x95, + 0xd4, 0x51, 0x8a, 0x6b, 0xb9, 0x82, 0x08, 0x95, 0x30, 0xf9, 0x56, 0x43, 0x4b, 0xdb, 0x81, 0xeb, + 0x45, 0xcc, 0x49, 0x64, 0x3d, 0x59, 0x7c, 0x2f, 0xf0, 0x07, 0xe7, 0x33, 0x02, 0xce, 0xed, 0x90, + 0xc9, 0xd7, 0x65, 0x34, 0x7d, 0x23, 0xdc, 0x0f, 0x92, 0x58, 0xbf, 0x82, 0xa6, 0x76, 0x3d, 0x9f, + 0xc5, 0x70, 0x95, 0x4d, 0x99, 0x78, 0x98, 0x62, 0x01, 0xa8, 0x97, 0x04, 0x4b, 0xf5, 0x9e, 0x70, + 0xea, 0x1f, 0xa0, 0x9a, 0x78, 0xcf, 0x30, 0xf2, 0x58, 0x0c, 0x53, 0x65, 0xca, 0xfc, 0x0f, 0xff, + 0x27, 0x05, 0x58, 0xfd, 0x93, 0x02, 0xa6, 0x12, 0x15, 0x89, 0xfa, 0x75, 0x54, 0x91, 0x33, 0x33, + 0x86, 0x7b, 0x72, 0xca, 0xbc, 0x04, 0xf3, 0x5a, 0x62, 0xf9, 0xbc, 0x96, 0x80, 0xca, 0xa2, 0x28, + 0xfa, 0xff, 0x73, 0xe1, 0x96, 0x21, 0xc3, 0xc5, 0x3f, 0x12, 0x6e, 0x16, 0xaf, 0xf4, 0xdb, 0x46, + 0x53, 0xf6, 0x20, 0x61, 0xd9, 0xa5, 0x6b, 0xf0, 0x3a, 0x00, 0x90, 0x1f, 0x36, 0xb7, 0x08, 0x15, + 0xe8, 0xd8, 0x0d, 0x33, 0xfd, 0x96, 0x37, 0xcc, 0x0e, 0xaa, 0x8a, 0x1d, 0xa9, 0xe3, 0xb9, 0x70, + 0xb9, 0xd4, 0xcd, 0x8d, 0xe3, 0x14, 0x57, 0xc4, 0xde, 0x03, 0x37, 0x6e, 0x45, 0x10, 0xb6, 0x5d, + 0x95, 0x28, 0x03, 0x78, 0xb7, 0x28, 0x26, 0x55, 0x3c, 0x2e, 0xb1, 0xe2, 0x20, 0xd1, 0xdf, 0x65, + 0x8e, 0xc8, 0x06, 0xf9, 0x4c, 0x43, 0x55, 0x21, 0x8f, 0x1d, 0x96, 0xe8, 0xd7, 0xd1, 0xb4, 0x03, + 0x86, 0xec, 0x10, 0xc4, 0x77, 0x2e, 0xe1, 0xce, 0x1b, 0x43, 0x30, 0x54, 0xad, 0xc0, 0x24, 0x54, + 0xc2, 0x7c, 0xa8, 0x38, 0x11, 0xb3, 0xb2, 0x5d, 0xb4, 0x24, 0x86, 0x8a, 0x84, 0xd4, 0xd9, 0x48, + 0x9b, 0xd0, 0xcc, 0x43, 0x3e, 0x9f, 0x44, 0x4b, 0x85, 0xed, 0x6e, 0x93, 0xf5, 0x23, 0x26, 0x16, + 0xb0, 0xf3, 0xdd, 0x95, 0xd7, 0xd1, 0xb4, 0xa8, 0x23, 0xfc, 0xbd, 0xba, 0xb9, 0xc2, 0x5f, 0x49, + 0x20, 0x67, 0x36, 0x5e, 0x89, 0xf3, 0x77, 0xca, 0x06, 0x5e, 0x29, 0x1f, 0x94, 0xaf, 0x1b, 0x71, + 0xf9, 0x50, 0xdb, 0x18, 0xd7, 0xe9, 0x9b, 0x0e, 0x58, 0x72, 0x88, 0x96, 0x0a, 0xbb, 0x70, 0xa1, + 0x14, 0x1f, 0x9e, 0xd9, 0x8a, 0xff, 0x7a, 0x6a, 0x2b, 0xce, 0xc9, 0xe6, 0x3f, 0xb3, 0xcb, 0xe9, + 0xb5, 0x0b, 0xf1, 0x99, 0x0d, 0xf8, 0x87, 0x49, 0x34, 0x77, 0xcf, 0x8e, 0x59, 0x74, 0xc0, 0xdc, + 0xad, 0xd0, 0x77, 0x59, 0xa4, 0xdf, 0x45, 0x65, 0xfe, 0xbd, 0x23, 0x4b, 0xbf, 0xd2, 0x16, 0x1f, + 0x43, 0xed, 0xec, 0x63, 0xa8, 0xfd, 0x20, 0xfb, 0x18, 0x32, 0x1b, 0xf2, 0xf7, 0x80, 0x9f, 0x2f, + 0x15, 0x5e, 0x8f, 0x91, 0x67, 0x3f, 0x63, 0x8d, 0x02, 0xce, 0x9b, 0xcf, 0xb7, 0x6c, 0xe6, 0x43, + 0xf9, 0xab, 0xa2, 0xf9, 0x00, 0x50, 0x82, 0x02, 0x8b, 0x50, 0x81, 0xea, 0x1f, 0xa3, 0xc5, 0x88, + 0x39, 0xcc, 0x3b, 0x60, 0x9d, 0x7c, 0x29, 0x12, 0xa7, 0xd0, 0x1e, 0xa6, 0x78, 0x41, 0x3a, 0xdf, + 0x2f, 0xec, 0x46, 0xcb, 0x90, 0xe6, 0xb4, 0x83, 0xd0, 0x33, 0x5c, 0xfd, 0x11, 0x5a, 0x88, 0x58, + 0x2f, 0x4c, 0x8a, 0xb9, 0xc5, 0x49, 0xfd, 0x77, 0x98, 0xe2, 0x79, 0xe1, 0x2b, 0xa6, 0x5e, 0x92, + 0xa9, 0xc7, 0x70, 0x42, 0x4f, 0x33, 0xc9, 0xf7, 0x5a, 0x5e, 0x48, 0xd1, 0xc0, 0xe7, 0x5e, 0xc8, + 0xec, 0xbb, 0x64, 0xf2, 0x0d, 0xbe, 0x4b, 0x36, 0xd0, 0x8c, 0xe5, 0xba, 0x11, 0x8b, 0xc5, 0xc8, + 0xad, 0x0a, 0x21, 0x4a, 0x48, 0xc9, 0x42, 0xda, 0x84, 0x66, 0x1e, 0xf3, 0xe6, 0xcb, 0x57, 0x8d, + 0x89, 0xa3, 0x57, 0x8d, 0x89, 0x97, 0xc7, 0x0d, 0xed, 0xe8, 0xb8, 0xa1, 0x3d, 0x3b, 0x69, 0x4c, + 0xbc, 0x38, 0x69, 0x68, 0x47, 0x27, 0x8d, 0x89, 0x1f, 0x4f, 0x1a, 0x13, 0x1f, 0x5d, 0x7a, 0x83, + 0x8f, 0x01, 0xd7, 0xb6, 0xa7, 0xe1, 0x35, 0x2f, 0xff, 0x1e, 0x00, 0x00, 0xff, 0xff, 0x95, 0x1d, + 0x77, 0x00, 0x8b, 0x0f, 0x00, 0x00, } func (m *FileVersion) Marshal() (dAtA []byte, err error) { @@ -752,6 +755,16 @@ func (m *FileInfoTruncated) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x8a } + { + size, err := m.Platform.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintStructs(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 if m.RawBlockSize != 0 { i = encodeVarintStructs(dAtA, i, uint64(m.RawBlockSize)) i-- @@ -1175,12 +1188,12 @@ func (m *ObservedFolder) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err4 != nil { - return 0, err4 + n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err5 != nil { + return 0, err5 } - i -= n4 - i = encodeVarintStructs(dAtA, i, uint64(n4)) + i -= n5 + i = encodeVarintStructs(dAtA, i, uint64(n5)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -1220,12 +1233,12 @@ func (m *ObservedDevice) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x12 } - n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) - if err5 != nil { - return 0, err5 + n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):]) + if err6 != nil { + return 0, err6 } - i -= n5 - i = encodeVarintStructs(dAtA, i, uint64(n5)) + i -= n6 + i = encodeVarintStructs(dAtA, i, uint64(n6)) i-- dAtA[i] = 0xa return len(dAtA) - i, nil @@ -1328,6 +1341,8 @@ func (m *FileInfoTruncated) ProtoSize() (n int) { if m.RawBlockSize != 0 { n += 1 + sovStructs(uint64(m.RawBlockSize)) } + l = m.Platform.ProtoSize() + n += 1 + l + sovStructs(uint64(l)) l = len(m.SymlinkTarget) if l > 0 { n += 2 + l + sovStructs(uint64(l)) @@ -2073,6 +2088,39 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error { break } } + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Platform", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStructs + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthStructs + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthStructs + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Platform.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 17: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field SymlinkTarget", wireType) diff --git a/lib/fs/basicfs.go b/lib/fs/basicfs.go index 9ace634a8..a6e2b17e7 100644 --- a/lib/fs/basicfs.go +++ b/lib/fs/basicfs.go @@ -129,14 +129,6 @@ func (f *BasicFilesystem) Chmod(name string, mode FileMode) error { return os.Chmod(name, os.FileMode(mode)) } -func (f *BasicFilesystem) Lchown(name string, uid, gid int) error { - name, err := f.rooted(name) - if err != nil { - return err - } - return os.Lchown(name, uid, gid) -} - func (f *BasicFilesystem) Chtimes(name string, atime time.Time, mtime time.Time) error { name, err := f.rooted(name) if err != nil { diff --git a/lib/fs/basicfs_platformdata_unix.go b/lib/fs/basicfs_platformdata_unix.go new file mode 100644 index 000000000..f7d567692 --- /dev/null +++ b/lib/fs/basicfs_platformdata_unix.go @@ -0,0 +1,18 @@ +// Copyright (C) 2022 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +//go:build !windows +// +build !windows + +package fs + +import ( + "github.com/syncthing/syncthing/lib/protocol" +) + +func (f *BasicFilesystem) PlatformData(name string) (protocol.PlatformData, error) { + return unixPlatformData(f, name) +} diff --git a/lib/fs/basicfs_platformdata_windows.go b/lib/fs/basicfs_platformdata_windows.go new file mode 100644 index 000000000..e1c14804a --- /dev/null +++ b/lib/fs/basicfs_platformdata_windows.go @@ -0,0 +1,69 @@ +// Copyright (C) 2022 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package fs + +import ( + "fmt" + "os/user" + + "github.com/syncthing/syncthing/lib/protocol" + "golang.org/x/sys/windows" +) + +func (f *BasicFilesystem) PlatformData(name string) (protocol.PlatformData, error) { + rootedName, err := f.rooted(name) + if err != nil { + return protocol.PlatformData{}, fmt.Errorf("rooted for %s: %w", name, err) + } + hdl, err := openReadOnlyWithBackupSemantics(rootedName) + if err != nil { + return protocol.PlatformData{}, fmt.Errorf("open %s: %w", rootedName, err) + } + defer windows.Close(hdl) + + // GetSecurityInfo returns an owner SID. + sd, err := windows.GetSecurityInfo(hdl, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION) + if err != nil { + return protocol.PlatformData{}, fmt.Errorf("get security info for %s: %w", rootedName, err) + } + owner, _, err := sd.Owner() + if err != nil { + return protocol.PlatformData{}, fmt.Errorf("get owner for %s: %w", rootedName, err) + } + + // The owner SID might represent a user or a group. We try to look it up + // as both, and set the appropriate fields in the OS data. + pd := &protocol.WindowsData{} + if us, err := user.LookupId(owner.String()); err == nil { + pd.OwnerName = us.Username + } else if gr, err := user.LookupGroupId(owner.String()); err == nil { + pd.OwnerName = gr.Name + pd.OwnerIsGroup = true + } else { + l.Debugf("Failed to resolve owner for %s: %v", rootedName, err) + } + + return protocol.PlatformData{Windows: pd}, nil +} + +func openReadOnlyWithBackupSemantics(path string) (fd windows.Handle, err error) { + // This is windows.Open but simplified to read-only only, and adding + // FILE_FLAG_BACKUP_SEMANTICS which is required to open directories. + if len(path) == 0 { + return windows.InvalidHandle, windows.ERROR_FILE_NOT_FOUND + } + pathp, err := windows.UTF16PtrFromString(path) + if err != nil { + return windows.InvalidHandle, err + } + var access uint32 = windows.GENERIC_READ + var sharemode uint32 = windows.FILE_SHARE_READ | windows.FILE_SHARE_WRITE + var sa *windows.SecurityAttributes + var createmode uint32 = windows.OPEN_EXISTING + var attrs uint32 = windows.FILE_ATTRIBUTE_READONLY | windows.FILE_FLAG_BACKUP_SEMANTICS + return windows.CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0) +} diff --git a/lib/fs/basicfs_test.go b/lib/fs/basicfs_test.go index 04db3bf4b..261167f79 100644 --- a/lib/fs/basicfs_test.go +++ b/lib/fs/basicfs_test.go @@ -11,6 +11,7 @@ import ( "path/filepath" "runtime" "sort" + "strconv" "strings" "testing" "time" @@ -84,7 +85,7 @@ func TestChownFile(t *testing.T) { newUID := 1000 + rand.Intn(30000) newGID := 1000 + rand.Intn(30000) - if err := fs.Lchown("file", newUID, newGID); err != nil { + if err := fs.Lchown("file", strconv.Itoa(newUID), strconv.Itoa(newGID)); err != nil { t.Error("Unexpected error:", err) } diff --git a/lib/fs/basicfs_unix.go b/lib/fs/basicfs_unix.go index 3d6a9bfd7..9f7f65831 100644 --- a/lib/fs/basicfs_unix.go +++ b/lib/fs/basicfs_unix.go @@ -12,6 +12,7 @@ package fs import ( "os" "path/filepath" + "strconv" "strings" ) @@ -57,6 +58,22 @@ func (f *BasicFilesystem) Roots() ([]string, error) { return []string{"/"}, nil } +func (f *BasicFilesystem) Lchown(name, uid, gid string) error { + name, err := f.rooted(name) + if err != nil { + return err + } + nuid, err := strconv.Atoi(uid) + if err != nil { + return err + } + ngid, err := strconv.Atoi(gid) + if err != nil { + return err + } + return os.Lchown(name, nuid, ngid) +} + // unrootedChecked returns the path relative to the folder root (same as // unrooted) or an error if the given path is not a subpath and handles the // special case when the given path is the folder root without a trailing diff --git a/lib/fs/basicfs_windows.go b/lib/fs/basicfs_windows.go index d23f03863..83445285a 100644 --- a/lib/fs/basicfs_windows.go +++ b/lib/fs/basicfs_windows.go @@ -17,6 +17,8 @@ import ( "strings" "syscall" "unsafe" + + "golang.org/x/sys/windows" ) var errNotSupported = errors.New("symlinks not supported") @@ -152,6 +154,42 @@ func (f *BasicFilesystem) Roots() ([]string, error) { return drives, nil } +func (f *BasicFilesystem) Lchown(name, uid, gid string) error { + name, err := f.rooted(name) + if err != nil { + return err + } + + hdl, err := windows.Open(name, windows.O_WRONLY, 0) + if err != nil { + return err + } + defer windows.Close(hdl) + + // Depending on whether we got an uid or a gid, we need to set the + // appropriate flag and parse the corresponding SID. The one we're not + // setting remains nil, which is what we want in the call to + // SetSecurityInfo. + + var si windows.SECURITY_INFORMATION + var ownerSID, groupSID *syscall.SID + if uid != "" { + ownerSID, err = syscall.StringToSid(uid) + if err == nil { + si |= windows.OWNER_SECURITY_INFORMATION + } + } else if gid != "" { + groupSID, err = syscall.StringToSid(uid) + if err == nil { + si |= windows.GROUP_SECURITY_INFORMATION + } + } else { + return errors.New("neither uid nor gid specified") + } + + return windows.SetSecurityInfo(hdl, windows.SE_FILE_OBJECT, si, (*windows.SID)(ownerSID), (*windows.SID)(groupSID), nil, nil) +} + // unrootedChecked returns the path relative to the folder root (same as // unrooted) or an error if the given path is not a subpath and handles the // special case when the given path is the folder root without a trailing diff --git a/lib/fs/casefs.go b/lib/fs/casefs.go index 71bef00d8..929aad120 100644 --- a/lib/fs/casefs.go +++ b/lib/fs/casefs.go @@ -153,7 +153,7 @@ func (f *caseFilesystem) Chmod(name string, mode FileMode) error { return f.Filesystem.Chmod(name, mode) } -func (f *caseFilesystem) Lchown(name string, uid, gid int) error { +func (f *caseFilesystem) Lchown(name, uid, gid string) error { if err := f.checkCase(name); err != nil { return err } diff --git a/lib/fs/errorfs.go b/lib/fs/errorfs.go index 1c9965af5..06564ba3d 100644 --- a/lib/fs/errorfs.go +++ b/lib/fs/errorfs.go @@ -9,6 +9,8 @@ package fs import ( "context" "time" + + "github.com/syncthing/syncthing/lib/protocol" ) type errorFilesystem struct { @@ -18,7 +20,7 @@ type errorFilesystem struct { } func (fs *errorFilesystem) Chmod(name string, mode FileMode) error { return fs.err } -func (fs *errorFilesystem) Lchown(name string, uid, gid int) error { return fs.err } +func (fs *errorFilesystem) Lchown(name, uid, gid string) error { return fs.err } func (fs *errorFilesystem) Chtimes(name string, atime time.Time, mtime time.Time) error { return fs.err } @@ -52,6 +54,9 @@ func (fs *errorFilesystem) SameFile(fi1, fi2 FileInfo) bool { return false } func (fs *errorFilesystem) Watch(path string, ignore Matcher, ctx context.Context, ignorePerms bool) (<-chan Event, <-chan error, error) { return nil, nil, fs.err } +func (fs *errorFilesystem) PlatformData(name string) (protocol.PlatformData, error) { + return protocol.PlatformData{}, fs.err +} func (fs *errorFilesystem) underlying() (Filesystem, bool) { return nil, false diff --git a/lib/fs/fakefs.go b/lib/fs/fakefs.go index 8e66f526f..a33985cb8 100644 --- a/lib/fs/fakefs.go +++ b/lib/fs/fakefs.go @@ -21,6 +21,8 @@ import ( "sync" "testing" "time" + + "github.com/syncthing/syncthing/lib/protocol" ) // see readShortAt() @@ -29,19 +31,19 @@ const randomBlockShift = 14 // 128k // fakeFS is a fake filesystem for testing and benchmarking. It has the // following properties: // -// - File metadata is kept in RAM. Specifically, we remember which files and -// directories exist, their dates, permissions and sizes. Symlinks are -// not supported. +// - File metadata is kept in RAM. Specifically, we remember which files and +// directories exist, their dates, permissions and sizes. Symlinks are +// not supported. // -// - File contents are generated pseudorandomly with just the file name as -// seed. Writes are discarded, other than having the effect of increasing -// the file size. If you only write data that you've read from a file with -// the same name on a different fakeFS, you'll never know the difference... +// - File contents are generated pseudorandomly with just the file name as +// seed. Writes are discarded, other than having the effect of increasing +// the file size. If you only write data that you've read from a file with +// the same name on a different fakeFS, you'll never know the difference... // // - We totally ignore permissions - pretend you are root. // -// - The root path can contain URL query-style parameters that pre populate -// the filesystem at creation with a certain amount of random data: +// - The root path can contain URL query-style parameters that pre populate +// the filesystem at creation with a certain amount of random data: // // files=n to generate n random files (default 0) // maxsize=n to generate files up to a total of n MiB (default 0) @@ -51,7 +53,6 @@ const randomBlockShift = 14 // 128k // latency=d to set the amount of time each "disk" operation takes, where d is time.ParseDuration format // // - Two fakeFS:s pointing at the same root path see the same files. -// type fakeFS struct { counters fakeFSCounters uri string @@ -220,7 +221,7 @@ func (fs *fakeFS) Chmod(name string, mode FileMode) error { return nil } -func (fs *fakeFS) Lchown(name string, uid, gid int) error { +func (fs *fakeFS) Lchown(name, uid, gid string) error { fs.mut.Lock() defer fs.mut.Unlock() fs.counters.Lchown++ @@ -229,8 +230,8 @@ func (fs *fakeFS) Lchown(name string, uid, gid int) error { if entry == nil { return os.ErrNotExist } - entry.uid = uid - entry.gid = gid + entry.uid, _ = strconv.Atoi(uid) + entry.gid, _ = strconv.Atoi(gid) return nil } @@ -656,6 +657,10 @@ func (fs *fakeFS) SameFile(fi1, fi2 FileInfo) bool { return ok && fi1.ModTime().Equal(fi2.ModTime()) && fi1.Mode() == fi2.Mode() && fi1.IsDir() == fi2.IsDir() && fi1.IsRegular() == fi2.IsRegular() && fi1.IsSymlink() == fi2.IsSymlink() && fi1.Owner() == fi2.Owner() && fi1.Group() == fi2.Group() } +func (fs *fakeFS) PlatformData(name string) (protocol.PlatformData, error) { + return unixPlatformData(fs, name) +} + func (fs *fakeFS) underlying() (Filesystem, bool) { return nil, false } diff --git a/lib/fs/fakefs_test.go b/lib/fs/fakefs_test.go index 3ace32470..04b3ecbad 100644 --- a/lib/fs/fakefs_test.go +++ b/lib/fs/fakefs_test.go @@ -119,7 +119,7 @@ func TestFakeFS(t *testing.T) { } // Chown - if err := fs.Lchown("dira", 1234, 5678); err != nil { + if err := fs.Lchown("dira", "1234", "5678"); err != nil { t.Fatal(err) } if info, err := fs.Lstat("dira"); err != nil { diff --git a/lib/fs/filesystem.go b/lib/fs/filesystem.go index d834f9950..0653b128a 100644 --- a/lib/fs/filesystem.go +++ b/lib/fs/filesystem.go @@ -14,6 +14,8 @@ import ( "path/filepath" "strings" "time" + + "github.com/syncthing/syncthing/lib/protocol" ) type filesystemWrapperType int32 @@ -30,7 +32,7 @@ const ( // The Filesystem interface abstracts access to the file system. type Filesystem interface { Chmod(name string, mode FileMode) error - Lchown(name string, uid, gid int) error + Lchown(name string, uid, gid string) error // uid/gid as strings; numeric on POSIX, SID on Windows, like in os/user package Chtimes(name string, atime time.Time, mtime time.Time) error Create(name string) (File, error) CreateSymlink(target, name string) error @@ -60,6 +62,7 @@ type Filesystem interface { URI() string Options() []Option SameFile(fi1, fi2 FileInfo) bool + PlatformData(name string) (protocol.PlatformData, error) // Used for unwrapping things underlying() (Filesystem, bool) diff --git a/lib/fs/mtimefs.go b/lib/fs/mtimefs.go index 832b872c9..2dfcbfe6b 100644 --- a/lib/fs/mtimefs.go +++ b/lib/fs/mtimefs.go @@ -59,7 +59,7 @@ func (o *optionMtime) apply(fs Filesystem) Filesystem { return f } -func (_ *optionMtime) String() string { +func (*optionMtime) String() string { return "mtime" } diff --git a/lib/fs/platform_common.go b/lib/fs/platform_common.go new file mode 100644 index 000000000..aea876c7d --- /dev/null +++ b/lib/fs/platform_common.go @@ -0,0 +1,55 @@ +// Copyright (C) 2022 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package fs + +import ( + "os/user" + "strconv" + + "github.com/syncthing/syncthing/lib/protocol" +) + +// unixPlatformData is used on all platforms, because apart from being the +// implementation for BasicFilesystem on Unixes it's also the implementation +// in fakeFS. +func unixPlatformData(fs Filesystem, name string) (protocol.PlatformData, error) { + stat, err := fs.Lstat(name) + if err != nil { + return protocol.PlatformData{}, err + } + + ownerUID := stat.Owner() + ownerName := "" + if u, err := user.LookupId(strconv.Itoa(ownerUID)); err == nil && u.Username != "" { + ownerName = u.Username + } else if ownerUID == 0 { + // We couldn't look up a name, but UID zero should be "root". This + // fixup works around the (unlikely) situation where the ownership + // is 0:0 but we can't look up a name for either uid zero or gid + // zero. If that were the case we'd return a zero PlatformData which + // wouldn't get serialized over the wire and the other side would + // assume a lack of ownership info... + ownerName = "root" + } + + groupID := stat.Group() + groupName := "" + if g, err := user.LookupGroupId(strconv.Itoa(groupID)); err == nil && g.Name != "" { + groupName = g.Name + } else if groupID == 0 { + groupName = "root" + } + + return protocol.PlatformData{ + Unix: &protocol.UnixData{ + OwnerName: ownerName, + GroupName: groupName, + UID: ownerUID, + GID: groupID, + }, + }, nil +} diff --git a/lib/model/folder.go b/lib/model/folder.go index 0091674ca..41d26a4dc 100644 --- a/lib/model/folder.go +++ b/lib/model/folder.go @@ -602,7 +602,13 @@ func (b *scanBatch) Update(fi protocol.FileInfo, snap *db.Snapshot) bool { b.Remove(fi.Name) return true } - case gf.IsEquivalentOptional(fi, b.f.modTimeWindow, false, false, protocol.FlagLocalReceiveOnly): + case gf.IsEquivalentOptional(fi, protocol.FileInfoComparison{ + ModTimeWindow: b.f.modTimeWindow, + IgnorePerms: b.f.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: protocol.FlagLocalReceiveOnly, + IgnoreOwnership: !b.f.SyncOwnership, + }): // 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 @@ -632,6 +638,7 @@ func (f *folder) scanSubdirsChangedAndNew(subDirs []string, batch *scanBatch) (i CurrentFiler: cFiler{snap}, Filesystem: f.mtimefs, IgnorePerms: f.IgnorePerms, + IgnoreOwnership: !f.SyncOwnership, AutoNormalize: f.AutoNormalize, Hashers: f.model.numHashers(f.ID), ShortID: f.shortID, diff --git a/lib/model/folder_recvonly.go b/lib/model/folder_recvonly.go index 827fbe5d8..41f2b24ea 100644 --- a/lib/model/folder_recvonly.go +++ b/lib/model/folder_recvonly.go @@ -126,7 +126,11 @@ func (f *receiveOnlyFolder) revert() error { } fi.SetDeleted(f.shortID) fi.Version = protocol.Vector{} // if this file ever resurfaces anywhere we want our delete to be strictly older - case gf.IsEquivalentOptional(fi, f.modTimeWindow, false, false, protocol.FlagLocalReceiveOnly): + case gf.IsEquivalentOptional(fi, protocol.FileInfoComparison{ + ModTimeWindow: f.modTimeWindow, + IgnoreFlags: protocol.FlagLocalReceiveOnly, + IgnoreOwnership: !f.SyncOwnership, + }): // What we have locally is equivalent to the global file. fi = gf default: diff --git a/lib/model/folder_sendonly.go b/lib/model/folder_sendonly.go index 9b6104fff..7ab6c6dad 100644 --- a/lib/model/folder_sendonly.go +++ b/lib/model/folder_sendonly.go @@ -72,7 +72,11 @@ func (f *sendOnlyFolder) pull() (bool, error) { return true } - if !file.IsEquivalentOptional(curFile, f.modTimeWindow, f.IgnorePerms, false, 0) { + if !file.IsEquivalentOptional(curFile, protocol.FileInfoComparison{ + ModTimeWindow: f.modTimeWindow, + IgnorePerms: f.IgnorePerms, + IgnoreOwnership: !f.SyncOwnership, + }) { return true } diff --git a/lib/model/folder_sendrecv.go b/lib/model/folder_sendrecv.go index e8f0af524..bc3f45c90 100644 --- a/lib/model/folder_sendrecv.go +++ b/lib/model/folder_sendrecv.go @@ -13,6 +13,7 @@ import ( "path/filepath" "runtime" "sort" + "strconv" "strings" "time" @@ -627,8 +628,8 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot, return err } - // Copy the parent owner and group, if we are supposed to do that. - if err := f.maybeCopyOwner(path); err != nil { + // Adjust the ownership, if we are supposed to do that. + if err := f.maybeAdjustOwnership(&file, path); err != nil { return err } @@ -754,7 +755,7 @@ func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, snap *db.Snaps if err := f.mtimefs.CreateSymlink(file.SymlinkTarget, path); err != nil { return err } - return f.maybeCopyOwner(path) + return f.maybeAdjustOwnership(&file, path) } if err = f.inWritableDir(createLink, file.Name); err == nil { @@ -989,7 +990,13 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn default: var fi protocol.FileInfo if fi, err = scanner.CreateFileInfo(stat, target.Name, f.mtimefs); err == nil { - if !fi.IsEquivalentOptional(curTarget, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) { + if !fi.IsEquivalentOptional(curTarget, protocol.FileInfoComparison{ + ModTimeWindow: f.modTimeWindow, + IgnorePerms: f.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: protocol.LocalAllFlags, + IgnoreOwnership: !f.SyncOwnership, + }) { // Target changed scanChan <- target.Name err = errModified @@ -1227,6 +1234,11 @@ func (f *sendReceiveFolder) shortcutFile(file protocol.FileInfo, dbUpdateChan ch } } + if err := f.maybeAdjustOwnership(&file, file.Name); err != nil { + f.newPullError(file.Name, err) + return + } + // Still need to re-write the trailer with the new encrypted fileinfo. if f.Type == config.FolderTypeReceiveEncrypted { err = inWritableDir(func(path string) error { @@ -1592,8 +1604,8 @@ func (f *sendReceiveFolder) performFinish(file, curFile protocol.FileInfo, hasCu } } - // Copy the parent owner and group, if we are supposed to do that. - if err := f.maybeCopyOwner(tempName); err != nil { + // Set ownership based on file metadata or parent, maybe. + if err := f.maybeAdjustOwnership(&file, tempName); err != nil { return err } @@ -1972,7 +1984,13 @@ func (f *sendReceiveFolder) deleteDirOnDiskHandleChildren(dir string, snap *db.S hasToBeScanned = true return nil } - if !cf.IsEquivalentOptional(diskFile, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) { + if !cf.IsEquivalentOptional(diskFile, protocol.FileInfoComparison{ + ModTimeWindow: f.modTimeWindow, + IgnorePerms: f.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: protocol.LocalAllFlags, + IgnoreOwnership: !f.SyncOwnership, + }) { // File on disk changed compared to what we have in db // -> schedule scan. scanChan <- path @@ -2041,7 +2059,13 @@ func (f *sendReceiveFolder) scanIfItemChanged(name string, stat fs.FileInfo, ite return errors.Wrap(err, "comparing item on disk to db") } - if !statItem.IsEquivalentOptional(item, f.modTimeWindow, f.IgnorePerms, true, protocol.LocalAllFlags) { + if !statItem.IsEquivalentOptional(item, protocol.FileInfoComparison{ + ModTimeWindow: f.modTimeWindow, + IgnorePerms: f.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: protocol.LocalAllFlags, + IgnoreOwnership: !f.SyncOwnership, + }) { return errModified } @@ -2074,11 +2098,23 @@ func (f *sendReceiveFolder) checkToBeDeleted(file, cur protocol.FileInfo, hasCur return f.scanIfItemChanged(file.Name, stat, cur, hasCur, scanChan) } -func (f *sendReceiveFolder) maybeCopyOwner(path string) error { - if !f.CopyOwnershipFromParent { - // Not supposed to do anything. - return nil +func (f *sendReceiveFolder) maybeAdjustOwnership(file *protocol.FileInfo, name string) error { + if f.SyncOwnership { + // Set ownership based on file metadata. + if err := f.syncOwnership(file, name); err != nil { + return err + } + } else if f.CopyOwnershipFromParent { + // Copy the parent owner and group. + if err := f.copyOwnershipFromParent(name); err != nil { + return err + } } + // Nothing to do + return nil +} + +func (f *sendReceiveFolder) copyOwnershipFromParent(path string) error { if runtime.GOOS == "windows" { // Can't do anything. return nil @@ -2088,7 +2124,7 @@ func (f *sendReceiveFolder) maybeCopyOwner(path string) error { if err != nil { return errors.Wrap(err, "copy owner from parent") } - if err := f.mtimefs.Lchown(path, info.Owner(), info.Group()); err != nil { + if err := f.mtimefs.Lchown(path, strconv.Itoa(info.Owner()), strconv.Itoa(info.Group())); err != nil { return errors.Wrap(err, "copy owner from parent") } return nil diff --git a/lib/model/folder_sendrecv_test.go b/lib/model/folder_sendrecv_test.go index 4793f74dd..608b5a87d 100644 --- a/lib/model/folder_sendrecv_test.go +++ b/lib/model/folder_sendrecv_test.go @@ -16,6 +16,7 @@ import ( "os" "path/filepath" "runtime" + "strconv" "strings" "testing" "time" @@ -811,7 +812,7 @@ func TestCopyOwner(t *testing.T) { // Create a parent dir with a certain owner/group. f.mtimefs.Mkdir("foo", 0755) - f.mtimefs.Lchown("foo", expOwner, expGroup) + f.mtimefs.Lchown("foo", strconv.Itoa(expOwner), strconv.Itoa(expGroup)) dir := protocol.FileInfo{ Name: "foo/bar", diff --git a/lib/model/folder_sendrecv_unix.go b/lib/model/folder_sendrecv_unix.go new file mode 100644 index 000000000..978159094 --- /dev/null +++ b/lib/model/folder_sendrecv_unix.go @@ -0,0 +1,45 @@ +// Copyright (C) 2022 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +//go:build !windows +// +build !windows + +package model + +import ( + "os/user" + "strconv" + + "github.com/syncthing/syncthing/lib/protocol" +) + +func (f *sendReceiveFolder) syncOwnership(file *protocol.FileInfo, path string) error { + if file.Platform.Unix == nil { + // No owner data, nothing to do + return nil + } + + // Try to look up the user and group by name, defaulting to the + // numerical UID and GID if there is no match. + + uid := strconv.Itoa(file.Platform.Unix.UID) + if file.Platform.Unix.OwnerName != "" { + us, err := user.Lookup(file.Platform.Unix.OwnerName) + if err == nil && us.Uid != "" { + uid = us.Uid + } + } + + gid := strconv.Itoa(file.Platform.Unix.GID) + if file.Platform.Unix.GroupName != "" { + gr, err := user.LookupGroup(file.Platform.Unix.GroupName) + if err == nil && gr.Gid != "" { + gid = gr.Gid + } + } + + return f.mtimefs.Lchown(path, uid, gid) +} diff --git a/lib/model/folder_sendrecv_windows.go b/lib/model/folder_sendrecv_windows.go new file mode 100644 index 000000000..28ebe01d1 --- /dev/null +++ b/lib/model/folder_sendrecv_windows.go @@ -0,0 +1,82 @@ +// Copyright (C) 2022 The Syncthing Authors. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at https://mozilla.org/MPL/2.0/. + +package model + +import ( + "errors" + "os/user" + "strings" + + "github.com/syncthing/syncthing/lib/protocol" +) + +func (f *sendReceiveFolder) syncOwnership(file *protocol.FileInfo, path string) error { + if file.Platform.Windows == nil || file.Platform.Windows.OwnerName == "" { + // No owner data, nothing to do + return nil + } + + l.Debugln("Owner name for %s is %s (group=%v)", path, file.Platform.Windows.OwnerName, file.Platform.Windows.OwnerIsGroup) + usid, gsid, err := lookupUserAndGroup(file.Platform.Windows.OwnerName, file.Platform.Windows.OwnerIsGroup) + if err != nil { + return err + } + + l.Debugln("Owner for %s resolved to uid=%q gid=%q", path, usid, gsid) + return f.mtimefs.Lchown(path, usid, gsid) +} + +func lookupUserAndGroup(name string, group bool) (string, string, error) { + // Look up either the the user or the group, returning the other kind as + // blank. This might seem an odd maneuver, but it matches what Chown + // wants as input and hides the ugly nested if:s down here. + + if group { + gr, err := lookupWithoutDomain(name, func(name string) (string, error) { + gr, err := user.LookupGroup(name) + if err == nil { + return gr.Gid, nil + } + return "", err + }) + if err != nil { + return "", "", err + } + return "", gr, nil + } + + us, err := lookupWithoutDomain(name, func(name string) (string, error) { + us, err := user.Lookup(name) + if err == nil { + return us.Uid, nil + } + return "", err + }) + if err != nil { + return "", "", err + } + return us, "", nil +} + +func lookupWithoutDomain(name string, lookup func(s string) (string, error)) (string, error) { + // Try to look up the user by name. The username will be either a plain + // username or a qualified DOMAIN\user. We'll first try to look up + // whatever we got, if that fails, we'll try again with just the user + // part without domain. + + v, err := lookup(name) + if err == nil { + return v, nil + } + parts := strings.Split(name, `\`) + if len(parts) == 2 { + if v, err := lookup(parts[1]); err == nil { + return v, nil + } + } + return "", errors.New("lookup failed") +} diff --git a/lib/protocol/bep.pb.go b/lib/protocol/bep.pb.go index 17843d53f..148da5be7 100644 --- a/lib/protocol/bep.pb.go +++ b/lib/protocol/bep.pb.go @@ -505,6 +505,7 @@ type FileInfo struct { Permissions uint32 `protobuf:"varint,4,opt,name=permissions,proto3" json:"permissions" xml:"permissions"` ModifiedNs int `protobuf:"varint,11,opt,name=modified_ns,json=modifiedNs,proto3,casttype=int" json:"modifiedNs" xml:"modifiedNs"` RawBlockSize int `protobuf:"varint,13,opt,name=block_size,json=blockSize,proto3,casttype=int" json:"blockSize" xml:"blockSize"` + Platform PlatformData `protobuf:"bytes,14,opt,name=platform,proto3" json:"platform" xml:"platform"` // The local_flags fields stores flags that are relevant to the local // host only. It is not part of the protocol, doesn't get sent or // received (we make sure to zero it), nonetheless we need it on our @@ -664,6 +665,128 @@ func (m *Counter) XXX_DiscardUnknown() { var xxx_messageInfo_Counter proto.InternalMessageInfo +type PlatformData struct { + Unix *UnixData `protobuf:"bytes,1,opt,name=unix,proto3" json:"unix" xml:"unix"` + Windows *WindowsData `protobuf:"bytes,2,opt,name=windows,proto3" json:"windows" xml:"windows"` +} + +func (m *PlatformData) Reset() { *m = PlatformData{} } +func (m *PlatformData) String() string { return proto.CompactTextString(m) } +func (*PlatformData) ProtoMessage() {} +func (*PlatformData) Descriptor() ([]byte, []int) { + return fileDescriptor_311ef540e10d9705, []int{11} +} +func (m *PlatformData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PlatformData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PlatformData.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PlatformData) XXX_Merge(src proto.Message) { + xxx_messageInfo_PlatformData.Merge(m, src) +} +func (m *PlatformData) XXX_Size() int { + return m.ProtoSize() +} +func (m *PlatformData) XXX_DiscardUnknown() { + xxx_messageInfo_PlatformData.DiscardUnknown(m) +} + +var xxx_messageInfo_PlatformData proto.InternalMessageInfo + +type UnixData struct { + // The owner name and group name are set when known (i.e., could be + // resolved on the source device), while the UID and GID are always set + // as they come directly from the stat() call. + OwnerName string `protobuf:"bytes,1,opt,name=owner_name,json=ownerName,proto3" json:"ownerName" xml:"ownerName"` + GroupName string `protobuf:"bytes,2,opt,name=group_name,json=groupName,proto3" json:"groupName" xml:"groupName"` + UID int `protobuf:"varint,3,opt,name=uid,proto3,casttype=int" json:"uid" xml:"uid"` + GID int `protobuf:"varint,4,opt,name=gid,proto3,casttype=int" json:"gid" xml:"gid"` +} + +func (m *UnixData) Reset() { *m = UnixData{} } +func (m *UnixData) String() string { return proto.CompactTextString(m) } +func (*UnixData) ProtoMessage() {} +func (*UnixData) Descriptor() ([]byte, []int) { + return fileDescriptor_311ef540e10d9705, []int{12} +} +func (m *UnixData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UnixData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UnixData.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UnixData) XXX_Merge(src proto.Message) { + xxx_messageInfo_UnixData.Merge(m, src) +} +func (m *UnixData) XXX_Size() int { + return m.ProtoSize() +} +func (m *UnixData) XXX_DiscardUnknown() { + xxx_messageInfo_UnixData.DiscardUnknown(m) +} + +var xxx_messageInfo_UnixData proto.InternalMessageInfo + +type WindowsData struct { + // Windows file objects have a single owner, which may be a user or a + // group. We keep the name of that account, and a flag to indicate what + // type it is. + OwnerName string `protobuf:"bytes,1,opt,name=owner_name,json=ownerName,proto3" json:"ownerName" xml:"ownerName"` + OwnerIsGroup bool `protobuf:"varint,2,opt,name=owner_is_group,json=ownerIsGroup,proto3" json:"ownerIsGroup" xml:"ownerIsGroup"` +} + +func (m *WindowsData) Reset() { *m = WindowsData{} } +func (m *WindowsData) String() string { return proto.CompactTextString(m) } +func (*WindowsData) ProtoMessage() {} +func (*WindowsData) Descriptor() ([]byte, []int) { + return fileDescriptor_311ef540e10d9705, []int{13} +} +func (m *WindowsData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *WindowsData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_WindowsData.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *WindowsData) XXX_Merge(src proto.Message) { + xxx_messageInfo_WindowsData.Merge(m, src) +} +func (m *WindowsData) XXX_Size() int { + return m.ProtoSize() +} +func (m *WindowsData) XXX_DiscardUnknown() { + xxx_messageInfo_WindowsData.DiscardUnknown(m) +} + +var xxx_messageInfo_WindowsData proto.InternalMessageInfo + type Request struct { ID int `protobuf:"varint,1,opt,name=id,proto3,casttype=int" json:"id" xml:"id"` Folder string `protobuf:"bytes,2,opt,name=folder,proto3" json:"folder" xml:"folder"` @@ -680,7 +803,7 @@ func (m *Request) Reset() { *m = Request{} } func (m *Request) String() string { return proto.CompactTextString(m) } func (*Request) ProtoMessage() {} func (*Request) Descriptor() ([]byte, []int) { - return fileDescriptor_311ef540e10d9705, []int{11} + return fileDescriptor_311ef540e10d9705, []int{14} } func (m *Request) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -719,7 +842,7 @@ func (m *Response) Reset() { *m = Response{} } func (m *Response) String() string { return proto.CompactTextString(m) } func (*Response) ProtoMessage() {} func (*Response) Descriptor() ([]byte, []int) { - return fileDescriptor_311ef540e10d9705, []int{12} + return fileDescriptor_311ef540e10d9705, []int{15} } func (m *Response) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -757,7 +880,7 @@ func (m *DownloadProgress) Reset() { *m = DownloadProgress{} } func (m *DownloadProgress) String() string { return proto.CompactTextString(m) } func (*DownloadProgress) ProtoMessage() {} func (*DownloadProgress) Descriptor() ([]byte, []int) { - return fileDescriptor_311ef540e10d9705, []int{13} + return fileDescriptor_311ef540e10d9705, []int{16} } func (m *DownloadProgress) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -798,7 +921,7 @@ func (m *FileDownloadProgressUpdate) Reset() { *m = FileDownloadProgress func (m *FileDownloadProgressUpdate) String() string { return proto.CompactTextString(m) } func (*FileDownloadProgressUpdate) ProtoMessage() {} func (*FileDownloadProgressUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_311ef540e10d9705, []int{14} + return fileDescriptor_311ef540e10d9705, []int{17} } func (m *FileDownloadProgressUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -834,7 +957,7 @@ func (m *Ping) Reset() { *m = Ping{} } func (m *Ping) String() string { return proto.CompactTextString(m) } func (*Ping) ProtoMessage() {} func (*Ping) Descriptor() ([]byte, []int) { - return fileDescriptor_311ef540e10d9705, []int{15} + return fileDescriptor_311ef540e10d9705, []int{18} } func (m *Ping) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -871,7 +994,7 @@ func (m *Close) Reset() { *m = Close{} } func (m *Close) String() string { return proto.CompactTextString(m) } func (*Close) ProtoMessage() {} func (*Close) Descriptor() ([]byte, []int) { - return fileDescriptor_311ef540e10d9705, []int{16} + return fileDescriptor_311ef540e10d9705, []int{19} } func (m *Close) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -918,6 +1041,9 @@ func init() { proto.RegisterType((*BlockInfo)(nil), "protocol.BlockInfo") proto.RegisterType((*Vector)(nil), "protocol.Vector") proto.RegisterType((*Counter)(nil), "protocol.Counter") + proto.RegisterType((*PlatformData)(nil), "protocol.PlatformData") + proto.RegisterType((*UnixData)(nil), "protocol.UnixData") + proto.RegisterType((*WindowsData)(nil), "protocol.WindowsData") proto.RegisterType((*Request)(nil), "protocol.Request") proto.RegisterType((*Response)(nil), "protocol.Response") proto.RegisterType((*DownloadProgress)(nil), "protocol.DownloadProgress") @@ -929,175 +1055,190 @@ func init() { func init() { proto.RegisterFile("lib/protocol/bep.proto", fileDescriptor_311ef540e10d9705) } var fileDescriptor_311ef540e10d9705 = []byte{ - // 2681 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0x4d, 0x6c, 0x1b, 0xc7, - 0xf5, 0xd7, 0x92, 0x94, 0x44, 0x8d, 0x24, 0x87, 0x1a, 0x7f, 0x6d, 0x68, 0x9b, 0xcb, 0xff, 0xc4, - 0xf9, 0x57, 0x51, 0x1a, 0x39, 0x51, 0x92, 0x36, 0x4d, 0x52, 0x07, 0xfc, 0x92, 0xc4, 0x44, 0x22, - 0xd9, 0x21, 0xed, 0xd4, 0x46, 0x0b, 0x62, 0xc5, 0x1d, 0x51, 0x0b, 0x2f, 0x77, 0xd9, 0x5d, 0x4a, - 0xb6, 0x82, 0x5e, 0xda, 0x5e, 0x02, 0x1e, 0x8a, 0x22, 0xa7, 0xa2, 0x28, 0xd1, 0xa0, 0x97, 0xde, - 0x0a, 0xf4, 0xd0, 0x4b, 0x4e, 0x3d, 0xe6, 0x68, 0x04, 0x28, 0x50, 0xf4, 0xb0, 0x80, 0xed, 0x4b, - 0xcb, 0x23, 0x8f, 0x3d, 0x15, 0xf3, 0xb1, 0xbb, 0xb3, 0xa2, 0x14, 0xc8, 0xc9, 0xa1, 0xb7, 0x7d, - 0xbf, 0xf7, 0x7b, 0x6f, 0x86, 0x6f, 0xde, 0x7b, 0xf3, 0x76, 0x09, 0xae, 0x58, 0xe6, 0xde, 0xad, - 0xbe, 0xeb, 0x0c, 0x9c, 0x8e, 0x63, 0xdd, 0xda, 0x23, 0xfd, 0x75, 0x26, 0xc0, 0x74, 0x80, 0x65, - 0x17, 0xc8, 0xa3, 0x01, 0x07, 0xb3, 0x2f, 0xb9, 0xa4, 0xef, 0x78, 0x9c, 0xbe, 0x77, 0xb8, 0x7f, - 0xab, 0xeb, 0x74, 0x1d, 0x26, 0xb0, 0x27, 0x4e, 0x42, 0x4f, 0x15, 0x30, 0xbb, 0x4d, 0x2c, 0xcb, - 0x81, 0x25, 0xb0, 0x68, 0x90, 0x23, 0xb3, 0x43, 0xda, 0xb6, 0xde, 0x23, 0xaa, 0x92, 0x57, 0x56, - 0x17, 0x8a, 0x68, 0xec, 0x6b, 0x80, 0xc3, 0x35, 0xbd, 0x47, 0x26, 0xbe, 0x96, 0x79, 0xd4, 0xb3, - 0xde, 0x45, 0x11, 0x84, 0xb0, 0xa4, 0xa7, 0x4e, 0x3a, 0x96, 0x49, 0xec, 0x01, 0x77, 0x92, 0x88, - 0x9c, 0x70, 0x38, 0xe6, 0x24, 0x82, 0x10, 0x96, 0xf4, 0xb0, 0x0e, 0x2e, 0x08, 0x27, 0x47, 0xc4, - 0xf5, 0x4c, 0xc7, 0x56, 0x93, 0xcc, 0xcf, 0xea, 0xd8, 0xd7, 0x96, 0xb9, 0xe6, 0x2e, 0x57, 0x4c, - 0x7c, 0xed, 0xa2, 0xe4, 0x4a, 0xa0, 0x08, 0xc7, 0x59, 0xe8, 0x2f, 0x0a, 0x98, 0xdb, 0x26, 0xba, - 0x41, 0x5c, 0x58, 0x00, 0xa9, 0xc1, 0x71, 0x9f, 0xff, 0xbc, 0x0b, 0x1b, 0x97, 0xd7, 0x83, 0xc0, - 0xad, 0xef, 0x12, 0xcf, 0xd3, 0xbb, 0xa4, 0x75, 0xdc, 0x27, 0xc5, 0x2b, 0x63, 0x5f, 0x63, 0xb4, - 0x89, 0xaf, 0x01, 0xe6, 0x9f, 0x0a, 0x08, 0x33, 0x0c, 0x1a, 0x60, 0xb1, 0xe3, 0xf4, 0xfa, 0x2e, - 0xf1, 0xd8, 0xde, 0x12, 0xcc, 0xd3, 0xf5, 0x29, 0x4f, 0xa5, 0x88, 0x53, 0xbc, 0x39, 0xf6, 0x35, - 0xd9, 0x68, 0xe2, 0x6b, 0x2b, 0x7c, 0xdf, 0x11, 0x86, 0xb0, 0xcc, 0x40, 0x3f, 0x01, 0xcb, 0x25, - 0xeb, 0xd0, 0x1b, 0x10, 0xb7, 0xe4, 0xd8, 0xfb, 0x66, 0x17, 0x7e, 0x04, 0xe6, 0xf7, 0x1d, 0xcb, - 0x20, 0xae, 0xa7, 0x2a, 0xf9, 0xe4, 0xea, 0xe2, 0x46, 0x26, 0x5a, 0x72, 0x93, 0x29, 0x8a, 0xda, - 0x97, 0xbe, 0x36, 0x33, 0xf6, 0xb5, 0x80, 0x38, 0xf1, 0xb5, 0x25, 0xb6, 0x0c, 0x97, 0x11, 0x0e, - 0x14, 0xe8, 0x8b, 0x14, 0x98, 0xe3, 0x46, 0x70, 0x1d, 0x24, 0x4c, 0x43, 0x1c, 0x77, 0xee, 0xa9, - 0xaf, 0x25, 0xaa, 0xe5, 0xb1, 0xaf, 0x25, 0x4c, 0x63, 0xe2, 0x6b, 0x69, 0x66, 0x6d, 0x1a, 0xe8, - 0xb3, 0xc7, 0x37, 0x13, 0xd5, 0x32, 0x4e, 0x98, 0x06, 0x5c, 0x07, 0xb3, 0x96, 0xbe, 0x47, 0x2c, - 0x71, 0xb8, 0xea, 0xd8, 0xd7, 0x38, 0x30, 0xf1, 0xb5, 0x45, 0xc6, 0x67, 0x12, 0xc2, 0x1c, 0x85, - 0xef, 0x81, 0x05, 0x97, 0xe8, 0x46, 0xdb, 0xb1, 0xad, 0x63, 0x76, 0x90, 0xe9, 0x62, 0x6e, 0xec, - 0x6b, 0x69, 0x0a, 0xd6, 0x6d, 0xeb, 0x78, 0xe2, 0x6b, 0x17, 0x98, 0x59, 0x00, 0x20, 0x1c, 0xea, - 0x60, 0x1b, 0x40, 0xb3, 0x6b, 0x3b, 0x2e, 0x69, 0xf7, 0x89, 0xdb, 0x33, 0x59, 0x68, 0x3c, 0x35, - 0xc5, 0xbc, 0xbc, 0x3e, 0xf6, 0xb5, 0x15, 0xae, 0x6d, 0x44, 0xca, 0x89, 0xaf, 0x5d, 0xe5, 0xbb, - 0x3e, 0xa9, 0x41, 0x78, 0x9a, 0x0d, 0x3f, 0x02, 0xcb, 0x62, 0x01, 0x83, 0x58, 0x64, 0x40, 0xd4, - 0x59, 0xe6, 0xfb, 0xff, 0xc7, 0xbe, 0xb6, 0xc4, 0x15, 0x65, 0x86, 0x4f, 0x7c, 0x0d, 0x4a, 0x6e, - 0x39, 0x88, 0x70, 0x8c, 0x03, 0x0d, 0x70, 0xc9, 0x30, 0x3d, 0x7d, 0xcf, 0x22, 0xed, 0x01, 0xe9, - 0xf5, 0xdb, 0xa6, 0x6d, 0x90, 0x47, 0xc4, 0x53, 0xe7, 0x98, 0xcf, 0x8d, 0xb1, 0xaf, 0x41, 0xa1, - 0x6f, 0x91, 0x5e, 0xbf, 0xca, 0xb5, 0x13, 0x5f, 0x53, 0x79, 0x4d, 0x4d, 0xa9, 0x10, 0x3e, 0x85, - 0x0f, 0x37, 0xc0, 0x5c, 0x5f, 0x3f, 0xf4, 0x88, 0xa1, 0xce, 0x33, 0xbf, 0xd9, 0xb1, 0xaf, 0x09, - 0x24, 0x3c, 0x70, 0x2e, 0x22, 0x2c, 0x70, 0x9a, 0x3c, 0xbc, 0x4a, 0x3d, 0x35, 0x73, 0x32, 0x79, - 0xca, 0x4c, 0x11, 0x25, 0x8f, 0x20, 0x86, 0xbe, 0xb8, 0x8c, 0x70, 0xa0, 0x40, 0x7f, 0x9b, 0x03, - 0x73, 0xdc, 0x08, 0x16, 0xc3, 0xe4, 0x59, 0x2a, 0x6e, 0x50, 0x07, 0xff, 0xf4, 0xb5, 0x34, 0xd7, - 0x55, 0xcb, 0x67, 0x25, 0xd3, 0xa7, 0x8f, 0x6f, 0x2a, 0x52, 0x42, 0xad, 0x81, 0x94, 0xd4, 0x2c, - 0x58, 0xed, 0xd9, 0xbc, 0x4d, 0xf0, 0xda, 0xb3, 0x59, 0x83, 0x60, 0x18, 0x7c, 0x1f, 0x2c, 0xe8, - 0x86, 0x41, 0x6b, 0x84, 0x78, 0x6a, 0x32, 0x9f, 0xa4, 0x39, 0x3b, 0xf6, 0xb5, 0x08, 0x9c, 0xf8, - 0xda, 0x32, 0xb3, 0x12, 0x08, 0xc2, 0x91, 0x0e, 0xfe, 0x34, 0x5e, 0xb9, 0xa9, 0x93, 0x3d, 0xe0, - 0xdb, 0x95, 0x2c, 0xcd, 0xf4, 0x0e, 0x71, 0x45, 0xeb, 0x9b, 0xe5, 0x05, 0x45, 0x33, 0x9d, 0x82, - 0xa2, 0xf1, 0xf1, 0x4c, 0x0f, 0x00, 0x84, 0x43, 0x1d, 0xdc, 0x02, 0x4b, 0x3d, 0xfd, 0x51, 0xdb, - 0x23, 0x3f, 0x3b, 0x24, 0x76, 0x87, 0xb0, 0x9c, 0x49, 0xf2, 0x5d, 0xf4, 0xf4, 0x47, 0x4d, 0x01, - 0x87, 0xbb, 0x90, 0x30, 0x84, 0x65, 0x06, 0x2c, 0x02, 0x60, 0xda, 0x03, 0xd7, 0x31, 0x0e, 0x3b, - 0xc4, 0x15, 0x29, 0xc2, 0x3a, 0x70, 0x84, 0x86, 0x1d, 0x38, 0x82, 0x10, 0x96, 0xf4, 0xb0, 0x0b, - 0xd2, 0x2c, 0x77, 0xdb, 0xa6, 0xa1, 0xa6, 0xf3, 0xca, 0x6a, 0xaa, 0xb8, 0x23, 0x0e, 0x77, 0x9e, - 0x65, 0x21, 0x3b, 0xdb, 0xe0, 0x91, 0xe6, 0x0c, 0x63, 0x57, 0x8d, 0x30, 0xfa, 0x42, 0xa6, 0x7d, - 0x23, 0xa0, 0xfd, 0x2e, 0x7a, 0xc4, 0x01, 0x1f, 0xfe, 0x1c, 0x64, 0xbd, 0x07, 0x26, 0xad, 0x14, - 0xbe, 0xf6, 0xc0, 0x74, 0xec, 0xb6, 0x4b, 0x7a, 0xce, 0x91, 0x6e, 0x79, 0xea, 0x02, 0xdb, 0xfc, - 0xed, 0xb1, 0xaf, 0xa9, 0x94, 0x55, 0x95, 0x48, 0x58, 0x70, 0x26, 0xbe, 0x96, 0x63, 0x2b, 0x9e, - 0x45, 0x40, 0xf8, 0x4c, 0x5b, 0xf8, 0x08, 0xbc, 0x48, 0xec, 0x8e, 0x7b, 0xdc, 0x67, 0xcb, 0xf6, - 0x75, 0xcf, 0x7b, 0xe8, 0xb8, 0x46, 0x7b, 0xe0, 0x3c, 0x20, 0xb6, 0x0a, 0x58, 0x52, 0xbf, 0x3f, - 0xf6, 0xb5, 0xab, 0x11, 0xa9, 0x21, 0x38, 0x2d, 0x4a, 0x99, 0xf8, 0xda, 0x0d, 0xb6, 0xf6, 0x19, - 0x7a, 0x84, 0xcf, 0xb2, 0x44, 0xbf, 0x54, 0xc0, 0x2c, 0x0b, 0x06, 0xad, 0x66, 0xde, 0x94, 0x45, - 0x0b, 0x66, 0xd5, 0xcc, 0x91, 0xa9, 0xf6, 0x2d, 0x70, 0x58, 0x01, 0xb3, 0xfb, 0xa6, 0x45, 0x3c, - 0x35, 0xc1, 0x6a, 0x19, 0x4a, 0x17, 0x81, 0x69, 0x91, 0xaa, 0xbd, 0xef, 0x14, 0xaf, 0x89, 0x6a, - 0xe6, 0xc4, 0xb0, 0x96, 0xa8, 0x84, 0x30, 0x07, 0xd1, 0xa7, 0x0a, 0x58, 0x64, 0x9b, 0xb8, 0xd3, - 0x37, 0xf4, 0x01, 0xf9, 0x5f, 0x6e, 0xe5, 0x09, 0x00, 0xe9, 0xc0, 0x20, 0x6c, 0x08, 0xca, 0x39, - 0x1a, 0xc2, 0x1a, 0x48, 0x79, 0xe6, 0x27, 0x84, 0x5d, 0x2c, 0x49, 0xce, 0xa5, 0x72, 0xc8, 0xa5, - 0x02, 0xc2, 0x0c, 0x83, 0x1f, 0x00, 0xd0, 0x73, 0x0c, 0x73, 0xdf, 0x24, 0x46, 0xdb, 0x63, 0x05, - 0x9a, 0x2c, 0xe6, 0x69, 0xf7, 0x08, 0xd0, 0xe6, 0xc4, 0xd7, 0x5e, 0xe0, 0xe5, 0x15, 0x20, 0x08, - 0x47, 0x5a, 0xda, 0x3f, 0x42, 0x07, 0x7b, 0xc7, 0xea, 0x12, 0xab, 0x8c, 0xf7, 0x83, 0xca, 0x68, - 0x1e, 0x38, 0xee, 0x80, 0x95, 0x43, 0xb8, 0x4c, 0xf1, 0x38, 0x2c, 0xb5, 0x08, 0x42, 0xb4, 0x12, - 0x04, 0x19, 0x4b, 0x54, 0xb8, 0x03, 0xe6, 0x83, 0x81, 0x87, 0x66, 0x7e, 0xac, 0x49, 0xdf, 0x25, - 0x9d, 0x81, 0xe3, 0x16, 0xf3, 0x41, 0x93, 0x3e, 0x0a, 0x07, 0x20, 0x5e, 0x70, 0x47, 0xc1, 0xe8, - 0x13, 0x68, 0xe0, 0xbb, 0x20, 0x1d, 0x36, 0x13, 0xc0, 0x7e, 0x2b, 0x6b, 0x46, 0x5e, 0xd4, 0x49, - 0x78, 0x33, 0xf2, 0xc2, 0x36, 0x12, 0xea, 0xe0, 0x87, 0x60, 0x6e, 0xcf, 0x72, 0x3a, 0x0f, 0x82, - 0xdb, 0xe2, 0x62, 0xb4, 0x91, 0x22, 0xc5, 0xd9, 0xb9, 0xde, 0x10, 0x7b, 0x11, 0xd4, 0xf0, 0xfa, - 0x67, 0x22, 0xc2, 0x02, 0xa6, 0xd3, 0x9c, 0x77, 0xdc, 0xb3, 0x4c, 0xfb, 0x41, 0x7b, 0xa0, 0xbb, - 0x5d, 0x32, 0x50, 0x57, 0xa2, 0x69, 0x4e, 0x68, 0x5a, 0x4c, 0x11, 0x4e, 0x73, 0x31, 0x14, 0xe1, - 0x38, 0x8b, 0xce, 0x98, 0xdc, 0x75, 0xfb, 0x40, 0xf7, 0x0e, 0x54, 0xc8, 0xea, 0x94, 0x75, 0x38, - 0x0e, 0x6f, 0xeb, 0xde, 0x41, 0x18, 0xf6, 0x08, 0x42, 0x58, 0xd2, 0xc3, 0xdb, 0x60, 0x41, 0xd4, - 0x26, 0x31, 0xd4, 0x8b, 0xcc, 0x05, 0x4b, 0x85, 0x10, 0x0c, 0x53, 0x21, 0x44, 0x10, 0x8e, 0xb4, - 0xb0, 0x28, 0xe6, 0x48, 0x3e, 0xfd, 0x5d, 0x99, 0x4e, 0xfb, 0x73, 0x0c, 0x92, 0x9b, 0x60, 0xf1, - 0xe4, 0x54, 0xb3, 0xcc, 0x3b, 0x7e, 0x3f, 0x36, 0xcf, 0xf0, 0x8e, 0xdf, 0x97, 0x27, 0x19, 0x99, - 0x01, 0x3f, 0x94, 0xd2, 0xd2, 0xf6, 0xd4, 0xc5, 0xbc, 0xb2, 0x3a, 0x5b, 0x7c, 0x45, 0xce, 0xc3, - 0x9a, 0x37, 0x95, 0x87, 0x35, 0x0f, 0xfd, 0xc7, 0xd7, 0x92, 0xa6, 0x3d, 0xc0, 0x12, 0x0d, 0xee, - 0x03, 0x1e, 0xa5, 0x36, 0xab, 0xaa, 0x65, 0xe6, 0x6a, 0xeb, 0xa9, 0xaf, 0x2d, 0x61, 0xfd, 0x21, - 0x3b, 0xfa, 0xa6, 0xf9, 0x09, 0xa1, 0x81, 0xda, 0x0b, 0x84, 0x30, 0x50, 0x21, 0x12, 0x38, 0xfe, - 0xec, 0xf1, 0xcd, 0x98, 0x19, 0x8e, 0x8c, 0x60, 0x19, 0x2c, 0x5a, 0x4e, 0x47, 0xb7, 0xda, 0xfb, - 0x96, 0xde, 0xf5, 0xd4, 0x7f, 0xcd, 0xb3, 0x1f, 0xcf, 0x4e, 0x91, 0xe1, 0x9b, 0x14, 0x0e, 0x37, - 0x1d, 0x41, 0x08, 0x4b, 0x7a, 0xb8, 0x0d, 0x96, 0x44, 0xba, 0xf3, 0x5c, 0xf8, 0xf7, 0x3c, 0x3b, - 0x49, 0x16, 0x43, 0xa1, 0x10, 0xd9, 0xb0, 0x22, 0x57, 0x09, 0x4f, 0x07, 0x99, 0x01, 0xbf, 0x47, - 0x07, 0x24, 0x3a, 0xc4, 0x19, 0x62, 0x5a, 0xbb, 0xce, 0x47, 0x21, 0x06, 0x85, 0x55, 0x26, 0x64, - 0x36, 0x0b, 0xb1, 0x27, 0x88, 0xc1, 0xbc, 0x69, 0x1f, 0xe9, 0x96, 0x19, 0x4c, 0x63, 0xef, 0x3c, - 0xf5, 0x35, 0x80, 0xf5, 0x87, 0x55, 0x8e, 0xf2, 0xcb, 0x91, 0x3d, 0x4a, 0x97, 0x23, 0x93, 0xe9, - 0xe5, 0x28, 0x31, 0x71, 0xc0, 0xa3, 0x15, 0x63, 0x3b, 0xb1, 0x81, 0x37, 0xcd, 0x5c, 0xb3, 0x8a, - 0xb1, 0x9d, 0xf8, 0xb0, 0xcb, 0x2b, 0x26, 0x86, 0x22, 0x1c, 0x67, 0xbd, 0x9b, 0xfa, 0xed, 0xe7, - 0xda, 0x0c, 0x7a, 0xa2, 0x80, 0x85, 0xb0, 0x7a, 0x69, 0xe3, 0x64, 0x21, 0x4b, 0xb2, 0x88, 0xb1, - 0x44, 0x3d, 0xe0, 0xa1, 0xe2, 0x89, 0x7a, 0xc0, 0x62, 0xc4, 0x30, 0x7a, 0x31, 0x38, 0xfb, 0xfb, - 0x1e, 0x19, 0xb0, 0x96, 0x9c, 0xe4, 0x17, 0x03, 0x47, 0xc2, 0x8b, 0x81, 0x8b, 0x08, 0x0b, 0x1c, - 0xbe, 0x21, 0x1a, 0x73, 0x82, 0xa5, 0xd0, 0x8d, 0xd3, 0x1b, 0x73, 0x90, 0x81, 0xbc, 0x3f, 0xbf, - 0x07, 0x16, 0x1e, 0x12, 0xfd, 0x01, 0x3f, 0x4a, 0x5e, 0x0d, 0xac, 0x65, 0x51, 0x50, 0x1c, 0x23, - 0x6f, 0x59, 0x01, 0x80, 0x70, 0xa8, 0x13, 0xbf, 0xf1, 0x3e, 0x98, 0xe3, 0x9d, 0x12, 0x36, 0x40, - 0xba, 0xe3, 0x1c, 0xda, 0x83, 0xe8, 0x7d, 0x69, 0x45, 0x1e, 0xf4, 0x98, 0xa6, 0xf8, 0x7f, 0xa2, - 0x85, 0x85, 0xd4, 0xf0, 0x8c, 0x04, 0x40, 0x27, 0x34, 0xa1, 0x42, 0xbf, 0x52, 0xc0, 0xbc, 0x30, - 0x84, 0xdb, 0xe1, 0xdc, 0x9b, 0x2a, 0xbe, 0x73, 0xe2, 0x02, 0xf8, 0xfa, 0x77, 0x28, 0xb9, 0xf9, - 0x8b, 0xd7, 0xa9, 0x23, 0xdd, 0x3a, 0xe4, 0x81, 0x4a, 0xf1, 0xd7, 0x29, 0x06, 0x84, 0xfd, 0x94, - 0x49, 0x08, 0x73, 0x14, 0xfd, 0x22, 0x05, 0xe6, 0x31, 0xed, 0xd3, 0xde, 0x00, 0xbe, 0x1d, 0xee, - 0x62, 0xb6, 0xf8, 0xf2, 0x59, 0xcb, 0x46, 0xc5, 0x18, 0x0c, 0xdc, 0xd1, 0x3d, 0x9f, 0x38, 0xf7, - 0x3d, 0x1f, 0xdc, 0xc9, 0xc9, 0x73, 0xdc, 0xc9, 0x51, 0xba, 0xa4, 0x9e, 0x3b, 0x5d, 0x66, 0xcf, - 0x9f, 0x2e, 0x41, 0x06, 0xcf, 0x9d, 0x23, 0x83, 0xeb, 0xe0, 0xc2, 0xbe, 0xeb, 0xf4, 0xd8, 0x6b, - 0x99, 0xe3, 0xea, 0xee, 0xb1, 0xa8, 0x56, 0x56, 0x52, 0x54, 0xd3, 0x0a, 0x14, 0x61, 0x49, 0xc5, - 0x50, 0x84, 0xe3, 0xac, 0x78, 0xae, 0xa6, 0x9f, 0x2f, 0x57, 0xe1, 0x6d, 0x90, 0xe6, 0x4d, 0xd6, - 0x76, 0xd8, 0x4d, 0x3f, 0x5b, 0x7c, 0x89, 0xf6, 0x09, 0x86, 0xd5, 0x9c, 0x30, 0x07, 0x85, 0x1c, - 0xfe, 0xec, 0x80, 0x80, 0xfe, 0xac, 0x80, 0x34, 0x26, 0x5e, 0xdf, 0xb1, 0x3d, 0xf2, 0x4d, 0x93, - 0x60, 0x0d, 0xa4, 0x0c, 0x7d, 0xa0, 0xb3, 0x14, 0x10, 0xd1, 0xa3, 0x72, 0x18, 0x3d, 0x2a, 0x20, - 0xcc, 0x30, 0xf8, 0x01, 0x48, 0x75, 0x1c, 0x83, 0x1f, 0xfe, 0x05, 0x79, 0x18, 0xa8, 0xb8, 0xae, - 0xe3, 0x96, 0x1c, 0x43, 0xdc, 0x74, 0x94, 0x14, 0x3a, 0xa0, 0x02, 0xc2, 0x0c, 0x43, 0x7f, 0x52, - 0x40, 0xa6, 0xec, 0x3c, 0xb4, 0x2d, 0x47, 0x37, 0x1a, 0xae, 0xd3, 0xa5, 0x6f, 0x4c, 0xdf, 0x68, - 0xdc, 0x6c, 0x83, 0xf9, 0x43, 0x36, 0xac, 0x06, 0x03, 0xe7, 0xcd, 0xf8, 0xcd, 0x7b, 0x72, 0x11, - 0x3e, 0xd9, 0x46, 0xef, 0xb6, 0xc2, 0x38, 0xf4, 0xcf, 0x65, 0x84, 0x03, 0x05, 0xfa, 0x63, 0x12, - 0x64, 0xcf, 0x76, 0x04, 0x7b, 0x60, 0x91, 0x33, 0xdb, 0xd2, 0x57, 0xa4, 0xd5, 0xf3, 0xec, 0x81, - 0xcd, 0x03, 0xec, 0x7e, 0x3b, 0x0c, 0xe5, 0xf0, 0x7e, 0x8b, 0x20, 0x84, 0x25, 0xfd, 0x73, 0xbd, - 0x1a, 0x4b, 0xd3, 0x63, 0xf2, 0xdb, 0x4f, 0x8f, 0x4d, 0xb0, 0xcc, 0x53, 0x34, 0xf8, 0x86, 0x91, - 0xca, 0x27, 0x57, 0x67, 0x8b, 0xeb, 0x63, 0x5f, 0x5b, 0xda, 0xe3, 0x97, 0x48, 0xf0, 0xf5, 0x62, - 0x25, 0x4a, 0x56, 0x0e, 0x06, 0xd9, 0x96, 0x99, 0xc1, 0x31, 0x2e, 0xdc, 0x8c, 0x0d, 0x17, 0xbc, - 0xd4, 0xbf, 0x73, 0xce, 0x61, 0x42, 0x1a, 0x1e, 0xd0, 0x1c, 0x48, 0x35, 0x4c, 0xbb, 0x8b, 0xde, - 0x03, 0xb3, 0x25, 0xcb, 0xf1, 0x58, 0xc7, 0x71, 0x89, 0xee, 0x39, 0xb6, 0x9c, 0x4a, 0x1c, 0x09, - 0x8f, 0x9a, 0x8b, 0x08, 0x0b, 0x7c, 0xed, 0x8b, 0x24, 0x58, 0x94, 0x3e, 0xfa, 0xc1, 0x1f, 0x82, - 0x6b, 0xbb, 0x95, 0x66, 0xb3, 0xb0, 0x55, 0x69, 0xb7, 0xee, 0x35, 0x2a, 0xed, 0xd2, 0xce, 0x9d, - 0x66, 0xab, 0x82, 0xdb, 0xa5, 0x7a, 0x6d, 0xb3, 0xba, 0x95, 0x99, 0xc9, 0x5e, 0x1f, 0x8e, 0xf2, - 0xaa, 0x64, 0x11, 0xff, 0x3c, 0xf7, 0x5d, 0x00, 0x63, 0xe6, 0xd5, 0x5a, 0xb9, 0xf2, 0xe3, 0x8c, - 0x92, 0xbd, 0x34, 0x1c, 0xe5, 0x33, 0x92, 0x15, 0x7f, 0xeb, 0xfb, 0x01, 0x78, 0x71, 0x9a, 0xdd, - 0xbe, 0xd3, 0x28, 0x17, 0x5a, 0x95, 0x4c, 0x22, 0x9b, 0x1d, 0x8e, 0xf2, 0x57, 0x4e, 0x1a, 0x89, - 0x14, 0x7c, 0x1d, 0x5c, 0x8a, 0x99, 0xe2, 0xca, 0x8f, 0xee, 0x54, 0x9a, 0xad, 0x4c, 0x32, 0x7b, - 0x65, 0x38, 0xca, 0x43, 0xc9, 0x2a, 0xb8, 0x26, 0x36, 0xc0, 0xe5, 0x13, 0x16, 0xcd, 0x46, 0xbd, - 0xd6, 0xac, 0x64, 0x52, 0xd9, 0xab, 0xc3, 0x51, 0xfe, 0x62, 0xcc, 0x44, 0x74, 0x95, 0x12, 0xc8, - 0xc5, 0x6c, 0xca, 0xf5, 0x8f, 0x6b, 0x3b, 0xf5, 0x42, 0xb9, 0xdd, 0xc0, 0xf5, 0x2d, 0x5c, 0x69, - 0x36, 0x33, 0xb3, 0x59, 0x6d, 0x38, 0xca, 0x5f, 0x93, 0x8c, 0xa7, 0x2a, 0x7c, 0x0d, 0xac, 0xc4, - 0x9c, 0x34, 0xaa, 0xb5, 0xad, 0xcc, 0x5c, 0xf6, 0xe2, 0x70, 0x94, 0x7f, 0x41, 0xb2, 0xa3, 0x67, - 0x39, 0x15, 0xbf, 0xd2, 0x4e, 0xbd, 0x59, 0xc9, 0xcc, 0x4f, 0xc5, 0x8f, 0x1d, 0xf8, 0xda, 0x1f, - 0x14, 0x00, 0xa7, 0xbf, 0xb3, 0xc2, 0x77, 0x80, 0x1a, 0x38, 0x29, 0xd5, 0x77, 0x1b, 0x74, 0x9f, - 0xd5, 0x7a, 0xad, 0x5d, 0xab, 0xd7, 0x2a, 0x99, 0x99, 0x58, 0x54, 0x25, 0xab, 0x9a, 0x63, 0x13, - 0x58, 0x07, 0x57, 0x4f, 0xb3, 0xdc, 0xb9, 0xff, 0x56, 0x46, 0xc9, 0x6e, 0x0c, 0x47, 0xf9, 0xcb, - 0xd3, 0x86, 0x3b, 0xf7, 0xdf, 0xfa, 0xea, 0xd7, 0x2f, 0x9f, 0xae, 0x58, 0xfb, 0xbd, 0x02, 0x16, - 0xe5, 0xad, 0xbd, 0x01, 0x2e, 0xc9, 0x8e, 0x77, 0x2b, 0xad, 0x42, 0xb9, 0xd0, 0x2a, 0x64, 0x66, - 0xf8, 0x19, 0x48, 0xd4, 0x5d, 0x32, 0xd0, 0x59, 0xdb, 0x7d, 0x15, 0xac, 0xc4, 0x7e, 0x45, 0xe5, - 0x6e, 0x05, 0x07, 0x19, 0x25, 0xef, 0x9f, 0x1c, 0x11, 0x17, 0xbe, 0x06, 0xa0, 0x4c, 0x2e, 0xec, - 0x7c, 0x5c, 0xb8, 0xd7, 0xcc, 0x24, 0xb2, 0x97, 0x87, 0xa3, 0xfc, 0x8a, 0xc4, 0x2e, 0x58, 0x0f, - 0xf5, 0x63, 0x6f, 0xed, 0xaf, 0x09, 0xb0, 0x24, 0xbf, 0xaa, 0xc0, 0xd7, 0xc0, 0xc5, 0xcd, 0xea, - 0x0e, 0xcd, 0xc4, 0xcd, 0x3a, 0x3f, 0x01, 0x2a, 0x66, 0x66, 0xf8, 0x72, 0x32, 0x95, 0x3e, 0xc3, - 0xef, 0x03, 0xf5, 0x04, 0xbd, 0x5c, 0xc5, 0x95, 0x52, 0xab, 0x8e, 0xef, 0x65, 0x94, 0xec, 0x8b, - 0x34, 0x60, 0xb2, 0x4d, 0xd9, 0x74, 0x59, 0x0b, 0x3a, 0x86, 0xb7, 0xc1, 0xb5, 0x13, 0x86, 0xcd, - 0x7b, 0xbb, 0x3b, 0xd5, 0xda, 0x47, 0x7c, 0xbd, 0x44, 0xf6, 0xc6, 0x70, 0x94, 0xbf, 0x2a, 0xdb, - 0x36, 0xf9, 0xdb, 0x1f, 0x85, 0xd2, 0x0a, 0xdc, 0x06, 0xf9, 0x33, 0xec, 0xa3, 0x0d, 0x24, 0xb3, - 0x68, 0x38, 0xca, 0x5f, 0x3f, 0xc5, 0x49, 0xb8, 0x8f, 0xb4, 0x02, 0xdf, 0x04, 0x57, 0x4e, 0xf7, - 0x14, 0xd4, 0xc5, 0x29, 0xf6, 0x6b, 0x7f, 0x57, 0xc0, 0x42, 0x78, 0xeb, 0xd1, 0xa0, 0x55, 0x30, - 0xae, 0xd3, 0x26, 0x51, 0xae, 0xb4, 0x6b, 0xf5, 0x36, 0x93, 0x82, 0xa0, 0x85, 0xbc, 0x9a, 0xc3, - 0x1e, 0x69, 0x8e, 0x4b, 0xf4, 0xad, 0x4a, 0xad, 0x82, 0xab, 0xa5, 0xe0, 0x44, 0x43, 0xf6, 0x16, - 0xb1, 0x89, 0x6b, 0x76, 0xe0, 0x5b, 0xe0, 0x6a, 0xdc, 0x79, 0xf3, 0x4e, 0x69, 0x3b, 0x88, 0x12, - 0xdb, 0xa0, 0xb4, 0x40, 0xf3, 0xb0, 0x73, 0xc0, 0x0e, 0xe6, 0xed, 0x98, 0x55, 0xb5, 0x76, 0xb7, - 0xb0, 0x53, 0x2d, 0x73, 0xab, 0x64, 0x56, 0x1d, 0x8e, 0xf2, 0x97, 0x42, 0x2b, 0xf1, 0xe2, 0x41, - 0xcd, 0xd6, 0xbe, 0x52, 0x40, 0xee, 0xeb, 0x2f, 0x2f, 0xf8, 0x31, 0x78, 0x85, 0xc5, 0x6b, 0xaa, - 0x15, 0x88, 0xbe, 0xc5, 0x63, 0x58, 0x68, 0x34, 0x2a, 0xb5, 0x72, 0x66, 0x26, 0xbb, 0x3a, 0x1c, - 0xe5, 0x6f, 0x7e, 0xbd, 0xcb, 0x42, 0xbf, 0x4f, 0x6c, 0xe3, 0x9c, 0x8e, 0x37, 0xeb, 0x78, 0xab, - 0xd2, 0xca, 0x28, 0xe7, 0x71, 0xbc, 0xe9, 0xb8, 0x5d, 0x32, 0x28, 0xee, 0x7e, 0xf9, 0x24, 0x37, - 0xf3, 0xf8, 0x49, 0x6e, 0xe6, 0xcb, 0xa7, 0x39, 0xe5, 0xf1, 0xd3, 0x9c, 0xf2, 0x9b, 0x67, 0xb9, - 0x99, 0xcf, 0x9f, 0xe5, 0x94, 0xc7, 0xcf, 0x72, 0x33, 0xff, 0x78, 0x96, 0x9b, 0xb9, 0xff, 0x6a, - 0xd7, 0x1c, 0x1c, 0x1c, 0xee, 0xad, 0x77, 0x9c, 0xde, 0x2d, 0xef, 0xd8, 0xee, 0x0c, 0x0e, 0x4c, - 0xbb, 0x2b, 0x3d, 0xc9, 0xff, 0xb7, 0xed, 0xcd, 0xb1, 0xa7, 0x37, 0xff, 0x1b, 0x00, 0x00, 0xff, - 0xff, 0xf7, 0xe3, 0xa9, 0xd7, 0x86, 0x1b, 0x00, 0x00, + // 2920 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0x4f, 0x6c, 0x1b, 0xc7, + 0xd5, 0xd7, 0x92, 0x94, 0x44, 0x8d, 0x64, 0x87, 0x1a, 0xff, 0x63, 0x68, 0x5b, 0xcb, 0x6f, 0xe2, + 0x7c, 0x9f, 0xa2, 0x7c, 0xb1, 0x13, 0x27, 0xf9, 0xbe, 0x34, 0x4e, 0x1d, 0x88, 0x22, 0x25, 0x33, + 0x91, 0x49, 0x65, 0x28, 0xdb, 0xb5, 0xd1, 0x82, 0x58, 0x71, 0x47, 0xd4, 0xc2, 0xe4, 0x2e, 0xbb, + 0x4b, 0xea, 0x4f, 0xd0, 0x4b, 0x5b, 0xa0, 0x08, 0x74, 0x28, 0x8a, 0x9c, 0x8a, 0xa2, 0x42, 0x83, + 0x02, 0x45, 0x6f, 0x05, 0x7a, 0xe8, 0xa1, 0x39, 0xf5, 0xe8, 0xa3, 0x11, 0xa0, 0x40, 0xd1, 0xc3, + 0x02, 0xb1, 0x2f, 0x2d, 0x8f, 0x3c, 0xf6, 0x54, 0xcc, 0x9b, 0xd9, 0xd9, 0x59, 0xfd, 0x09, 0x94, + 0xe4, 0xd0, 0xdb, 0xbe, 0xdf, 0xfb, 0xb3, 0xc3, 0x37, 0xef, 0xfd, 0xe6, 0xcd, 0x12, 0x5d, 0xec, + 0x38, 0x1b, 0x37, 0x7a, 0xbe, 0xd7, 0xf7, 0x5a, 0x5e, 0xe7, 0xc6, 0x06, 0xeb, 0x5d, 0x07, 0x01, + 0x67, 0x23, 0xac, 0x30, 0xc5, 0x76, 0xfb, 0x02, 0x2c, 0xbc, 0xe4, 0xb3, 0x9e, 0x17, 0x08, 0xf3, + 0x8d, 0xc1, 0xe6, 0x8d, 0xb6, 0xd7, 0xf6, 0x40, 0x80, 0x27, 0x61, 0x44, 0x9e, 0x19, 0x68, 0xfc, + 0x0e, 0xeb, 0x74, 0x3c, 0xbc, 0x84, 0xa6, 0x6d, 0xb6, 0xed, 0xb4, 0x58, 0xd3, 0xb5, 0xba, 0x2c, + 0x6f, 0x14, 0x8d, 0xf9, 0xa9, 0x12, 0x19, 0x86, 0x26, 0x12, 0x70, 0xcd, 0xea, 0xb2, 0x51, 0x68, + 0xe6, 0x76, 0xbb, 0x9d, 0x77, 0x49, 0x0c, 0x11, 0xaa, 0xe9, 0x79, 0x90, 0x56, 0xc7, 0x61, 0x6e, + 0x5f, 0x04, 0x49, 0xc5, 0x41, 0x04, 0x9c, 0x08, 0x12, 0x43, 0x84, 0x6a, 0x7a, 0x5c, 0x47, 0x67, + 0x65, 0x90, 0x6d, 0xe6, 0x07, 0x8e, 0xe7, 0xe6, 0xd3, 0x10, 0x67, 0x7e, 0x18, 0x9a, 0x67, 0x84, + 0xe6, 0xbe, 0x50, 0x8c, 0x42, 0xf3, 0x9c, 0x16, 0x4a, 0xa2, 0x84, 0x26, 0xad, 0xc8, 0x1f, 0x0d, + 0x34, 0x71, 0x87, 0x59, 0x36, 0xf3, 0xf1, 0x22, 0xca, 0xf4, 0xf7, 0x7a, 0xe2, 0xe7, 0x9d, 0xbd, + 0x79, 0xe1, 0x7a, 0x94, 0xb8, 0xeb, 0x77, 0x59, 0x10, 0x58, 0x6d, 0xb6, 0xbe, 0xd7, 0x63, 0xa5, + 0x8b, 0xc3, 0xd0, 0x04, 0xb3, 0x51, 0x68, 0x22, 0x88, 0xcf, 0x05, 0x42, 0x01, 0xc3, 0x36, 0x9a, + 0x6e, 0x79, 0xdd, 0x9e, 0xcf, 0x02, 0x58, 0x5b, 0x0a, 0x22, 0x5d, 0x39, 0x12, 0x69, 0x29, 0xb6, + 0x29, 0x5d, 0x1b, 0x86, 0xa6, 0xee, 0x34, 0x0a, 0xcd, 0x59, 0xb1, 0xee, 0x18, 0x23, 0x54, 0xb7, + 0x20, 0xdf, 0x47, 0x67, 0x96, 0x3a, 0x83, 0xa0, 0xcf, 0xfc, 0x25, 0xcf, 0xdd, 0x74, 0xda, 0xf8, + 0x43, 0x34, 0xb9, 0xe9, 0x75, 0x6c, 0xe6, 0x07, 0x79, 0xa3, 0x98, 0x9e, 0x9f, 0xbe, 0x99, 0x8b, + 0x5f, 0xb9, 0x0c, 0x8a, 0x92, 0xf9, 0x24, 0x34, 0xc7, 0x86, 0xa1, 0x19, 0x19, 0x8e, 0x42, 0x73, + 0x06, 0x5e, 0x23, 0x64, 0x42, 0x23, 0x05, 0xf9, 0x3c, 0x83, 0x26, 0x84, 0x13, 0xbe, 0x8e, 0x52, + 0x8e, 0x2d, 0xb7, 0x7b, 0xee, 0x59, 0x68, 0xa6, 0xaa, 0xe5, 0x61, 0x68, 0xa6, 0x1c, 0x7b, 0x14, + 0x9a, 0x59, 0xf0, 0x76, 0x6c, 0xf2, 0xe9, 0xd3, 0x6b, 0xa9, 0x6a, 0x99, 0xa6, 0x1c, 0x1b, 0x5f, + 0x47, 0xe3, 0x1d, 0x6b, 0x83, 0x75, 0xe4, 0xe6, 0xe6, 0x87, 0xa1, 0x29, 0x80, 0x51, 0x68, 0x4e, + 0x83, 0x3d, 0x48, 0x84, 0x0a, 0x14, 0xdf, 0x42, 0x53, 0x3e, 0xb3, 0xec, 0xa6, 0xe7, 0x76, 0xf6, + 0x60, 0x23, 0xb3, 0xa5, 0xb9, 0x61, 0x68, 0x66, 0x39, 0x58, 0x77, 0x3b, 0x7b, 0xa3, 0xd0, 0x3c, + 0x0b, 0x6e, 0x11, 0x40, 0xa8, 0xd2, 0xe1, 0x26, 0xc2, 0x4e, 0xdb, 0xf5, 0x7c, 0xd6, 0xec, 0x31, + 0xbf, 0xeb, 0x40, 0x6a, 0x82, 0x7c, 0x06, 0xa2, 0xbc, 0x3e, 0x0c, 0xcd, 0x59, 0xa1, 0x5d, 0x8b, + 0x95, 0xa3, 0xd0, 0xbc, 0x24, 0x56, 0x7d, 0x58, 0x43, 0xe8, 0x51, 0x6b, 0xfc, 0x21, 0x3a, 0x23, + 0x5f, 0x60, 0xb3, 0x0e, 0xeb, 0xb3, 0xfc, 0x38, 0xc4, 0xfe, 0xef, 0x61, 0x68, 0xce, 0x08, 0x45, + 0x19, 0xf0, 0x51, 0x68, 0x62, 0x2d, 0xac, 0x00, 0x09, 0x4d, 0xd8, 0x60, 0x1b, 0x9d, 0xb7, 0x9d, + 0xc0, 0xda, 0xe8, 0xb0, 0x66, 0x9f, 0x75, 0x7b, 0x4d, 0xc7, 0xb5, 0xd9, 0x2e, 0x0b, 0xf2, 0x13, + 0x10, 0xf3, 0xe6, 0x30, 0x34, 0xb1, 0xd4, 0xaf, 0xb3, 0x6e, 0xaf, 0x2a, 0xb4, 0xa3, 0xd0, 0xcc, + 0x8b, 0x9e, 0x3a, 0xa2, 0x22, 0xf4, 0x18, 0x7b, 0x7c, 0x13, 0x4d, 0xf4, 0xac, 0x41, 0xc0, 0xec, + 0xfc, 0x24, 0xc4, 0x2d, 0x0c, 0x43, 0x53, 0x22, 0x6a, 0xc3, 0x85, 0x48, 0xa8, 0xc4, 0x79, 0xf1, + 0x88, 0x2e, 0x0d, 0xf2, 0xb9, 0xc3, 0xc5, 0x53, 0x06, 0x45, 0x5c, 0x3c, 0xd2, 0x50, 0xc5, 0x12, + 0x32, 0xa1, 0x91, 0x82, 0xfc, 0x65, 0x02, 0x4d, 0x08, 0x27, 0x5c, 0x52, 0xc5, 0x33, 0x53, 0xba, + 0xc9, 0x03, 0xfc, 0x3d, 0x34, 0xb3, 0x42, 0x57, 0x2d, 0x9f, 0x54, 0x4c, 0x9f, 0x3c, 0xbd, 0x66, + 0x68, 0x05, 0xb5, 0x80, 0x32, 0x1a, 0x59, 0x40, 0xef, 0xb9, 0x82, 0x26, 0x44, 0xef, 0xb9, 0x40, + 0x10, 0x80, 0xe1, 0xf7, 0xd0, 0x94, 0x65, 0xdb, 0xbc, 0x47, 0x58, 0x90, 0x4f, 0x17, 0xd3, 0xbc, + 0x66, 0x87, 0xa1, 0x19, 0x83, 0xa3, 0xd0, 0x3c, 0x03, 0x5e, 0x12, 0x21, 0x34, 0xd6, 0xe1, 0x1f, + 0x24, 0x3b, 0x37, 0x73, 0x98, 0x03, 0xbe, 0x5d, 0xcb, 0xf2, 0x4a, 0x6f, 0x31, 0x5f, 0x52, 0xdf, + 0xb8, 0x68, 0x28, 0x5e, 0xe9, 0x1c, 0x94, 0xc4, 0x27, 0x2a, 0x3d, 0x02, 0x08, 0x55, 0x3a, 0xbc, + 0x82, 0x66, 0xba, 0xd6, 0x6e, 0x33, 0x60, 0x3f, 0x1c, 0x30, 0xb7, 0xc5, 0xa0, 0x66, 0xd2, 0x62, + 0x15, 0x5d, 0x6b, 0xb7, 0x21, 0x61, 0xb5, 0x0a, 0x0d, 0x23, 0x54, 0xb7, 0xc0, 0x25, 0x84, 0x1c, + 0xb7, 0xef, 0x7b, 0xf6, 0xa0, 0xc5, 0x7c, 0x59, 0x22, 0xc0, 0xc0, 0x31, 0xaa, 0x18, 0x38, 0x86, + 0x08, 0xd5, 0xf4, 0xb8, 0x8d, 0xb2, 0x50, 0xbb, 0x4d, 0xc7, 0xce, 0x67, 0x8b, 0xc6, 0x7c, 0xa6, + 0xb4, 0x2a, 0x37, 0x77, 0x12, 0xaa, 0x10, 0xf6, 0x36, 0x7a, 0xe4, 0x35, 0x03, 0xd6, 0x55, 0x5b, + 0x65, 0x5f, 0xca, 0x9c, 0x37, 0x22, 0xb3, 0x5f, 0xc5, 0x8f, 0x34, 0xb2, 0xc7, 0x3f, 0x42, 0x85, + 0xe0, 0xb1, 0xc3, 0x3b, 0x45, 0xbc, 0xbb, 0xef, 0x78, 0x6e, 0xd3, 0x67, 0x5d, 0x6f, 0xdb, 0xea, + 0x04, 0xf9, 0x29, 0x58, 0xfc, 0xed, 0x61, 0x68, 0xe6, 0xb9, 0x55, 0x55, 0x33, 0xa2, 0xd2, 0x66, + 0x14, 0x9a, 0x73, 0xf0, 0xc6, 0x93, 0x0c, 0x08, 0x3d, 0xd1, 0x17, 0xef, 0xa2, 0x17, 0x99, 0xdb, + 0xf2, 0xf7, 0x7a, 0xf0, 0xda, 0x9e, 0x15, 0x04, 0x3b, 0x9e, 0x6f, 0x37, 0xfb, 0xde, 0x63, 0xe6, + 0xe6, 0x11, 0x14, 0xf5, 0x7b, 0xc3, 0xd0, 0xbc, 0x14, 0x1b, 0xad, 0x49, 0x9b, 0x75, 0x6e, 0x32, + 0x0a, 0xcd, 0xab, 0xf0, 0xee, 0x13, 0xf4, 0x84, 0x9e, 0xe4, 0x49, 0x7e, 0x62, 0xa0, 0x71, 0x48, + 0x06, 0xef, 0x66, 0x41, 0xca, 0x92, 0x82, 0xa1, 0x9b, 0x05, 0x72, 0x84, 0xbe, 0x25, 0x8e, 0x2b, + 0x68, 0x7c, 0xd3, 0xe9, 0xb0, 0x20, 0x9f, 0x82, 0x5e, 0xc6, 0xda, 0x41, 0xe0, 0x74, 0x58, 0xd5, + 0xdd, 0xf4, 0x4a, 0x97, 0x65, 0x37, 0x0b, 0x43, 0xd5, 0x4b, 0x5c, 0x22, 0x54, 0x80, 0xe4, 0x13, + 0x03, 0x4d, 0xc3, 0x22, 0xee, 0xf5, 0x6c, 0xab, 0xcf, 0xfe, 0x93, 0x4b, 0xf9, 0xf3, 0x34, 0xca, + 0x46, 0x0e, 0x8a, 0x10, 0x8c, 0x53, 0x10, 0xc2, 0x02, 0xca, 0x04, 0xce, 0xc7, 0x0c, 0x0e, 0x96, + 0xb4, 0xb0, 0xe5, 0xb2, 0xb2, 0xe5, 0x02, 0xa1, 0x80, 0xe1, 0xf7, 0x11, 0xea, 0x7a, 0xb6, 0xb3, + 0xe9, 0x30, 0xbb, 0x19, 0x40, 0x83, 0xa6, 0x4b, 0x45, 0xce, 0x1e, 0x11, 0xda, 0x18, 0x85, 0xe6, + 0x0b, 0xa2, 0xbd, 0x22, 0x84, 0xd0, 0x58, 0xcb, 0xf9, 0x43, 0x05, 0xd8, 0xd8, 0xcb, 0xcf, 0x40, + 0x67, 0xbc, 0x17, 0x75, 0x46, 0x63, 0xcb, 0xf3, 0xfb, 0xd0, 0x0e, 0xea, 0x35, 0xa5, 0x3d, 0xd5, + 0x6a, 0x31, 0x44, 0x78, 0x27, 0x48, 0x63, 0xaa, 0x99, 0xe2, 0x55, 0x34, 0x19, 0x0d, 0x3c, 0xbc, + 0xf2, 0x13, 0x24, 0x7d, 0x9f, 0xb5, 0xfa, 0x9e, 0x5f, 0x2a, 0x46, 0x24, 0xbd, 0xad, 0x06, 0x20, + 0xd1, 0x70, 0xdb, 0xd1, 0xe8, 0x13, 0x69, 0xf0, 0xbb, 0x28, 0xab, 0xc8, 0x04, 0xc1, 0x6f, 0x05, + 0x32, 0x0a, 0x62, 0x26, 0x11, 0x64, 0x14, 0x28, 0x1a, 0x51, 0x3a, 0xfc, 0x01, 0x9a, 0xd8, 0xe8, + 0x78, 0xad, 0xc7, 0xd1, 0x69, 0x71, 0x2e, 0x5e, 0x48, 0x89, 0xe3, 0xb0, 0xaf, 0x57, 0xe5, 0x5a, + 0xa4, 0xa9, 0x3a, 0xfe, 0x41, 0x24, 0x54, 0xc2, 0x7c, 0x9a, 0x0b, 0xf6, 0xba, 0x1d, 0xc7, 0x7d, + 0xdc, 0xec, 0x5b, 0x7e, 0x9b, 0xf5, 0xf3, 0xb3, 0xf1, 0x34, 0x27, 0x35, 0xeb, 0xa0, 0x50, 0xd3, + 0x5c, 0x02, 0x25, 0x34, 0x69, 0xc5, 0x67, 0x4c, 0x11, 0xba, 0xb9, 0x65, 0x05, 0x5b, 0x79, 0x0c, + 0x7d, 0x0a, 0x0c, 0x27, 0xe0, 0x3b, 0x56, 0xb0, 0xa5, 0xd2, 0x1e, 0x43, 0x84, 0x6a, 0x7a, 0x7c, + 0x1b, 0x4d, 0xc9, 0xde, 0x64, 0x76, 0xfe, 0x1c, 0x84, 0x80, 0x52, 0x50, 0xa0, 0x2a, 0x05, 0x85, + 0x10, 0x1a, 0x6b, 0x71, 0x49, 0xce, 0x91, 0x62, 0xfa, 0xbb, 0x78, 0xb4, 0xec, 0x4f, 0x31, 0x48, + 0x2e, 0xa3, 0xe9, 0xc3, 0x53, 0xcd, 0x19, 0xc1, 0xf8, 0xbd, 0xc4, 0x3c, 0x23, 0x18, 0xbf, 0xa7, + 0x4f, 0x32, 0xba, 0x05, 0xfe, 0x40, 0x2b, 0x4b, 0x37, 0xc8, 0x4f, 0x17, 0x8d, 0xf9, 0xf1, 0xd2, + 0x2b, 0x7a, 0x1d, 0xd6, 0x82, 0x23, 0x75, 0x58, 0x0b, 0xc8, 0xbf, 0x42, 0x33, 0xed, 0xb8, 0x7d, + 0xaa, 0x99, 0xe1, 0x4d, 0x24, 0xb2, 0xd4, 0x84, 0xae, 0x3a, 0x03, 0xa1, 0x56, 0x9e, 0x85, 0xe6, + 0x0c, 0xb5, 0x76, 0x60, 0xeb, 0x1b, 0xce, 0xc7, 0x8c, 0x27, 0x6a, 0x23, 0x12, 0x54, 0xa2, 0x14, + 0x12, 0x05, 0xfe, 0xf4, 0xe9, 0xb5, 0x84, 0x1b, 0x8d, 0x9d, 0xf0, 0x7d, 0x94, 0xed, 0x75, 0xac, + 0xfe, 0xa6, 0xe7, 0x77, 0xf3, 0x67, 0xa1, 0xd8, 0xb5, 0x1c, 0xae, 0x49, 0x4d, 0xd9, 0xea, 0x5b, + 0x25, 0x22, 0xcb, 0x4c, 0xd9, 0xab, 0xca, 0x8d, 0x00, 0x42, 0x95, 0x0e, 0x97, 0xd1, 0x74, 0xc7, + 0x6b, 0x59, 0x9d, 0xe6, 0x66, 0xc7, 0x6a, 0x07, 0xf9, 0x7f, 0x4c, 0x42, 0x52, 0xa1, 0x3a, 0x00, + 0x5f, 0xe6, 0xb0, 0x4a, 0x46, 0x0c, 0x11, 0xaa, 0xe9, 0xf1, 0x1d, 0x34, 0x23, 0xdb, 0x48, 0xd4, + 0xd8, 0x3f, 0x27, 0xa1, 0x42, 0x60, 0x6f, 0xa4, 0x42, 0x56, 0xd9, 0xac, 0xde, 0x7d, 0xa2, 0xcc, + 0x74, 0x0b, 0xfc, 0x7f, 0x7c, 0xf0, 0xe2, 0xc3, 0xa1, 0x2d, 0xa7, 0xc0, 0x2b, 0x62, 0xc4, 0x02, + 0x48, 0x75, 0xaf, 0x94, 0x61, 0xc6, 0x82, 0x27, 0x4c, 0xd1, 0xa4, 0xe3, 0x6e, 0x5b, 0x1d, 0x27, + 0x9a, 0xf2, 0xde, 0x79, 0x16, 0x9a, 0x88, 0x5a, 0x3b, 0x55, 0x81, 0x8a, 0x43, 0x17, 0x1e, 0xb5, + 0x43, 0x17, 0x64, 0x7e, 0xe8, 0x6a, 0x96, 0x34, 0xb2, 0xe3, 0x9d, 0xe8, 0x7a, 0x89, 0x41, 0x3a, + 0x0b, 0xa1, 0xa1, 0x13, 0x5d, 0x2f, 0x39, 0x44, 0x8b, 0x4e, 0x4c, 0xa0, 0x84, 0x26, 0xad, 0xde, + 0xcd, 0xfc, 0xf2, 0x33, 0x73, 0x8c, 0x7c, 0x69, 0xa0, 0x29, 0xc5, 0x0a, 0x9c, 0x90, 0x21, 0x65, + 0x69, 0xc8, 0x18, 0x34, 0xc0, 0x96, 0x48, 0x95, 0x68, 0x80, 0x2d, 0xc8, 0x11, 0x60, 0xfc, 0xc0, + 0xf1, 0x36, 0x37, 0x03, 0xd6, 0x07, 0xaa, 0x4f, 0x8b, 0x03, 0x47, 0x20, 0xea, 0xc0, 0x11, 0x22, + 0xa1, 0x12, 0xc7, 0x6f, 0x48, 0xc2, 0x4f, 0x41, 0x69, 0x5e, 0x3d, 0x9e, 0xf0, 0xa3, 0xca, 0x16, + 0xbc, 0x7f, 0x0b, 0x4d, 0xed, 0x30, 0xeb, 0xb1, 0xd8, 0x4a, 0xd1, 0x65, 0x40, 0x85, 0x1c, 0x94, + 0xdb, 0x28, 0x0a, 0x2a, 0x02, 0x08, 0x55, 0x3a, 0xf9, 0x1b, 0x1f, 0xa1, 0x09, 0xc1, 0xc0, 0x78, + 0x0d, 0x65, 0x5b, 0xde, 0xc0, 0xed, 0xc7, 0xf7, 0xb0, 0x59, 0x7d, 0x80, 0x04, 0x4d, 0xe9, 0xbf, + 0xa2, 0x9a, 0x8d, 0x4c, 0xd5, 0x1e, 0x49, 0x80, 0x4f, 0x7e, 0x52, 0x45, 0x7e, 0x6a, 0xa0, 0x49, + 0xe9, 0x88, 0xef, 0xa8, 0x79, 0x3a, 0x53, 0x7a, 0xe7, 0xd0, 0xc1, 0xf2, 0xd5, 0x77, 0x33, 0xfd, + 0x50, 0x91, 0xd7, 0xb4, 0x6d, 0xab, 0x33, 0x10, 0x89, 0xca, 0x88, 0x6b, 0x1a, 0x00, 0x8a, 0xa7, + 0x41, 0x22, 0x54, 0xa0, 0xe4, 0x77, 0x06, 0x9a, 0xd1, 0xfb, 0x8e, 0x33, 0xdc, 0xc0, 0x75, 0x76, + 0x61, 0x31, 0x89, 0x83, 0xfd, 0x9e, 0xeb, 0xec, 0x42, 0x67, 0x16, 0x9e, 0x84, 0xa6, 0xc1, 0x37, + 0x80, 0xdb, 0xa9, 0x0d, 0xe0, 0x02, 0xa1, 0x80, 0xe1, 0x8f, 0xd0, 0xe4, 0x8e, 0xe3, 0xda, 0xde, + 0x4e, 0x00, 0xcb, 0x98, 0xd6, 0x87, 0xed, 0x07, 0x42, 0x01, 0x91, 0x8a, 0x32, 0x52, 0x64, 0xad, + 0xd2, 0x25, 0x65, 0x42, 0x23, 0x0d, 0xf9, 0x59, 0x0a, 0x65, 0xa3, 0x15, 0xf0, 0x13, 0xdd, 0xdb, + 0x71, 0x99, 0xaf, 0x7f, 0xb2, 0x00, 0x1a, 0x07, 0x54, 0xce, 0xdc, 0x82, 0x9d, 0x14, 0x42, 0x68, + 0xac, 0xe5, 0x01, 0xda, 0xbe, 0x37, 0xe8, 0xe9, 0x9f, 0x2b, 0x20, 0x00, 0xa0, 0x89, 0x00, 0x0a, + 0x21, 0x34, 0xd6, 0xe2, 0x5b, 0x28, 0x3d, 0x70, 0x6c, 0xa8, 0xf6, 0xf1, 0xd2, 0x2b, 0xcf, 0x42, + 0x33, 0x7d, 0x0f, 0xf6, 0x88, 0xa3, 0xa3, 0xd0, 0x9c, 0x12, 0x29, 0x71, 0x6c, 0x8d, 0x13, 0xb9, + 0x05, 0xe5, 0x7a, 0xee, 0xdc, 0x76, 0x6c, 0x28, 0x49, 0xe9, 0xbc, 0x22, 0x9c, 0xdb, 0x9a, 0x73, + 0x3b, 0xe9, 0xbc, 0xc2, 0x9d, 0x39, 0xf6, 0x6b, 0x03, 0x4d, 0x6b, 0x39, 0xfc, 0xf6, 0xb9, 0x58, + 0x45, 0x67, 0x45, 0x00, 0x27, 0x68, 0xc2, 0x0f, 0x84, 0x7c, 0xc8, 0xbb, 0x30, 0x68, 0xaa, 0xc1, + 0x0a, 0xc7, 0xd5, 0x5d, 0x58, 0x07, 0x09, 0x4d, 0xd8, 0x90, 0x1f, 0x67, 0xd0, 0x24, 0xe5, 0xf3, + 0x44, 0xd0, 0xc7, 0x6f, 0xab, 0xaa, 0x1e, 0x2f, 0xbd, 0x7c, 0x52, 0x19, 0xc7, 0xbf, 0x31, 0xba, + 0x18, 0xc6, 0xf3, 0x68, 0xea, 0xd4, 0xf3, 0x68, 0x34, 0x3b, 0xa6, 0x4f, 0x31, 0x3b, 0xc6, 0xf4, + 0x93, 0xf9, 0xda, 0xf4, 0x33, 0x7e, 0x7a, 0xfa, 0x89, 0x18, 0x71, 0xe2, 0x14, 0x8c, 0x58, 0x47, + 0x67, 0x37, 0x7d, 0xaf, 0x0b, 0x9f, 0x0f, 0x3c, 0xdf, 0xf2, 0xf7, 0x24, 0xfb, 0x03, 0x45, 0x73, + 0xcd, 0x7a, 0xa4, 0x50, 0x14, 0x9d, 0x40, 0x09, 0x4d, 0x5a, 0x25, 0xb9, 0x2f, 0xfb, 0xf5, 0xb8, + 0x0f, 0xdf, 0x46, 0x59, 0x31, 0x0c, 0xb8, 0x1e, 0x4c, 0xa4, 0xe3, 0xa5, 0x97, 0x78, 0x93, 0x02, + 0x56, 0xf3, 0x54, 0x93, 0x4a, 0x59, 0xfd, 0xec, 0xc8, 0x80, 0xfc, 0xc1, 0x40, 0x59, 0xca, 0x82, + 0x9e, 0xe7, 0x06, 0xec, 0x9b, 0x16, 0xc1, 0x02, 0xca, 0xd8, 0x56, 0xdf, 0x82, 0x12, 0x90, 0xd9, + 0xe3, 0xb2, 0xca, 0x1e, 0x17, 0x08, 0x05, 0x0c, 0xbf, 0x8f, 0x32, 0x2d, 0xcf, 0x16, 0x9b, 0x7f, + 0x56, 0x1f, 0x5a, 0x2b, 0xbe, 0xef, 0xf9, 0x4b, 0x9e, 0x2d, 0x27, 0x32, 0x6e, 0xa4, 0x02, 0x70, + 0x81, 0x50, 0xc0, 0xc8, 0xef, 0x0d, 0x94, 0x2b, 0x7b, 0x3b, 0x6e, 0xc7, 0xb3, 0xec, 0x35, 0xdf, + 0x6b, 0xf3, 0x9b, 0xfd, 0x37, 0xba, 0x16, 0x35, 0xd1, 0xe4, 0x00, 0x2e, 0x55, 0xd1, 0xc5, 0xe8, + 0x5a, 0x72, 0x42, 0x3c, 0xfc, 0x12, 0x71, 0x03, 0x8b, 0xbf, 0xc1, 0x48, 0x67, 0x15, 0x5f, 0xc8, + 0x84, 0x46, 0x0a, 0xf2, 0xdb, 0x34, 0x2a, 0x9c, 0x1c, 0x08, 0x77, 0xd1, 0xb4, 0xb0, 0x6c, 0x6a, + 0x5f, 0x3b, 0xe7, 0x4f, 0xb3, 0x06, 0x98, 0x5b, 0x61, 0x5e, 0x1a, 0x28, 0x59, 0xcd, 0x4b, 0x31, + 0x44, 0xa8, 0xa6, 0xff, 0x5a, 0x9f, 0x70, 0xb4, 0x5b, 0x4e, 0xfa, 0xdb, 0xdf, 0x72, 0x1a, 0xe8, + 0x8c, 0x28, 0xd1, 0xe8, 0x5b, 0x5b, 0xa6, 0x98, 0x9e, 0x1f, 0x2f, 0x5d, 0xe7, 0x9c, 0xb5, 0x21, + 0x86, 0x92, 0xe8, 0x2b, 0xdb, 0x6c, 0x5c, 0xac, 0x02, 0x8c, 0xaa, 0x2d, 0x37, 0x46, 0x13, 0xb6, + 0x78, 0x39, 0x31, 0x04, 0x8b, 0x56, 0xff, 0x9f, 0x53, 0x0e, 0xbd, 0xda, 0x90, 0x4b, 0x26, 0x50, + 0x66, 0xcd, 0x71, 0xdb, 0xe4, 0x16, 0x1a, 0x5f, 0xea, 0x78, 0x01, 0x30, 0x8e, 0xcf, 0xac, 0xc0, + 0x73, 0xf5, 0x52, 0x12, 0x88, 0xda, 0x6a, 0x21, 0x12, 0x2a, 0xf1, 0x85, 0xcf, 0xd3, 0x68, 0x5a, + 0xfb, 0x38, 0x8d, 0xbf, 0x8b, 0x2e, 0xdf, 0xad, 0x34, 0x1a, 0x8b, 0x2b, 0x95, 0xe6, 0xfa, 0xc3, + 0xb5, 0x4a, 0x73, 0x69, 0xf5, 0x5e, 0x63, 0xbd, 0x42, 0x9b, 0x4b, 0xf5, 0xda, 0x72, 0x75, 0x25, + 0x37, 0x56, 0xb8, 0xb2, 0x7f, 0x50, 0xcc, 0x6b, 0x1e, 0xc9, 0xcf, 0xc8, 0xff, 0x8b, 0x70, 0xc2, + 0xbd, 0x5a, 0x2b, 0x57, 0xbe, 0x97, 0x33, 0x0a, 0xe7, 0xf7, 0x0f, 0x8a, 0x39, 0xcd, 0x4b, 0x7c, + 0x9d, 0xf8, 0x0e, 0x7a, 0xf1, 0xa8, 0x75, 0xf3, 0xde, 0x5a, 0x79, 0x71, 0xbd, 0x92, 0x4b, 0x15, + 0x0a, 0xfb, 0x07, 0xc5, 0x8b, 0x87, 0x9d, 0x64, 0x09, 0xbe, 0x8e, 0xce, 0x27, 0x5c, 0x69, 0xe5, + 0xa3, 0x7b, 0x95, 0xc6, 0x7a, 0x2e, 0x5d, 0xb8, 0xb8, 0x7f, 0x50, 0xc4, 0x9a, 0x57, 0x74, 0x4c, + 0xdc, 0x44, 0x17, 0x0e, 0x79, 0x34, 0xd6, 0xea, 0xb5, 0x46, 0x25, 0x97, 0x29, 0x5c, 0xda, 0x3f, + 0x28, 0x9e, 0x4b, 0xb8, 0x48, 0x56, 0x59, 0x42, 0x73, 0x09, 0x9f, 0x72, 0xfd, 0x41, 0x6d, 0xb5, + 0xbe, 0x58, 0x6e, 0xae, 0xd1, 0xfa, 0x0a, 0xad, 0x34, 0x1a, 0xb9, 0xf1, 0x82, 0xb9, 0x7f, 0x50, + 0xbc, 0xac, 0x39, 0x1f, 0xe9, 0xf0, 0x05, 0x34, 0x9b, 0x08, 0xb2, 0x56, 0xad, 0xad, 0xe4, 0x26, + 0x0a, 0xe7, 0xf6, 0x0f, 0x8a, 0x2f, 0x68, 0x7e, 0x7c, 0x2f, 0x8f, 0xe4, 0x6f, 0x69, 0xb5, 0xde, + 0xa8, 0xe4, 0x26, 0x8f, 0xe4, 0x0f, 0x36, 0x7c, 0xe1, 0x37, 0x06, 0xc2, 0x47, 0xff, 0x0f, 0xc0, + 0xef, 0xa0, 0x7c, 0x14, 0x64, 0xa9, 0x7e, 0x77, 0x8d, 0xaf, 0xb3, 0x5a, 0xaf, 0x35, 0x6b, 0xf5, + 0x5a, 0x25, 0x37, 0x96, 0xc8, 0xaa, 0xe6, 0x55, 0xf3, 0x5c, 0x86, 0xeb, 0xe8, 0xd2, 0x71, 0x9e, + 0xab, 0x8f, 0xde, 0xca, 0x19, 0x85, 0x9b, 0xfb, 0x07, 0xc5, 0x0b, 0x47, 0x1d, 0x57, 0x1f, 0xbd, + 0xf5, 0xc5, 0xcf, 0x5f, 0x3e, 0x5e, 0xb1, 0xc0, 0xc7, 0x08, 0x7d, 0x69, 0x6f, 0xa0, 0xf3, 0x7a, + 0xe0, 0xbb, 0x95, 0xf5, 0xc5, 0xf2, 0xe2, 0xfa, 0x62, 0x6e, 0x4c, 0xec, 0x81, 0x66, 0x7a, 0x97, + 0xf5, 0x2d, 0xa0, 0xdd, 0x57, 0xd1, 0x6c, 0xe2, 0x57, 0x54, 0xee, 0x57, 0x68, 0x54, 0x51, 0xfa, + 0xfa, 0xd9, 0x36, 0xf3, 0xf1, 0x6b, 0x08, 0xeb, 0xc6, 0x8b, 0xab, 0x0f, 0x16, 0x1f, 0x36, 0x72, + 0xa9, 0xc2, 0x85, 0xfd, 0x83, 0xe2, 0xac, 0x66, 0xbd, 0xd8, 0xd9, 0xb1, 0xf6, 0x82, 0x85, 0x3f, + 0xa5, 0xd0, 0x8c, 0x7e, 0xa5, 0xc6, 0xaf, 0xa1, 0x73, 0xcb, 0xd5, 0x55, 0x5e, 0x89, 0xcb, 0x75, + 0xb1, 0x03, 0x5c, 0xcc, 0x8d, 0x89, 0xd7, 0xe9, 0xa6, 0xfc, 0x19, 0xff, 0x3f, 0xca, 0x1f, 0x32, + 0x2f, 0x57, 0x69, 0x65, 0x69, 0xbd, 0x4e, 0x1f, 0xe6, 0x8c, 0xc2, 0x8b, 0x3c, 0x61, 0xba, 0x4f, + 0xd9, 0xf1, 0x81, 0x82, 0xf6, 0xf0, 0x6d, 0x74, 0xf9, 0x90, 0x63, 0xe3, 0xe1, 0xdd, 0xd5, 0x6a, + 0xed, 0x43, 0xf1, 0xbe, 0x54, 0xe1, 0xea, 0xfe, 0x41, 0xf1, 0x92, 0xee, 0xdb, 0x10, 0x5f, 0x29, + 0x38, 0x94, 0x35, 0xf0, 0x1d, 0x54, 0x3c, 0xc1, 0x3f, 0x5e, 0x40, 0xba, 0x40, 0xf6, 0x0f, 0x8a, + 0x57, 0x8e, 0x09, 0xa2, 0xd6, 0x91, 0x35, 0xf0, 0x9b, 0xe8, 0xe2, 0xf1, 0x91, 0xa2, 0xbe, 0x38, + 0xc6, 0x7f, 0xe1, 0xaf, 0x06, 0x9a, 0x52, 0xa7, 0x1e, 0x4f, 0x5a, 0x85, 0xd2, 0x3a, 0x27, 0x89, + 0x72, 0xa5, 0x59, 0xab, 0x37, 0x41, 0x8a, 0x92, 0xa6, 0xec, 0x6a, 0x1e, 0x3c, 0xf2, 0x1a, 0xd7, + 0xcc, 0x57, 0x2a, 0xb5, 0x0a, 0xad, 0x2e, 0x45, 0x3b, 0xaa, 0xac, 0x57, 0x98, 0xcb, 0x7c, 0xa7, + 0x85, 0xdf, 0x42, 0x97, 0x92, 0xc1, 0x1b, 0xf7, 0x96, 0xee, 0x44, 0x59, 0x82, 0x05, 0x6a, 0x2f, + 0x68, 0x0c, 0x5a, 0x5b, 0xb0, 0x31, 0x6f, 0x27, 0xbc, 0xaa, 0xb5, 0xfb, 0x8b, 0xab, 0xd5, 0xb2, + 0xf0, 0x4a, 0x17, 0xf2, 0xfb, 0x07, 0xc5, 0xf3, 0xca, 0x4b, 0x5e, 0x64, 0xb9, 0xdb, 0xc2, 0x17, + 0x06, 0x9a, 0xfb, 0xea, 0xc3, 0x0b, 0x3f, 0x40, 0xaf, 0x40, 0xbe, 0x8e, 0x50, 0x81, 0xe4, 0x2d, + 0x91, 0xc3, 0xc5, 0xb5, 0xb5, 0x4a, 0xad, 0x9c, 0x1b, 0x2b, 0xcc, 0xef, 0x1f, 0x14, 0xaf, 0x7d, + 0x75, 0xc8, 0xc5, 0x5e, 0x8f, 0xb9, 0xf6, 0x29, 0x03, 0x2f, 0xd7, 0xe9, 0x4a, 0x65, 0x3d, 0x67, + 0x9c, 0x26, 0xf0, 0xb2, 0xe7, 0xb7, 0x59, 0xbf, 0x74, 0xf7, 0xc9, 0x97, 0x73, 0x63, 0x4f, 0xbf, + 0x9c, 0x1b, 0x7b, 0xf2, 0x6c, 0xce, 0x78, 0xfa, 0x6c, 0xce, 0xf8, 0xc5, 0xf3, 0xb9, 0xb1, 0xcf, + 0x9e, 0xcf, 0x19, 0x4f, 0x9f, 0xcf, 0x8d, 0xfd, 0xed, 0xf9, 0xdc, 0xd8, 0xa3, 0x57, 0xdb, 0x4e, + 0x7f, 0x6b, 0xb0, 0x71, 0xbd, 0xe5, 0x75, 0x6f, 0x04, 0x7b, 0x6e, 0xab, 0xbf, 0xe5, 0xb8, 0x6d, + 0xed, 0x49, 0xff, 0x5f, 0x78, 0x63, 0x02, 0x9e, 0xde, 0xfc, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xc7, 0x92, 0x60, 0x1e, 0x2e, 0x1e, 0x00, 0x00, } func (m *Hello) Marshal() (dAtA []byte, err error) { @@ -1582,6 +1723,16 @@ func (m *FileInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x82 } } + { + size, err := m.Platform.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 if m.RawBlockSize != 0 { i = encodeVarintBep(dAtA, i, uint64(m.RawBlockSize)) i-- @@ -1787,6 +1938,140 @@ func (m *Counter) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PlatformData) Marshal() (dAtA []byte, err error) { + size := m.ProtoSize() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PlatformData) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PlatformData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Windows != nil { + { + size, err := m.Windows.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.Unix != nil { + { + size, err := m.Unix.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintBep(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *UnixData) Marshal() (dAtA []byte, err error) { + size := m.ProtoSize() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UnixData) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UnixData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GID != 0 { + i = encodeVarintBep(dAtA, i, uint64(m.GID)) + i-- + dAtA[i] = 0x20 + } + if m.UID != 0 { + i = encodeVarintBep(dAtA, i, uint64(m.UID)) + i-- + dAtA[i] = 0x18 + } + if len(m.GroupName) > 0 { + i -= len(m.GroupName) + copy(dAtA[i:], m.GroupName) + i = encodeVarintBep(dAtA, i, uint64(len(m.GroupName))) + i-- + dAtA[i] = 0x12 + } + if len(m.OwnerName) > 0 { + i -= len(m.OwnerName) + copy(dAtA[i:], m.OwnerName) + i = encodeVarintBep(dAtA, i, uint64(len(m.OwnerName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *WindowsData) Marshal() (dAtA []byte, err error) { + size := m.ProtoSize() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *WindowsData) MarshalTo(dAtA []byte) (int, error) { + size := m.ProtoSize() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *WindowsData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.OwnerIsGroup { + i-- + if m.OwnerIsGroup { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x10 + } + if len(m.OwnerName) > 0 { + i -= len(m.OwnerName) + copy(dAtA[i:], m.OwnerName) + i = encodeVarintBep(dAtA, i, uint64(len(m.OwnerName))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *Request) Marshal() (dAtA []byte, err error) { size := m.ProtoSize() dAtA = make([]byte, size) @@ -2287,6 +2572,8 @@ func (m *FileInfo) ProtoSize() (n int) { if m.RawBlockSize != 0 { n += 1 + sovBep(uint64(m.RawBlockSize)) } + l = m.Platform.ProtoSize() + n += 1 + l + sovBep(uint64(l)) if len(m.Blocks) > 0 { for _, e := range m.Blocks { l = e.ProtoSize() @@ -2367,6 +2654,62 @@ func (m *Counter) ProtoSize() (n int) { return n } +func (m *PlatformData) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Unix != nil { + l = m.Unix.ProtoSize() + n += 1 + l + sovBep(uint64(l)) + } + if m.Windows != nil { + l = m.Windows.ProtoSize() + n += 1 + l + sovBep(uint64(l)) + } + return n +} + +func (m *UnixData) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.OwnerName) + if l > 0 { + n += 1 + l + sovBep(uint64(l)) + } + l = len(m.GroupName) + if l > 0 { + n += 1 + l + sovBep(uint64(l)) + } + if m.UID != 0 { + n += 1 + sovBep(uint64(m.UID)) + } + if m.GID != 0 { + n += 1 + sovBep(uint64(m.GID)) + } + return n +} + +func (m *WindowsData) ProtoSize() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.OwnerName) + if l > 0 { + n += 1 + l + sovBep(uint64(l)) + } + if m.OwnerIsGroup { + n += 2 + } + return n +} + func (m *Request) ProtoSize() (n int) { if m == nil { return 0 @@ -3912,6 +4255,39 @@ func (m *FileInfo) Unmarshal(dAtA []byte) error { break } } + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Platform", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Platform.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex case 16: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field Blocks", wireType) @@ -4433,6 +4809,382 @@ func (m *Counter) Unmarshal(dAtA []byte) error { } return nil } +func (m *PlatformData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PlatformData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PlatformData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Unix", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Unix == nil { + m.Unix = &UnixData{} + } + if err := m.Unix.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Windows", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthBep + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthBep + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Windows == nil { + m.Windows = &WindowsData{} + } + if err := m.Windows.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipBep(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UnixData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UnixData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UnixData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OwnerName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthBep + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OwnerName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthBep + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GroupName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UID", wireType) + } + m.UID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.UID |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GID", wireType) + } + m.GID = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GID |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipBep(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *WindowsData) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: WindowsData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: WindowsData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OwnerName", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthBep + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthBep + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OwnerName = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field OwnerIsGroup", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowBep + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.OwnerIsGroup = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipBep(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthBep + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *Request) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/lib/protocol/bep_extensions.go b/lib/protocol/bep_extensions.go index 719aa6102..078e12216 100644 --- a/lib/protocol/bep_extensions.go +++ b/lib/protocol/bep_extensions.go @@ -53,14 +53,14 @@ func (m Hello) Magic() uint32 { func (f FileInfo) String() string { switch f.Type { case FileInfoTypeDirectory: - return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v}", - f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions) + return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, Platform:%v}", + f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.Platform) case FileInfoTypeFile: - return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d, Blocks:%v, BlocksHash:%x}", - f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize, f.Blocks, f.BlocksHash) + return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d, Blocks:%v, BlocksHash:%x, Platform:%v}", + f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize, f.Blocks, f.BlocksHash, f.Platform) case FileInfoTypeSymlink, FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile: - return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q}", - f.Name, f.Type, f.Sequence, f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget) + return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q, Platform:%v}", + f.Name, f.Type, f.Sequence, f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget, f.Platform) default: panic("mystery file type detected") } @@ -190,30 +190,42 @@ func WinsConflict(f, other FileIntf) bool { return f.FileVersion().Compare(other.FileVersion()) == ConcurrentGreater } -func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool { - return f.isEquivalent(other, modTimeWindow, false, false, 0) +type FileInfoComparison struct { + ModTimeWindow time.Duration + IgnorePerms bool + IgnoreBlocks bool + IgnoreFlags uint32 + IgnoreOwnership bool } -func (f FileInfo) IsEquivalentOptional(other FileInfo, modTimeWindow time.Duration, ignorePerms bool, ignoreBlocks bool, ignoreFlags uint32) bool { - return f.isEquivalent(other, modTimeWindow, ignorePerms, ignoreBlocks, ignoreFlags) +func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool { + return f.isEquivalent(other, FileInfoComparison{ModTimeWindow: modTimeWindow}) +} + +func (f FileInfo) IsEquivalentOptional(other FileInfo, comp FileInfoComparison) bool { + return f.isEquivalent(other, comp) } // isEquivalent checks that the two file infos represent the same actual file content, // i.e. it does purposely not check only selected (see below) struct members. // Permissions (config) and blocks (scanning) can be excluded from the comparison. // Any file info is not "equivalent", if it has different -// - type -// - deleted flag -// - invalid flag -// - permissions, unless they are ignored +// - type +// - deleted flag +// - invalid flag +// - permissions, unless they are ignored +// // A file is not "equivalent", if it has different -// - modification time (difference bigger than modTimeWindow) -// - size -// - blocks, unless there are no blocks to compare (scanning) +// - modification time (difference bigger than modTimeWindow) +// - size +// - blocks, unless there are no blocks to compare (scanning) +// - os data +// // A symlink is not "equivalent", if it has different -// - target +// - target +// // A directory does not have anything specific to check. -func (f FileInfo) isEquivalent(other FileInfo, modTimeWindow time.Duration, ignorePerms bool, ignoreBlocks bool, ignoreFlags uint32) bool { +func (f FileInfo) isEquivalent(other FileInfo, comp FileInfoComparison) bool { if f.MustRescan() || other.MustRescan() { // These are per definition not equivalent because they don't // represent a valid state, even if both happen to have the @@ -222,20 +234,37 @@ func (f FileInfo) isEquivalent(other FileInfo, modTimeWindow time.Duration, igno } // Mask out the ignored local flags before checking IsInvalid() below - f.LocalFlags &^= ignoreFlags - other.LocalFlags &^= ignoreFlags + f.LocalFlags &^= comp.IgnoreFlags + other.LocalFlags &^= comp.IgnoreFlags if f.Name != other.Name || f.Type != other.Type || f.Deleted != other.Deleted || f.IsInvalid() != other.IsInvalid() { return false } - if !ignorePerms && !f.NoPermissions && !other.NoPermissions && !PermsEqual(f.Permissions, other.Permissions) { + // 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 f.Platform.Windows != nil && other.Platform.Windows != nil { + if *f.Platform.Windows != *other.Platform.Windows { + return false + } + } + } + + if !comp.IgnorePerms && !f.NoPermissions && !other.NoPermissions && !PermsEqual(f.Permissions, other.Permissions) { return false } switch f.Type { case FileInfoTypeFile: - return f.Size == other.Size && ModTimeEqual(f.ModTime(), other.ModTime(), modTimeWindow) && (ignoreBlocks || f.BlocksEqual(other)) + return f.Size == other.Size && ModTimeEqual(f.ModTime(), other.ModTime(), comp.ModTimeWindow) && (comp.IgnoreBlocks || f.BlocksEqual(other)) case FileInfoTypeSymlink: return f.SymlinkTarget == other.SymlinkTarget case FileInfoTypeDirectory: diff --git a/lib/protocol/protocol_test.go b/lib/protocol/protocol_test.go index 54e3ec70e..f9bb7c476 100644 --- a/lib/protocol/protocol_test.go +++ b/lib/protocol/protocol_test.go @@ -872,10 +872,10 @@ func TestIsEquivalent(t *testing.T) { continue } - if res := tc.a.isEquivalent(tc.b, 0, ignPerms, ignBlocks, tc.ignFlags); res != tc.eq { + if res := tc.a.isEquivalent(tc.b, FileInfoComparison{IgnorePerms: ignPerms, IgnoreBlocks: ignBlocks, IgnoreFlags: tc.ignFlags}); res != tc.eq { t.Errorf("Case %d:\na: %v\nb: %v\na.IsEquivalent(b, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq) } - if res := tc.b.isEquivalent(tc.a, 0, ignPerms, ignBlocks, tc.ignFlags); res != tc.eq { + if res := tc.b.isEquivalent(tc.a, FileInfoComparison{IgnorePerms: ignPerms, IgnoreBlocks: ignBlocks, IgnoreFlags: tc.ignFlags}); res != tc.eq { t.Errorf("Case %d:\na: %v\nb: %v\nb.IsEquivalent(a, %v, %v) => %v, expected %v", i, tc.a, tc.b, ignPerms, ignBlocks, res, tc.eq) } } diff --git a/lib/scanner/virtualfs_test.go b/lib/scanner/virtualfs_test.go index 365747565..5eff7c11e 100644 --- a/lib/scanner/virtualfs_test.go +++ b/lib/scanner/virtualfs_test.go @@ -15,6 +15,7 @@ import ( "time" "github.com/syncthing/syncthing/lib/fs" + "github.com/syncthing/syncthing/lib/protocol" ) type infiniteFS struct { @@ -54,6 +55,10 @@ func (i infiniteFS) Open(name string) (fs.File, error) { return &fakeFile{name, i.filesize, 0}, nil } +func (i infiniteFS) PlatformData(name string) (protocol.PlatformData, error) { + return protocol.PlatformData{}, nil +} + type singleFileFS struct { fs.Filesystem name string @@ -100,6 +105,10 @@ func (s singleFileFS) Options() []fs.Option { return nil } +func (s singleFileFS) PlatformData(name string) (protocol.PlatformData, error) { + return protocol.PlatformData{}, nil +} + type fakeInfo struct { name string size int64 diff --git a/lib/scanner/walk.go b/lib/scanner/walk.go index 447cb0f09..71618a15e 100644 --- a/lib/scanner/walk.go +++ b/lib/scanner/walk.go @@ -40,9 +40,10 @@ type Config struct { // The Filesystem provides an abstraction on top of the actual filesystem. Filesystem fs.Filesystem // If IgnorePerms is true, changes to permission bits will not be - // detected. Scanned files will get zero permission bits and the - // NoPermissionBits flag set. + // detected. IgnorePerms bool + // If IgnoreOwnership is true, changes to ownership will not be detected. + IgnoreOwnership bool // When AutoNormalize is set, file names that are in UTF8 but incorrect // normalization form will be corrected. AutoNormalize bool @@ -381,13 +382,22 @@ func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileIn } } - f, _ := CreateFileInfo(info, relPath, nil) + f, err := CreateFileInfo(info, relPath, w.Filesystem) + if err != nil { + return err + } f = w.updateFileInfo(f, curFile) f.NoPermissions = w.IgnorePerms f.RawBlockSize = blockSize if hasCurFile { - if curFile.IsEquivalentOptional(f, w.ModTimeWindow, w.IgnorePerms, true, w.LocalFlags) { + if curFile.IsEquivalentOptional(f, protocol.FileInfoComparison{ + ModTimeWindow: w.ModTimeWindow, + IgnorePerms: w.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: w.LocalFlags, + IgnoreOwnership: w.IgnoreOwnership, + }) { l.Debugln(w, "unchanged:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm) return nil } @@ -416,12 +426,21 @@ func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileIn func (w *walker) walkDir(ctx context.Context, relPath string, info fs.FileInfo, finishedChan chan<- ScanResult) error { curFile, hasCurFile := w.CurrentFiler.CurrentFile(relPath) - f, _ := CreateFileInfo(info, relPath, nil) + f, err := CreateFileInfo(info, relPath, w.Filesystem) + if err != nil { + return err + } f = w.updateFileInfo(f, curFile) f.NoPermissions = w.IgnorePerms if hasCurFile { - if curFile.IsEquivalentOptional(f, w.ModTimeWindow, w.IgnorePerms, true, w.LocalFlags) { + if curFile.IsEquivalentOptional(f, protocol.FileInfoComparison{ + ModTimeWindow: w.ModTimeWindow, + IgnorePerms: w.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: w.LocalFlags, + IgnoreOwnership: w.IgnoreOwnership, + }) { l.Debugln(w, "unchanged:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm) return nil } @@ -466,7 +485,13 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, info fs.FileIn f = w.updateFileInfo(f, curFile) if hasCurFile { - if curFile.IsEquivalentOptional(f, w.ModTimeWindow, w.IgnorePerms, true, w.LocalFlags) { + if curFile.IsEquivalentOptional(f, protocol.FileInfoComparison{ + ModTimeWindow: w.ModTimeWindow, + IgnorePerms: w.IgnorePerms, + IgnoreBlocks: true, + IgnoreFlags: w.LocalFlags, + IgnoreOwnership: w.IgnoreOwnership, + }) { l.Debugln(w, "unchanged:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm) return nil } @@ -550,17 +575,28 @@ func (w *walker) normalizePath(path string, info fs.FileInfo) (normPath string, return "", errUTF8Conflict } -// updateFileInfo updates walker specific members of protocol.FileInfo that do not depend on type -func (w *walker) updateFileInfo(file, curFile protocol.FileInfo) protocol.FileInfo { - if file.Type == protocol.FileInfoTypeFile && runtime.GOOS == "windows" { +// updateFileInfo updates walker specific members of protocol.FileInfo that +// do not depend on type, and things that should be preserved from the +// previous version of the FileInfo. +func (w *walker) updateFileInfo(dst, src protocol.FileInfo) protocol.FileInfo { + if dst.Type == protocol.FileInfoTypeFile && runtime.GOOS == "windows" { // If we have an existing index entry, copy the executable bits // from there. - file.Permissions |= (curFile.Permissions & 0111) + dst.Permissions |= (src.Permissions & 0111) } - file.Version = curFile.Version.Update(w.ShortID) - file.ModifiedBy = w.ShortID - file.LocalFlags = w.LocalFlags - return file + dst.Version = src.Version.Update(w.ShortID) + dst.ModifiedBy = w.ShortID + dst.LocalFlags = w.LocalFlags + + // Copy OS data from src to dst, unless it was already set on dst. + if dst.Platform.Unix == nil { + dst.Platform.Unix = src.Platform.Unix + } + if dst.Platform.Windows == nil { + dst.Platform.Windows = src.Platform.Windows + } + + return dst } func handleError(ctx context.Context, context, path string, err error, finishedChan chan<- ScanResult) { @@ -632,6 +668,11 @@ func (noCurrentFiler) CurrentFile(name string) (protocol.FileInfo, bool) { func CreateFileInfo(fi fs.FileInfo, name string, filesystem fs.Filesystem) (protocol.FileInfo, error) { f := protocol.FileInfo{Name: name} + if plat, err := filesystem.PlatformData(name); err == nil { + f.Platform = plat + } else { + return protocol.FileInfo{}, fmt.Errorf("reading platform data: %w", err) + } if fi.IsSymlink() { f.Type = protocol.FileInfoTypeSymlink target, err := filesystem.ReadSymlink(name) diff --git a/lib/scanner/walk_test.go b/lib/scanner/walk_test.go index 00f2456d7..165cd7183 100644 --- a/lib/scanner/walk_test.go +++ b/lib/scanner/walk_test.go @@ -543,6 +543,79 @@ func TestWalkReceiveOnly(t *testing.T) { } } +func TestScanOwnershipPOSIX(t *testing.T) { + // This test works on all operating systems because the FakeFS is always POSIXy. + + fakeFS := fs.NewFilesystem(fs.FilesystemTypeFake, "TestScanOwnership") + current := make(fakeCurrentFiler) + + fakeFS.Create("root-owned") + fakeFS.Create("user-owned") + fakeFS.Lchown("user-owned", "1234", "5678") + fakeFS.Mkdir("user-owned-dir", 0755) + fakeFS.Lchown("user-owned-dir", "2345", "6789") + + expected := []struct { + name string + uid, gid int + }{ + {"root-owned", 0, 0}, + {"user-owned", 1234, 5678}, + {"user-owned-dir", 2345, 6789}, + } + + files := walkDir(fakeFS, ".", current, nil, 0) + if len(files) != len(expected) { + t.Fatalf("expected %d items, not %d", len(expected), len(files)) + } + for i := range expected { + if files[i].Name != expected[i].name { + t.Errorf("expected %s, got %s", expected[i].name, files[i].Name) + continue + } + + if files[i].Platform.Unix == nil { + t.Error("failed to load POSIX data on", files[i].Name) + continue + } + if files[i].Platform.Unix.UID != expected[i].uid { + t.Errorf("expected %d, got %d", expected[i].uid, files[i].Platform.Unix.UID) + } + if files[i].Platform.Unix.GID != expected[i].gid { + t.Errorf("expected %d, got %d", expected[i].gid, files[i].Platform.Unix.GID) + } + } +} + +func TestScanOwnershipWindows(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("This test only works on Windows") + } + + testFS := fs.NewFilesystem(fs.FilesystemTypeBasic, t.TempDir()) + current := make(fakeCurrentFiler) + + fd, err := testFS.Create("user-owned") + if err != nil { + t.Fatal(err) + } + fd.Close() + + files := walkDir(testFS, ".", current, nil, 0) + if len(files) != 1 { + t.Fatalf("expected %d items, not %d", 1, len(files)) + } + t.Log(files[0]) + + // The file should have an owner name set. + if files[0].Platform.Windows == nil { + t.Fatal("failed to load Windows data") + } + if files[0].Platform.Windows.OwnerName == "" { + t.Errorf("expected owner name to be set") + } +} + func walkDir(fs fs.Filesystem, dir string, cfiler CurrentFiler, matcher *ignore.Matcher, localFlags uint32) []protocol.FileInfo { cfg, cancel := testConfig() defer cancel() diff --git a/proto/lib/config/folderconfiguration.proto b/proto/lib/config/folderconfiguration.proto index a0a838186..1f76bde6a 100644 --- a/proto/lib/config/folderconfiguration.proto +++ b/proto/lib/config/folderconfiguration.proto @@ -54,6 +54,7 @@ message FolderConfiguration { fs.CopyRangeMethod copy_range_method = 32 [(ext.default) = "standard"]; bool case_sensitive_fs = 33 [(ext.goname) = "CaseSensitiveFS", (ext.xml) = "caseSensitiveFS", (ext.json) = "caseSensitiveFS"]; bool follow_junctions = 34 [(ext.goname) = "JunctionsAsDirs", (ext.xml) = "junctionsAsDirs", (ext.json) = "junctionsAsDirs"]; + bool sync_ownership = 35; // Legacy deprecated bool read_only = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"]; diff --git a/proto/lib/db/structs.proto b/proto/lib/db/structs.proto index f27acda32..9bb8300aa 100644 --- a/proto/lib/db/structs.proto +++ b/proto/lib/db/structs.proto @@ -36,6 +36,7 @@ message FileInfoTruncated { uint32 permissions = 4; int32 modified_ns = 11; int32 block_size = 13 [(ext.goname) = "RawBlockSize"]; + protocol.PlatformData platform = 14; // see bep.proto uint32 local_flags = 1000; diff --git a/proto/lib/protocol/bep.proto b/proto/lib/protocol/bep.proto index b12c94914..167cd22cf 100644 --- a/proto/lib/protocol/bep.proto +++ b/proto/lib/protocol/bep.proto @@ -107,6 +107,7 @@ message FileInfo { uint32 permissions = 4; int32 modified_ns = 11; int32 block_size = 13 [(ext.goname) = "RawBlockSize"]; + PlatformData platform = 14; // The local_flags fields stores flags that are relevant to the local // host only. It is not part of the protocol, doesn't get sent or @@ -147,6 +148,29 @@ message Counter { uint64 value = 2; } +message PlatformData { + UnixData unix = 1 [(gogoproto.nullable) = true]; + WindowsData windows = 2 [(gogoproto.nullable) = true]; +} + +message UnixData { + // The owner name and group name are set when known (i.e., could be + // resolved on the source device), while the UID and GID are always set + // as they come directly from the stat() call. + string owner_name = 1; + string group_name = 2; + int32 uid = 3 [(ext.goname) = "UID"]; + int32 gid = 4 [(ext.goname) = "GID"]; +} + +message WindowsData { + // Windows file objects have a single owner, which may be a user or a + // group. We keep the name of that account, and a flag to indicate what + // type it is. + string owner_name = 1; + bool owner_is_group = 2; +} + // Request message Request {