bep_extensions.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (C) 2014 The Protocol Authors.
  2. //go:generate go run ../../script/protofmt.go bep.proto
  3. //go:generate protoc --proto_path=../../../../../:../../../../gogo/protobuf/protobuf:. --gogofast_out=. bep.proto
  4. package protocol
  5. import (
  6. "bytes"
  7. "encoding/binary"
  8. "errors"
  9. "fmt"
  10. "time"
  11. "github.com/minio/sha256-simd"
  12. "github.com/syncthing/syncthing/lib/rand"
  13. )
  14. const (
  15. SyntheticDirectorySize = 128
  16. )
  17. var (
  18. sha256OfEmptyBlock = sha256.Sum256(make([]byte, BlockSize))
  19. HelloMessageMagic = uint32(0x2EA7D90B)
  20. )
  21. func (m Hello) Magic() uint32 {
  22. return HelloMessageMagic
  23. }
  24. func (f FileInfo) String() string {
  25. return fmt.Sprintf("File{Name:%q, Type:%v, Sequence:%d, Permissions:0%o, ModTime:%v, Version:%v, Length:%d, Deleted:%v, Invalid:%v, NoPermissions:%v, Blocks:%v}",
  26. f.Name, f.Type, f.Sequence, f.Permissions, f.ModTime(), f.Version, f.Size, f.Deleted, f.Invalid, f.NoPermissions, f.Blocks)
  27. }
  28. func (f FileInfo) IsDeleted() bool {
  29. return f.Deleted
  30. }
  31. func (f FileInfo) IsInvalid() bool {
  32. return f.Invalid
  33. }
  34. func (f FileInfo) IsDirectory() bool {
  35. return f.Type == FileInfoTypeDirectory
  36. }
  37. func (f FileInfo) IsSymlink() bool {
  38. switch f.Type {
  39. case FileInfoTypeSymlinkDirectory, FileInfoTypeSymlinkFile, FileInfoTypeSymlinkUnknown:
  40. return true
  41. default:
  42. return false
  43. }
  44. }
  45. func (f FileInfo) HasPermissionBits() bool {
  46. return !f.NoPermissions
  47. }
  48. func (f FileInfo) FileSize() int64 {
  49. if f.Deleted {
  50. return 0
  51. }
  52. if f.IsDirectory() {
  53. return SyntheticDirectorySize
  54. }
  55. return f.Size
  56. }
  57. func (f FileInfo) FileName() string {
  58. return f.Name
  59. }
  60. func (f FileInfo) ModTime() time.Time {
  61. return time.Unix(f.ModifiedS, int64(f.ModifiedNs))
  62. }
  63. // WinsConflict returns true if "f" is the one to choose when it is in
  64. // conflict with "other".
  65. func (f FileInfo) WinsConflict(other FileInfo) bool {
  66. // If a modification is in conflict with a delete, we pick the
  67. // modification.
  68. if !f.IsDeleted() && other.IsDeleted() {
  69. return true
  70. }
  71. if f.IsDeleted() && !other.IsDeleted() {
  72. return false
  73. }
  74. // The one with the newer modification time wins.
  75. if f.ModTime().After(other.ModTime()) {
  76. return true
  77. }
  78. if f.ModTime().Before(other.ModTime()) {
  79. return false
  80. }
  81. // The modification times were equal. Use the device ID in the version
  82. // vector as tie breaker.
  83. return f.Version.Compare(other.Version) == ConcurrentGreater
  84. }
  85. func (b BlockInfo) String() string {
  86. return fmt.Sprintf("Block{%d/%d/%x}", b.Offset, b.Size, b.Hash)
  87. }
  88. // IsEmpty returns true if the block is a full block of zeroes.
  89. func (b BlockInfo) IsEmpty() bool {
  90. return b.Size == BlockSize && bytes.Equal(b.Hash, sha256OfEmptyBlock[:])
  91. }
  92. type IndexID uint64
  93. func (i IndexID) String() string {
  94. return fmt.Sprintf("0x%16X", uint64(i))
  95. }
  96. func (i IndexID) Marshal() ([]byte, error) {
  97. bs := make([]byte, 8)
  98. binary.BigEndian.PutUint64(bs, uint64(i))
  99. return bs, nil
  100. }
  101. func (i *IndexID) Unmarshal(bs []byte) error {
  102. if len(bs) != 8 {
  103. return errors.New("incorrect IndexID length")
  104. }
  105. *i = IndexID(binary.BigEndian.Uint64(bs))
  106. return nil
  107. }
  108. func NewIndexID() IndexID {
  109. return IndexID(rand.Int64())
  110. }