summaryrefslogtreecommitdiff
path: root/libgo/go/cmd/go/go_windows_test.go
blob: aa68a195802aea70108138fcad1a97aafe4ec299 (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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"internal/testenv"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"syscall"
	"testing"
)

func TestAbsolutePath(t *testing.T) {
	tmp, err := ioutil.TempDir("", "TestAbsolutePath")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmp)

	file := filepath.Join(tmp, "a.go")
	err = ioutil.WriteFile(file, []byte{}, 0644)
	if err != nil {
		t.Fatal(err)
	}
	dir := filepath.Join(tmp, "dir")
	err = os.Mkdir(dir, 0777)
	if err != nil {
		t.Fatal(err)
	}

	wd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	defer os.Chdir(wd)

	// Chdir so current directory and a.go reside on the same drive.
	err = os.Chdir(dir)
	if err != nil {
		t.Fatal(err)
	}

	noVolume := file[len(filepath.VolumeName(file)):]
	wrongPath := filepath.Join(dir, noVolume)
	output, err := exec.Command(testenv.GoToolPath(t), "build", noVolume).CombinedOutput()
	if err == nil {
		t.Fatal("build should fail")
	}
	if strings.Contains(string(output), wrongPath) {
		t.Fatalf("wrong output found: %v %v", err, string(output))
	}
}

func isWindowsXP(t *testing.T) bool {
	v, err := syscall.GetVersion()
	if err != nil {
		t.Fatalf("GetVersion failed: %v", err)
	}
	major := byte(v)
	return major < 6
}

func runIcacls(t *testing.T, args ...string) string {
	t.Helper()
	out, err := exec.Command("icacls", args...).CombinedOutput()
	if err != nil {
		t.Fatalf("icacls failed: %v\n%v", err, string(out))
	}
	return string(out)
}

func runGetACL(t *testing.T, path string) string {
	t.Helper()
	cmd := fmt.Sprintf(`Get-Acl "%s" | Select -expand AccessToString`, path)
	out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
	if err != nil {
		t.Fatalf("Get-Acl failed: %v\n%v", err, string(out))
	}
	return string(out)
}

// For issue 22343: verify that executable file created by "go build" command
// has discretionary access control list (DACL) set as if the file
// was created in the destination directory.
func TestACL(t *testing.T) {
	if isWindowsXP(t) {
		t.Skip("Windows XP does not have powershell command")
	}

	tmpdir, err := ioutil.TempDir("", "TestACL")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tmpdir)

	newtmpdir := filepath.Join(tmpdir, "tmp")
	err = os.Mkdir(newtmpdir, 0777)
	if err != nil {
		t.Fatal(err)
	}

	// When TestACL/tmp directory is created, it will have
	// the same security attributes as TestACL.
	// Add Guest account full access to TestACL/tmp - this
	// will make all files created in TestACL/tmp have different
	// security attributes to the files created in TestACL.
	runIcacls(t, newtmpdir,
		"/grant", "guest:(oi)(ci)f", // add Guest user to have full access
	)

	src := filepath.Join(tmpdir, "main.go")
	err = ioutil.WriteFile(src, []byte("package main; func main() { }\n"), 0644)
	if err != nil {
		t.Fatal(err)
	}
	exe := filepath.Join(tmpdir, "main.exe")
	cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, src)
	cmd.Env = append(os.Environ(),
		"TMP="+newtmpdir,
		"TEMP="+newtmpdir,
	)
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("go command failed: %v\n%v", err, string(out))
	}

	// exe file is expected to have the same security attributes as the src.
	if got, expected := runGetACL(t, exe), runGetACL(t, src); got != expected {
		t.Fatalf("expected Get-Acl output of \n%v\n, got \n%v\n", expected, got)
	}
}