1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package testenv
6
7import (
8	"os"
9	"path/filepath"
10	"sync"
11	"syscall"
12)
13
14var symlinkOnce sync.Once
15var winSymlinkErr error
16
17func initWinHasSymlink() {
18	tmpdir, err := os.MkdirTemp("", "symtest")
19	if err != nil {
20		panic("failed to create temp directory: " + err.Error())
21	}
22	defer os.RemoveAll(tmpdir)
23
24	err = os.Symlink("target", filepath.Join(tmpdir, "symlink"))
25	if err != nil {
26		err = err.(*os.LinkError).Err
27		switch err {
28		case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD:
29			winSymlinkErr = err
30		}
31	}
32}
33
34func hasSymlink() (ok bool, reason string) {
35	symlinkOnce.Do(initWinHasSymlink)
36
37	switch winSymlinkErr {
38	case nil:
39		return true, ""
40	case syscall.EWINDOWS:
41		return false, ": symlinks are not supported on your version of Windows"
42	case syscall.ERROR_PRIVILEGE_NOT_HELD:
43		return false, ": you don't have enough privileges to create symlinks"
44	}
45
46	return false, ""
47}
48