Eric Bower
·
2026-05-31
1package rsyncsender
2
3import (
4 "fmt"
5 "sort"
6
7 "github.com/picosh/pico/pkg/rsync-receiver/rsyncstats"
8 "github.com/picosh/pico/pkg/rsync-receiver/rsyncwire"
9)
10
11// rsync/main.c:client_run am_sender.
12func (st *Transfer) Do(crd *rsyncwire.CountingReader, cwr *rsyncwire.CountingWriter, paths []string, exclusionList *filterRuleList) (*rsyncstats.TransferStats, error) {
13 if exclusionList == nil {
14 exclusionList = &filterRuleList{}
15 }
16
17 // “Update exchange” as per
18 // https://github.com/kristapsdz/openrsync/blob/master/rsync.5
19
20 // send file list
21 fileList, err := st.SendFileList(st.Opts, paths, exclusionList)
22 if err != nil {
23 return nil, err
24 }
25
26 st.Logger.Debug("file list sent")
27
28 // Sort the file list. The client sorts, so we need to sort, too (in the
29 // same way!), otherwise our indices do not match what the client will
30 // request.
31 sort.Slice(fileList.Files, func(i, j int) bool {
32 return fileList.Files[i].WPath < fileList.Files[j].WPath
33 })
34
35 if err := st.SendFiles(fileList); err != nil {
36 return nil, err
37 }
38
39 // send statistics:
40 // total bytes read (from network connection)
41 if err := st.Conn.WriteInt64(crd.BytesRead); err != nil {
42 return nil, err
43 }
44 // total bytes written (to network connection)
45 if err := st.Conn.WriteInt64(cwr.BytesWritten); err != nil {
46 return nil, err
47 }
48 // total size of files
49 if err := st.Conn.WriteInt64(fileList.TotalSize); err != nil {
50 return nil, err
51 }
52
53 st.Logger.Debug("reading final int32")
54
55 finish, err := st.Conn.ReadInt32()
56 if err != nil {
57 return nil, err
58 }
59 if finish != -1 {
60 return nil, fmt.Errorf("protocol error: expected final -1, got %d", finish)
61 }
62
63 return &rsyncstats.TransferStats{
64 Read: crd.BytesRead,
65 Written: cwr.BytesWritten,
66 Size: fileList.TotalSize,
67 }, nil
68}