Source file src/os/exec/lp_windows.go

     1  // Copyright 2010 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 exec
     6  
     7  import (
     8  	"errors"
     9  	"io/fs"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  )
    14  
    15  // ErrNotFound is the error resulting if a path search failed to find an executable file.
    16  var ErrNotFound = errors.New("executable file not found in %PATH%")
    17  
    18  func chkStat(file string) error {
    19  	d, err := os.Stat(file)
    20  	if err != nil {
    21  		return err
    22  	}
    23  	if d.IsDir() {
    24  		return fs.ErrPermission
    25  	}
    26  	return nil
    27  }
    28  
    29  func hasExt(file string) bool {
    30  	i := strings.LastIndex(file, ".")
    31  	if i < 0 {
    32  		return false
    33  	}
    34  	return strings.LastIndexAny(file, `:\/`) < i
    35  }
    36  
    37  func findExecutable(file string, exts []string) (string, error) {
    38  	if len(exts) == 0 {
    39  		return file, chkStat(file)
    40  	}
    41  	if hasExt(file) {
    42  		if chkStat(file) == nil {
    43  			return file, nil
    44  		}
    45  	}
    46  	for _, e := range exts {
    47  		if f := file + e; chkStat(f) == nil {
    48  			return f, nil
    49  		}
    50  	}
    51  	return "", fs.ErrNotExist
    52  }
    53  
    54  // LookPath searches for an executable named file in the
    55  // directories named by the PATH environment variable.
    56  // If file contains a slash, it is tried directly and the PATH is not consulted.
    57  // LookPath also uses PATHEXT environment variable to match
    58  // a suitable candidate.
    59  // The result may be an absolute path or a path relative to the current directory.
    60  func LookPath(file string) (string, error) {
    61  	var exts []string
    62  	x := os.Getenv(`PATHEXT`)
    63  	if x != "" {
    64  		for _, e := range strings.Split(strings.ToLower(x), `;`) {
    65  			if e == "" {
    66  				continue
    67  			}
    68  			if e[0] != '.' {
    69  				e = "." + e
    70  			}
    71  			exts = append(exts, e)
    72  		}
    73  	} else {
    74  		exts = []string{".com", ".exe", ".bat", ".cmd"}
    75  	}
    76  
    77  	if strings.ContainsAny(file, `:\/`) {
    78  		if f, err := findExecutable(file, exts); err == nil {
    79  			return f, nil
    80  		} else {
    81  			return "", &Error{file, err}
    82  		}
    83  	}
    84  	if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
    85  		return f, nil
    86  	}
    87  	path := os.Getenv("path")
    88  	for _, dir := range filepath.SplitList(path) {
    89  		if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil {
    90  			return f, nil
    91  		}
    92  	}
    93  	return "", &Error{file, ErrNotFound}
    94  }
    95  

View as plain text