Eric Bower
·
2026-05-31
1package rsyncreceiver
2
3import (
4 "context"
5
6 "github.com/picosh/pico/pkg/rsync-receiver/rsyncstats"
7 "github.com/picosh/pico/pkg/rsync-receiver/rsyncwire"
8 "github.com/picosh/pico/pkg/rsync-receiver/utils"
9 "golang.org/x/sync/errgroup"
10)
11
12func (rt *Transfer) deleteFiles(fileList []*utils.ReceiverFile) error {
13 if rt.IOErrors > 0 {
14 rt.Logger.Debug("IO error encountered, skipping file deletion")
15 return nil
16 }
17
18 return rt.Files.Remove(fileList)
19}
20
21// rsync/main.c:do_recv.
22func (rt *Transfer) Do(c *rsyncwire.Conn, fileList []*utils.ReceiverFile, noReport bool) (*rsyncstats.TransferStats, error) {
23 if rt.Opts.DeleteMode {
24 if err := rt.deleteFiles(fileList); err != nil {
25 return nil, err
26 }
27 }
28
29 ctx := context.Background()
30 eg, ctx := errgroup.WithContext(ctx)
31 eg.Go(func() error {
32 return rt.GenerateFiles(fileList)
33 })
34 eg.Go(func() error {
35 // Ensure we don’t block on the receiver when the generator returns an
36 // error.
37 errChan := make(chan error)
38 go func() {
39 errChan <- rt.RecvFiles(fileList)
40 }()
41 select {
42 case <-ctx.Done():
43 return ctx.Err()
44 case err := <-errChan:
45 return err
46 }
47 })
48 if err := eg.Wait(); err != nil {
49 return nil, err
50 }
51
52 var stats *rsyncstats.TransferStats
53 if !noReport {
54 var err error
55 stats, err = report(c)
56 rt.Logger.Debug("report", "stats", stats)
57 if err != nil {
58 return nil, err
59 }
60 }
61
62 // send final goodbye message
63 if err := c.WriteInt32(-1); err != nil {
64 return nil, err
65 }
66
67 return stats, nil
68}
69
70// rsync/main.c:report.
71func report(c *rsyncwire.Conn) (*rsyncstats.TransferStats, error) {
72 // read statistics:
73 // total bytes read (from network connection)
74 read, err := c.ReadInt64()
75 if err != nil {
76 return nil, err
77 }
78 // total bytes written (to network connection)
79 written, err := c.ReadInt64()
80 if err != nil {
81 return nil, err
82 }
83 // total size of files
84 size, err := c.ReadInt64()
85 if err != nil {
86 return nil, err
87 }
88
89 return &rsyncstats.TransferStats{
90 Read: read,
91 Written: written,
92 Size: size,
93 }, nil
94}