| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package robustio wraps I/O functions that are prone to failure on Windows, |
| // transparently retrying errors up to an arbitrary timeout. |
| // |
| // Errors are classified heuristically and retries are bounded, so the functions |
| // in this package do not completely eliminate spurious errors. However, they do |
| // significantly reduce the rate of failure in practice. |
| // |
| // If so, the error will likely wrap one of: |
| // The functions in this package do not completely eliminate spurious errors, |
| // but substantially reduce their rate of occurrence in practice. |
| package robustio |
| |
| import "time" |
| |
| // Rename is like os.Rename, but on Windows retries errors that may occur if the |
| // file is concurrently read or overwritten. |
| // |
| // (See golang.org/issue/31247 and golang.org/issue/32188.) |
| func Rename(oldpath, newpath string) error { |
| return rename(oldpath, newpath) |
| } |
| |
| // ReadFile is like os.ReadFile, but on Windows retries errors that may |
| // occur if the file is concurrently replaced. |
| // |
| // (See golang.org/issue/31247 and golang.org/issue/32188.) |
| func ReadFile(filename string) ([]byte, error) { |
| return readFile(filename) |
| } |
| |
| // RemoveAll is like os.RemoveAll, but on Windows retries errors that may occur |
| // if an executable file in the directory has recently been executed. |
| // |
| // (See golang.org/issue/19491.) |
| func RemoveAll(path string) error { |
| return removeAll(path) |
| } |
| |
| // IsEphemeralError reports whether err is one of the errors that the functions |
| // in this package attempt to mitigate. |
| // |
| // Errors considered ephemeral include: |
| // - syscall.ERROR_ACCESS_DENIED |
| // - syscall.ERROR_FILE_NOT_FOUND |
| // - internal/syscall/windows.ERROR_SHARING_VIOLATION |
| // |
| // This set may be expanded in the future; programs must not rely on the |
| // non-ephemerality of any given error. |
| func IsEphemeralError(err error) bool { |
| return isEphemeralError(err) |
| } |
| |
| // A FileID uniquely identifies a file in the file system. |
| // |
| // If GetFileID(name1) returns the same ID as GetFileID(name2), the two file |
| // names denote the same file. |
| // A FileID is comparable, and thus suitable for use as a map key. |
| type FileID struct { |
| device, inode uint64 |
| } |
| |
| // GetFileID returns the file system's identifier for the file, and its |
| // modification time. |
| // Like os.Stat, it reads through symbolic links. |
| func GetFileID(filename string) (FileID, time.Time, error) { return getFileID(filename) } |