Browse Source

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.
Jakob Borg 3 years ago
parent
commit
adce6fa473

+ 1 - 1
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

+ 2 - 1
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=

+ 1 - 4
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 {

+ 167 - 129
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)

+ 2 - 2
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)
 		}
 	}

+ 152 - 104
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)

+ 0 - 8
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 {

+ 18 - 0
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)
+}

+ 69 - 0
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)
+}

+ 2 - 1
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)
 	}
 

+ 17 - 0
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

+ 38 - 0
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

+ 1 - 1
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
 	}

+ 6 - 1
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

+ 18 - 13
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
 }

+ 1 - 1
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 {

+ 4 - 1
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)

+ 1 - 1
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"
 }
 

+ 55 - 0
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
+}

+ 8 - 1
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,

+ 5 - 1
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:

+ 5 - 1
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
 		}
 

+ 49 - 13
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

+ 2 - 1
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",

+ 45 - 0
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)
+}

+ 82 - 0
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")
+}

+ 927 - 175
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

+ 51 - 22
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
 }
 
+type FileInfoComparison struct {
+	ModTimeWindow   time.Duration
+	IgnorePerms     bool
+	IgnoreBlocks    bool
+	IgnoreFlags     uint32
+	IgnoreOwnership bool
+}
+
 func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool {
-	return f.isEquivalent(other, modTimeWindow, false, false, 0)
+	return f.isEquivalent(other, FileInfoComparison{ModTimeWindow: modTimeWindow})
 }
 
-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) 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:

+ 2 - 2
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)
 				}
 			}

+ 9 - 0
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

+ 56 - 15
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)

+ 73 - 0
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()

+ 1 - 0
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"];

+ 1 - 0
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;

+ 24 - 0
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 {