compiler: build separation runtime with clite
This commit is contained in:
144
runtime/internal/lib/os/error.go
Normal file
144
runtime/internal/lib/os/error.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2009 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 os
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Portable analogs of some common system call errors.
|
||||
//
|
||||
// Errors returned from this package may be tested against these errors
|
||||
// with errors.Is.
|
||||
var (
|
||||
// ErrInvalid indicates an invalid argument.
|
||||
// Methods on File will return this error when the receiver is nil.
|
||||
ErrInvalid = fs.ErrInvalid // "invalid argument"
|
||||
|
||||
ErrPermission = fs.ErrPermission // "permission denied"
|
||||
ErrExist = fs.ErrExist // "file already exists"
|
||||
ErrNotExist = fs.ErrNotExist // "file does not exist"
|
||||
ErrClosed = fs.ErrClosed // "file already closed"
|
||||
|
||||
// TODO(xsw):
|
||||
// ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
|
||||
// ErrDeadlineExceeded = errDeadlineExceeded() // "i/o timeout"
|
||||
)
|
||||
|
||||
// func errNoDeadline() error { return poll.ErrNoDeadline }
|
||||
|
||||
// errDeadlineExceeded returns the value for os.ErrDeadlineExceeded.
|
||||
// This error comes from the internal/poll package, which is also
|
||||
// used by package net. Doing it this way ensures that the net
|
||||
// package will return os.ErrDeadlineExceeded for an exceeded deadline,
|
||||
// as documented by net.Conn.SetDeadline, without requiring any extra
|
||||
// work in the net package and without requiring the internal/poll
|
||||
// package to import os (which it can't, because that would be circular).
|
||||
// func errDeadlineExceeded() error { return poll.ErrDeadlineExceeded }
|
||||
|
||||
type timeout interface {
|
||||
Timeout() bool
|
||||
}
|
||||
|
||||
// PathError records an error and the operation and file path that caused it.
|
||||
type PathError = fs.PathError
|
||||
|
||||
// SyscallError records an error from a specific system call.
|
||||
type SyscallError struct {
|
||||
Syscall string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *SyscallError) Error() string { return e.Syscall + ": " + e.Err.Error() }
|
||||
|
||||
func (e *SyscallError) Unwrap() error { return e.Err }
|
||||
|
||||
// Timeout reports whether this error represents a timeout.
|
||||
func (e *SyscallError) Timeout() bool {
|
||||
t, ok := e.Err.(timeout)
|
||||
return ok && t.Timeout()
|
||||
}
|
||||
|
||||
// NewSyscallError returns, as an error, a new SyscallError
|
||||
// with the given system call name and error details.
|
||||
// As a convenience, if err is nil, NewSyscallError returns nil.
|
||||
func NewSyscallError(syscall string, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &SyscallError{syscall, err}
|
||||
}
|
||||
|
||||
// IsExist returns a boolean indicating whether the error is known to report
|
||||
// that a file or directory already exists. It is satisfied by ErrExist as
|
||||
// well as some syscall errors.
|
||||
//
|
||||
// This function predates errors.Is. It only supports errors returned by
|
||||
// the os package. New code should use errors.Is(err, fs.ErrExist).
|
||||
func IsExist(err error) bool {
|
||||
return underlyingErrorIs(err, ErrExist)
|
||||
}
|
||||
|
||||
// IsNotExist returns a boolean indicating whether the error is known to
|
||||
// report that a file or directory does not exist. It is satisfied by
|
||||
// ErrNotExist as well as some syscall errors.
|
||||
//
|
||||
// This function predates errors.Is. It only supports errors returned by
|
||||
// the os package. New code should use errors.Is(err, fs.ErrNotExist).
|
||||
func IsNotExist(err error) bool {
|
||||
return underlyingErrorIs(err, ErrNotExist)
|
||||
}
|
||||
|
||||
// IsPermission returns a boolean indicating whether the error is known to
|
||||
// report that permission is denied. It is satisfied by ErrPermission as well
|
||||
// as some syscall errors.
|
||||
//
|
||||
// This function predates errors.Is. It only supports errors returned by
|
||||
// the os package. New code should use errors.Is(err, fs.ErrPermission).
|
||||
func IsPermission(err error) bool {
|
||||
return underlyingErrorIs(err, ErrPermission)
|
||||
}
|
||||
|
||||
// IsTimeout returns a boolean indicating whether the error is known
|
||||
// to report that a timeout occurred.
|
||||
//
|
||||
// This function predates errors.Is, and the notion of whether an
|
||||
// error indicates a timeout can be ambiguous. For example, the Unix
|
||||
// error EWOULDBLOCK sometimes indicates a timeout and sometimes does not.
|
||||
// New code should use errors.Is with a value appropriate to the call
|
||||
// returning the error, such as os.ErrDeadlineExceeded.
|
||||
func IsTimeout(err error) bool {
|
||||
terr, ok := underlyingError(err).(timeout)
|
||||
return ok && terr.Timeout()
|
||||
}
|
||||
|
||||
type syscallErrorType = syscall.Errno
|
||||
|
||||
func underlyingErrorIs(err, target error) bool {
|
||||
// Note that this function is not errors.Is:
|
||||
// underlyingError only unwraps the specific error-wrapping types
|
||||
// that it historically did, not all errors implementing Unwrap().
|
||||
err = underlyingError(err)
|
||||
if err == target {
|
||||
return true
|
||||
}
|
||||
// To preserve prior behavior, only examine syscall errors.
|
||||
e, ok := err.(syscallErrorType)
|
||||
return ok && e.Is(target)
|
||||
}
|
||||
|
||||
// underlyingError returns the underlying error for known os error types.
|
||||
func underlyingError(err error) error {
|
||||
switch err := err.(type) {
|
||||
case *PathError:
|
||||
return err.Err
|
||||
case *LinkError:
|
||||
return err.Err
|
||||
case *SyscallError:
|
||||
return err.Err
|
||||
}
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user