github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/go/path/filepath/symlink_windows.go (about)

     1  // Copyright 2012 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  	"syscall"
     9  )
    10  
    11  func toShort(path string) (string, error) {
    12  	p, err := syscall.UTF16FromString(path)
    13  	if err != nil {
    14  		return "", err
    15  	}
    16  	b := p // GetShortPathName says we can reuse buffer
    17  	n := uint32(len(b))
    18  	for {
    19  		n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
    20  		if err != nil {
    21  			return "", err
    22  		}
    23  		if n <= uint32(len(b)) {
    24  			return syscall.UTF16ToString(b[:n]), nil
    25  		}
    26  		b = make([]uint16, n)
    27  	}
    28  }
    29  
    30  func toLong(path string) (string, error) {
    31  	p, err := syscall.UTF16FromString(path)
    32  	if err != nil {
    33  		return "", err
    34  	}
    35  	b := p // GetLongPathName says we can reuse buffer
    36  	n := uint32(len(b))
    37  	for {
    38  		n, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
    39  		if err != nil {
    40  			return "", err
    41  		}
    42  		if n <= uint32(len(b)) {
    43  			return syscall.UTF16ToString(b[:n]), nil
    44  		}
    45  		b = make([]uint16, n)
    46  	}
    47  }
    48  
    49  func evalSymlinks(path string) (string, error) {
    50  	path, err := walkSymlinks(path)
    51  	if err != nil {
    52  		return "", err
    53  	}
    54  
    55  	p, err := toShort(path)
    56  	if err != nil {
    57  		return "", err
    58  	}
    59  	p, err = toLong(p)
    60  	if err != nil {
    61  		return "", err
    62  	}
    63  	// syscall.GetLongPathName does not change the case of the drive letter,
    64  	// but the result of EvalSymlinks must be unique, so we have
    65  	// EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`).
    66  	// Make drive letter upper case.
    67  	if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
    68  		p = string(p[0]+'A'-'a') + p[1:]
    69  	}
    70  	return Clean(p), nil
    71  }