golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/internal/robustio/robustio_windows.go (about)

     1  // Copyright 2019 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 robustio
     6  
     7  import (
     8  	"errors"
     9  	"syscall"
    10  	"time"
    11  )
    12  
    13  const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND
    14  
    15  // isEphemeralError returns true if err may be resolved by waiting.
    16  func isEphemeralError(err error) bool {
    17  	var errno syscall.Errno
    18  	if errors.As(err, &errno) {
    19  		switch errno {
    20  		case syscall.ERROR_ACCESS_DENIED,
    21  			syscall.ERROR_FILE_NOT_FOUND,
    22  			ERROR_SHARING_VIOLATION:
    23  			return true
    24  		}
    25  	}
    26  	return false
    27  }
    28  
    29  // Note: it may be convenient to have this helper return fs.FileInfo, but
    30  // implementing this is actually quite involved on Windows. Since we only
    31  // currently use mtime, keep it simple.
    32  func getFileID(filename string) (FileID, time.Time, error) {
    33  	filename16, err := syscall.UTF16PtrFromString(filename)
    34  	if err != nil {
    35  		return FileID{}, time.Time{}, err
    36  	}
    37  	h, err := syscall.CreateFile(filename16, 0, 0, nil, syscall.OPEN_EXISTING, uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS), 0)
    38  	if err != nil {
    39  		return FileID{}, time.Time{}, err
    40  	}
    41  	defer syscall.CloseHandle(h)
    42  	var i syscall.ByHandleFileInformation
    43  	if err := syscall.GetFileInformationByHandle(h, &i); err != nil {
    44  		return FileID{}, time.Time{}, err
    45  	}
    46  	mtime := time.Unix(0, i.LastWriteTime.Nanoseconds())
    47  	return FileID{
    48  		device: uint64(i.VolumeSerialNumber),
    49  		inode:  uint64(i.FileIndexHigh)<<32 | uint64(i.FileIndexLow),
    50  	}, mtime, nil
    51  }