Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func (s *PHPStore) discoverPHPViaPHP(dir, binName string) *Version {
}
php = filepath.Clean(php)
var err error
php, err = filepath.EvalSymlinks(php)
php, err = evalSymlinks(php)
if err != nil {
s.log(" %s is not a valid symlink", php)
return nil
Expand Down Expand Up @@ -332,7 +332,7 @@ func (s *PHPStore) pathDirectories(configDir string) []string {
seen := make(map[string]bool)
for _, dir := range filepath.SplitList(path) {
dir = strings.Replace(dir, "%%USERPROFILE%%", user, 1)
edir, err := filepath.EvalSymlinks(dir)
edir, err := evalSymlinks(dir)
if err != nil {
continue
}
Expand Down
7 changes: 7 additions & 0 deletions fsutils_others.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build !windows

package phpstore

import "path/filepath"

var evalSymlinks = filepath.EvalSymlinks
39 changes: 39 additions & 0 deletions fsutils_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package phpstore

import (
"errors"
"os"
"path/filepath"
"syscall"
)

// Taken from https://github.com/golangci/golangci-lint/blob/main/pkg/fsutils/fsutils_windows.go

// This is a workaround for the behavior of [filepath.EvalSymlinks],
// which fails with [syscall.ENOTDIR] if the specified path contains a junction on Windows.
// Junctions can occur, for example, when a volume is mounted as a subdirectory inside another drive.
// This can usually happen when using the Dev Drives feature and replacing existing directories.
// See: https://github.com/golang/go/issues/40180
//
// Since [syscall.ENOTDIR] is only returned when calling [filepath.EvalSymlinks] on Windows
// if part of the presented path is a junction and nothing before was a symlink,
// we simply treat this as NOT symlink,
// because a symlink over the junction makes no sense at all.
func evalSymlinks(path string) (string, error) {
resolved, err := filepath.EvalSymlinks(path)
if err == nil {
return resolved, nil
}

if !errors.Is(err, syscall.ENOTDIR) {
return "", err
}

_, err = os.Stat(path)
if err != nil {
return "", err
}

// If exists, we make the path cleaned before being used
return filepath.Abs(path), nil
}
2 changes: 1 addition & 1 deletion store.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (s *PHPStore) loadVersions() {
// addVersion ensures that all versions are unique in the store
func (s *PHPStore) addVersion(version *Version) int {
idx, ok := s.seen[version.PHPPath]
sl, _ := filepath.EvalSymlinks(version.PHPPath)
sl, _ := evalSymlinks(version.PHPPath)
// double-check to see if that's not just a symlink to another existing version
if !ok && sl != "" {
idx, ok = s.seen[sl]
Expand Down
10 changes: 5 additions & 5 deletions version.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,35 +185,35 @@ func (v *Version) setServer(fpm, cgi, phpconfig, phpize, phpdbg string) string {
msg := fmt.Sprintf(" Found PHP: %s", v.PHPPath)
fpm = filepath.Clean(fpm)
if _, err := os.Stat(fpm); err == nil {
if fpm, err := filepath.EvalSymlinks(fpm); err == nil {
if fpm, err := evalSymlinks(fpm); err == nil {
v.FPMPath = fpm
msg += fmt.Sprintf(", with FPM: %s", fpm)
}
}
cgi = filepath.Clean(cgi)
if _, err := os.Stat(cgi); err == nil {
if cgi, err := filepath.EvalSymlinks(cgi); err == nil {
if cgi, err := evalSymlinks(cgi); err == nil {
v.CGIPath = cgi
msg += fmt.Sprintf(", with CGI: %s", cgi)
}
}
phpconfig = filepath.Clean(phpconfig)
if _, err := os.Stat(phpconfig); err == nil {
if phpconfig, err := filepath.EvalSymlinks(phpconfig); err == nil {
if phpconfig, err := evalSymlinks(phpconfig); err == nil {
v.PHPConfigPath = phpconfig
msg += fmt.Sprintf(", with php-config: %s", phpconfig)
}
}
phpize = filepath.Clean(phpize)
if _, err := os.Stat(phpize); err == nil {
if phpize, err := filepath.EvalSymlinks(phpize); err == nil {
if phpize, err := evalSymlinks(phpize); err == nil {
v.PHPizePath = phpize
msg += fmt.Sprintf(", with phpize: %s", phpize)
}
}
phpdbg = filepath.Clean(phpdbg)
if _, err := os.Stat(phpdbg); err == nil {
if phpdbg, err := filepath.EvalSymlinks(phpdbg); err == nil {
if phpdbg, err := evalSymlinks(phpdbg); err == nil {
v.PHPdbgPath = phpdbg
msg += fmt.Sprintf(", with phpdbg: %s", phpdbg)
}
Expand Down