Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit c8cec8e

Browse files
Verify rsync protocol version match prior to proceeding (#71)
* Verify rsync protocol version match prior to proceeding. `sync.Version()` proceeds with a warning that there may be a version mismatch if it timesout. `syncCmd.version` assumes rsync is present in the path. `wsep.RemoteExecer` isn't available publicly on GitHub, so I took a best guess with it and `wsep.ExitError`. * Add context to sync.Version. * Correct syncCmd.version, sync.Version. Passing `s.ReadLine` to `strings.Split` was a mistake since it returns three values. Having access to `wsep` helped the compiler find the bugs. * Update local, remote version checks to avoid blanks. * Remove go from io.Copy in internal/sync/sync.go#Version * Return error directly in internal/sync/sync.go#Version * Update [vV]ersion comment strings; remove extraneous error check.
1 parent 9b58d37 commit c8cec8e

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

cmd/coder/sync.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package main
22

33
import (
4+
"bytes"
5+
"fmt"
6+
"log"
47
"os"
8+
"os/exec"
59
"path/filepath"
610
"strings"
711

@@ -29,6 +33,23 @@ func (cmd *syncCmd) RegisterFlags(fl *pflag.FlagSet) {
2933
fl.BoolVarP(&cmd.init, "init", "i", false, "do initial transfer and exit")
3034
}
3135

36+
// version returns local rsync protocol version as a string.
37+
func (_ *syncCmd) version() string {
38+
cmd := exec.Command("rsync", "--version")
39+
out, err := cmd.CombinedOutput()
40+
if err != nil {
41+
log.Fatal(err)
42+
}
43+
44+
firstLine, err := bytes.NewBuffer(out).ReadString('\n')
45+
if err != nil {
46+
log.Fatal(err)
47+
}
48+
versionString := strings.Split(firstLine, "protocol version ")
49+
50+
return versionString[1]
51+
}
52+
3253
func (cmd *syncCmd) Run(fl *pflag.FlagSet) {
3354
var (
3455
local = fl.Arg(0)
@@ -71,6 +92,16 @@ func (cmd *syncCmd) Run(fl *pflag.FlagSet) {
7192
LocalDir: absLocal,
7293
Client: entClient,
7394
}
95+
96+
localVersion := cmd.version()
97+
remoteVersion, rsyncErr := s.Version()
98+
99+
if rsyncErr != nil {
100+
flog.Info("Unable to determine remote rsync version. Proceeding cautiously.")
101+
} else if localVersion != remoteVersion {
102+
flog.Fatal(fmt.Sprintf("rsync protocol mismatch. %s.", localVersion, rsyncErr))
103+
}
104+
74105
for err == nil || err == sync.ErrRestartSync {
75106
err = s.Run()
76107
}

internal/sync/sync.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sync
22

33
import (
4+
"bytes"
45
"context"
56
"errors"
67
"fmt"
@@ -10,6 +11,7 @@ import (
1011
"os/exec"
1112
"path"
1213
"path/filepath"
14+
"strings"
1315
"sync"
1416
"sync/atomic"
1517
"time"
@@ -261,6 +263,44 @@ const (
261263
maxAcceptableDispatch = time.Millisecond * 50
262264
)
263265

266+
// Version returns remote protocol version as a string.
267+
// Or, an error if one exists.
268+
func (s Sync) Version() (string, error) {
269+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
270+
defer cancel()
271+
272+
conn, err := s.Client.DialWsep(ctx, s.Env)
273+
if err != nil {
274+
return "", err
275+
}
276+
defer conn.Close(websocket.CloseNormalClosure, "")
277+
278+
execer := wsep.RemoteExecer(conn)
279+
process, err := execer.Start(ctx, wsep.Command{
280+
Command: "rsync",
281+
Args: []string{"--version"},
282+
})
283+
if err != nil {
284+
return "", err
285+
}
286+
buf := &bytes.Buffer{}
287+
io.Copy(buf, process.Stdout())
288+
289+
err = process.Wait()
290+
if err != nil {
291+
return "", err
292+
}
293+
294+
firstLine, err := buf.ReadString('\n')
295+
if err != nil {
296+
return "", err
297+
}
298+
299+
versionString := strings.Split(firstLine, "protocol version ")
300+
301+
return versionString[1], nil
302+
}
303+
264304
// Run starts the sync synchronously.
265305
// Use this command to debug what wasn't sync'd correctly:
266306
// rsync -e "coder sh" -nicr ~/Projects/cdr/coder-cli/. ammar:/home/coder/coder-cli/

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy