mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-18 11:05:14 +00:00
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.
This commit is contained in:
parent
34a5f087c8
commit
adce6fa473
2
go.mod
2
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
|
||||
|
3
go.sum
3
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=
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
lib/fs/basicfs_platformdata_unix.go
Normal file
18
lib/fs/basicfs_platformdata_unix.go
Normal file
@ -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
lib/fs/basicfs_platformdata_windows.go
Normal file
69
lib/fs/basicfs_platformdata_windows.go
Normal file
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -59,7 +59,7 @@ func (o *optionMtime) apply(fs Filesystem) Filesystem {
|
||||
return f
|
||||
}
|
||||
|
||||
func (_ *optionMtime) String() string {
|
||||
func (*optionMtime) String() string {
|
||||
return "mtime"
|
||||
}
|
||||
|
||||
|
55
lib/fs/platform_common.go
Normal file
55
lib/fs/platform_common.go
Normal file
@ -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
|
||||
}
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
lib/model/folder_sendrecv_unix.go
Normal file
45
lib/model/folder_sendrecv_unix.go
Normal file
@ -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
lib/model/folder_sendrecv_windows.go
Normal file
82
lib/model/folder_sendrecv_windows.go
Normal file
@ -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")
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -53,14 +53,14 @@ func (m Hello) Magic() uint32 {
|
||||
func (f FileInfo) String() string {
|
||||
switch f.Type {
|
||||
case FileInfoTypeDirectory:
|
||||
return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions)
|
||||
return fmt.Sprintf("Directory{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, Platform:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.Platform)
|
||||
case FileInfoTypeFile:
|
||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d, Blocks:%v, BlocksHash:%x}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize, f.Blocks, f.BlocksHash)
|
||||
return fmt.Sprintf("File{Name:%q, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, VersionHash:%x, Length:%d, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, BlockSize:%d, Blocks:%v, BlocksHash:%x, Platform:%v}",
|
||||
f.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Size, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.RawBlockSize, f.Blocks, f.BlocksHash, f.Platform)
|
||||
case FileInfoTypeSymlink, FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile:
|
||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q}",
|
||||
f.Name, f.Type, f.Sequence, f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget)
|
||||
return fmt.Sprintf("Symlink{Name:%q, Type:%v, Sequence:%d, Version:%v, VersionHash:%x, Deleted:%v, Invalid:%v, LocalFlags:0x%x, NoPermissions:%v, SymlinkTarget:%q, Platform:%v}",
|
||||
f.Name, f.Type, f.Sequence, f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget, f.Platform)
|
||||
default:
|
||||
panic("mystery file type detected")
|
||||
}
|
||||
@ -190,30 +190,42 @@ func WinsConflict(f, other FileIntf) bool {
|
||||
return f.FileVersion().Compare(other.FileVersion()) == ConcurrentGreater
|
||||
}
|
||||
|
||||
func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool {
|
||||
return f.isEquivalent(other, modTimeWindow, false, false, 0)
|
||||
type FileInfoComparison struct {
|
||||
ModTimeWindow time.Duration
|
||||
IgnorePerms bool
|
||||
IgnoreBlocks bool
|
||||
IgnoreFlags uint32
|
||||
IgnoreOwnership bool
|
||||
}
|
||||
|
||||
func (f FileInfo) IsEquivalentOptional(other FileInfo, modTimeWindow time.Duration, ignorePerms bool, ignoreBlocks bool, ignoreFlags uint32) bool {
|
||||
return f.isEquivalent(other, modTimeWindow, ignorePerms, ignoreBlocks, ignoreFlags)
|
||||
func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool {
|
||||
return f.isEquivalent(other, FileInfoComparison{ModTimeWindow: modTimeWindow})
|
||||
}
|
||||
|
||||
func (f FileInfo) IsEquivalentOptional(other FileInfo, comp FileInfoComparison) bool {
|
||||
return f.isEquivalent(other, comp)
|
||||
}
|
||||
|
||||
// isEquivalent checks that the two file infos represent the same actual file content,
|
||||
// i.e. it does purposely not check only selected (see below) struct members.
|
||||
// Permissions (config) and blocks (scanning) can be excluded from the comparison.
|
||||
// Any file info is not "equivalent", if it has different
|
||||
// - type
|
||||
// - deleted flag
|
||||
// - invalid flag
|
||||
// - permissions, unless they are ignored
|
||||
// - type
|
||||
// - deleted flag
|
||||
// - invalid flag
|
||||
// - permissions, unless they are ignored
|
||||
//
|
||||
// A file is not "equivalent", if it has different
|
||||
// - modification time (difference bigger than modTimeWindow)
|
||||
// - size
|
||||
// - blocks, unless there are no blocks to compare (scanning)
|
||||
// - modification time (difference bigger than modTimeWindow)
|
||||
// - size
|
||||
// - blocks, unless there are no blocks to compare (scanning)
|
||||
// - os data
|
||||
//
|
||||
// A symlink is not "equivalent", if it has different
|
||||
// - target
|
||||
// - target
|
||||
//
|
||||
// A directory does not have anything specific to check.
|
||||
func (f FileInfo) isEquivalent(other FileInfo, modTimeWindow time.Duration, ignorePerms bool, ignoreBlocks bool, ignoreFlags uint32) bool {
|
||||
func (f FileInfo) isEquivalent(other FileInfo, comp FileInfoComparison) bool {
|
||||
if f.MustRescan() || other.MustRescan() {
|
||||
// These are per definition not equivalent because they don't
|
||||
// represent a valid state, even if both happen to have the
|
||||
@ -222,20 +234,37 @@ func (f FileInfo) isEquivalent(other FileInfo, modTimeWindow time.Duration, igno
|
||||
}
|
||||
|
||||
// Mask out the ignored local flags before checking IsInvalid() below
|
||||
f.LocalFlags &^= ignoreFlags
|
||||
other.LocalFlags &^= ignoreFlags
|
||||
f.LocalFlags &^= comp.IgnoreFlags
|
||||
other.LocalFlags &^= comp.IgnoreFlags
|
||||
|
||||
if f.Name != other.Name || f.Type != other.Type || f.Deleted != other.Deleted || f.IsInvalid() != other.IsInvalid() {
|
||||
return false
|
||||
}
|
||||
|
||||
if !ignorePerms && !f.NoPermissions && !other.NoPermissions && !PermsEqual(f.Permissions, other.Permissions) {
|
||||
// OS data comparison is special: we consider a difference only if an
|
||||
// entry for the same OS exists on both sides and they are different.
|
||||
// Otherwise a file would become different as soon as it's synced from
|
||||
// Windows to Linux, as Linux would add a new POSIX entry for the file.
|
||||
if !comp.IgnoreOwnership && f.Platform != other.Platform {
|
||||
if f.Platform.Unix != nil && other.Platform.Unix != nil {
|
||||
if *f.Platform.Unix != *other.Platform.Unix {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if f.Platform.Windows != nil && other.Platform.Windows != nil {
|
||||
if *f.Platform.Windows != *other.Platform.Windows {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !comp.IgnorePerms && !f.NoPermissions && !other.NoPermissions && !PermsEqual(f.Permissions, other.Permissions) {
|
||||
return false
|
||||
}
|
||||
|
||||
switch f.Type {
|
||||
case FileInfoTypeFile:
|
||||
return f.Size == other.Size && ModTimeEqual(f.ModTime(), other.ModTime(), modTimeWindow) && (ignoreBlocks || f.BlocksEqual(other))
|
||||
return f.Size == other.Size && ModTimeEqual(f.ModTime(), other.ModTime(), comp.ModTimeWindow) && (comp.IgnoreBlocks || f.BlocksEqual(other))
|
||||
case FileInfoTypeSymlink:
|
||||
return f.SymlinkTarget == other.SymlinkTarget
|
||||
case FileInfoTypeDirectory:
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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"];
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user