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/crypto v0.0.0-20210921155107-089bfa567519
|
||||||
golang.org/x/mod v0.5.1 // indirect
|
golang.org/x/mod v0.5.1 // indirect
|
||||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d
|
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/text v0.3.7
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||||
golang.org/x/tools v0.1.7
|
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-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-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-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-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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
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=
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if skippy < 0 {
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
return ErrInvalidLengthConfig
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) < 0 {
|
|
||||||
return ErrInvalidLengthConfig
|
return ErrInvalidLengthConfig
|
||||||
}
|
}
|
||||||
if (iNdEx + skippy) > l {
|
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"`
|
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"`
|
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"`
|
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
|
// Legacy deprecated
|
||||||
DeprecatedReadOnly bool `protobuf:"varint,9000,opt,name=read_only,json=readOnly,proto3" json:"-" xml:"ro,attr,omitempty"` // Deprecated: Do not use.
|
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.
|
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{
|
var fileDescriptor_44a9785876ed3afa = []byte{
|
||||||
// 2043 bytes of a gzipped FileDescriptorProto
|
// 2074 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x6f, 0x24, 0x47,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0xcd, 0x6f, 0xdc, 0xc6,
|
||||||
0x15, 0x77, 0x7b, 0xbf, 0xec, 0xf2, 0x77, 0x79, 0xbd, 0xdb, 0xf1, 0x26, 0x53, 0x93, 0x66, 0x36,
|
0x15, 0x17, 0xe5, 0x2f, 0x69, 0xf4, 0x3d, 0xb2, 0xec, 0xb1, 0x9c, 0xec, 0x6c, 0x98, 0x75, 0xaa,
|
||||||
0x38, 0x51, 0xe2, 0xdd, 0x75, 0x10, 0x12, 0x2b, 0x16, 0xc8, 0xd8, 0xb1, 0x58, 0x16, 0x67, 0x47,
|
0x04, 0x89, 0x6c, 0x2b, 0x45, 0x81, 0x1a, 0x75, 0xdb, 0xac, 0x14, 0xa1, 0xae, 0xab, 0x78, 0x41,
|
||||||
0xed, 0x85, 0x15, 0x01, 0xa9, 0xe9, 0xe9, 0xae, 0x99, 0xa9, 0xb8, 0xbf, 0xa8, 0xea, 0x59, 0x7b,
|
0xb9, 0x35, 0x9a, 0x16, 0x60, 0xb9, 0xe4, 0xec, 0x2e, 0x23, 0x7e, 0x75, 0x86, 0x6b, 0x69, 0x7d,
|
||||||
0xf6, 0x10, 0x2d, 0x17, 0x04, 0x22, 0x07, 0x64, 0x0e, 0xdc, 0x50, 0x24, 0x10, 0x82, 0xfc, 0x03,
|
0x08, 0xdc, 0x4b, 0xd1, 0xa2, 0x39, 0x14, 0xea, 0xa1, 0xd7, 0x00, 0x2d, 0x8a, 0x36, 0xff, 0x40,
|
||||||
0x48, 0xfc, 0x05, 0x7b, 0x41, 0x9e, 0x13, 0x42, 0x1c, 0x4a, 0x8a, 0xf7, 0x36, 0xc7, 0x3e, 0xfa,
|
0x81, 0xfe, 0x05, 0xbe, 0x14, 0xda, 0x53, 0x51, 0xf4, 0x30, 0x40, 0xe4, 0xdb, 0x5e, 0x0a, 0xf0,
|
||||||
0x84, 0xaa, 0xaa, 0xbb, 0xa7, 0xbb, 0x67, 0x22, 0x21, 0x71, 0x9b, 0xfa, 0xfd, 0x5e, 0xbd, 0xf7,
|
0xe8, 0x53, 0x31, 0x33, 0x24, 0x97, 0xe4, 0x6e, 0x80, 0x02, 0xb9, 0xed, 0xfc, 0x7e, 0x6f, 0xde,
|
||||||
0xeb, 0x57, 0xaf, 0x5e, 0xbf, 0x1e, 0xd0, 0xf0, 0x48, 0xfb, 0x8e, 0x13, 0x06, 0x1d, 0xd2, 0xbd,
|
0xfb, 0xf1, 0xcd, 0x9b, 0xc7, 0xc7, 0x05, 0x0d, 0xcf, 0x6d, 0xdf, 0xb6, 0xc3, 0xa0, 0xe3, 0x76,
|
||||||
0xd3, 0x09, 0x3d, 0x17, 0x53, 0xb5, 0xe8, 0x53, 0x3b, 0x26, 0x61, 0xb0, 0x1d, 0xd1, 0x30, 0x0e,
|
0x6f, 0x77, 0x42, 0xcf, 0x21, 0x54, 0x2d, 0xfa, 0xd4, 0x8a, 0xdd, 0x30, 0xd8, 0x8e, 0x68, 0x18,
|
||||||
0xe1, 0x55, 0x05, 0x6e, 0xde, 0x9a, 0xb0, 0x8e, 0x07, 0x11, 0x56, 0x46, 0x9b, 0x1b, 0x05, 0x92,
|
0x87, 0xf0, 0xb2, 0x02, 0x37, 0x6f, 0x4e, 0x58, 0xc7, 0x83, 0x88, 0x28, 0xa3, 0xcd, 0x8d, 0x02,
|
||||||
0x91, 0xe7, 0x19, 0xbc, 0x59, 0x80, 0xa3, 0xbe, 0xe7, 0x85, 0xd4, 0xc5, 0x34, 0xe5, 0xb6, 0x0a,
|
0xc9, 0xdc, 0x67, 0x19, 0xbc, 0x59, 0x80, 0xa3, 0xbe, 0xe7, 0x85, 0xd4, 0x21, 0x34, 0xe5, 0xb6,
|
||||||
0xdc, 0x33, 0x4c, 0x19, 0x09, 0x03, 0x12, 0x74, 0xa7, 0x28, 0xd8, 0x44, 0x05, 0xcb, 0xb6, 0x17,
|
0x0a, 0xdc, 0x53, 0x42, 0x99, 0x1b, 0x06, 0x6e, 0xd0, 0x9d, 0xa2, 0x60, 0x13, 0x17, 0x2c, 0xdb,
|
||||||
0x3a, 0x47, 0x55, 0x57, 0x50, 0x18, 0x74, 0xd8, 0x1d, 0x21, 0x88, 0xa5, 0xd8, 0xeb, 0x29, 0xe6,
|
0x5e, 0x68, 0x1f, 0x55, 0x5d, 0x41, 0x61, 0xd0, 0x61, 0xb7, 0x85, 0x20, 0x96, 0x62, 0xaf, 0xa5,
|
||||||
0x84, 0xd1, 0x80, 0xda, 0x41, 0x17, 0xfb, 0x38, 0xee, 0x85, 0x6e, 0xca, 0xce, 0xe3, 0x93, 0x58,
|
0x98, 0x1d, 0x46, 0x03, 0x6a, 0x05, 0x5d, 0xe2, 0x93, 0xb8, 0x17, 0x3a, 0x29, 0x3b, 0x4f, 0x4e,
|
||||||
0xfd, 0x34, 0xfe, 0x75, 0x09, 0xbc, 0xb6, 0x2f, 0x9f, 0x67, 0x0f, 0x3f, 0x23, 0x0e, 0xde, 0x2d,
|
0x62, 0xf5, 0x53, 0xff, 0xd7, 0x05, 0x70, 0x63, 0x5f, 0x3e, 0xcf, 0x1e, 0x79, 0xea, 0xda, 0x64,
|
||||||
0x2a, 0x80, 0x5f, 0x68, 0x60, 0xde, 0x95, 0xb8, 0x45, 0x5c, 0x5d, 0xab, 0x6b, 0x5b, 0x8b, 0xcd,
|
0xb7, 0xa8, 0x00, 0x7e, 0xa1, 0x81, 0x79, 0x47, 0xe2, 0xa6, 0xeb, 0x20, 0xad, 0xae, 0x6d, 0x2d,
|
||||||
0xcf, 0xb4, 0x97, 0x1c, 0xcd, 0xfc, 0x87, 0xa3, 0x6f, 0x74, 0x49, 0xdc, 0xeb, 0xb7, 0xb7, 0x9d,
|
0x36, 0x3f, 0xd3, 0x5e, 0x70, 0x3c, 0xf3, 0x1f, 0x8e, 0xbf, 0xd9, 0x75, 0xe3, 0x5e, 0xbf, 0xbd,
|
||||||
0xd0, 0xbf, 0xc3, 0x06, 0x81, 0x13, 0xf7, 0x48, 0xd0, 0x2d, 0xfc, 0x12, 0x12, 0x64, 0x10, 0x27,
|
0x6d, 0x87, 0xfe, 0x6d, 0x36, 0x08, 0xec, 0xb8, 0xe7, 0x06, 0xdd, 0xc2, 0x2f, 0x21, 0x41, 0x06,
|
||||||
0xf4, 0xb6, 0x95, 0xf7, 0x87, 0x7b, 0xe7, 0x1c, 0xcd, 0x65, 0xbf, 0x47, 0x1c, 0xcd, 0xb9, 0xe9,
|
0xb1, 0x43, 0x6f, 0x5b, 0x79, 0x7f, 0xb0, 0x77, 0xce, 0xf1, 0x5c, 0xf6, 0x7b, 0xc4, 0xf1, 0x9c,
|
||||||
0xef, 0x84, 0xa3, 0xa5, 0x13, 0xdf, 0xbb, 0x6f, 0x10, 0xf7, 0x5d, 0x3b, 0x8e, 0xa9, 0x31, 0x3a,
|
0x93, 0xfe, 0x4e, 0x38, 0x5e, 0x3a, 0xf1, 0xbd, 0x7b, 0xba, 0xeb, 0xbc, 0x6b, 0xc5, 0x31, 0xd5,
|
||||||
0x6b, 0x5c, 0x4b, 0x7f, 0x27, 0x67, 0x8d, 0xdc, 0xee, 0xd7, 0xc3, 0x86, 0x76, 0x3a, 0x6c, 0xe4,
|
0x47, 0x67, 0x8d, 0x2b, 0xe9, 0xef, 0xe4, 0xac, 0x91, 0xdb, 0xfd, 0x66, 0xd8, 0xd0, 0x4e, 0x87,
|
||||||
0x3e, 0xcc, 0x8c, 0x71, 0xe1, 0x5f, 0x34, 0xb0, 0x44, 0x82, 0x98, 0x86, 0x6e, 0xdf, 0xc1, 0xae,
|
0x8d, 0xdc, 0x87, 0x91, 0x31, 0x0e, 0xfc, 0x8b, 0x06, 0x96, 0xdc, 0x20, 0xa6, 0xa1, 0xd3, 0xb7,
|
||||||
0xd5, 0x1e, 0xe8, 0xb3, 0x52, 0xf0, 0x8b, 0xff, 0x4b, 0xf0, 0x88, 0xa3, 0xc5, 0xb1, 0xd7, 0xe6,
|
0x89, 0x63, 0xb6, 0x07, 0x68, 0x56, 0x0a, 0x7e, 0xfe, 0xb5, 0x04, 0x8f, 0x38, 0x5e, 0x1c, 0x7b,
|
||||||
0x20, 0xe1, 0xe8, 0xa6, 0x12, 0x5a, 0x00, 0x73, 0xc9, 0x6b, 0x13, 0xa8, 0x10, 0x6c, 0x96, 0x3c,
|
0x6d, 0x0e, 0x12, 0x8e, 0xaf, 0x2b, 0xa1, 0x05, 0x30, 0x97, 0xbc, 0x36, 0x81, 0x0a, 0xc1, 0x46,
|
||||||
0x40, 0x07, 0xac, 0xe3, 0xc0, 0xa1, 0x83, 0x48, 0xe4, 0xd8, 0x8a, 0x6c, 0xc6, 0x8e, 0x43, 0xea,
|
0xc9, 0x03, 0xb4, 0xc1, 0x3a, 0x09, 0x6c, 0x3a, 0x88, 0x44, 0x8e, 0xcd, 0xc8, 0x62, 0xec, 0x38,
|
||||||
0xea, 0x97, 0xea, 0xda, 0xd6, 0x7c, 0x73, 0x67, 0xc4, 0x11, 0x1c, 0xd3, 0xad, 0x94, 0x4d, 0x38,
|
0xa4, 0x0e, 0xba, 0x50, 0xd7, 0xb6, 0xe6, 0x9b, 0x3b, 0x23, 0x8e, 0xe1, 0x98, 0x6e, 0xa5, 0x6c,
|
||||||
0xd2, 0x65, 0xd8, 0x49, 0xca, 0x30, 0xa7, 0xd8, 0x1b, 0x7f, 0xac, 0x83, 0x75, 0x75, 0xb0, 0xe5,
|
0xc2, 0x31, 0x92, 0x61, 0x27, 0x29, 0xdd, 0x98, 0x62, 0xaf, 0xff, 0xb7, 0x0e, 0xd6, 0xd5, 0xc1,
|
||||||
0x23, 0x3d, 0x04, 0xb3, 0xe9, 0x51, 0xce, 0x37, 0x77, 0xcf, 0x39, 0x9a, 0x95, 0x8f, 0x38, 0x4b,
|
0x96, 0x8f, 0xf4, 0x10, 0xcc, 0xa6, 0x47, 0x39, 0xdf, 0xdc, 0x3d, 0xe7, 0x78, 0x56, 0x3e, 0xe2,
|
||||||
0x44, 0x84, 0x5a, 0xe9, 0x04, 0xea, 0x41, 0xe8, 0xe2, 0x8e, 0xdd, 0xf7, 0xe2, 0xfb, 0x46, 0x4c,
|
0xac, 0x2b, 0x22, 0xd4, 0x4a, 0x27, 0x50, 0x0f, 0x42, 0x87, 0x74, 0xac, 0xbe, 0x17, 0xdf, 0xd3,
|
||||||
0xfb, 0xb8, 0x78, 0x24, 0xa7, 0xc3, 0xc6, 0xec, 0xc3, 0xbd, 0xcf, 0xc5, 0xb3, 0xcd, 0x12, 0x17,
|
0x63, 0xda, 0x27, 0xc5, 0x23, 0x39, 0x1d, 0x36, 0x66, 0x1f, 0xec, 0x7d, 0x2e, 0x9e, 0x6d, 0xd6,
|
||||||
0xfe, 0x08, 0x5c, 0xf1, 0xec, 0x36, 0xf6, 0x64, 0xc6, 0xe7, 0x9b, 0xdf, 0x1d, 0x71, 0xa4, 0x80,
|
0x75, 0xe0, 0x8f, 0xc1, 0x25, 0xcf, 0x6a, 0x13, 0x4f, 0x66, 0x7c, 0xbe, 0xf9, 0xbd, 0x11, 0xc7,
|
||||||
0x84, 0xa3, 0xba, 0x74, 0x2a, 0x57, 0xa9, 0x5f, 0x8a, 0x59, 0x6c, 0xd3, 0xf8, 0xbe, 0xd1, 0xb1,
|
0x0a, 0x48, 0x38, 0xae, 0x4b, 0xa7, 0x72, 0x95, 0xfa, 0xa5, 0x84, 0xc5, 0x16, 0x8d, 0xef, 0xe9,
|
||||||
0x3d, 0x26, 0xdd, 0x82, 0x31, 0xfd, 0x62, 0xd8, 0x98, 0x31, 0xd5, 0x66, 0xd8, 0x05, 0x2b, 0x1d,
|
0x1d, 0xcb, 0x63, 0xd2, 0x2d, 0x18, 0xd3, 0xcf, 0x87, 0x8d, 0x19, 0x43, 0x6d, 0x86, 0x5d, 0xb0,
|
||||||
0xe2, 0x61, 0x36, 0x60, 0x31, 0xf6, 0x2d, 0x51, 0xdf, 0x32, 0x49, 0xcb, 0x3b, 0x70, 0xbb, 0xc3,
|
0xd2, 0x71, 0x3d, 0xc2, 0x06, 0x2c, 0x26, 0xbe, 0x29, 0xea, 0x5b, 0x26, 0x69, 0x79, 0x07, 0x6e,
|
||||||
0xb6, 0xf7, 0x73, 0xea, 0xc9, 0x20, 0xc2, 0xcd, 0x77, 0x46, 0x1c, 0x2d, 0x77, 0x4a, 0x58, 0xc2,
|
0x77, 0xd8, 0xf6, 0x7e, 0x4e, 0x3d, 0x1e, 0x44, 0xa4, 0xf9, 0xce, 0x88, 0xe3, 0xe5, 0x4e, 0x09,
|
||||||
0xd1, 0x75, 0x19, 0xbd, 0x0c, 0x1b, 0x66, 0xc5, 0x0e, 0x1e, 0x80, 0xcb, 0x91, 0x1d, 0xf7, 0xf4,
|
0x4b, 0x38, 0xbe, 0x2a, 0xa3, 0x97, 0x61, 0xdd, 0xa8, 0xd8, 0xc1, 0x03, 0x70, 0x31, 0xb2, 0xe2,
|
||||||
0xcb, 0x52, 0xfe, 0xb7, 0x46, 0x1c, 0xc9, 0x75, 0xc2, 0xd1, 0x2d, 0xb9, 0x5f, 0x2c, 0x52, 0xf1,
|
0x1e, 0xba, 0x28, 0xe5, 0x7f, 0x7b, 0xc4, 0xb1, 0x5c, 0x27, 0x1c, 0xdf, 0x94, 0xfb, 0xc5, 0x22,
|
||||||
0x79, 0x4a, 0x3e, 0x15, 0xc2, 0xe7, 0x73, 0xe6, 0xe2, 0xac, 0xa1, 0x7d, 0x6a, 0xca, 0x6d, 0xb0,
|
0x15, 0x9f, 0xa7, 0xe4, 0x53, 0x21, 0x7c, 0x3e, 0x67, 0x5e, 0x9d, 0x35, 0xb4, 0x4f, 0x0d, 0xb9,
|
||||||
0x05, 0x2e, 0x4b, 0xb1, 0x57, 0x52, 0xb1, 0xea, 0xf6, 0x6e, 0xab, 0xe3, 0x90, 0x62, 0xb7, 0x44,
|
0x0d, 0xb6, 0xc0, 0x45, 0x29, 0xf6, 0x52, 0x2a, 0x56, 0xdd, 0xde, 0x6d, 0x75, 0x1c, 0x52, 0xec,
|
||||||
0x88, 0x58, 0x49, 0x5c, 0x91, 0x21, 0xc4, 0x22, 0x2f, 0xa3, 0xf9, 0x7c, 0x65, 0x4a, 0x2b, 0xf8,
|
0x96, 0x08, 0x11, 0x2b, 0x89, 0x2b, 0x32, 0x84, 0x58, 0xe4, 0x65, 0x34, 0x9f, 0xaf, 0x0c, 0x69,
|
||||||
0x33, 0x70, 0x4d, 0xd5, 0x39, 0xd3, 0xaf, 0xd6, 0x2f, 0x6d, 0x2d, 0xec, 0xbc, 0x59, 0x76, 0x3a,
|
0x05, 0x7f, 0x0e, 0xae, 0xa8, 0x3a, 0x67, 0xe8, 0x72, 0xfd, 0xc2, 0xd6, 0xc2, 0xce, 0x1b, 0x65,
|
||||||
0xe5, 0xf2, 0x36, 0x91, 0x28, 0xfb, 0x11, 0x47, 0xd9, 0xce, 0x84, 0xa3, 0x45, 0x19, 0x4a, 0xad,
|
0xa7, 0x53, 0x2e, 0x6f, 0x13, 0x8b, 0xb2, 0x1f, 0x71, 0x9c, 0xed, 0x4c, 0x38, 0x5e, 0x94, 0xa1,
|
||||||
0x0d, 0x33, 0x23, 0xe0, 0xef, 0x35, 0xb0, 0x46, 0x31, 0x73, 0xec, 0xc0, 0x22, 0x41, 0x8c, 0xe9,
|
0xd4, 0x5a, 0x37, 0x32, 0x02, 0xfe, 0x41, 0x03, 0x6b, 0x94, 0x30, 0xdb, 0x0a, 0x4c, 0x37, 0x88,
|
||||||
0x33, 0xdb, 0xb3, 0x98, 0x7e, 0xad, 0xae, 0x6d, 0x5d, 0x69, 0x76, 0x47, 0x1c, 0xad, 0x28, 0xf2,
|
0x09, 0x7d, 0x6a, 0x79, 0x26, 0x43, 0x57, 0xea, 0xda, 0xd6, 0xa5, 0x66, 0x77, 0xc4, 0xf1, 0x8a,
|
||||||
0x61, 0xca, 0x1d, 0x26, 0x1c, 0xbd, 0x2d, 0x3d, 0x55, 0xf0, 0x6a, 0x8a, 0xde, 0xff, 0xe6, 0xdd,
|
0x22, 0x1f, 0xa4, 0xdc, 0x61, 0xc2, 0xf1, 0xdb, 0xd2, 0x53, 0x05, 0xaf, 0xa6, 0xe8, 0xfd, 0x6f,
|
||||||
0xbb, 0xc6, 0x05, 0x47, 0x97, 0x48, 0x10, 0x8f, 0xce, 0x1a, 0xd7, 0xa7, 0x99, 0x5f, 0x9c, 0x35,
|
0xdd, 0xb9, 0xa3, 0xbf, 0xe2, 0xf8, 0x82, 0x1b, 0xc4, 0xa3, 0xb3, 0xc6, 0xd5, 0x69, 0xe6, 0xaf,
|
||||||
0x2e, 0x0b, 0x3b, 0xb3, 0x1a, 0x04, 0xfe, 0x43, 0x03, 0xb0, 0xc3, 0xac, 0x63, 0x3b, 0x76, 0x7a,
|
0xce, 0x1a, 0x17, 0x85, 0x9d, 0x51, 0x0d, 0x02, 0xff, 0xa1, 0x01, 0xd8, 0x61, 0xe6, 0xb1, 0x15,
|
||||||
0x98, 0x5a, 0x38, 0xb0, 0xdb, 0x1e, 0x76, 0xf5, 0xb9, 0xba, 0xb6, 0x35, 0xd7, 0xfc, 0xad, 0x76,
|
0xdb, 0x3d, 0x42, 0x4d, 0x12, 0x58, 0x6d, 0x8f, 0x38, 0x68, 0xae, 0xae, 0x6d, 0xcd, 0x35, 0x7f,
|
||||||
0xce, 0xd1, 0xea, 0xfe, 0xe1, 0x53, 0xc5, 0x7e, 0xa8, 0xc8, 0x11, 0x47, 0xab, 0x1d, 0x56, 0xc6,
|
0xa7, 0x9d, 0x73, 0xbc, 0xba, 0x7f, 0xf8, 0x44, 0xb1, 0x1f, 0x2a, 0x72, 0xc4, 0xf1, 0x6a, 0x87,
|
||||||
0x12, 0x8e, 0xde, 0x51, 0x45, 0x50, 0x21, 0xaa, 0x6a, 0xb3, 0x1a, 0xdf, 0x98, 0x6a, 0x28, 0x74,
|
0x95, 0xb1, 0x84, 0xe3, 0x77, 0x54, 0x11, 0x54, 0x88, 0xaa, 0xda, 0xac, 0xc6, 0x37, 0xa6, 0x1a,
|
||||||
0x0a, 0x8b, 0xd3, 0x61, 0x63, 0x22, 0xac, 0x39, 0x11, 0x14, 0xfe, 0xbd, 0x2c, 0xde, 0xc5, 0x9e,
|
0x0a, 0x9d, 0xc2, 0xe2, 0x74, 0xd8, 0x98, 0x08, 0x6b, 0x4c, 0x04, 0x85, 0x7f, 0x2f, 0x8b, 0x77,
|
||||||
0x3d, 0xb0, 0x98, 0x3e, 0x2f, 0x73, 0xfa, 0x1b, 0x21, 0x7e, 0x25, 0xf7, 0xb2, 0x27, 0xc8, 0x43,
|
0x88, 0x67, 0x0d, 0x4c, 0x86, 0xe6, 0x65, 0x4e, 0x7f, 0x2b, 0xc4, 0xaf, 0xe4, 0x5e, 0xf6, 0x04,
|
||||||
0x91, 0xe7, 0xdc, 0x8d, 0x82, 0x12, 0x8e, 0xbe, 0x5e, 0x96, 0xae, 0xf0, 0xaa, 0xf2, 0x7b, 0xa5,
|
0x79, 0x28, 0xf2, 0x9c, 0xbb, 0x51, 0x50, 0xc2, 0xf1, 0x37, 0xca, 0xd2, 0x15, 0x5e, 0x55, 0x7e,
|
||||||
0x2c, 0x4f, 0x33, 0xbe, 0x38, 0x6b, 0xcc, 0xde, 0xbb, 0x7b, 0x3a, 0x6c, 0x54, 0xa3, 0x9a, 0xd5,
|
0xb7, 0x94, 0xe5, 0x69, 0xc6, 0xaf, 0xce, 0x1a, 0xb3, 0x77, 0xef, 0x9c, 0x0e, 0x1b, 0xd5, 0xa8,
|
||||||
0x98, 0xf0, 0xe7, 0x60, 0x91, 0x74, 0x83, 0x90, 0x62, 0x2b, 0xc2, 0xd4, 0x67, 0x3a, 0x90, 0xf9,
|
0x46, 0x35, 0x26, 0xfc, 0x05, 0x58, 0x74, 0xbb, 0x41, 0x48, 0x89, 0x19, 0x11, 0xea, 0x33, 0x04,
|
||||||
0x7e, 0x30, 0xe2, 0x68, 0x41, 0xe1, 0x2d, 0x01, 0x27, 0x1c, 0xdd, 0x50, 0xdd, 0x62, 0x8c, 0xe5,
|
0x64, 0xbe, 0xef, 0x8f, 0x38, 0x5e, 0x50, 0x78, 0x4b, 0xc0, 0x09, 0xc7, 0xd7, 0x54, 0xb7, 0x18,
|
||||||
0xe5, 0xbb, 0x5a, 0x05, 0xcd, 0xe2, 0x56, 0xf8, 0x4b, 0x0d, 0x2c, 0xdb, 0xfd, 0x38, 0xb4, 0x82,
|
0x63, 0x79, 0xf9, 0xae, 0x56, 0x41, 0xa3, 0xb8, 0x15, 0xfe, 0x4a, 0x03, 0xcb, 0x56, 0x3f, 0x0e,
|
||||||
0x90, 0xfa, 0xb6, 0x47, 0x9e, 0x63, 0x7d, 0x41, 0x06, 0xf9, 0x78, 0xc4, 0xd1, 0x92, 0x60, 0x3e,
|
0xcd, 0x20, 0xa4, 0xbe, 0xe5, 0xb9, 0xcf, 0x08, 0x5a, 0x90, 0x41, 0x3e, 0x1e, 0x71, 0xbc, 0x24,
|
||||||
0xca, 0x88, 0x3c, 0x03, 0x25, 0xf4, 0xab, 0x4e, 0x0e, 0x4e, 0x5a, 0x65, 0xc7, 0x66, 0x96, 0xfd,
|
0x98, 0x8f, 0x32, 0x22, 0xcf, 0x40, 0x09, 0xfd, 0xaa, 0x93, 0x83, 0x93, 0x56, 0xd9, 0xb1, 0x19,
|
||||||
0xc2, 0x10, 0x2c, 0xf9, 0x24, 0xb0, 0x5c, 0xc2, 0x8e, 0xac, 0x0e, 0xc5, 0x58, 0x5f, 0xac, 0x6b,
|
0x65, 0xbf, 0x30, 0x04, 0x4b, 0xbe, 0x1b, 0x98, 0x8e, 0xcb, 0x8e, 0xcc, 0x0e, 0x25, 0x04, 0x2d,
|
||||||
0x5b, 0x0b, 0x3b, 0x8b, 0xd9, 0xb5, 0x3a, 0x24, 0xcf, 0x71, 0xf3, 0x41, 0x7a, 0x83, 0x16, 0x7c,
|
0xd6, 0xb5, 0xad, 0x85, 0x9d, 0xc5, 0xec, 0x5a, 0x1d, 0xba, 0xcf, 0x48, 0xf3, 0x7e, 0x7a, 0x83,
|
||||||
0x12, 0xec, 0x11, 0x76, 0xb4, 0x4f, 0xb1, 0x50, 0x84, 0xa4, 0xa2, 0x02, 0x56, 0x3c, 0x8a, 0xfa,
|
0x16, 0x7c, 0x37, 0xd8, 0x73, 0xd9, 0xd1, 0x3e, 0x25, 0x42, 0x11, 0x96, 0x8a, 0x0a, 0x58, 0xf1,
|
||||||
0x6d, 0xe3, 0xe2, 0xac, 0x71, 0xe9, 0x5e, 0xfd, 0xb6, 0x59, 0xdc, 0x06, 0xbb, 0x00, 0x8c, 0xdf,
|
0x28, 0xea, 0xb7, 0xf4, 0x57, 0x67, 0x8d, 0x0b, 0x77, 0xeb, 0xb7, 0x8c, 0xe2, 0x36, 0xd8, 0x05,
|
||||||
0xf3, 0xfa, 0x92, 0x8c, 0x86, 0xb2, 0x68, 0x3f, 0xce, 0x99, 0xf2, 0x15, 0x7e, 0x2b, 0x15, 0x50,
|
0x60, 0xfc, 0x9e, 0x47, 0x4b, 0x32, 0x1a, 0xce, 0xa2, 0xfd, 0x24, 0x67, 0xca, 0x57, 0xf8, 0xad,
|
||||||
0xd8, 0x9a, 0x70, 0xb4, 0x2a, 0xe3, 0x8f, 0x21, 0xc3, 0x2c, 0xf0, 0xf0, 0x01, 0xb8, 0xe6, 0x84,
|
0x54, 0x40, 0x61, 0x6b, 0xc2, 0xf1, 0xaa, 0x8c, 0x3f, 0x86, 0x74, 0xa3, 0xc0, 0xc3, 0xfb, 0xe0,
|
||||||
0x11, 0xc1, 0x94, 0xe9, 0xcb, 0xb2, 0xda, 0xbe, 0x26, 0x7a, 0x40, 0x0a, 0xe5, 0xaf, 0xd9, 0x74,
|
0x8a, 0x1d, 0x46, 0x2e, 0xa1, 0x0c, 0x2d, 0xcb, 0x6a, 0x7b, 0x53, 0xf4, 0x80, 0x14, 0xca, 0x5f,
|
||||||
0x9d, 0xd5, 0x8d, 0x99, 0x19, 0xc0, 0x7f, 0x6a, 0xe0, 0x86, 0x98, 0x30, 0x30, 0xb5, 0x7c, 0xfb,
|
0xb3, 0xe9, 0x3a, 0xab, 0x1b, 0x23, 0x33, 0x80, 0xff, 0xd4, 0xc0, 0x35, 0x31, 0x61, 0x10, 0x6a,
|
||||||
0xc4, 0x8a, 0x70, 0xe0, 0x92, 0xa0, 0x6b, 0x1d, 0x91, 0xb6, 0xbe, 0x22, 0xdd, 0xfd, 0x41, 0x14,
|
0xfa, 0xd6, 0x89, 0x19, 0x91, 0xc0, 0x71, 0x83, 0xae, 0x79, 0xe4, 0xb6, 0xd1, 0x8a, 0x74, 0xf7,
|
||||||
0xef, 0x7a, 0x4b, 0x9a, 0x1c, 0xd8, 0x27, 0x2d, 0x65, 0xf0, 0x88, 0x34, 0x47, 0x1c, 0xad, 0x47,
|
0x47, 0x51, 0xbc, 0xeb, 0x2d, 0x69, 0x72, 0x60, 0x9d, 0xb4, 0x94, 0xc1, 0x43, 0xb7, 0x39, 0xe2,
|
||||||
0x93, 0x70, 0xc2, 0xd1, 0x6b, 0xaa, 0x89, 0x4e, 0x72, 0x85, 0xb2, 0x9d, 0xba, 0x75, 0x3a, 0x7c,
|
0x78, 0x3d, 0x9a, 0x84, 0x13, 0x8e, 0x6f, 0xa8, 0x26, 0x3a, 0xc9, 0x15, 0xca, 0x76, 0xea, 0xd6,
|
||||||
0x3a, 0x6c, 0x4c, 0x8b, 0x6f, 0x4e, 0xb1, 0x6d, 0x8b, 0x74, 0xf4, 0x6c, 0xd6, 0x13, 0xe9, 0x58,
|
0xe9, 0xf0, 0xe9, 0xb0, 0x31, 0x2d, 0xbe, 0x31, 0xc5, 0xb6, 0x2d, 0xd2, 0xd1, 0xb3, 0x58, 0x4f,
|
||||||
0x1d, 0xa7, 0x23, 0x85, 0xf2, 0x74, 0xa4, 0xeb, 0x71, 0x3a, 0x52, 0x00, 0x7e, 0x00, 0xae, 0xc8,
|
0xa4, 0x63, 0x75, 0x9c, 0x8e, 0x14, 0xca, 0xd3, 0x91, 0xae, 0xc7, 0xe9, 0x48, 0x01, 0xf8, 0x01,
|
||||||
0x59, 0x4b, 0x5f, 0x93, 0xbd, 0x7c, 0x2d, 0x3b, 0x31, 0x11, 0xff, 0xb1, 0x20, 0x9a, 0xba, 0x78,
|
0xb8, 0x24, 0x67, 0x2d, 0xb4, 0x26, 0x7b, 0xf9, 0x5a, 0x76, 0x62, 0x22, 0xfe, 0x23, 0x41, 0x34,
|
||||||
0xd9, 0x49, 0x9b, 0x84, 0xa3, 0x05, 0xe9, 0x4d, 0xae, 0x0c, 0x53, 0xa1, 0xf0, 0x11, 0x58, 0x4a,
|
0x91, 0x78, 0xd9, 0x49, 0x9b, 0x84, 0xe3, 0x05, 0xe9, 0x4d, 0xae, 0x74, 0x43, 0xa1, 0xf0, 0x21,
|
||||||
0x2f, 0x94, 0x8b, 0x3d, 0x1c, 0x63, 0x1d, 0xca, 0x62, 0x7f, 0x4b, 0x4e, 0x16, 0x92, 0xd8, 0x93,
|
0x58, 0x4a, 0x2f, 0x94, 0x43, 0x3c, 0x12, 0x13, 0x04, 0x65, 0xb1, 0xbf, 0x25, 0x27, 0x0b, 0x49,
|
||||||
0x78, 0xc2, 0x11, 0x2c, 0x5c, 0x29, 0x05, 0x1a, 0x66, 0xc9, 0x06, 0x9e, 0x00, 0x5d, 0xf6, 0xe9,
|
0xec, 0x49, 0x3c, 0xe1, 0x18, 0x16, 0xae, 0x94, 0x02, 0x75, 0xa3, 0x64, 0x03, 0x4f, 0x00, 0x92,
|
||||||
0x88, 0x86, 0x5d, 0x8a, 0x19, 0x2b, 0x36, 0xec, 0x75, 0xf9, 0x7c, 0xe2, 0xe5, 0xbb, 0x21, 0x6c,
|
0x7d, 0x3a, 0xa2, 0x61, 0x97, 0x12, 0xc6, 0x8a, 0x0d, 0x7b, 0x5d, 0x3e, 0x9f, 0x78, 0xf9, 0x6e,
|
||||||
0x5a, 0xa9, 0x49, 0xb1, 0x6d, 0xab, 0xd7, 0xd9, 0x54, 0x36, 0x7f, 0xf6, 0xe9, 0x9b, 0xe1, 0x21,
|
0x08, 0x9b, 0x56, 0x6a, 0x52, 0x6c, 0xdb, 0xea, 0x75, 0x36, 0x95, 0xcd, 0x9f, 0x7d, 0xfa, 0x66,
|
||||||
0x58, 0x4e, 0xeb, 0x22, 0xb2, 0xfb, 0x0c, 0x5b, 0x4c, 0xbf, 0x2e, 0xe3, 0xbd, 0x27, 0x9e, 0x43,
|
0x78, 0x08, 0x96, 0xd3, 0xba, 0x88, 0xac, 0x3e, 0x23, 0x26, 0x43, 0x57, 0x65, 0xbc, 0xf7, 0xc4,
|
||||||
0x31, 0x2d, 0x41, 0x1c, 0xe6, 0xcf, 0x51, 0x04, 0x73, 0xef, 0x25, 0x53, 0x88, 0xc1, 0x92, 0xa8,
|
0x73, 0x28, 0xa6, 0x25, 0x88, 0xc3, 0xfc, 0x39, 0x8a, 0x60, 0xee, 0xbd, 0x64, 0x0a, 0x09, 0x58,
|
||||||
0x32, 0x91, 0x54, 0x8f, 0x38, 0x31, 0xd3, 0x37, 0xa4, 0xcf, 0xef, 0x09, 0x9f, 0xbe, 0x7d, 0xb2,
|
0x12, 0x55, 0x26, 0x92, 0xea, 0xb9, 0x76, 0xcc, 0xd0, 0x86, 0xf4, 0xf9, 0x7d, 0xe1, 0xd3, 0xb7,
|
||||||
0x9b, 0xe1, 0xe3, 0x5b, 0x57, 0x00, 0xa7, 0x76, 0x40, 0xd5, 0xe9, 0xcc, 0xd2, 0x6e, 0xe8, 0x82,
|
0x4e, 0x76, 0x33, 0x7c, 0x7c, 0xeb, 0x0a, 0xe0, 0xd4, 0x0e, 0xa8, 0x3a, 0x9d, 0x51, 0xda, 0x0d,
|
||||||
0xeb, 0x2e, 0x61, 0xa2, 0x33, 0x5b, 0x2c, 0xb2, 0x29, 0xc3, 0x96, 0x1c, 0x00, 0xf4, 0x1b, 0xf2,
|
0x1d, 0x70, 0xd5, 0x71, 0x99, 0xe8, 0xcc, 0x26, 0x8b, 0x2c, 0xca, 0x88, 0x29, 0x07, 0x00, 0x74,
|
||||||
0x24, 0xe4, 0xc8, 0x95, 0xf2, 0x87, 0x92, 0x96, 0xa3, 0x45, 0x3e, 0x72, 0x4d, 0x52, 0x86, 0x39,
|
0x4d, 0x9e, 0x84, 0x1c, 0xb9, 0x52, 0xfe, 0x50, 0xd2, 0x72, 0xb4, 0xc8, 0x47, 0xae, 0x49, 0x4a,
|
||||||
0xc5, 0xbe, 0x18, 0x25, 0xc6, 0x7e, 0x64, 0x91, 0xc0, 0xc5, 0x27, 0x98, 0xe9, 0x37, 0x27, 0xa2,
|
0x37, 0xa6, 0xd8, 0x17, 0xa3, 0xc4, 0xc4, 0x8f, 0x4c, 0x37, 0x70, 0xc8, 0x09, 0x61, 0xe8, 0xfa,
|
||||||
0x3c, 0xc1, 0x7e, 0xf4, 0x50, 0xb1, 0xd5, 0x28, 0x05, 0x6a, 0x1c, 0xa5, 0x00, 0xc2, 0x1d, 0x70,
|
0x44, 0x94, 0xc7, 0xc4, 0x8f, 0x1e, 0x28, 0xb6, 0x1a, 0xa5, 0x40, 0x8d, 0xa3, 0x14, 0x40, 0xb8,
|
||||||
0x55, 0x1e, 0x80, 0xab, 0xeb, 0xd2, 0xef, 0xe6, 0x88, 0xa3, 0x14, 0xc9, 0xdf, 0xf0, 0x6a, 0x69,
|
0x03, 0x2e, 0xcb, 0x03, 0x70, 0x10, 0x92, 0x7e, 0x37, 0x47, 0x1c, 0xa7, 0x48, 0xfe, 0x86, 0x57,
|
||||||
0x98, 0x29, 0x0e, 0x63, 0x70, 0xf3, 0x18, 0xdb, 0x47, 0x96, 0xa8, 0x6a, 0x2b, 0xee, 0x51, 0xcc,
|
0x4b, 0xdd, 0x48, 0x71, 0x18, 0x83, 0xeb, 0xc7, 0xc4, 0x3a, 0x32, 0x45, 0x55, 0x9b, 0x71, 0x8f,
|
||||||
0x7a, 0xa1, 0xe7, 0x5a, 0x91, 0x13, 0xeb, 0xaf, 0xc9, 0x84, 0x8b, 0xf6, 0x7e, 0x5d, 0x98, 0x7c,
|
0x12, 0xd6, 0x0b, 0x3d, 0xc7, 0x8c, 0xec, 0x18, 0xdd, 0x90, 0x09, 0x17, 0xed, 0xfd, 0xaa, 0x30,
|
||||||
0xdf, 0x66, 0xbd, 0x27, 0x99, 0x41, 0xcb, 0x89, 0x13, 0x8e, 0x36, 0xa5, 0xcb, 0x69, 0x64, 0x7e,
|
0xf9, 0x81, 0xc5, 0x7a, 0x8f, 0x33, 0x83, 0x96, 0x1d, 0x27, 0x1c, 0x6f, 0x4a, 0x97, 0xd3, 0xc8,
|
||||||
0xa8, 0x53, 0xb7, 0xc2, 0x5d, 0xb0, 0xe0, 0xdb, 0xf4, 0x08, 0x53, 0x2b, 0xb0, 0x7d, 0xac, 0x6f,
|
0xfc, 0x50, 0xa7, 0x6e, 0x85, 0xbb, 0x60, 0xc1, 0xb7, 0xe8, 0x11, 0xa1, 0x66, 0x60, 0xf9, 0x04,
|
||||||
0xca, 0xe1, 0xca, 0x10, 0xed, 0x4c, 0xc1, 0x1f, 0xd9, 0x3e, 0xce, 0xdb, 0xd9, 0x18, 0x32, 0xcc,
|
0x6d, 0xca, 0xe1, 0x4a, 0x17, 0xed, 0x4c, 0xc1, 0x1f, 0x59, 0x3e, 0xc9, 0xdb, 0xd9, 0x18, 0xd2,
|
||||||
0x02, 0x0f, 0x07, 0x60, 0x53, 0x7c, 0xc4, 0x58, 0xe1, 0x71, 0x80, 0x29, 0xeb, 0x91, 0xc8, 0xea,
|
0x8d, 0x02, 0x0f, 0x07, 0x60, 0x53, 0x7c, 0xc4, 0x98, 0xe1, 0x71, 0x40, 0x28, 0xeb, 0xb9, 0x91,
|
||||||
0xd0, 0xd0, 0xb7, 0x22, 0x9b, 0xe2, 0x20, 0xd6, 0x6f, 0xc9, 0x14, 0x7c, 0x7b, 0xc4, 0xd1, 0x4d,
|
0xd9, 0xa1, 0xa1, 0x6f, 0x46, 0x16, 0x25, 0x41, 0x8c, 0x6e, 0xca, 0x14, 0x7c, 0x67, 0xc4, 0xf1,
|
||||||
0x61, 0xf5, 0x38, 0x33, 0xda, 0xa7, 0xa1, 0xdf, 0x92, 0x26, 0x09, 0x47, 0x6f, 0x64, 0x1d, 0x6f,
|
0x75, 0x61, 0xf5, 0x28, 0x33, 0xda, 0xa7, 0xa1, 0xdf, 0x92, 0x26, 0x09, 0xc7, 0xaf, 0x67, 0x1d,
|
||||||
0x1a, 0x6f, 0x98, 0x5f, 0xb5, 0x13, 0xfe, 0x4a, 0x03, 0x6b, 0x7e, 0xe8, 0x5a, 0x31, 0xf1, 0xb1,
|
0x6f, 0x1a, 0xaf, 0x1b, 0x5f, 0xb5, 0x13, 0xfe, 0x5a, 0x03, 0x6b, 0x7e, 0xe8, 0x98, 0xb1, 0xeb,
|
||||||
0x75, 0x4c, 0x02, 0x37, 0x3c, 0xb6, 0x98, 0xfe, 0xba, 0x4c, 0xd8, 0x4f, 0xcf, 0x39, 0x5a, 0x33,
|
0x13, 0xf3, 0xd8, 0x0d, 0x9c, 0xf0, 0xd8, 0x64, 0xe8, 0x35, 0x99, 0xb0, 0x9f, 0x9d, 0x73, 0xbc,
|
||||||
0xed, 0xe3, 0x83, 0xd0, 0x7d, 0x42, 0x7c, 0xfc, 0x54, 0xb2, 0xe2, 0x1d, 0xbe, 0xec, 0x97, 0x90,
|
0x66, 0x58, 0xc7, 0x07, 0xa1, 0xf3, 0xd8, 0xf5, 0xc9, 0x13, 0xc9, 0x8a, 0x77, 0xf8, 0xb2, 0x5f,
|
||||||
0x7c, 0x04, 0x2d, 0xc3, 0x59, 0xe6, 0x4e, 0x87, 0x8d, 0x49, 0x2f, 0x66, 0xc5, 0x07, 0x7c, 0xa1,
|
0x42, 0xf2, 0x11, 0xb4, 0x0c, 0x67, 0x99, 0x3b, 0x1d, 0x36, 0x26, 0xbd, 0x18, 0x15, 0x1f, 0xf0,
|
||||||
0x81, 0x8d, 0xf4, 0x9a, 0x38, 0x7d, 0x2a, 0xb4, 0x59, 0xc7, 0x94, 0xc4, 0x98, 0xe9, 0x6f, 0x48,
|
0xb9, 0x06, 0x36, 0xd2, 0x6b, 0x62, 0xf7, 0xa9, 0xd0, 0x66, 0x1e, 0x53, 0x37, 0x26, 0x0c, 0xbd,
|
||||||
0x31, 0x3f, 0x14, 0xad, 0x57, 0x15, 0x7c, 0xca, 0x3f, 0x95, 0x74, 0xc2, 0xd1, 0xed, 0xc2, 0xad,
|
0x2e, 0xc5, 0xfc, 0x48, 0xb4, 0x5e, 0x55, 0xf0, 0x29, 0xff, 0x44, 0xd2, 0x09, 0xc7, 0xb7, 0x0a,
|
||||||
0x29, 0x71, 0x85, 0xcb, 0xb3, 0x53, 0xb8, 0x3b, 0xda, 0x8e, 0x39, 0xcd, 0x93, 0x68, 0x62, 0x59,
|
0xb7, 0xa6, 0xc4, 0x15, 0x2e, 0xcf, 0x4e, 0xe1, 0xee, 0x68, 0x3b, 0xc6, 0x34, 0x4f, 0xa2, 0x89,
|
||||||
0x6d, 0x77, 0xc4, 0x17, 0x93, 0x5e, 0x1b, 0x37, 0xb1, 0x94, 0xd8, 0x17, 0x78, 0x7e, 0xf9, 0x8b,
|
0x65, 0xb5, 0xdd, 0x11, 0x5f, 0x4c, 0xa8, 0x36, 0x6e, 0x62, 0x29, 0xb1, 0x2f, 0xf0, 0xfc, 0xf2,
|
||||||
0xa0, 0x61, 0x96, 0x6c, 0xa0, 0x07, 0x56, 0xe5, 0x97, 0xac, 0x25, 0x7a, 0x81, 0xa5, 0xfa, 0x2b,
|
0x17, 0x41, 0xdd, 0x28, 0xd9, 0x40, 0x0f, 0xac, 0xca, 0x2f, 0x59, 0x53, 0xf4, 0x02, 0x53, 0xf5,
|
||||||
0x92, 0xfd, 0xf5, 0x46, 0xd6, 0x5f, 0x9b, 0x82, 0x1f, 0x37, 0x59, 0x39, 0xdc, 0xb7, 0x4b, 0x58,
|
0x57, 0x2c, 0xfb, 0xeb, 0xb5, 0xac, 0xbf, 0x36, 0x05, 0x3f, 0x6e, 0xb2, 0x72, 0xb8, 0x6f, 0x97,
|
||||||
0x9e, 0xd9, 0x32, 0x6c, 0x98, 0x15, 0x3b, 0xf8, 0x99, 0x06, 0xd6, 0x64, 0x09, 0xc9, 0x0f, 0x61,
|
0xb0, 0x3c, 0xb3, 0x65, 0x58, 0x37, 0x2a, 0x76, 0xf0, 0x33, 0x0d, 0xac, 0xc9, 0x12, 0x92, 0x1f,
|
||||||
0x4b, 0x7d, 0x09, 0xeb, 0x75, 0x19, 0x6f, 0x5d, 0x7c, 0x48, 0xec, 0x86, 0xd1, 0xc0, 0x14, 0xdc,
|
0xc2, 0xa6, 0xfa, 0x12, 0x46, 0x75, 0x19, 0x6f, 0x5d, 0x7c, 0x48, 0xec, 0x86, 0xd1, 0xc0, 0x10,
|
||||||
0x81, 0xa4, 0x9a, 0x8f, 0xc4, 0x28, 0xe6, 0x94, 0xc1, 0x84, 0xa3, 0xad, 0xbc, 0x8c, 0x0a, 0x78,
|
0xdc, 0x81, 0xa4, 0x9a, 0x0f, 0xc5, 0x28, 0x66, 0x97, 0xc1, 0x84, 0xe3, 0xad, 0xbc, 0x8c, 0x0a,
|
||||||
0x21, 0x8d, 0x2c, 0xb6, 0x03, 0xd7, 0xa6, 0xae, 0x78, 0xff, 0xcf, 0x65, 0x0b, 0xb3, 0xea, 0x08,
|
0x78, 0x21, 0x8d, 0x2c, 0xb6, 0x02, 0xc7, 0xa2, 0x8e, 0x78, 0xff, 0xcf, 0x65, 0x0b, 0xa3, 0xea,
|
||||||
0xfe, 0x59, 0xc8, 0xb1, 0x45, 0x03, 0xc5, 0x01, 0x23, 0x31, 0x79, 0x26, 0x32, 0xaa, 0xbf, 0x29,
|
0x08, 0xfe, 0x59, 0xc8, 0xb1, 0x44, 0x03, 0x25, 0x01, 0x73, 0x63, 0xf7, 0xa9, 0xc8, 0x28, 0x7a,
|
||||||
0xd3, 0x79, 0x22, 0xe6, 0xc2, 0x5d, 0x9b, 0xe1, 0xc3, 0x8c, 0xdb, 0x97, 0x73, 0xa1, 0x53, 0x86,
|
0x43, 0xa6, 0xf3, 0x44, 0xcc, 0x85, 0xbb, 0x16, 0x23, 0x87, 0x19, 0xb7, 0x2f, 0xe7, 0x42, 0xbb,
|
||||||
0x12, 0x8e, 0x36, 0x94, 0x98, 0x32, 0x2e, 0x66, 0xa0, 0x09, 0xdb, 0x49, 0x48, 0x8c, 0x81, 0x95,
|
0x0c, 0x25, 0x1c, 0x6f, 0x28, 0x31, 0x65, 0x5c, 0xcc, 0x40, 0x13, 0xb6, 0x93, 0x90, 0x18, 0x03,
|
||||||
0x20, 0x66, 0xc5, 0x86, 0xc1, 0x3f, 0x69, 0x60, 0xb5, 0x13, 0x7a, 0x5e, 0x78, 0x6c, 0x7d, 0xd2,
|
0x2b, 0x41, 0x8c, 0x8a, 0x0d, 0x83, 0x7f, 0xd2, 0xc0, 0x6a, 0x27, 0xf4, 0xbc, 0xf0, 0xd8, 0xfc,
|
||||||
0x0f, 0x1c, 0x31, 0x8e, 0x30, 0xdd, 0x18, 0xab, 0xfc, 0x41, 0x06, 0x7e, 0xc0, 0xf6, 0x08, 0x65,
|
0xa4, 0x1f, 0xd8, 0x62, 0x1c, 0x61, 0x48, 0x1f, 0xab, 0xfc, 0x61, 0x06, 0x7e, 0xc0, 0xf6, 0x5c,
|
||||||
0x42, 0xe5, 0x27, 0x65, 0x28, 0x57, 0x59, 0xc1, 0xa5, 0xca, 0xaa, 0xed, 0x24, 0x24, 0x54, 0x56,
|
0xca, 0x84, 0xca, 0x4f, 0xca, 0x50, 0xae, 0xb2, 0x82, 0x4b, 0x95, 0x55, 0xdb, 0x49, 0x48, 0xa8,
|
||||||
0x82, 0x98, 0x2b, 0x4a, 0x51, 0x0e, 0xc3, 0x23, 0x30, 0x4f, 0xb1, 0xed, 0x5a, 0x61, 0xe0, 0x0d,
|
0xac, 0x04, 0x31, 0x56, 0x94, 0xa2, 0x1c, 0x86, 0x8f, 0xc0, 0xb2, 0xa8, 0xa8, 0x71, 0x77, 0x40,
|
||||||
0xf4, 0xbf, 0xee, 0x4b, 0x79, 0x07, 0xe7, 0x1c, 0xc1, 0x3d, 0x1c, 0x51, 0xec, 0xd8, 0x31, 0x76,
|
0x6f, 0x4a, 0x89, 0xe2, 0xfb, 0x6a, 0x49, 0x30, 0xf9, 0xbd, 0x4e, 0x38, 0x5e, 0x57, 0x2f, 0xbf,
|
||||||
0x4d, 0x6c, 0xbb, 0x8f, 0x03, 0x6f, 0x30, 0xe2, 0x48, 0x7b, 0x2f, 0xff, 0x7a, 0xa7, 0xa1, 0x1c,
|
0x22, 0xaa, 0x1b, 0x65, 0x2b, 0x78, 0x04, 0xe6, 0x29, 0xb1, 0x1c, 0x33, 0x0c, 0xbc, 0x01, 0xfa,
|
||||||
0x0f, 0xdf, 0x0d, 0x7d, 0x22, 0x7a, 0x75, 0x3c, 0x90, 0x5f, 0xef, 0x13, 0xa8, 0xae, 0x99, 0x73,
|
0xeb, 0xbe, 0x74, 0x76, 0x70, 0xce, 0x31, 0xdc, 0x23, 0x11, 0x25, 0xb6, 0x15, 0x13, 0xc7, 0x20,
|
||||||
0x34, 0x75, 0x00, 0x7f, 0x01, 0xd6, 0x4a, 0x33, 0xa3, 0xec, 0x9f, 0x7f, 0x13, 0x41, 0xb5, 0xe6,
|
0x96, 0xf3, 0x28, 0xf0, 0x06, 0x23, 0x8e, 0xb5, 0xf7, 0xf2, 0xbf, 0x03, 0x68, 0x28, 0xe7, 0xcd,
|
||||||
0x87, 0xe7, 0x1c, 0xe9, 0xe3, 0xa0, 0x07, 0xe3, 0xc9, 0xaf, 0xe5, 0xc4, 0x59, 0xe8, 0x5a, 0x75,
|
0x77, 0x43, 0xdf, 0x15, 0xcd, 0x3f, 0x1e, 0xc8, 0xbf, 0x03, 0x26, 0x50, 0xa4, 0x19, 0x73, 0x34,
|
||||||
0x70, 0x6c, 0x39, 0x71, 0x41, 0x81, 0xae, 0x99, 0xcb, 0x65, 0x12, 0xfe, 0x04, 0x5c, 0x53, 0xef,
|
0x75, 0x00, 0x7f, 0x09, 0xd6, 0x4a, 0x43, 0xa8, 0x6c, 0xc8, 0x7f, 0x13, 0x41, 0xb5, 0xe6, 0x87,
|
||||||
0x4b, 0xa6, 0x7f, 0xb1, 0x2f, 0xef, 0xfa, 0x77, 0x44, 0xe3, 0x19, 0x07, 0x52, 0x73, 0x10, 0x2b,
|
0xe7, 0x1c, 0xa3, 0x71, 0xd0, 0x83, 0xf1, 0x28, 0xd9, 0xb2, 0xe3, 0x2c, 0x74, 0xad, 0x3a, 0x89,
|
||||||
0x3f, 0x5c, 0xba, 0xa5, 0xe0, 0x3a, 0xbd, 0xe0, 0xba, 0x66, 0x66, 0xfe, 0x9a, 0x8f, 0x5e, 0x7e,
|
0xb6, 0xec, 0xb8, 0xa0, 0x00, 0x69, 0xc6, 0x72, 0x99, 0x84, 0x3f, 0x05, 0x57, 0xd4, 0x0b, 0x98,
|
||||||
0x59, 0x9b, 0x19, 0x7e, 0x59, 0x9b, 0x79, 0x79, 0x5e, 0xd3, 0x86, 0xe7, 0x35, 0xed, 0x77, 0xaf,
|
0xa1, 0x2f, 0xf6, 0x65, 0xf3, 0xf8, 0xae, 0xe8, 0x64, 0xe3, 0x40, 0x6a, 0xb0, 0x62, 0xe5, 0x87,
|
||||||
0x6a, 0x33, 0x9f, 0xbf, 0xaa, 0x69, 0xc3, 0x57, 0xb5, 0x99, 0x7f, 0xbf, 0xaa, 0xcd, 0x7c, 0xfc,
|
0x4b, 0xb7, 0x14, 0x5c, 0xa7, 0x1d, 0x03, 0x69, 0x46, 0xe6, 0xaf, 0xf9, 0xf0, 0xc5, 0x97, 0xb5,
|
||||||
0xf6, 0xff, 0xf0, 0x7f, 0x89, 0xba, 0xae, 0xed, 0xab, 0xf2, 0x7f, 0x93, 0xf7, 0xff, 0x1b, 0x00,
|
0x99, 0xe1, 0x97, 0xb5, 0x99, 0x17, 0xe7, 0x35, 0x6d, 0x78, 0x5e, 0xd3, 0x7e, 0xff, 0xb2, 0x36,
|
||||||
0x00, 0xff, 0xff, 0x3e, 0xb6, 0x85, 0xe6, 0x55, 0x13, 0x00, 0x00,
|
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) {
|
func (m *FolderDeviceConfiguration) Marshal() (dAtA []byte, err error) {
|
||||||
|
@ -383,6 +386,18 @@ func (m *FolderConfiguration) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0xc0
|
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 {
|
if m.JunctionsAsDirs {
|
||||||
i--
|
i--
|
||||||
if m.JunctionsAsDirs {
|
if m.JunctionsAsDirs {
|
||||||
|
@ -817,6 +832,9 @@ func (m *FolderConfiguration) ProtoSize() (n int) {
|
||||||
if m.JunctionsAsDirs {
|
if m.JunctionsAsDirs {
|
||||||
n += 3
|
n += 3
|
||||||
}
|
}
|
||||||
|
if m.SyncOwnership {
|
||||||
|
n += 3
|
||||||
|
}
|
||||||
if m.DeprecatedReadOnly {
|
if m.DeprecatedReadOnly {
|
||||||
n += 4
|
n += 4
|
||||||
}
|
}
|
||||||
|
@ -1764,6 +1782,26 @@ func (m *FolderConfiguration) Unmarshal(dAtA []byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.JunctionsAsDirs = bool(v != 0)
|
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:
|
case 9000:
|
||||||
if wireType != 0 {
|
if wireType != 0 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field DeprecatedReadOnly", wireType)
|
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())
|
t.Error("Unexpected additional file via sequence", f.FileName())
|
||||||
return true
|
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
|
found = true
|
||||||
} else {
|
} else {
|
||||||
t.Errorf("Wrong file via sequence, got %v, expected %v", f, e)
|
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)
|
f := fi.(protocol.FileInfo)
|
||||||
delete(need, f.Name)
|
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)
|
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"`
|
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"`
|
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"`
|
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
|
// see bep.proto
|
||||||
LocalFlags uint32 `protobuf:"varint,1000,opt,name=local_flags,json=localFlags,proto3" json:"localFlags" xml:"localFlags"`
|
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"`
|
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) }
|
func init() { proto.RegisterFile("lib/db/structs.proto", fileDescriptor_5465d80e8cba02e3) }
|
||||||
|
|
||||||
var fileDescriptor_5465d80e8cba02e3 = []byte{
|
var fileDescriptor_5465d80e8cba02e3 = []byte{
|
||||||
// 1476 bytes of a gzipped FileDescriptorProto
|
// 1510 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x4d, 0x6f, 0xdb, 0x46,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x6f, 0xdb, 0x46,
|
||||||
0x13, 0x36, 0x2d, 0xf9, 0x43, 0x2b, 0xf9, 0x8b, 0x79, 0x6d, 0xe8, 0xf5, 0xfb, 0x56, 0xab, 0x6e,
|
0x16, 0x37, 0x2d, 0xd9, 0x96, 0x46, 0xf2, 0x17, 0xb3, 0x36, 0xb8, 0xde, 0x5d, 0x8d, 0x76, 0xe2,
|
||||||
0x1c, 0x40, 0xfd, 0x80, 0x0c, 0x38, 0x88, 0x51, 0x04, 0x68, 0x83, 0x30, 0xae, 0x13, 0x07, 0x69,
|
0x00, 0xda, 0x0f, 0xc8, 0x80, 0x83, 0x18, 0x8b, 0x00, 0xdb, 0x20, 0x8c, 0xeb, 0xc4, 0x41, 0x9a,
|
||||||
0x52, 0xac, 0x83, 0xa4, 0x68, 0x0f, 0x82, 0x48, 0xae, 0x65, 0x22, 0x14, 0xa9, 0x72, 0x69, 0x3b,
|
0x04, 0xe3, 0x20, 0x29, 0xda, 0x83, 0xc0, 0x8f, 0xb1, 0x4c, 0x84, 0x22, 0x55, 0x92, 0xb6, 0xa3,
|
||||||
0xca, 0xad, 0x97, 0x02, 0xbd, 0x05, 0x41, 0x0f, 0x45, 0x51, 0x14, 0x39, 0xf5, 0x27, 0xf4, 0x17,
|
0xdc, 0x7a, 0x29, 0xd0, 0x5b, 0x10, 0xf4, 0x50, 0x14, 0x45, 0x91, 0x53, 0xff, 0x84, 0xfe, 0x05,
|
||||||
0x14, 0x45, 0x8e, 0x3e, 0x16, 0x3d, 0xb0, 0x88, 0x7d, 0x69, 0x75, 0xd4, 0xa9, 0xe8, 0xa9, 0xd8,
|
0x45, 0x91, 0xa3, 0x8f, 0x45, 0x0f, 0x2c, 0x62, 0x5f, 0x5a, 0x1d, 0x75, 0xec, 0xa9, 0x98, 0x37,
|
||||||
0xd9, 0xe5, 0x92, 0xb2, 0x91, 0x22, 0x49, 0x7d, 0xd3, 0x3c, 0xf3, 0xcc, 0x88, 0x9c, 0x7d, 0x66,
|
0xc3, 0x21, 0x65, 0x23, 0x45, 0x92, 0xfa, 0xc6, 0xf7, 0x7b, 0xbf, 0xf7, 0x24, 0xbe, 0xf9, 0xbd,
|
||||||
0x76, 0x88, 0xfe, 0xe3, 0x7b, 0xf6, 0xaa, 0x6b, 0xaf, 0xf2, 0x38, 0xda, 0x73, 0x62, 0xde, 0xec,
|
0x37, 0x8f, 0xe8, 0x2f, 0xbe, 0x67, 0xaf, 0xb9, 0xf6, 0x5a, 0x9c, 0x44, 0xfb, 0x4e, 0x12, 0xb7,
|
||||||
0x45, 0x61, 0x1c, 0x9a, 0xe3, 0xae, 0xbd, 0x7c, 0x3e, 0x62, 0xbd, 0x90, 0xaf, 0x02, 0x60, 0xef,
|
0xfb, 0x51, 0x98, 0x84, 0xfa, 0xa4, 0x6b, 0xaf, 0x5c, 0x8c, 0x58, 0x3f, 0x8c, 0xd7, 0x00, 0xb0,
|
||||||
0xed, 0xac, 0x76, 0xc2, 0x4e, 0x08, 0x06, 0xfc, 0x92, 0xc4, 0x65, 0xdc, 0x09, 0xc3, 0x8e, 0xcf,
|
0xf7, 0x77, 0xd7, 0xba, 0x61, 0x37, 0x04, 0x03, 0x9e, 0x04, 0x71, 0x05, 0x77, 0xc3, 0xb0, 0xeb,
|
||||||
0x32, 0x56, 0xec, 0x75, 0x19, 0x8f, 0xdb, 0xdd, 0x9e, 0x22, 0x2c, 0x89, 0xfc, 0xf0, 0xd3, 0x09,
|
0xb3, 0x9c, 0x95, 0x78, 0x3d, 0x16, 0x27, 0x56, 0xaf, 0x2f, 0x09, 0xcb, 0x3c, 0x3f, 0x3c, 0x3a,
|
||||||
0xfd, 0x55, 0x9b, 0xa5, 0x78, 0x89, 0x3d, 0x8c, 0xe5, 0x4f, 0xf2, 0xfd, 0x38, 0x2a, 0x6f, 0x7a,
|
0xa1, 0xbf, 0x66, 0xb3, 0x0c, 0xaf, 0xb2, 0x27, 0x89, 0x78, 0x24, 0xdf, 0x4c, 0xa2, 0xda, 0x96,
|
||||||
0x3e, 0xbb, 0xc7, 0x22, 0xee, 0x85, 0x81, 0x79, 0x0b, 0x4d, 0xed, 0xcb, 0x9f, 0x55, 0xa3, 0x6e,
|
0xe7, 0xb3, 0x87, 0x2c, 0x8a, 0xbd, 0x30, 0xd0, 0xef, 0xa0, 0x99, 0x03, 0xf1, 0x68, 0x68, 0x4d,
|
||||||
0x34, 0xca, 0x6b, 0xf3, 0xcd, 0x34, 0x41, 0xf3, 0x1e, 0x73, 0xe2, 0x30, 0xb2, 0xea, 0xcf, 0x12,
|
0xad, 0x55, 0x5b, 0x5f, 0x68, 0x67, 0x09, 0xda, 0x0f, 0x99, 0x93, 0x84, 0x91, 0xd9, 0x7c, 0x99,
|
||||||
0x3c, 0x36, 0x48, 0x70, 0x4a, 0x1c, 0x26, 0x78, 0xe6, 0x61, 0xd7, 0xbf, 0x4c, 0x94, 0x4d, 0x68,
|
0xe2, 0x89, 0x61, 0x8a, 0x33, 0xe2, 0x28, 0xc5, 0xb3, 0x4f, 0x7a, 0xfe, 0x55, 0x22, 0x6d, 0x42,
|
||||||
0xea, 0x31, 0xd7, 0xd1, 0x94, 0xcb, 0x7c, 0x16, 0x33, 0xb7, 0x3a, 0x5e, 0x37, 0x1a, 0xd3, 0xd6,
|
0x33, 0x8f, 0xbe, 0x81, 0x66, 0x5c, 0xe6, 0xb3, 0x84, 0xb9, 0xc6, 0x64, 0x53, 0x6b, 0x55, 0xcc,
|
||||||
0xff, 0x45, 0x9c, 0x82, 0x74, 0x9c, 0xb2, 0x09, 0x4d, 0x3d, 0xe6, 0x25, 0x11, 0xb7, 0xef, 0x39,
|
0xbf, 0xf3, 0x38, 0x09, 0xa9, 0x38, 0x69, 0x13, 0x9a, 0x79, 0xf4, 0x2b, 0x3c, 0xee, 0xc0, 0x73,
|
||||||
0x8c, 0x57, 0x0b, 0xf5, 0x42, 0xa3, 0x62, 0xfd, 0x4f, 0xc6, 0x01, 0x34, 0x4c, 0x70, 0x45, 0xc5,
|
0x58, 0x6c, 0x94, 0x9a, 0xa5, 0x56, 0xdd, 0xfc, 0x9b, 0x88, 0x03, 0x68, 0x94, 0xe2, 0xba, 0x8c,
|
||||||
0x09, 0x1b, 0xc2, 0xc0, 0x61, 0x52, 0x34, 0xe7, 0x05, 0xfb, 0x6d, 0xdf, 0x73, 0x5b, 0x69, 0x78,
|
0xe3, 0x36, 0x84, 0x81, 0x43, 0xa7, 0x68, 0xde, 0x0b, 0x0e, 0x2c, 0xdf, 0x73, 0x3b, 0x59, 0x78,
|
||||||
0x11, 0xc2, 0xdf, 0x1a, 0x24, 0x78, 0x56, 0xb9, 0x36, 0x74, 0x96, 0x73, 0x90, 0x65, 0x04, 0x26,
|
0x19, 0xc2, 0xff, 0x35, 0x4c, 0xf1, 0x9c, 0x74, 0x6d, 0xaa, 0x2c, 0x17, 0x20, 0xcb, 0x18, 0x4c,
|
||||||
0xf4, 0x04, 0x8d, 0x7c, 0x61, 0xa0, 0xb2, 0x2a, 0xce, 0x2d, 0x8f, 0xc7, 0xa6, 0x8f, 0xa6, 0xd5,
|
0xe8, 0x29, 0x1a, 0xf9, 0x54, 0x43, 0x35, 0x59, 0x9c, 0x3b, 0x5e, 0x9c, 0xe8, 0x3e, 0xaa, 0xc8,
|
||||||
0xdb, 0xf1, 0xaa, 0x51, 0x2f, 0x34, 0xca, 0x6b, 0x73, 0x4d, 0xd7, 0x6e, 0xe6, 0x6a, 0x68, 0x5d,
|
0xb7, 0x8b, 0x0d, 0xad, 0x59, 0x6a, 0xd5, 0xd6, 0xe7, 0xdb, 0xae, 0xdd, 0x2e, 0xd4, 0xd0, 0xbc,
|
||||||
0x11, 0x05, 0x3a, 0x4a, 0x70, 0x99, 0xb6, 0x0f, 0x14, 0xc6, 0x07, 0x09, 0xd6, 0x71, 0xa7, 0x0a,
|
0xc6, 0x0b, 0x74, 0x9c, 0xe2, 0x1a, 0xb5, 0x0e, 0x25, 0x16, 0x0f, 0x53, 0xac, 0xe2, 0xce, 0x14,
|
||||||
0xf6, 0xe4, 0x70, 0x25, 0xcf, 0xa5, 0x9a, 0x79, 0xb9, 0xf8, 0xcd, 0x53, 0x3c, 0x46, 0xfe, 0x44,
|
0xec, 0xf9, 0xd1, 0x6a, 0x91, 0x4b, 0x15, 0xf3, 0x6a, 0xf9, 0xcb, 0x17, 0x78, 0x82, 0x1c, 0xd5,
|
||||||
0x68, 0x41, 0xfc, 0xc1, 0x56, 0xb0, 0x13, 0xde, 0x8d, 0xf6, 0x02, 0xa7, 0x2d, 0x8a, 0xf4, 0x36,
|
0xd0, 0x22, 0xff, 0x81, 0xed, 0x60, 0x37, 0x7c, 0x10, 0xed, 0x07, 0x8e, 0xc5, 0x8b, 0xf4, 0x6f,
|
||||||
0x2a, 0x06, 0xed, 0x2e, 0x83, 0x73, 0x2a, 0x59, 0x4b, 0x83, 0x04, 0x83, 0x3d, 0x4c, 0x30, 0x82,
|
0x54, 0x0e, 0xac, 0x1e, 0x83, 0x73, 0xaa, 0x9a, 0xcb, 0xc3, 0x14, 0x83, 0x3d, 0x4a, 0x31, 0x82,
|
||||||
0xec, 0xc2, 0x20, 0x14, 0x30, 0xc1, 0xe5, 0xde, 0x23, 0x56, 0x2d, 0xd4, 0x8d, 0x46, 0x41, 0x72,
|
0xec, 0xdc, 0x20, 0x14, 0x30, 0xce, 0x8d, 0xbd, 0xa7, 0xcc, 0x28, 0x35, 0xb5, 0x56, 0x49, 0x70,
|
||||||
0x85, 0xad, 0xb9, 0xc2, 0x20, 0x14, 0x30, 0xf3, 0x0a, 0x42, 0xdd, 0xd0, 0xf5, 0x76, 0x3c, 0xe6,
|
0xb9, 0xad, 0xb8, 0xdc, 0x20, 0x14, 0x30, 0xfd, 0x1a, 0x42, 0xbd, 0xd0, 0xf5, 0x76, 0x3d, 0xe6,
|
||||||
0xb6, 0x78, 0x75, 0x02, 0x22, 0xea, 0x83, 0x04, 0x97, 0x52, 0x74, 0x7b, 0x98, 0xe0, 0x39, 0x08,
|
0x76, 0x62, 0x63, 0x0a, 0x22, 0x9a, 0xc3, 0x14, 0x57, 0x33, 0x74, 0x67, 0x94, 0xe2, 0x79, 0x08,
|
||||||
0xd3, 0x08, 0xa1, 0x99, 0xd7, 0xfc, 0xd1, 0x40, 0x65, 0x9d, 0xc1, 0xee, 0x57, 0x2b, 0x75, 0xa3,
|
0x53, 0x08, 0xa1, 0xb9, 0x57, 0xff, 0x4e, 0x43, 0x35, 0x95, 0xc1, 0x1e, 0x18, 0xf5, 0xa6, 0xd6,
|
||||||
0x51, 0xb4, 0xbe, 0x36, 0x44, 0x59, 0x7e, 0x4d, 0xf0, 0xc5, 0x8e, 0x17, 0xef, 0xee, 0xd9, 0x4d,
|
0x2a, 0x9b, 0x5f, 0x68, 0xbc, 0x2c, 0x3f, 0xa5, 0xf8, 0x72, 0xd7, 0x4b, 0xf6, 0xf6, 0xed, 0xb6,
|
||||||
0x27, 0xec, 0xae, 0xf2, 0x7e, 0xe0, 0xc4, 0xbb, 0x5e, 0xd0, 0xc9, 0xfd, 0xca, 0x8b, 0xb6, 0xb9,
|
0x13, 0xf6, 0xd6, 0xe2, 0x41, 0xe0, 0x24, 0x7b, 0x5e, 0xd0, 0x2d, 0x3c, 0x15, 0x45, 0xdb, 0xde,
|
||||||
0xbd, 0x1b, 0x46, 0xf1, 0xd6, 0xc6, 0x20, 0xc1, 0xfa, 0xa1, 0xac, 0xfe, 0x30, 0xc1, 0xf3, 0x23,
|
0xd9, 0x0b, 0xa3, 0x64, 0x7b, 0x73, 0x98, 0x62, 0xf5, 0xa7, 0xcc, 0xc1, 0x28, 0xc5, 0x0b, 0x63,
|
||||||
0xff, 0x6f, 0xf5, 0xc9, 0xb7, 0x87, 0x2b, 0xaf, 0x93, 0x98, 0xe6, 0xd2, 0xe6, 0xc5, 0x5f, 0xfa,
|
0xbf, 0x6f, 0x0e, 0xc8, 0x57, 0x47, 0xab, 0xef, 0x92, 0x98, 0x16, 0xd2, 0x16, 0xc5, 0x5f, 0xfd,
|
||||||
0xf7, 0xe2, 0xbf, 0x8c, 0xa6, 0x39, 0xfb, 0x7c, 0x8f, 0x05, 0x0e, 0xab, 0x22, 0xa8, 0x62, 0x4d,
|
0xf3, 0xe2, 0xbf, 0x8a, 0x2a, 0x31, 0xfb, 0x64, 0x9f, 0x05, 0x0e, 0x33, 0x10, 0x54, 0xb1, 0xc1,
|
||||||
0xa8, 0x20, 0xc5, 0x86, 0x09, 0x9e, 0x95, 0xb5, 0x57, 0x00, 0xa1, 0xda, 0x67, 0xde, 0x41, 0xb3,
|
0x55, 0x90, 0x61, 0xa3, 0x14, 0xcf, 0x89, 0xda, 0x4b, 0x80, 0x50, 0xe5, 0xd3, 0xef, 0xa1, 0xb9,
|
||||||
0xbc, 0xdf, 0xf5, 0xbd, 0xe0, 0x41, 0x2b, 0x6e, 0x47, 0x1d, 0x16, 0x57, 0x17, 0xe0, 0x94, 0x1b,
|
0x78, 0xd0, 0xf3, 0xbd, 0xe0, 0x71, 0x27, 0xb1, 0xa2, 0x2e, 0x4b, 0x8c, 0x45, 0x38, 0xe5, 0xd6,
|
||||||
0x83, 0x04, 0xcf, 0x28, 0xcf, 0x5d, 0x70, 0x68, 0x1d, 0x8f, 0xa0, 0x84, 0x8e, 0xb2, 0xcc, 0x6b,
|
0x30, 0xc5, 0xb3, 0xd2, 0xf3, 0x00, 0x1c, 0x4a, 0xc7, 0x63, 0x28, 0xa1, 0xe3, 0x2c, 0xfd, 0x06,
|
||||||
0xa8, 0x6c, 0xfb, 0xa1, 0xf3, 0x80, 0xb7, 0x76, 0xdb, 0x7c, 0xb7, 0x6a, 0xd6, 0x8d, 0x46, 0xc5,
|
0xaa, 0xd9, 0x7e, 0xe8, 0x3c, 0x8e, 0x3b, 0x7b, 0x56, 0xbc, 0x67, 0xe8, 0x4d, 0xad, 0x55, 0x37,
|
||||||
0x22, 0xa2, 0xac, 0x12, 0xbe, 0xd1, 0xe6, 0xbb, 0xba, 0xac, 0x19, 0x44, 0x68, 0xce, 0x6f, 0x7e,
|
0x09, 0x2f, 0xab, 0x80, 0x6f, 0x59, 0xf1, 0x9e, 0x2a, 0x6b, 0x0e, 0x11, 0x5a, 0xf0, 0xeb, 0xef,
|
||||||
0x80, 0x4a, 0x2c, 0x70, 0xa2, 0x7e, 0x4f, 0x34, 0xf4, 0x39, 0x48, 0x01, 0xc2, 0xd0, 0xa0, 0x16,
|
0xa1, 0x2a, 0x0b, 0x9c, 0x68, 0xd0, 0xe7, 0x0d, 0x7d, 0x01, 0x52, 0x80, 0x30, 0x14, 0xa8, 0x84,
|
||||||
0x86, 0x46, 0x08, 0xcd, 0xbc, 0xa6, 0x85, 0x8a, 0x71, 0xbf, 0xc7, 0x60, 0x16, 0xcc, 0xae, 0x2d,
|
0xa1, 0x10, 0x42, 0x73, 0xaf, 0x6e, 0xa2, 0x72, 0x32, 0xe8, 0x33, 0x98, 0x05, 0x73, 0xeb, 0xcb,
|
||||||
0x65, 0xc5, 0xd5, 0xe2, 0xee, 0xf7, 0x98, 0x54, 0xa7, 0xe0, 0x69, 0x75, 0x0a, 0x83, 0x50, 0xc0,
|
0x79, 0x71, 0x95, 0xb8, 0x07, 0x7d, 0x26, 0xd4, 0xc9, 0x79, 0x4a, 0x9d, 0xdc, 0x20, 0x14, 0x30,
|
||||||
0xcc, 0x4d, 0x54, 0xee, 0xb1, 0xa8, 0xeb, 0x71, 0xd9, 0x82, 0xc5, 0xba, 0xd1, 0x98, 0xb1, 0x56,
|
0x7d, 0x0b, 0xd5, 0xfa, 0x2c, 0xea, 0x79, 0xb1, 0x68, 0xc1, 0x72, 0x53, 0x6b, 0xcd, 0x9a, 0xab,
|
||||||
0x06, 0x09, 0xce, 0xc3, 0xc3, 0x04, 0x2f, 0x40, 0x64, 0x0e, 0x23, 0x34, 0xcf, 0x30, 0x6f, 0xe6,
|
0xc3, 0x14, 0x17, 0xe1, 0x51, 0x8a, 0x17, 0x21, 0xb2, 0x80, 0x11, 0x5a, 0x64, 0xe8, 0xb7, 0x0b,
|
||||||
0x34, 0x1a, 0xf0, 0x6a, 0xb9, 0x6e, 0x34, 0x26, 0x60, 0x4e, 0x68, 0x41, 0xdc, 0xe6, 0xa7, 0x74,
|
0x1a, 0x0d, 0x62, 0xa3, 0xd6, 0xd4, 0x5a, 0x53, 0x30, 0x27, 0x94, 0x20, 0xee, 0xc6, 0x67, 0x74,
|
||||||
0x76, 0x9b, 0x93, 0xbf, 0x12, 0x5c, 0xf0, 0x82, 0x98, 0xe6, 0x68, 0xe6, 0x0e, 0x92, 0x55, 0x6a,
|
0x76, 0x37, 0x26, 0xbf, 0xa5, 0xb8, 0xe4, 0x05, 0x09, 0x2d, 0xd0, 0xf4, 0x5d, 0x24, 0xaa, 0xd4,
|
||||||
0x41, 0x8f, 0xcd, 0x40, 0xaa, 0xeb, 0x47, 0x09, 0xae, 0xd0, 0xf6, 0x81, 0x25, 0x1c, 0xdb, 0xde,
|
0x81, 0x1e, 0x9b, 0x85, 0x54, 0x37, 0x8f, 0x53, 0x5c, 0xa7, 0xd6, 0xa1, 0xc9, 0x1d, 0x3b, 0xde,
|
||||||
0x23, 0x26, 0x0a, 0x65, 0xa7, 0x86, 0x2e, 0x94, 0x46, 0xd2, 0xc4, 0x4f, 0x0e, 0x57, 0x46, 0xc2,
|
0x53, 0xc6, 0x0b, 0x65, 0x67, 0x86, 0x2a, 0x94, 0x42, 0xb2, 0xc4, 0xcf, 0x8f, 0x56, 0xc7, 0xc2,
|
||||||
0x68, 0x16, 0x64, 0x6e, 0xa0, 0xb2, 0x1f, 0x3a, 0x6d, 0xbf, 0xb5, 0xe3, 0xb7, 0x3b, 0xbc, 0xfa,
|
0x68, 0x1e, 0xa4, 0x3f, 0x44, 0x95, 0xbe, 0x6f, 0x25, 0xbb, 0x61, 0xd4, 0x33, 0xe6, 0x40, 0xa0,
|
||||||
0xfb, 0x14, 0xbc, 0x3c, 0x9c, 0x22, 0xe0, 0x9b, 0x02, 0xd6, 0x0f, 0x9d, 0x41, 0x84, 0xe6, 0xfc,
|
0x85, 0x1a, 0xde, 0x97, 0x9e, 0x4d, 0x2b, 0xb1, 0x4c, 0x22, 0x65, 0xaa, 0xf8, 0x4a, 0x6d, 0x19,
|
||||||
0xe6, 0x0d, 0x54, 0x51, 0x12, 0x95, 0x5a, 0xf8, 0x63, 0x0a, 0x4e, 0x12, 0x6a, 0xa8, 0x1c, 0x4a,
|
0x40, 0xa8, 0xf2, 0xe9, 0x9b, 0xa8, 0xe6, 0x87, 0x8e, 0xe5, 0x77, 0x76, 0x7d, 0xab, 0x1b, 0x1b,
|
||||||
0x0d, 0x0b, 0x79, 0x65, 0x4b, 0x39, 0xe4, 0x19, 0xf9, 0xf1, 0x3e, 0xf9, 0x2a, 0xe3, 0x9d, 0xa2,
|
0xbf, 0xcc, 0x40, 0x51, 0x41, 0x1d, 0x80, 0x6f, 0x71, 0x58, 0x15, 0x23, 0x87, 0x08, 0x2d, 0xf8,
|
||||||
0x29, 0x35, 0x65, 0xab, 0x53, 0x10, 0xf7, 0xde, 0x51, 0x82, 0x11, 0x6d, 0x1f, 0x6c, 0x49, 0x54,
|
0xf5, 0x5b, 0xa8, 0x2e, 0xa5, 0x2f, 0x34, 0xf6, 0xeb, 0x0c, 0x28, 0x04, 0xce, 0x46, 0x3a, 0xa4,
|
||||||
0x64, 0x51, 0x04, 0x9d, 0x45, 0xd9, 0x62, 0x56, 0xe6, 0x98, 0x34, 0xe5, 0x89, 0x8e, 0x09, 0xc2,
|
0xca, 0x16, 0x8b, 0x1d, 0x23, 0x64, 0x56, 0x64, 0x14, 0xaf, 0x8d, 0xe9, 0xb7, 0xb9, 0x36, 0x28,
|
||||||
0x56, 0x5e, 0x1a, 0xd3, 0x90, 0x1a, 0x3a, 0x26, 0x08, 0x3f, 0x1e, 0x11, 0x87, 0xec, 0x98, 0x11,
|
0x9a, 0x91, 0xd3, 0xdb, 0x98, 0x81, 0xb8, 0xff, 0x1d, 0xa7, 0x18, 0x51, 0xeb, 0x70, 0x5b, 0xa0,
|
||||||
0x94, 0xd0, 0x51, 0x96, 0x1a, 0xbd, 0xf7, 0x51, 0x09, 0x8e, 0x02, 0x66, 0xff, 0x4d, 0x34, 0x29,
|
0x3c, 0x8b, 0x24, 0xa8, 0x2c, 0xd2, 0xe6, 0x33, 0xb8, 0xc0, 0xa4, 0x19, 0x8f, 0x77, 0x62, 0x10,
|
||||||
0xbb, 0x41, 0x4d, 0xfe, 0x73, 0x99, 0x82, 0x81, 0x24, 0x24, 0x6c, 0xbd, 0xa1, 0x26, 0x84, 0xa2,
|
0x76, 0x8a, 0x92, 0xab, 0x40, 0x6a, 0xe8, 0xc4, 0x20, 0xbc, 0x3f, 0x26, 0x3a, 0xd1, 0x89, 0x63,
|
||||||
0x0e, 0x13, 0x5c, 0xce, 0x4e, 0x9a, 0x50, 0x05, 0x93, 0x1f, 0x0c, 0xb4, 0xb8, 0x15, 0xb8, 0x5e,
|
0x28, 0xa1, 0xe3, 0x2c, 0x39, 0xd2, 0x1f, 0xa1, 0x2a, 0x1c, 0x31, 0xdc, 0x29, 0xb7, 0xd1, 0xb4,
|
||||||
0xc4, 0x9c, 0x58, 0xd5, 0x93, 0xf1, 0x3b, 0x81, 0xdf, 0x3f, 0x9b, 0x56, 0x3d, 0xb3, 0x43, 0x26,
|
0xe8, 0x32, 0x79, 0xa3, 0x5c, 0xc8, 0x4f, 0x15, 0x48, 0xbc, 0x35, 0xcc, 0x7f, 0xc8, 0x23, 0x95,
|
||||||
0xdf, 0x15, 0xd1, 0xe4, 0xb5, 0x70, 0x2f, 0x88, 0xb9, 0x79, 0x09, 0x4d, 0xec, 0x78, 0x3e, 0xe3,
|
0xd4, 0x51, 0x8a, 0x6b, 0xb9, 0x82, 0x08, 0x95, 0x30, 0xf9, 0x56, 0x43, 0x4b, 0xdb, 0x81, 0xeb,
|
||||||
0x70, 0xe5, 0x4c, 0x58, 0x78, 0x90, 0x60, 0x09, 0xe8, 0x97, 0x04, 0x4b, 0xf7, 0x88, 0x74, 0x9a,
|
0x45, 0xcc, 0x49, 0x64, 0x3d, 0x59, 0x7c, 0x2f, 0xf0, 0x07, 0xe7, 0x33, 0x02, 0xce, 0xed, 0x90,
|
||||||
0x1f, 0xa1, 0xb2, 0x7c, 0xcf, 0x30, 0xf2, 0x18, 0x87, 0xee, 0x9f, 0xb0, 0xde, 0x11, 0x4f, 0x92,
|
0xc9, 0xd7, 0x65, 0x34, 0x7d, 0x23, 0xdc, 0x0f, 0x92, 0x58, 0xbf, 0x82, 0xa6, 0x76, 0x3d, 0x9f,
|
||||||
0x83, 0xf5, 0x93, 0xe4, 0x30, 0x9d, 0x28, 0x4f, 0x34, 0xaf, 0xa2, 0x69, 0x35, 0xdb, 0x38, 0xdc,
|
0xc5, 0x70, 0x95, 0x4d, 0x99, 0x78, 0x98, 0x62, 0x01, 0xa8, 0x97, 0x04, 0x4b, 0xf5, 0x9e, 0x70,
|
||||||
0x67, 0x13, 0xd6, 0x05, 0x98, 0xab, 0x0a, 0xcb, 0xe6, 0xaa, 0x02, 0x74, 0x16, 0x4d, 0x31, 0xdf,
|
0xea, 0x1f, 0xa0, 0x9a, 0x78, 0xcf, 0x30, 0xf2, 0x58, 0x0c, 0x53, 0x65, 0xca, 0xfc, 0x0f, 0xff,
|
||||||
0xcf, 0x84, 0x5b, 0x84, 0x0c, 0xe7, 0xff, 0x49, 0xb8, 0x69, 0xbc, 0xd6, 0x6f, 0x13, 0x4d, 0xd8,
|
0x27, 0x05, 0x58, 0xfd, 0x93, 0x02, 0xa6, 0x12, 0x15, 0x89, 0xfa, 0x75, 0x54, 0x91, 0x33, 0x33,
|
||||||
0xfd, 0x98, 0xa5, 0x97, 0x63, 0x55, 0xd4, 0x01, 0x80, 0xec, 0xb0, 0x85, 0x45, 0xa8, 0x44, 0x47,
|
0x86, 0x7b, 0x72, 0xca, 0xbc, 0x04, 0xf3, 0x5a, 0x62, 0xf9, 0xbc, 0x96, 0x80, 0xca, 0xa2, 0x28,
|
||||||
0x6e, 0x82, 0xc9, 0x57, 0xbc, 0x09, 0xb6, 0x51, 0x49, 0xee, 0x32, 0x2d, 0xcf, 0x85, 0x4b, 0xa0,
|
0xfa, 0xff, 0x73, 0xe1, 0x96, 0x21, 0xc3, 0xc5, 0x3f, 0x12, 0x6e, 0x16, 0xaf, 0xf4, 0xdb, 0x46,
|
||||||
0x62, 0xad, 0x1f, 0x25, 0x78, 0x5a, 0xee, 0x27, 0x70, 0x33, 0x4e, 0x4b, 0xc2, 0x96, 0xab, 0x13,
|
0x53, 0xf6, 0x20, 0x61, 0xd9, 0xa5, 0x6b, 0xf0, 0x3a, 0x00, 0x90, 0x1f, 0x36, 0xb7, 0x08, 0x15,
|
||||||
0xa5, 0x80, 0xe8, 0x16, 0xcd, 0xa4, 0x9a, 0x27, 0x24, 0x96, 0x1f, 0x24, 0xe6, 0xeb, 0xcc, 0x11,
|
0xe8, 0xd8, 0x0d, 0x33, 0xfd, 0x96, 0x37, 0xcc, 0x0e, 0xaa, 0x8a, 0x1d, 0xa9, 0xe3, 0xb9, 0x70,
|
||||||
0xd5, 0x20, 0x5f, 0x1a, 0xa8, 0x24, 0xe5, 0xb1, 0xcd, 0x62, 0xf3, 0x2a, 0x9a, 0x74, 0xc0, 0x50,
|
0xb9, 0xd4, 0xcd, 0x8d, 0xe3, 0x14, 0x57, 0xc4, 0xde, 0x03, 0x37, 0x6e, 0x45, 0x10, 0xb6, 0x5d,
|
||||||
0x1d, 0x82, 0xc4, 0x6e, 0x24, 0xdd, 0x59, 0x63, 0x48, 0x86, 0xae, 0x15, 0x98, 0x84, 0x2a, 0x58,
|
0x95, 0x28, 0x03, 0x78, 0xb7, 0x28, 0x26, 0x55, 0x3c, 0x2e, 0xb1, 0xe2, 0x20, 0xd1, 0xdf, 0x65,
|
||||||
0x0c, 0x15, 0x27, 0x62, 0xed, 0x74, 0x67, 0x2c, 0xc8, 0xa1, 0xa2, 0x20, 0x7d, 0x36, 0xca, 0x26,
|
0x8e, 0xc8, 0x06, 0xf9, 0x4c, 0x43, 0x55, 0x21, 0x8f, 0x1d, 0x96, 0xe8, 0xd7, 0xd1, 0xb4, 0x03,
|
||||||
0x34, 0xf5, 0x90, 0xaf, 0xc6, 0xd1, 0x62, 0x6e, 0x0b, 0xdb, 0x60, 0xbd, 0x88, 0xc9, 0x45, 0xe9,
|
0x86, 0xec, 0x10, 0xc4, 0x77, 0x2e, 0xe1, 0xce, 0x1b, 0x43, 0x30, 0x54, 0xad, 0xc0, 0x24, 0x54,
|
||||||
0x6c, 0x77, 0xda, 0x35, 0x34, 0x29, 0xeb, 0x08, 0x8f, 0x57, 0xb1, 0x96, 0xc5, 0x2b, 0x49, 0xe4,
|
0xc2, 0x7c, 0xa8, 0x38, 0x11, 0xb3, 0xb2, 0x5d, 0xb4, 0x24, 0x86, 0x8a, 0x84, 0xd4, 0xd9, 0x48,
|
||||||
0xd4, 0x66, 0xaa, 0x70, 0xf1, 0x4e, 0xe9, 0xc0, 0x2b, 0x64, 0x83, 0xf2, 0x45, 0x23, 0x2e, 0x1b,
|
0x9b, 0xd0, 0xcc, 0x43, 0x3e, 0x9f, 0x44, 0x4b, 0x85, 0xed, 0x6e, 0x93, 0xf5, 0x23, 0x26, 0x16,
|
||||||
0x6a, 0xeb, 0xa3, 0x3a, 0x7d, 0xd9, 0x01, 0x4b, 0x0e, 0xd0, 0x62, 0x6e, 0x67, 0xcd, 0x95, 0xe2,
|
0xb0, 0xf3, 0xdd, 0x95, 0xd7, 0xd1, 0xb4, 0xa8, 0x23, 0xfc, 0xbd, 0xba, 0xb9, 0xc2, 0x5f, 0x49,
|
||||||
0x93, 0x53, 0xdb, 0xeb, 0x7f, 0x4f, 0x6c, 0xaf, 0x19, 0xd9, 0x7a, 0x53, 0x15, 0xe5, 0xc5, 0x8b,
|
0x20, 0x67, 0x36, 0x5e, 0x89, 0xf3, 0x77, 0xca, 0x06, 0x5e, 0x29, 0x1f, 0x94, 0xaf, 0x1b, 0x71,
|
||||||
0xeb, 0xa9, 0x4d, 0xf5, 0xe7, 0x71, 0x34, 0x7b, 0xc7, 0xe6, 0x2c, 0xda, 0x67, 0xee, 0x66, 0xe8,
|
0xf9, 0x50, 0xdb, 0x18, 0xd7, 0xe9, 0x9b, 0x0e, 0x58, 0x72, 0x88, 0x96, 0x0a, 0xbb, 0x70, 0xa1,
|
||||||
0xbb, 0x2c, 0x32, 0x6f, 0xa3, 0xa2, 0xf8, 0x2e, 0x51, 0xa5, 0x5f, 0x6e, 0xca, 0x8f, 0x96, 0x66,
|
0x14, 0x1f, 0x9e, 0xd9, 0x8a, 0xff, 0x7a, 0x6a, 0x2b, 0xce, 0xc9, 0xe6, 0x3f, 0xb3, 0xcb, 0xe9,
|
||||||
0xfa, 0xd1, 0xd2, 0xbc, 0x9b, 0x7e, 0xb4, 0x58, 0x35, 0xf5, 0x7f, 0xc0, 0xcf, 0x2e, 0x7f, 0xaf,
|
0xb5, 0x0b, 0xf1, 0x99, 0x0d, 0xf8, 0x87, 0x49, 0x34, 0x77, 0xcf, 0x8e, 0x59, 0x74, 0xc0, 0xdc,
|
||||||
0xcb, 0xc8, 0xe3, 0xdf, 0xb0, 0x41, 0x01, 0x17, 0xcd, 0xe7, 0xb7, 0x6d, 0xe6, 0x43, 0xf9, 0x4b,
|
0xad, 0xd0, 0x77, 0x59, 0xa4, 0xdf, 0x45, 0x65, 0xfe, 0xbd, 0x23, 0x4b, 0xbf, 0xd2, 0x16, 0x1f,
|
||||||
0xb2, 0xf9, 0x00, 0xd0, 0x82, 0x02, 0x8b, 0x50, 0x89, 0x9a, 0x9f, 0xa1, 0x85, 0x88, 0x39, 0xcc,
|
0x43, 0xed, 0xec, 0x63, 0xa8, 0xfd, 0x20, 0xfb, 0x18, 0x32, 0x1b, 0xf2, 0xf7, 0x80, 0x9f, 0x2f,
|
||||||
0xdb, 0x67, 0xad, 0x6c, 0x79, 0x91, 0xa7, 0xd0, 0x1c, 0x24, 0x78, 0x5e, 0x39, 0x3f, 0xcc, 0xed,
|
0x15, 0x5e, 0x8f, 0x91, 0x67, 0x3f, 0x63, 0x8d, 0x02, 0xce, 0x9b, 0xcf, 0xb7, 0x6c, 0xe6, 0x43,
|
||||||
0x30, 0x4b, 0x90, 0xe6, 0xa4, 0x83, 0xd0, 0x53, 0x5c, 0xf3, 0x3e, 0x9a, 0x8f, 0x58, 0x37, 0x8c,
|
0xf9, 0xab, 0xa2, 0xf9, 0x00, 0x50, 0x82, 0x02, 0x8b, 0x50, 0x81, 0xea, 0x1f, 0xa3, 0xc5, 0x88,
|
||||||
0xf3, 0xb9, 0xe5, 0x49, 0xbd, 0x3b, 0x48, 0xf0, 0x9c, 0xf4, 0xe5, 0x53, 0x2f, 0xaa, 0xd4, 0x23,
|
0x39, 0xcc, 0x3b, 0x60, 0x9d, 0x7c, 0x29, 0x12, 0xa7, 0xd0, 0x1e, 0xa6, 0x78, 0x41, 0x3a, 0xdf,
|
||||||
0x38, 0xa1, 0x27, 0x99, 0xe4, 0x27, 0x23, 0x2b, 0xa4, 0x6c, 0xe0, 0x33, 0x2f, 0x64, 0xfa, 0xfd,
|
0x2f, 0xec, 0x46, 0xcb, 0x90, 0xe6, 0xb4, 0x83, 0xd0, 0x33, 0x5c, 0xfd, 0x11, 0x5a, 0x88, 0x58,
|
||||||
0x30, 0xfe, 0x12, 0xdf, 0x0f, 0xeb, 0x68, 0xaa, 0xed, 0xba, 0x11, 0xe3, 0x72, 0xe4, 0x96, 0xa4,
|
0x2f, 0x4c, 0x8a, 0xb9, 0xc5, 0x49, 0xfd, 0x77, 0x98, 0xe2, 0x79, 0xe1, 0x2b, 0xa6, 0x5e, 0x92,
|
||||||
0x10, 0x15, 0xa4, 0x65, 0xa1, 0x6c, 0x42, 0x53, 0x8f, 0x75, 0xfd, 0xd9, 0xf3, 0xda, 0xd8, 0xe1,
|
0xa9, 0xc7, 0x70, 0x42, 0x4f, 0x33, 0xc9, 0xf7, 0x5a, 0x5e, 0x48, 0xd1, 0xc0, 0xe7, 0x5e, 0xc8,
|
||||||
0xf3, 0xda, 0xd8, 0xb3, 0xa3, 0x9a, 0x71, 0x78, 0x54, 0x33, 0x1e, 0x1f, 0xd7, 0xc6, 0x9e, 0x1e,
|
0xec, 0xbb, 0x64, 0xf2, 0x0d, 0xbe, 0x4b, 0x36, 0xd0, 0x8c, 0xe5, 0xba, 0x11, 0x8b, 0xc5, 0xc8,
|
||||||
0xd7, 0x8c, 0xc3, 0xe3, 0xda, 0xd8, 0x2f, 0xc7, 0xb5, 0xb1, 0x4f, 0x2f, 0xbc, 0xc4, 0xd2, 0xee,
|
0xad, 0x0a, 0x21, 0x4a, 0x48, 0xc9, 0x42, 0xda, 0x84, 0x66, 0x1e, 0xf3, 0xe6, 0xcb, 0x57, 0x8d,
|
||||||
0xda, 0xf6, 0x24, 0xbc, 0xe6, 0xc5, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xb3, 0xa4, 0xea, 0xfc,
|
0x89, 0xa3, 0x57, 0x8d, 0x89, 0x97, 0xc7, 0x0d, 0xed, 0xe8, 0xb8, 0xa1, 0x3d, 0x3b, 0x69, 0x4c,
|
||||||
0x33, 0x0f, 0x00, 0x00,
|
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) {
|
func (m *FileVersion) Marshal() (dAtA []byte, err error) {
|
||||||
|
@ -752,6 +755,16 @@ func (m *FileInfoTruncated) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x8a
|
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 {
|
if m.RawBlockSize != 0 {
|
||||||
i = encodeVarintStructs(dAtA, i, uint64(m.RawBlockSize))
|
i = encodeVarintStructs(dAtA, i, uint64(m.RawBlockSize))
|
||||||
i--
|
i--
|
||||||
|
@ -1175,12 +1188,12 @@ func (m *ObservedFolder) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x12
|
dAtA[i] = 0x12
|
||||||
}
|
}
|
||||||
n4, err4 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||||
if err4 != nil {
|
if err5 != nil {
|
||||||
return 0, err4
|
return 0, err5
|
||||||
}
|
}
|
||||||
i -= n4
|
i -= n5
|
||||||
i = encodeVarintStructs(dAtA, i, uint64(n4))
|
i = encodeVarintStructs(dAtA, i, uint64(n5))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0xa
|
dAtA[i] = 0xa
|
||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
|
@ -1220,12 +1233,12 @@ func (m *ObservedDevice) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0x12
|
dAtA[i] = 0x12
|
||||||
}
|
}
|
||||||
n5, err5 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
n6, err6 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||||
if err5 != nil {
|
if err6 != nil {
|
||||||
return 0, err5
|
return 0, err6
|
||||||
}
|
}
|
||||||
i -= n5
|
i -= n6
|
||||||
i = encodeVarintStructs(dAtA, i, uint64(n5))
|
i = encodeVarintStructs(dAtA, i, uint64(n6))
|
||||||
i--
|
i--
|
||||||
dAtA[i] = 0xa
|
dAtA[i] = 0xa
|
||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
|
@ -1328,6 +1341,8 @@ func (m *FileInfoTruncated) ProtoSize() (n int) {
|
||||||
if m.RawBlockSize != 0 {
|
if m.RawBlockSize != 0 {
|
||||||
n += 1 + sovStructs(uint64(m.RawBlockSize))
|
n += 1 + sovStructs(uint64(m.RawBlockSize))
|
||||||
}
|
}
|
||||||
|
l = m.Platform.ProtoSize()
|
||||||
|
n += 1 + l + sovStructs(uint64(l))
|
||||||
l = len(m.SymlinkTarget)
|
l = len(m.SymlinkTarget)
|
||||||
if l > 0 {
|
if l > 0 {
|
||||||
n += 2 + l + sovStructs(uint64(l))
|
n += 2 + l + sovStructs(uint64(l))
|
||||||
|
@ -2073,6 +2088,39 @@ func (m *FileInfoTruncated) Unmarshal(dAtA []byte) error {
|
||||||
break
|
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:
|
case 17:
|
||||||
if wireType != 2 {
|
if wireType != 2 {
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field SymlinkTarget", wireType)
|
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))
|
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 {
|
func (f *BasicFilesystem) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||||
name, err := f.rooted(name)
|
name, err := f.rooted(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -84,7 +85,7 @@ func TestChownFile(t *testing.T) {
|
||||||
newUID := 1000 + rand.Intn(30000)
|
newUID := 1000 + rand.Intn(30000)
|
||||||
newGID := 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)
|
t.Error("Unexpected error:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ package fs
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,6 +58,22 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
||||||
return []string{"/"}, nil
|
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
|
// 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
|
// 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
|
// special case when the given path is the folder root without a trailing
|
||||||
|
|
|
@ -17,6 +17,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNotSupported = errors.New("symlinks not supported")
|
var errNotSupported = errors.New("symlinks not supported")
|
||||||
|
@ -152,6 +154,42 @@ func (f *BasicFilesystem) Roots() ([]string, error) {
|
||||||
return drives, nil
|
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
|
// 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
|
// 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
|
// 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)
|
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 {
|
if err := f.checkCase(name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ package fs
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
type errorFilesystem struct {
|
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) 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 {
|
func (fs *errorFilesystem) Chtimes(name string, atime time.Time, mtime time.Time) error {
|
||||||
return fs.err
|
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) {
|
func (fs *errorFilesystem) Watch(path string, ignore Matcher, ctx context.Context, ignorePerms bool) (<-chan Event, <-chan error, error) {
|
||||||
return nil, nil, fs.err
|
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) {
|
func (fs *errorFilesystem) underlying() (Filesystem, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
// see readShortAt()
|
// see readShortAt()
|
||||||
|
@ -29,19 +31,19 @@ const randomBlockShift = 14 // 128k
|
||||||
// fakeFS is a fake filesystem for testing and benchmarking. It has the
|
// fakeFS is a fake filesystem for testing and benchmarking. It has the
|
||||||
// following properties:
|
// following properties:
|
||||||
//
|
//
|
||||||
// - File metadata is kept in RAM. Specifically, we remember which files and
|
// - File metadata is kept in RAM. Specifically, we remember which files and
|
||||||
// directories exist, their dates, permissions and sizes. Symlinks are
|
// directories exist, their dates, permissions and sizes. Symlinks are
|
||||||
// not supported.
|
// not supported.
|
||||||
//
|
//
|
||||||
// - File contents are generated pseudorandomly with just the file name as
|
// - File contents are generated pseudorandomly with just the file name as
|
||||||
// seed. Writes are discarded, other than having the effect of increasing
|
// 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 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...
|
// the same name on a different fakeFS, you'll never know the difference...
|
||||||
//
|
//
|
||||||
// - We totally ignore permissions - pretend you are root.
|
// - We totally ignore permissions - pretend you are root.
|
||||||
//
|
//
|
||||||
// - The root path can contain URL query-style parameters that pre populate
|
// - The root path can contain URL query-style parameters that pre populate
|
||||||
// the filesystem at creation with a certain amount of random data:
|
// the filesystem at creation with a certain amount of random data:
|
||||||
//
|
//
|
||||||
// files=n to generate n random files (default 0)
|
// files=n to generate n random files (default 0)
|
||||||
// maxsize=n to generate files up to a total of n MiB (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
|
// 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.
|
// - Two fakeFS:s pointing at the same root path see the same files.
|
||||||
//
|
|
||||||
type fakeFS struct {
|
type fakeFS struct {
|
||||||
counters fakeFSCounters
|
counters fakeFSCounters
|
||||||
uri string
|
uri string
|
||||||
|
@ -220,7 +221,7 @@ func (fs *fakeFS) Chmod(name string, mode FileMode) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs *fakeFS) Lchown(name string, uid, gid int) error {
|
func (fs *fakeFS) Lchown(name, uid, gid string) error {
|
||||||
fs.mut.Lock()
|
fs.mut.Lock()
|
||||||
defer fs.mut.Unlock()
|
defer fs.mut.Unlock()
|
||||||
fs.counters.Lchown++
|
fs.counters.Lchown++
|
||||||
|
@ -229,8 +230,8 @@ func (fs *fakeFS) Lchown(name string, uid, gid int) error {
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
return os.ErrNotExist
|
return os.ErrNotExist
|
||||||
}
|
}
|
||||||
entry.uid = uid
|
entry.uid, _ = strconv.Atoi(uid)
|
||||||
entry.gid = gid
|
entry.gid, _ = strconv.Atoi(gid)
|
||||||
return nil
|
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()
|
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) {
|
func (fs *fakeFS) underlying() (Filesystem, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ func TestFakeFS(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chown
|
// Chown
|
||||||
if err := fs.Lchown("dira", 1234, 5678); err != nil {
|
if err := fs.Lchown("dira", "1234", "5678"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if info, err := fs.Lstat("dira"); err != nil {
|
if info, err := fs.Lstat("dira"); err != nil {
|
||||||
|
|
|
@ -14,6 +14,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
type filesystemWrapperType int32
|
type filesystemWrapperType int32
|
||||||
|
@ -30,7 +32,7 @@ const (
|
||||||
// The Filesystem interface abstracts access to the file system.
|
// The Filesystem interface abstracts access to the file system.
|
||||||
type Filesystem interface {
|
type Filesystem interface {
|
||||||
Chmod(name string, mode FileMode) error
|
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
|
Chtimes(name string, atime time.Time, mtime time.Time) error
|
||||||
Create(name string) (File, error)
|
Create(name string) (File, error)
|
||||||
CreateSymlink(target, name string) error
|
CreateSymlink(target, name string) error
|
||||||
|
@ -60,6 +62,7 @@ type Filesystem interface {
|
||||||
URI() string
|
URI() string
|
||||||
Options() []Option
|
Options() []Option
|
||||||
SameFile(fi1, fi2 FileInfo) bool
|
SameFile(fi1, fi2 FileInfo) bool
|
||||||
|
PlatformData(name string) (protocol.PlatformData, error)
|
||||||
|
|
||||||
// Used for unwrapping things
|
// Used for unwrapping things
|
||||||
underlying() (Filesystem, bool)
|
underlying() (Filesystem, bool)
|
||||||
|
|
|
@ -59,7 +59,7 @@ func (o *optionMtime) apply(fs Filesystem) Filesystem {
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_ *optionMtime) String() string {
|
func (*optionMtime) String() string {
|
||||||
return "mtime"
|
return "mtime"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
b.Remove(fi.Name)
|
||||||
return true
|
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.
|
// What we have locally is equivalent to the global file.
|
||||||
l.Debugf("%v scanning: Merging identical locally changed item with global", b.f, fi)
|
l.Debugf("%v scanning: Merging identical locally changed item with global", b.f, fi)
|
||||||
fi = gf
|
fi = gf
|
||||||
|
@ -632,6 +638,7 @@ func (f *folder) scanSubdirsChangedAndNew(subDirs []string, batch *scanBatch) (i
|
||||||
CurrentFiler: cFiler{snap},
|
CurrentFiler: cFiler{snap},
|
||||||
Filesystem: f.mtimefs,
|
Filesystem: f.mtimefs,
|
||||||
IgnorePerms: f.IgnorePerms,
|
IgnorePerms: f.IgnorePerms,
|
||||||
|
IgnoreOwnership: !f.SyncOwnership,
|
||||||
AutoNormalize: f.AutoNormalize,
|
AutoNormalize: f.AutoNormalize,
|
||||||
Hashers: f.model.numHashers(f.ID),
|
Hashers: f.model.numHashers(f.ID),
|
||||||
ShortID: f.shortID,
|
ShortID: f.shortID,
|
||||||
|
|
|
@ -126,7 +126,11 @@ func (f *receiveOnlyFolder) revert() error {
|
||||||
}
|
}
|
||||||
fi.SetDeleted(f.shortID)
|
fi.SetDeleted(f.shortID)
|
||||||
fi.Version = protocol.Vector{} // if this file ever resurfaces anywhere we want our delete to be strictly older
|
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.
|
// What we have locally is equivalent to the global file.
|
||||||
fi = gf
|
fi = gf
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -72,7 +72,11 @@ func (f *sendOnlyFolder) pull() (bool, error) {
|
||||||
return true
|
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
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -627,8 +628,8 @@ func (f *sendReceiveFolder) handleDir(file protocol.FileInfo, snap *db.Snapshot,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the parent owner and group, if we are supposed to do that.
|
// Adjust the ownership, if we are supposed to do that.
|
||||||
if err := f.maybeCopyOwner(path); err != nil {
|
if err := f.maybeAdjustOwnership(&file, path); err != nil {
|
||||||
return err
|
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 {
|
if err := f.mtimefs.CreateSymlink(file.SymlinkTarget, path); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return f.maybeCopyOwner(path)
|
return f.maybeAdjustOwnership(&file, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = f.inWritableDir(createLink, file.Name); err == nil {
|
if err = f.inWritableDir(createLink, file.Name); err == nil {
|
||||||
|
@ -989,7 +990,13 @@ func (f *sendReceiveFolder) renameFile(cur, source, target protocol.FileInfo, sn
|
||||||
default:
|
default:
|
||||||
var fi protocol.FileInfo
|
var fi protocol.FileInfo
|
||||||
if fi, err = scanner.CreateFileInfo(stat, target.Name, f.mtimefs); err == nil {
|
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
|
// Target changed
|
||||||
scanChan <- target.Name
|
scanChan <- target.Name
|
||||||
err = errModified
|
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.
|
// Still need to re-write the trailer with the new encrypted fileinfo.
|
||||||
if f.Type == config.FolderTypeReceiveEncrypted {
|
if f.Type == config.FolderTypeReceiveEncrypted {
|
||||||
err = inWritableDir(func(path string) error {
|
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.
|
// Set ownership based on file metadata or parent, maybe.
|
||||||
if err := f.maybeCopyOwner(tempName); err != nil {
|
if err := f.maybeAdjustOwnership(&file, tempName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1972,7 +1984,13 @@ func (f *sendReceiveFolder) deleteDirOnDiskHandleChildren(dir string, snap *db.S
|
||||||
hasToBeScanned = true
|
hasToBeScanned = true
|
||||||
return nil
|
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
|
// File on disk changed compared to what we have in db
|
||||||
// -> schedule scan.
|
// -> schedule scan.
|
||||||
scanChan <- path
|
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")
|
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
|
return errModified
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2074,11 +2098,23 @@ func (f *sendReceiveFolder) checkToBeDeleted(file, cur protocol.FileInfo, hasCur
|
||||||
return f.scanIfItemChanged(file.Name, stat, cur, hasCur, scanChan)
|
return f.scanIfItemChanged(file.Name, stat, cur, hasCur, scanChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *sendReceiveFolder) maybeCopyOwner(path string) error {
|
func (f *sendReceiveFolder) maybeAdjustOwnership(file *protocol.FileInfo, name string) error {
|
||||||
if !f.CopyOwnershipFromParent {
|
if f.SyncOwnership {
|
||||||
// Not supposed to do anything.
|
// Set ownership based on file metadata.
|
||||||
return nil
|
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" {
|
if runtime.GOOS == "windows" {
|
||||||
// Can't do anything.
|
// Can't do anything.
|
||||||
return nil
|
return nil
|
||||||
|
@ -2088,7 +2124,7 @@ func (f *sendReceiveFolder) maybeCopyOwner(path string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "copy owner from parent")
|
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 errors.Wrap(err, "copy owner from parent")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -811,7 +812,7 @@ func TestCopyOwner(t *testing.T) {
|
||||||
// Create a parent dir with a certain owner/group.
|
// Create a parent dir with a certain owner/group.
|
||||||
|
|
||||||
f.mtimefs.Mkdir("foo", 0755)
|
f.mtimefs.Mkdir("foo", 0755)
|
||||||
f.mtimefs.Lchown("foo", expOwner, expGroup)
|
f.mtimefs.Lchown("foo", strconv.Itoa(expOwner), strconv.Itoa(expGroup))
|
||||||
|
|
||||||
dir := protocol.FileInfo{
|
dir := protocol.FileInfo{
|
||||||
Name: "foo/bar",
|
Name: "foo/bar",
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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 {
|
func (f FileInfo) String() string {
|
||||||
switch f.Type {
|
switch f.Type {
|
||||||
case FileInfoTypeDirectory:
|
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}",
|
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.Name, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.Platform)
|
||||||
case FileInfoTypeFile:
|
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}",
|
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.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:
|
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}",
|
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.Name, f.Type, f.Sequence, f.Version, f.VersionHash, f.Deleted, f.RawInvalid, f.LocalFlags, f.NoPermissions, f.SymlinkTarget, f.Platform)
|
||||||
default:
|
default:
|
||||||
panic("mystery file type detected")
|
panic("mystery file type detected")
|
||||||
}
|
}
|
||||||
|
@ -190,30 +190,42 @@ func WinsConflict(f, other FileIntf) bool {
|
||||||
return f.FileVersion().Compare(other.FileVersion()) == ConcurrentGreater
|
return f.FileVersion().Compare(other.FileVersion()) == ConcurrentGreater
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool {
|
type FileInfoComparison struct {
|
||||||
return f.isEquivalent(other, modTimeWindow, false, false, 0)
|
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 {
|
func (f FileInfo) IsEquivalent(other FileInfo, modTimeWindow time.Duration) bool {
|
||||||
return f.isEquivalent(other, modTimeWindow, ignorePerms, ignoreBlocks, ignoreFlags)
|
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,
|
// 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.
|
// i.e. it does purposely not check only selected (see below) struct members.
|
||||||
// Permissions (config) and blocks (scanning) can be excluded from the comparison.
|
// Permissions (config) and blocks (scanning) can be excluded from the comparison.
|
||||||
// Any file info is not "equivalent", if it has different
|
// Any file info is not "equivalent", if it has different
|
||||||
// - type
|
// - type
|
||||||
// - deleted flag
|
// - deleted flag
|
||||||
// - invalid flag
|
// - invalid flag
|
||||||
// - permissions, unless they are ignored
|
// - permissions, unless they are ignored
|
||||||
|
//
|
||||||
// A file is not "equivalent", if it has different
|
// A file is not "equivalent", if it has different
|
||||||
// - modification time (difference bigger than modTimeWindow)
|
// - modification time (difference bigger than modTimeWindow)
|
||||||
// - size
|
// - size
|
||||||
// - blocks, unless there are no blocks to compare (scanning)
|
// - blocks, unless there are no blocks to compare (scanning)
|
||||||
|
// - os data
|
||||||
|
//
|
||||||
// A symlink is not "equivalent", if it has different
|
// A symlink is not "equivalent", if it has different
|
||||||
// - target
|
// - target
|
||||||
|
//
|
||||||
// A directory does not have anything specific to check.
|
// 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() {
|
if f.MustRescan() || other.MustRescan() {
|
||||||
// These are per definition not equivalent because they don't
|
// These are per definition not equivalent because they don't
|
||||||
// represent a valid state, even if both happen to have the
|
// 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
|
// Mask out the ignored local flags before checking IsInvalid() below
|
||||||
f.LocalFlags &^= ignoreFlags
|
f.LocalFlags &^= comp.IgnoreFlags
|
||||||
other.LocalFlags &^= ignoreFlags
|
other.LocalFlags &^= comp.IgnoreFlags
|
||||||
|
|
||||||
if f.Name != other.Name || f.Type != other.Type || f.Deleted != other.Deleted || f.IsInvalid() != other.IsInvalid() {
|
if f.Name != other.Name || f.Type != other.Type || f.Deleted != other.Deleted || f.IsInvalid() != other.IsInvalid() {
|
||||||
return false
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
switch f.Type {
|
switch f.Type {
|
||||||
case FileInfoTypeFile:
|
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:
|
case FileInfoTypeSymlink:
|
||||||
return f.SymlinkTarget == other.SymlinkTarget
|
return f.SymlinkTarget == other.SymlinkTarget
|
||||||
case FileInfoTypeDirectory:
|
case FileInfoTypeDirectory:
|
||||||
|
|
|
@ -872,10 +872,10 @@ func TestIsEquivalent(t *testing.T) {
|
||||||
continue
|
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)
|
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)
|
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"
|
"time"
|
||||||
|
|
||||||
"github.com/syncthing/syncthing/lib/fs"
|
"github.com/syncthing/syncthing/lib/fs"
|
||||||
|
"github.com/syncthing/syncthing/lib/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
type infiniteFS struct {
|
type infiniteFS struct {
|
||||||
|
@ -54,6 +55,10 @@ func (i infiniteFS) Open(name string) (fs.File, error) {
|
||||||
return &fakeFile{name, i.filesize, 0}, nil
|
return &fakeFile{name, i.filesize, 0}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i infiniteFS) PlatformData(name string) (protocol.PlatformData, error) {
|
||||||
|
return protocol.PlatformData{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type singleFileFS struct {
|
type singleFileFS struct {
|
||||||
fs.Filesystem
|
fs.Filesystem
|
||||||
name string
|
name string
|
||||||
|
@ -100,6 +105,10 @@ func (s singleFileFS) Options() []fs.Option {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s singleFileFS) PlatformData(name string) (protocol.PlatformData, error) {
|
||||||
|
return protocol.PlatformData{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type fakeInfo struct {
|
type fakeInfo struct {
|
||||||
name string
|
name string
|
||||||
size int64
|
size int64
|
||||||
|
|
|
@ -40,9 +40,10 @@ type Config struct {
|
||||||
// The Filesystem provides an abstraction on top of the actual filesystem.
|
// The Filesystem provides an abstraction on top of the actual filesystem.
|
||||||
Filesystem fs.Filesystem
|
Filesystem fs.Filesystem
|
||||||
// If IgnorePerms is true, changes to permission bits will not be
|
// If IgnorePerms is true, changes to permission bits will not be
|
||||||
// detected. Scanned files will get zero permission bits and the
|
// detected.
|
||||||
// NoPermissionBits flag set.
|
|
||||||
IgnorePerms bool
|
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
|
// When AutoNormalize is set, file names that are in UTF8 but incorrect
|
||||||
// normalization form will be corrected.
|
// normalization form will be corrected.
|
||||||
AutoNormalize bool
|
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 = w.updateFileInfo(f, curFile)
|
||||||
f.NoPermissions = w.IgnorePerms
|
f.NoPermissions = w.IgnorePerms
|
||||||
f.RawBlockSize = blockSize
|
f.RawBlockSize = blockSize
|
||||||
|
|
||||||
if hasCurFile {
|
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)
|
l.Debugln(w, "unchanged:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm)
|
||||||
return nil
|
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 {
|
func (w *walker) walkDir(ctx context.Context, relPath string, info fs.FileInfo, finishedChan chan<- ScanResult) error {
|
||||||
curFile, hasCurFile := w.CurrentFiler.CurrentFile(relPath)
|
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 = w.updateFileInfo(f, curFile)
|
||||||
f.NoPermissions = w.IgnorePerms
|
f.NoPermissions = w.IgnorePerms
|
||||||
|
|
||||||
if hasCurFile {
|
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)
|
l.Debugln(w, "unchanged:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -466,7 +485,13 @@ func (w *walker) walkSymlink(ctx context.Context, relPath string, info fs.FileIn
|
||||||
f = w.updateFileInfo(f, curFile)
|
f = w.updateFileInfo(f, curFile)
|
||||||
|
|
||||||
if hasCurFile {
|
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)
|
l.Debugln(w, "unchanged:", curFile, info.ModTime().Unix(), info.Mode()&fs.ModePerm)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -550,17 +575,28 @@ func (w *walker) normalizePath(path string, info fs.FileInfo) (normPath string,
|
||||||
return "", errUTF8Conflict
|
return "", errUTF8Conflict
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateFileInfo updates walker specific members of protocol.FileInfo that do not depend on type
|
// updateFileInfo updates walker specific members of protocol.FileInfo that
|
||||||
func (w *walker) updateFileInfo(file, curFile protocol.FileInfo) protocol.FileInfo {
|
// do not depend on type, and things that should be preserved from the
|
||||||
if file.Type == protocol.FileInfoTypeFile && runtime.GOOS == "windows" {
|
// 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
|
// If we have an existing index entry, copy the executable bits
|
||||||
// from there.
|
// from there.
|
||||||
file.Permissions |= (curFile.Permissions & 0111)
|
dst.Permissions |= (src.Permissions & 0111)
|
||||||
}
|
}
|
||||||
file.Version = curFile.Version.Update(w.ShortID)
|
dst.Version = src.Version.Update(w.ShortID)
|
||||||
file.ModifiedBy = w.ShortID
|
dst.ModifiedBy = w.ShortID
|
||||||
file.LocalFlags = w.LocalFlags
|
dst.LocalFlags = w.LocalFlags
|
||||||
return file
|
|
||||||
|
// 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) {
|
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) {
|
func CreateFileInfo(fi fs.FileInfo, name string, filesystem fs.Filesystem) (protocol.FileInfo, error) {
|
||||||
f := protocol.FileInfo{Name: name}
|
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() {
|
if fi.IsSymlink() {
|
||||||
f.Type = protocol.FileInfoTypeSymlink
|
f.Type = protocol.FileInfoTypeSymlink
|
||||||
target, err := filesystem.ReadSymlink(name)
|
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 {
|
func walkDir(fs fs.Filesystem, dir string, cfiler CurrentFiler, matcher *ignore.Matcher, localFlags uint32) []protocol.FileInfo {
|
||||||
cfg, cancel := testConfig()
|
cfg, cancel := testConfig()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
|
@ -54,6 +54,7 @@ message FolderConfiguration {
|
||||||
fs.CopyRangeMethod copy_range_method = 32 [(ext.default) = "standard"];
|
fs.CopyRangeMethod copy_range_method = 32 [(ext.default) = "standard"];
|
||||||
bool case_sensitive_fs = 33 [(ext.goname) = "CaseSensitiveFS", (ext.xml) = "caseSensitiveFS", (ext.json) = "caseSensitiveFS"];
|
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 follow_junctions = 34 [(ext.goname) = "JunctionsAsDirs", (ext.xml) = "junctionsAsDirs", (ext.json) = "junctionsAsDirs"];
|
||||||
|
bool sync_ownership = 35;
|
||||||
|
|
||||||
// Legacy deprecated
|
// Legacy deprecated
|
||||||
bool read_only = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"];
|
bool read_only = 9000 [deprecated=true, (ext.xml) = "ro,attr,omitempty"];
|
||||||
|
|
|
@ -36,6 +36,7 @@ message FileInfoTruncated {
|
||||||
uint32 permissions = 4;
|
uint32 permissions = 4;
|
||||||
int32 modified_ns = 11;
|
int32 modified_ns = 11;
|
||||||
int32 block_size = 13 [(ext.goname) = "RawBlockSize"];
|
int32 block_size = 13 [(ext.goname) = "RawBlockSize"];
|
||||||
|
protocol.PlatformData platform = 14;
|
||||||
|
|
||||||
// see bep.proto
|
// see bep.proto
|
||||||
uint32 local_flags = 1000;
|
uint32 local_flags = 1000;
|
||||||
|
|
|
@ -107,6 +107,7 @@ message FileInfo {
|
||||||
uint32 permissions = 4;
|
uint32 permissions = 4;
|
||||||
int32 modified_ns = 11;
|
int32 modified_ns = 11;
|
||||||
int32 block_size = 13 [(ext.goname) = "RawBlockSize"];
|
int32 block_size = 13 [(ext.goname) = "RawBlockSize"];
|
||||||
|
PlatformData platform = 14;
|
||||||
|
|
||||||
// The local_flags fields stores flags that are relevant to the local
|
// 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
|
// host only. It is not part of the protocol, doesn't get sent or
|
||||||
|
@ -147,6 +148,29 @@ message Counter {
|
||||||
uint64 value = 2;
|
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
|
// Request
|
||||||
|
|
||||||
message Request {
|
message Request {
|
||||||
|
|
Loading…
Reference in New Issue