Skip to content

Commit 7a9d9c3

Browse files
board: use go paths helper instead of cmd (#498)
1 parent 26e6320 commit 7a9d9c3

File tree

13 files changed

+139
-84
lines changed

13 files changed

+139
-84
lines changed

.github/workflows/semgrep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Semgrep Full Scan
22
on:
33
schedule:
4-
- cron: '0 6 * * MON' # Esecuzione settimanale ogni lunedì alle 6 del mattino
4+
- cron: "0 6 * * MON" # Esecuzione settimanale ogni lunedì alle 6 del mattino
55

66
permissions:
77
contents: read

Taskfile.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ tasks:
224224
225225
rm -rf "${TMP_PATH}"
226226
echo "Examples installed successfully."
227-
silent: false
228227
229228
wails:dev:
230229
desc: Run the Wails dev locally

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.24.5
55
require (
66
github.com/Andrew-M-C/go.emoji v1.1.4
77
github.com/arduino/arduino-cli v1.2.2
8-
github.com/arduino/go-paths-helper v1.13.1
8+
github.com/arduino/go-paths-helper v1.14.0
99
github.com/codeclysm/extract/v4 v4.0.0
1010
github.com/compose-spec/compose-go/v2 v2.7.1
1111
github.com/containerd/errdefs v1.0.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd
5959
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
6060
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
6161
github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
62-
github.com/arduino/go-paths-helper v1.13.1 h1:M7SCdLB2VldxOdChnjZkxAZwWZdDtNY4IlHL9nxGQFo=
63-
github.com/arduino/go-paths-helper v1.13.1/go.mod h1:dDodKn2ZX4iwuoBMapdDO+5d0oDLBeM4BS0xS4i40Ak=
62+
github.com/arduino/go-paths-helper v1.14.0 h1:b4C8KJa7CNz2XnzTWg97M3LAmzWSWrj+m/o5/skzv3Y=
63+
github.com/arduino/go-paths-helper v1.14.0/go.mod h1:dDodKn2ZX4iwuoBMapdDO+5d0oDLBeM4BS0xS4i40Ak=
6464
github.com/arduino/go-properties-orderedmap v1.8.1 h1:nU5S6cXPwMoxZs4ORw61wPTALNfriIduvNB4cxTmNYM=
6565
github.com/arduino/go-properties-orderedmap v1.8.1/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
6666
github.com/arduino/go-serial-utils v0.1.2 h1:MRFwME4w/uaVkJ1R+wzz4KSbI9cF9IDVrYorazvjpTk=

pkg/appsync/appsync_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ func TestEnableSyncApp(t *testing.T) {
4848

4949
// Init the file system on the remote connections.
5050
for _, remote := range remotes {
51-
out, err := remote.conn.GetCmd(t.Context(), "mkdir", "-p", "apps/test/python").Output()
51+
out, err := remote.conn.GetCmd("mkdir", "-p", "apps/test/python").Output(t.Context())
5252
require.NoError(t, err, "output: %q", out)
53-
out, err = remote.conn.GetCmd(t.Context(), "touch", "apps/test/python/main.py").Output()
53+
out, err = remote.conn.GetCmd("touch", "apps/test/python/main.py").Output(t.Context())
5454
require.NoError(t, err, "output: %q", out)
55-
out, err = remote.conn.GetCmd(t.Context(), "mkdir", "-p", "apps/test/sketch/").Output()
55+
out, err = remote.conn.GetCmd("mkdir", "-p", "apps/test/sketch/").Output(t.Context())
5656
require.NoError(t, err, "output: %q", out)
57-
out, err = remote.conn.GetCmd(t.Context(), "touch", "apps/test/sketch/sketch.ino").Output()
57+
out, err = remote.conn.GetCmd("touch", "apps/test/sketch/sketch.ino").Output(t.Context())
5858
require.NoError(t, err, "output: %q", out)
59-
out, err = remote.conn.GetCmd(t.Context(), "touch", "apps/test/app.yml").Output()
59+
out, err = remote.conn.GetCmd("touch", "apps/test/app.yml").Output(t.Context())
6060
require.NoError(t, err, "output: %q", out)
6161
}
6262

pkg/board/local.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,61 @@ package board
33
import (
44
"context"
55
"io"
6-
"os/exec"
6+
7+
"github.com/arduino/go-paths-helper"
78

89
"github.com/bcmi-labs/orchestrator/pkg/board/remote"
910
)
1011

1112
type LocalCmder struct{}
1213

13-
func (l *LocalCmder) GetCmd(ctx context.Context, cmd string, args ...string) remote.Cmder {
14-
return &LocalCmd{
15-
cmd: exec.CommandContext(ctx, cmd, args...),
14+
func (l *LocalCmder) GetCmd(cmd string, args ...string) remote.Cmder {
15+
var cmdArgs []string
16+
cmdArgs = append(cmdArgs, cmd)
17+
if len(args) > 0 {
18+
cmdArgs = append(cmdArgs, args...)
1619
}
20+
command, _ := paths.NewProcess(nil, cmdArgs...)
21+
return &LocalCmd{cmd: command}
1722
}
1823

19-
func (l *LocalCmder) GetCmdAsUser(ctx context.Context, user string, cmd string, args ...string) remote.Cmder {
20-
return l.GetCmd(ctx, cmd, args...)
24+
func (l *LocalCmder) GetCmdAsUser(user string, cmd string, args ...string) remote.Cmder {
25+
return l.GetCmd(cmd, args...)
2126
}
2227

2328
type LocalCmd struct {
24-
cmd *exec.Cmd
29+
cmd *paths.Process
2530
}
2631

27-
func (l *LocalCmd) Run() error {
28-
return l.cmd.Run()
32+
func (l *LocalCmd) Run(ctx context.Context) error {
33+
return l.cmd.RunWithinContext(ctx)
2934
}
3035

31-
func (l *LocalCmd) Output() ([]byte, error) {
32-
return l.cmd.CombinedOutput()
36+
func (l *LocalCmd) Output(ctx context.Context) ([]byte, error) {
37+
return l.cmd.RunAndCaptureCombinedOutput(ctx)
3338
}
3439

35-
func (l *LocalCmd) Interactive() (io.WriteCloser, io.Reader, remote.Closer, error) {
36-
l.cmd.Stderr = l.cmd.Stdout // Redirect stderr to stdout
40+
func (l *LocalCmd) Interactive() (io.WriteCloser, io.Reader, io.Reader, remote.Closer, error) {
3741
stdin, err := l.cmd.StdinPipe()
3842
if err != nil {
39-
return nil, nil, nil, err
43+
return nil, nil, nil, nil, err
4044
}
4145
stdout, err := l.cmd.StdoutPipe()
4246
if err != nil {
43-
return nil, nil, nil, err
47+
return nil, nil, nil, nil, err
48+
}
49+
stderr, err := l.cmd.StderrPipe()
50+
if err != nil {
51+
return nil, nil, nil, nil, err
4452
}
4553

4654
if err := l.cmd.Start(); err != nil {
47-
return nil, nil, nil, err
55+
return nil, nil, nil, nil, err
4856
}
4957

50-
return stdin, stdout, func() error {
58+
return stdin, stdout, stderr, func() error {
5159
_ = stdout.Close()
60+
_ = stderr.Close()
5261
if err := l.cmd.Wait(); err != nil {
5362
return err
5463
}

pkg/board/remote/adb/adb.go

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import (
1111
"math/rand/v2"
1212
"net"
1313
"os"
14-
"os/exec"
1514
"os/user"
1615
"path/filepath"
1716
"runtime"
1817
"strings"
1918

19+
"github.com/arduino/go-paths-helper"
20+
2021
"github.com/bcmi-labs/orchestrator/pkg/board/remote"
2122
)
2223

@@ -45,7 +46,11 @@ func FromHost(host string, adbPath string) (*ADBConnection, error) {
4546
if adbPath == "" {
4647
adbPath = FindAdbPath()
4748
}
48-
if err := exec.Command(adbPath, "connect", host).Run(); err != nil {
49+
cmd, err := paths.NewProcess(nil, adbPath, "connect", host)
50+
if err != nil {
51+
return nil, err
52+
}
53+
if err := cmd.Run(); err != nil {
4954
return nil, fmt.Errorf("failed to connect to ADB host %s: %w", host, err)
5055
}
5156
return FromSerial(host, adbPath)
@@ -59,7 +64,11 @@ func (a *ADBConnection) Forward(ctx context.Context, remotePort int) (int, error
5964

6065
local := fmt.Sprintf("tcp:%d", hostAvailablePort)
6166
remote := fmt.Sprintf("tcp:%d", remotePort)
62-
if err := exec.CommandContext(ctx, a.adbPath, "-s", a.host, "forward", local, remote).Run(); err != nil { // nolint:gosec
67+
cmd, err := paths.NewProcess(nil, a.adbPath, "-s", a.host, "forward", local, remote)
68+
if err != nil {
69+
return hostAvailablePort, err
70+
}
71+
if err := cmd.RunWithinContext(ctx); err != nil {
6372
return hostAvailablePort, fmt.Errorf(
6473
"failed to forward ADB port %s to %s: %w",
6574
local,
@@ -71,15 +80,22 @@ func (a *ADBConnection) Forward(ctx context.Context, remotePort int) (int, error
7180
}
7281

7382
func (a *ADBConnection) ForwardKillAll(ctx context.Context) error {
74-
if err := exec.CommandContext(ctx, a.adbPath, "-s", a.host, "killforward-all").Run(); err != nil { // nolint:gosec
83+
cmd, err := paths.NewProcess(nil, a.adbPath, "-s", a.host, "killforward-all")
84+
if err != nil {
85+
return err
86+
}
87+
if err := cmd.RunWithinContext(ctx); err != nil {
7588
return fmt.Errorf("failed to kill all ADB forwarded ports: %w", err)
7689
}
7790
return nil
7891
}
7992

8093
func (a *ADBConnection) List(path string) ([]remote.FileInfo, error) {
81-
cmd := exec.Command(a.adbPath, "-s", a.host, "shell", "ls", "-la", path) // nolint:gosec
82-
cmd.Stderr = os.Stdout
94+
cmd, err := paths.NewProcess(nil, a.adbPath, "-s", a.host, "shell", "ls", "-la", path)
95+
if err != nil {
96+
return nil, err
97+
}
98+
cmd.RedirectStderrTo(os.Stdout)
8399
output, err := cmd.StdoutPipe()
84100
if err != nil {
85101
return nil, err
@@ -123,7 +139,10 @@ func (a *ADBConnection) List(path string) ([]remote.FileInfo, error) {
123139
}
124140

125141
func (a *ADBConnection) Stats(path string) (remote.FileInfo, error) {
126-
cmd := exec.Command(a.adbPath, "-s", a.host, "shell", "file", path) // nolint:gosec
142+
cmd, err := paths.NewProcess(nil, a.adbPath, "-s", a.host, "shell", "file", path)
143+
if err != nil {
144+
return remote.FileInfo{}, err
145+
}
127146
output, err := cmd.StdoutPipe()
128147
if err != nil {
129148
return remote.FileInfo{}, err
@@ -167,28 +186,34 @@ func (a *ADBConnection) WriteFile(r io.Reader, path string) error {
167186
}
168187

169188
func (a *ADBConnection) MkDirAll(path string) error {
170-
cmd := exec.Command(a.adbPath, "-s", a.host, "shell", "install", "-o", username, "-g", username, "-m", "755", "-d", path) // nolint:gosec
171-
out, err := cmd.CombinedOutput()
189+
cmd, err := paths.NewProcess(nil, a.adbPath, "-s", a.host, "shell", "install", "-o", username, "-g", username, "-m", "755", "-d", path)
190+
if err != nil {
191+
return err
192+
}
193+
stdout, err := cmd.RunAndCaptureCombinedOutput(context.Background())
172194
if err != nil {
173-
return fmt.Errorf("failed to create directory %q: %w: %s", path, err, out)
195+
return fmt.Errorf("failed to create directory %q: %w: %s", path, err, string(stdout))
174196
}
175197
return nil
176198
}
177199

178200
func (a *ADBConnection) Remove(path string) error {
179-
cmd := exec.Command(a.adbPath, "-s", a.host, "shell", "rm", "-r", path) // nolint:gosec
180-
out, err := cmd.CombinedOutput()
201+
cmd, err := paths.NewProcess(nil, a.adbPath, "-s", a.host, "shell", "rm", "-r", path) // nolint:gosec
202+
if err != nil {
203+
return err
204+
}
205+
stdout, err := cmd.RunAndCaptureCombinedOutput(context.Background())
181206
if err != nil {
182-
return fmt.Errorf("failed to remove path %q: %w: %s", path, err, out)
207+
return fmt.Errorf("failed to remove path %q: %w: %s", path, err, string(stdout))
183208
}
184209
return nil
185210
}
186211

187212
type ADBCommand struct {
188-
cmd *exec.Cmd
213+
cmd *paths.Process
189214
}
190215

191-
func (a *ADBConnection) GetCmd(ctx context.Context, cmd string, args ...string) remote.Cmder {
216+
func (a *ADBConnection) GetCmd(cmd string, args ...string) remote.Cmder {
192217
for i, arg := range args {
193218
if strings.Contains(arg, " ") {
194219
args[i] = fmt.Sprintf("%q", arg)
@@ -197,42 +222,48 @@ func (a *ADBConnection) GetCmd(ctx context.Context, cmd string, args ...string)
197222

198223
// TODO: fix command injection vulnerability
199224
var cmds []string
200-
cmds = append(cmds, "-s", a.host, "shell", cmd)
201-
cmds = append(cmds, args...)
202-
203-
cmdd := exec.CommandContext(ctx, a.adbPath, cmds...) // nolint:gosec
204-
return &ADBCommand{
205-
cmd: cmdd,
225+
cmds = append(cmds, a.adbPath, "-s", a.host, "shell", cmd)
226+
if len(args) > 0 {
227+
cmds = append(cmds, args...)
206228
}
229+
230+
command, _ := paths.NewProcess(nil, cmds...)
231+
return &ADBCommand{cmd: command}
207232
}
208233

209-
func (a *ADBCommand) Run() error {
210-
return a.cmd.Run()
234+
func (a *ADBCommand) Run(ctx context.Context) error {
235+
return a.cmd.RunWithinContext(ctx)
211236
}
212237

213-
func (a *ADBCommand) Output() ([]byte, error) {
214-
return a.cmd.CombinedOutput()
238+
func (a *ADBCommand) Output(ctx context.Context) ([]byte, error) {
239+
return a.cmd.RunAndCaptureCombinedOutput(ctx)
215240
}
216241

217-
func (a *ADBCommand) Interactive() (io.WriteCloser, io.Reader, remote.Closer, error) {
218-
a.cmd.Stderr = a.cmd.Stdout // Redirect stderr to stdout
242+
func (a *ADBCommand) Interactive() (io.WriteCloser, io.Reader, io.Reader, remote.Closer, error) {
219243
stdin, err := a.cmd.StdinPipe()
220244
if err != nil {
221-
return nil, nil, nil, fmt.Errorf("failed to get stdin pipe: %w", err)
245+
return nil, nil, nil, nil, fmt.Errorf("failed to get stdin pipe: %w", err)
222246
}
223247
stdout, err := a.cmd.StdoutPipe()
224248
if err != nil {
225-
return nil, nil, nil, fmt.Errorf("failed to get stdout pipe: %w", err)
249+
return nil, nil, nil, nil, fmt.Errorf("failed to get stdout pipe: %w", err)
250+
}
251+
stderr, err := a.cmd.StderrPipe()
252+
if err != nil {
253+
return nil, nil, nil, nil, fmt.Errorf("failed to get stderr pipe: %w", err)
226254
}
227255

228256
if err := a.cmd.Start(); err != nil {
229-
return nil, nil, nil, fmt.Errorf("failed to start command: %w", err)
257+
return nil, nil, nil, nil, fmt.Errorf("failed to start command: %w", err)
230258
}
231259

232-
return stdin, stdout, func() error {
260+
return stdin, stdout, stderr, func() error {
233261
if err := stdout.Close(); err != nil {
234262
return fmt.Errorf("failed to close stdout pipe: %w", err)
235263
}
264+
if err := stderr.Close(); err != nil {
265+
return fmt.Errorf("failed to close stderr pipe: %w", err)
266+
}
236267
if err := a.cmd.Wait(); err != nil {
237268
return fmt.Errorf("command failed: %w", err)
238269
}

pkg/board/remote/adb/adb_nowindows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ func adbWriteFile(a *ADBConnection, r io.Reader, pathStr string) error {
3131
if err != nil {
3232
return fmt.Errorf("failed to create command for creating file %q: %w", pathStr, err)
3333
}
34-
stdout, stderr, err := cmd.RunAndCaptureOutput(context.TODO())
34+
stdout, err := cmd.RunAndCaptureCombinedOutput(context.TODO())
3535
if err != nil {
36-
return fmt.Errorf("failed to start command for creating file %q: %w: %s%s", pathStr, err, string(stdout), string(stderr))
36+
return fmt.Errorf("failed to start command for creating file %q: %w: %s", pathStr, err, string(stdout))
3737
}
3838

3939
// Write the content to the file.

pkg/board/remote/adb/adb_windows.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ func adbWriteFile(a *ADBConnection, r io.Reader, pathStr string) error {
4545
if err != nil {
4646
return fmt.Errorf("cannot create process: %w", err)
4747
}
48-
stdout, stderr, err := cmd.RunAndCaptureOutput(context.TODO())
48+
stdout, err := cmd.RunAndCaptureCombinedOutput(context.TODO())
4949
if err != nil {
50-
return fmt.Errorf("failed to create file to %q: %w: %s: %s", pathStr, err, string(stdout), string(stderr))
50+
return fmt.Errorf("failed to create file to %q: %w: %s", pathStr, err, string(stdout))
5151
}
5252

5353
// Write the content to the file.

pkg/board/remote/remote.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ type RemoteFs interface {
2626
}
2727

2828
type RemoteShell interface {
29-
GetCmd(ctx context.Context, cmd string, args ...string) Cmder
29+
GetCmd(cmd string, args ...string) Cmder
3030
}
3131

3232
type Forwarder interface {
@@ -37,7 +37,7 @@ type Forwarder interface {
3737
type Closer func() error
3838

3939
type Cmder interface {
40-
Run() error
41-
Output() ([]byte, error)
42-
Interactive() (io.WriteCloser, io.Reader, Closer, error)
40+
Run(ctx context.Context) error
41+
Output(ctx context.Context) ([]byte, error)
42+
Interactive() (io.WriteCloser, io.Reader, io.Reader, Closer, error)
4343
}

0 commit comments

Comments
 (0)