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 package testenv 6 7 import ( 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "sync" 12 "syscall" 13 ) 14 15 var symlinkOnce sync.Once 16 var winSymlinkErr error 17 18 func initWinHasSymlink() { 19 tmpdir, err := ioutil.TempDir("", "symtest") 20 if err != nil { 21 panic("failed to create temp directory: " + err.Error()) 22 } 23 defer os.RemoveAll(tmpdir) 24 25 err = os.Symlink("target", filepath.Join(tmpdir, "symlink")) 26 if err != nil { 27 err = err.(*os.LinkError).Err 28 switch err { 29 case syscall.EWINDOWS, syscall.ERROR_PRIVILEGE_NOT_HELD: 30 winSymlinkErr = err 31 } 32 } 33 os.Remove("target") 34 } 35 36 func hasSymlink() (ok bool, reason string) { 37 symlinkOnce.Do(initWinHasSymlink) 38 39 switch winSymlinkErr { 40 case nil: 41 return true, "" 42 case syscall.EWINDOWS: 43 return false, ": symlinks are not supported on your version of Windows" 44 case syscall.ERROR_PRIVILEGE_NOT_HELD: 45 return false, ": you don't have enough privileges to create symlinks" 46 } 47 48 return false, "" 49 } 50