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
5//go:build !windows
6
7package testenv
8
9import (
10	"fmt"
11	"os"
12	"path/filepath"
13	"runtime"
14)
15
16func hasSymlink() (ok bool, reason string) {
17	switch runtime.GOOS {
18	case "plan9":
19		return false, ""
20	case "android", "wasip1":
21		// For wasip1, some runtimes forbid absolute symlinks,
22		// or symlinks that escape the current working directory.
23		// Perform a simple test to see whether the runtime
24		// supports symlinks or not. If we get a permission
25		// error, the runtime does not support symlinks.
26		dir, err := os.MkdirTemp("", "")
27		if err != nil {
28			return false, ""
29		}
30		defer func() {
31			_ = os.RemoveAll(dir)
32		}()
33		fpath := filepath.Join(dir, "testfile.txt")
34		if err := os.WriteFile(fpath, nil, 0644); err != nil {
35			return false, ""
36		}
37		if err := os.Symlink(fpath, filepath.Join(dir, "testlink")); err != nil {
38			if SyscallIsNotSupported(err) {
39				return false, fmt.Sprintf("symlinks unsupported: %s", err.Error())
40			}
41			return false, ""
42		}
43	}
44
45	return true, ""
46}
47