summaryrefslogtreecommitdiff
path: root/pkg/specgen/winpath.go
blob: 0df4ebdd7b768c99fefc551d582bde83e69f1caf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package specgen

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/pkg/errors"
)

func isHostWinPath(path string) bool {
	return shouldResolveWinPaths() && strings.HasPrefix(path, `\\`) || hasWinDriveScheme(path, 0) || winPathExists(path)
}

func hasWinDriveScheme(path string, start int) bool {
	if len(path) < start+2 || path[start+1] != ':' {
		return false
	}

	drive := rune(path[start])
	return drive < unicode.MaxASCII && unicode.IsLetter(drive)
}

// Converts a Windows path to a WSL guest path if local env is a WSL linux guest or this is a Windows client.
func ConvertWinMountPath(path string) (string, error) {
	if !shouldResolveWinPaths() {
		return path, nil
	}

	if strings.HasPrefix(path, "/") {
		// Handle /[driveletter]/windows/path form (e.g. c:\Users\bar == /c/Users/bar)
		if len(path) > 2 && path[2] == '/' && shouldResolveUnixWinVariant(path) {
			drive := unicode.ToLower(rune(path[1]))
			if unicode.IsLetter(drive) && drive <= unicode.MaxASCII {
				return fmt.Sprintf("/mnt/%c/%s", drive, path[3:]), nil
			}
		}

		// unix path - pass through
		return path, nil
	}

	// Convert remote win client relative paths to absolute
	path = resolveRelativeOnWindows(path)

	// Strip extended marker prefix if present
	path = strings.TrimPrefix(path, `\\?\`)

	// Drive installed via wsl --mount
	switch {
	case strings.HasPrefix(path, `\\.\`):
		path = "/mnt/wsl/" + path[4:]
	case len(path) > 1 && path[1] == ':':
		path = "/mnt/" + strings.ToLower(path[0:1]) + path[2:]
	default:
		return path, errors.New("unsupported UNC path")
	}

	return strings.ReplaceAll(path, `\`, "/"), nil
}