Eric Bower
·
2026-05-31
1package rsync
2
3import (
4 "fmt"
5
6 "github.com/picosh/pico/pkg/rsync-receiver/rsyncwire"
7)
8
9// rsync/rsync.h:struct sum_buf.
10type SumBuf struct {
11 Offset int64
12 Len int64
13 Index int32
14 Sum1 uint32
15 Sum2 [16]byte
16}
17
18// TODO: remove connection.go:sumHead in favor of this type.
19type SumHead struct {
20 // “number of blocks” (openrsync)
21 // “how many chunks” (rsync)
22 ChecksumCount int32
23
24 // “block length in the file” (openrsync)
25 // maximum (1 << 29) for older rsync, (1 << 17) for newer
26 BlockLength int32
27
28 // “long checksum length” (openrsync)
29 ChecksumLength int32
30
31 // “terminal (remainder) block length” (openrsync)
32 // RemainderLength is flength % BlockLength
33 RemainderLength int32
34
35 Sums []SumBuf
36}
37
38func (sh *SumHead) ReadFrom(c *rsyncwire.Conn) error {
39 // TODO(protocol>=30): update maxBlockLen
40 const maxBlockLen = 1 << 29 // see rsync.h:OLD_MAX_BLOCK_SIZE
41
42 var err error
43 sh.ChecksumCount, err = c.ReadInt32()
44 if err != nil {
45 return err
46 }
47 if sh.ChecksumCount < 0 {
48 return fmt.Errorf("invalid checksum count %d", sh.ChecksumCount)
49 }
50
51 sh.BlockLength, err = c.ReadInt32()
52 if err != nil {
53 return err
54 }
55 if sh.BlockLength < 0 || sh.BlockLength > maxBlockLen {
56 return fmt.Errorf("invalid block length %d", sh.BlockLength)
57 }
58
59 sh.ChecksumLength, err = c.ReadInt32()
60 if err != nil {
61 return err
62 }
63 // TODO(protocol>=27): update max sh.ChecksumLength check
64 if sh.ChecksumLength < 0 || sh.ChecksumLength > 16 {
65 return fmt.Errorf("invalid checksum length %d", sh.ChecksumLength)
66 }
67
68 sh.RemainderLength, err = c.ReadInt32()
69 if err != nil {
70 return err
71 }
72 if sh.RemainderLength < 0 || sh.RemainderLength > sh.BlockLength {
73 return fmt.Errorf("invalid remainder length %d", sh.RemainderLength)
74 }
75
76 return nil
77}
78
79func (sh *SumHead) WriteTo(c *rsyncwire.Conn) error {
80 var buf rsyncwire.Buffer
81 buf.WriteInt32(sh.ChecksumCount)
82 buf.WriteInt32(sh.BlockLength)
83 buf.WriteInt32(sh.ChecksumLength)
84 buf.WriteInt32(sh.RemainderLength)
85 return c.WriteString(buf.String())
86}