Source file src/path/filepath/path_windows.go

     1  // Copyright 2024 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 filepath
     6  
     7  import (
     8  	"os"
     9  	"strings"
    10  	"syscall"
    11  )
    12  
    13  // HasPrefix exists for historical compatibility and should not be used.
    14  //
    15  // Deprecated: HasPrefix does not respect path boundaries and
    16  // does not ignore case when required.
    17  func HasPrefix(p, prefix string) bool {
    18  	if strings.HasPrefix(p, prefix) {
    19  		return true
    20  	}
    21  	return strings.HasPrefix(strings.ToLower(p), strings.ToLower(prefix))
    22  }
    23  
    24  func splitList(path string) []string {
    25  	// The same implementation is used in LookPath in os/exec;
    26  	// consider changing os/exec when changing this.
    27  
    28  	if path == "" {
    29  		return []string{}
    30  	}
    31  
    32  	// Split path, respecting but preserving quotes.
    33  	list := []string{}
    34  	start := 0
    35  	quo := false
    36  	for i := 0; i < len(path); i++ {
    37  		switch c := path[i]; {
    38  		case c == '"':
    39  			quo = !quo
    40  		case c == ListSeparator && !quo:
    41  			list = append(list, path[start:i])
    42  			start = i + 1
    43  		}
    44  	}
    45  	list = append(list, path[start:])
    46  
    47  	// Remove quotes.
    48  	for i, s := range list {
    49  		list[i] = strings.ReplaceAll(s, `"`, ``)
    50  	}
    51  
    52  	return list
    53  }
    54  
    55  func abs(path string) (string, error) {
    56  	if path == "" {
    57  		// syscall.FullPath returns an error on empty path, because it's not a valid path.
    58  		// To implement Abs behavior of returning working directory on empty string input,
    59  		// special-case empty path by changing it to "." path. See golang.org/issue/24441.
    60  		path = "."
    61  	}
    62  	fullPath, err := syscall.FullPath(path)
    63  	if err != nil {
    64  		return "", err
    65  	}
    66  	return Clean(fullPath), nil
    67  }
    68  
    69  func join(elem []string) string {
    70  	var b strings.Builder
    71  	var lastChar byte
    72  	for _, e := range elem {
    73  		switch {
    74  		case b.Len() == 0:
    75  			// Add the first non-empty path element unchanged.
    76  		case os.IsPathSeparator(lastChar):
    77  			// If the path ends in a slash, strip any leading slashes from the next
    78  			// path element to avoid creating a UNC path (any path starting with "\\")
    79  			// from non-UNC elements.
    80  			//
    81  			// The correct behavior for Join when the first element is an incomplete UNC
    82  			// path (for example, "\\") is underspecified. We currently join subsequent
    83  			// elements so Join("\\", "host", "share") produces "\\host\share".
    84  			for len(e) > 0 && os.IsPathSeparator(e[0]) {
    85  				e = e[1:]
    86  			}
    87  			// If the path is \ and the next path element is ??,
    88  			// add an extra .\ to create \.\?? rather than \??\
    89  			// (a Root Local Device path).
    90  			if b.Len() == 1 && strings.HasPrefix(e, "??") && (len(e) == len("??") || os.IsPathSeparator(e[2])) {
    91  				b.WriteString(`.\`)
    92  			}
    93  		case lastChar == ':':
    94  			// If the path ends in a colon, keep the path relative to the current directory
    95  			// on a drive and don't add a separator. Preserve leading slashes in the next
    96  			// path element, which may make the path absolute.
    97  			//
    98  			// 	Join(`C:`, `f`) = `C:f`
    99  			//	Join(`C:`, `\f`) = `C:\f`
   100  		default:
   101  			// In all other cases, add a separator between elements.
   102  			b.WriteByte('\\')
   103  			lastChar = '\\'
   104  		}
   105  		if len(e) > 0 {
   106  			b.WriteString(e)
   107  			lastChar = e[len(e)-1]
   108  		}
   109  	}
   110  	if b.Len() == 0 {
   111  		return ""
   112  	}
   113  	return Clean(b.String())
   114  }
   115  
   116  func sameWord(a, b string) bool {
   117  	return strings.EqualFold(a, b)
   118  }
   119  

View as plain text