@@ -3,14 +3,17 @@ package main
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "log"
6
7
"math/rand"
7
8
"net"
8
9
"net/http"
9
10
"os"
10
11
"os/exec"
11
12
"os/signal"
12
13
"path/filepath"
14
+ "regexp"
13
15
"runtime"
16
+ "sort"
14
17
"strconv"
15
18
"strings"
16
19
"syscall"
@@ -107,7 +110,6 @@ func sshCode(host, dir string, o options) error {
107
110
108
111
// Downloads the latest code-server and allows it to be executed.
109
112
sshCmdStr := fmt .Sprintf ("ssh %v %v '/usr/bin/env bash -l'" , o .sshFlags , host )
110
-
111
113
sshCmd := exec .Command ("sh" , "-l" , "-c" , sshCmdStr )
112
114
sshCmd .Stdout = os .Stdout
113
115
sshCmd .Stderr = os .Stderr
@@ -146,10 +148,9 @@ func sshCode(host, dir string, o options) error {
146
148
flog .Info ("Tunneling remote port %v to %v" , o .remotePort , o .bindAddr )
147
149
148
150
sshCmdStr :=
149
- fmt .Sprintf ("ssh -tt -q -L %v:localhost:%v %v %v 'cd %v; %v --host 127.0.0.1 --auth none --port=%v'" ,
150
- o .bindAddr , o .remotePort , o .sshFlags , host , dir , codeServerPath , o .remotePort ,
151
+ fmt .Sprintf ("ssh -tt -q -L %v:localhost:%v %v %v '%v %v --host 127.0.0.1 --auth none --port=%v'" ,
152
+ o .bindAddr , o .remotePort , o .sshFlags , host , codeServerPath , dir , o .remotePort ,
151
153
)
152
-
153
154
// Starts code-server and forwards the remote port.
154
155
sshCmd := exec .Command ("sh" , "-l" , "-c" , sshCmdStr )
155
156
sshCmd .Stdin = os .Stdin
@@ -341,7 +342,6 @@ func randomPort() (string, error) {
341
342
// checkSSHDirectory performs sanity and safety checks on sshDirectory, and
342
343
// returns a new value for o.reuseConnection depending on the checks.
343
344
func checkSSHDirectory (sshDirectory string , reuseConnection bool ) bool {
344
-
345
345
if runtime .GOOS == "windows" {
346
346
flog .Info ("OS is windows, disabling connection reuse feature" )
347
347
return false
@@ -463,8 +463,8 @@ func syncUserSettings(sshFlags string, host string, back bool) error {
463
463
return err
464
464
}
465
465
466
- //const remoteSettingsDir = ".local/share/code-server/User/"
467
- var remoteSettingsDir = windowsVarFix ( "remoteSettingsDir" )
466
+ var remoteSettingsDir = windowsVarFix ( ".local/share/code-server/User/" )
467
+
468
468
var (
469
469
src = localConfDir + "/"
470
470
dest = host + ":" + remoteSettingsDir
@@ -489,8 +489,7 @@ func syncExtensions(sshFlags string, host string, back bool) error {
489
489
return err
490
490
}
491
491
492
- //const remoteExtensionsDir = ".local/share/code-server/extensions/"
493
- var remoteExtensionsDir = windowsVarFix ("remoteExtensionsDir" )
492
+ var remoteExtensionsDir = windowsVarFix (".local/share/code-server/extensions/" )
494
493
495
494
var (
496
495
src = localExtensionsDir + "/"
@@ -561,8 +560,10 @@ chmod +x %v`,
561
560
func ensureDir (path string ) error {
562
561
_ , err := os .Stat (path )
563
562
if os .IsNotExist (err ) {
563
+ // This fixes a issue where GO reads `/c/` as `C:\c\` and creates
564
+ // empty directories on HOST/CLIENT that dont need to exist
564
565
if runtime .GOOS == "windows" && strings .HasPrefix (path , "/c/" ) {
565
- path = path [3 :]
566
+ path = "C:" + path [2 :]
566
567
}
567
568
err = os .MkdirAll (path , 0750 )
568
569
}
@@ -624,3 +625,73 @@ func parseGCPSSHCmd(instance string) (ip, sshFlags string, err error) {
624
625
625
626
return strings .TrimSpace (userIP ), sshFlags , nil
626
627
}
628
+
629
+ // gitbashMountPoints returns all mount points in a msys2 system and then trunicates
630
+ // the mount point for `/` from the path provided (dir), this is done to fix an
631
+ // issue with how msys2 provides file paths to go, example. When you feed a filepath
632
+ // as user input to go, `command /opt` for example, msys2 will pass `C:\<path to msys2 directory>\opt`
633
+ // This causes an issue whith this program where when you run `sshcode.exe user@server /opt`,
634
+ // GO and msys2 will attempt to pass `C:\<path to msys2 directory>\opt` to the server.
635
+ // This function is used to prevent this.
636
+ func gitbashWindowsDir (dir string ) string {
637
+
638
+ // if dir is left empty, line82:main.go will set it to `~`, this makes it so that
639
+ // if dir is `~`, return `~/` instead of continuing with the gitbashWindowsDir()
640
+ // function. this prevens windows from trying to send a litteral instead of a relative
641
+ if dir == "~" {
642
+ return "~/"
643
+ }
644
+
645
+ //If msys feeds a `C:` path, clense
646
+ if strings .HasPrefix (dir , "C:" ) {
647
+ mountPoints := gitbashMountPointsAndHome ()
648
+
649
+ // Apply mount points
650
+ absDir , _ := filepath .Abs (dir )
651
+ absDir = filepath .ToSlash (absDir )
652
+ for _ , mp := range mountPoints {
653
+ if strings .HasPrefix (absDir , mp [0 ]) {
654
+ resolved := strings .Replace (absDir , mp [0 ], mp [1 ], 1 )
655
+
656
+ // Sometimes the resolved path can go from user input `/Workspace`
657
+ // to `//Workspace`, this if statement checks that and removes it
658
+ if strings .HasPrefix (resolved , "//" ) {
659
+ resolved = strings .TrimPrefix (resolved , "/" )
660
+ flog .Info ("Resolved windows path '%s' to '%s" , dir , resolved )
661
+ return resolved
662
+ }
663
+
664
+ flog .Info ("Resolved windows path '%s' to '%s" , dir , resolved )
665
+ return resolved
666
+ }
667
+ }
668
+
669
+ }
670
+ return dir
671
+ }
672
+
673
+ // This function returns an array with MINGW64 mount points including relative home dir
674
+ func gitbashMountPointsAndHome () [][]string {
675
+ mountPoints := [][]string {{filepath .ToSlash (os .Getenv ("HOME" )), "~" }}
676
+
677
+ // Load mount points
678
+ out , err := exec .Command ("mount" ).Output ()
679
+ if err != nil {
680
+ //log.Error(err)
681
+ log .Println (err )
682
+ }
683
+ lines := strings .Split (string (out ), "\n " )
684
+ var mountRx = regexp .MustCompile (`^(.*) on (.*) type` )
685
+ for _ , line := range lines {
686
+ extract := mountRx .FindStringSubmatch (line )
687
+ if len (extract ) > 0 {
688
+ mountPoints = append (mountPoints , []string {extract [1 ], extract [2 ]})
689
+ }
690
+ }
691
+
692
+ // Sort by size to get more restrictive mount points first
693
+ sort .Slice (mountPoints , func (i , j int ) bool {
694
+ return len (mountPoints [i ][0 ]) > len (mountPoints [j ][0 ])
695
+ })
696
+ return mountPoints
697
+ }
0 commit comments