1package system // import "github.com/docker/docker/pkg/system"
2
3import (
4	"fmt"
5	"path/filepath"
6	"runtime"
7	"strings"
8)
9
10const defaultUnixPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
11
12// DefaultPathEnv is unix style list of directories to search for
13// executables. Each directory is separated from the next by a colon
14// ':' character .
15func DefaultPathEnv(os string) string {
16	if runtime.GOOS == "windows" {
17		if os != runtime.GOOS {
18			return defaultUnixPathEnv
19		}
20		// Deliberately empty on Windows containers on Windows as the default path will be set by
21		// the container. Docker has no context of what the default path should be.
22		return ""
23	}
24	return defaultUnixPathEnv
25
26}
27
28// PathVerifier defines the subset of a PathDriver that CheckSystemDriveAndRemoveDriveLetter
29// actually uses in order to avoid system depending on containerd/continuity.
30type PathVerifier interface {
31	IsAbs(string) bool
32}
33
34// CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter,
35// is the system drive.
36// On Linux: this is a no-op.
37// On Windows: this does the following>
38// CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path.
39// This is used, for example, when validating a user provided path in docker cp.
40// If a drive letter is supplied, it must be the system drive. The drive letter
41// is always removed. Also, it translates it to OS semantics (IOW / to \). We
42// need the path in this syntax so that it can ultimately be concatenated with
43// a Windows long-path which doesn't support drive-letters. Examples:
44// C:			--> Fail
45// C:\			--> \
46// a			--> a
47// /a			--> \a
48// d:\			--> Fail
49func CheckSystemDriveAndRemoveDriveLetter(path string, driver PathVerifier) (string, error) {
50	if runtime.GOOS != "windows" || LCOWSupported() {
51		return path, nil
52	}
53
54	if len(path) == 2 && string(path[1]) == ":" {
55		return "", fmt.Errorf("No relative path specified in %q", path)
56	}
57	if !driver.IsAbs(path) || len(path) < 2 {
58		return filepath.FromSlash(path), nil
59	}
60	if string(path[1]) == ":" && !strings.EqualFold(string(path[0]), "c") {
61		return "", fmt.Errorf("The specified path is not on the system drive (C:)")
62	}
63	return filepath.FromSlash(path[2:]), nil
64}
65