snapshot: sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
Содержимое пина, зафиксированного в go.mod sing-box-lx, одним коммитом без истории. Полная история SagerNet/gvisor — 1.45 ГБ и клонируется в каждой CI-джобе; наша дельта — одна вставка в одну функцию, история для неё не нужна. Module path github.com/sagernet/gvisor сохранён намеренно: на него опирается replace-директива суперпроекта. Патч поверх — отдельным коммитом, чтобы дельта читалась одним git show и переносилась на новый пин копированием. SPECS/TASKS/048-GVISOR_HANDSHAKE_NIL_CRASH
This commit is contained in:
commit
2c4ae3b0a4
712 changed files with 185689 additions and 0 deletions
44
pkg/syserr/host_darwin.go
Normal file
44
pkg/syserr/host_darwin.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2021 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package syserr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const maxErrno = 107
|
||||
|
||||
var darwinHostTranslations [maxErrno]*Error
|
||||
|
||||
func getHostTranslation(err unix.Errno) *Error {
|
||||
if uint64(err) >= uint64(len(darwinHostTranslations)) {
|
||||
return nil
|
||||
}
|
||||
return darwinHostTranslations[err]
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/1270): We currently only add translations for errors
|
||||
// that exist both on Darwin and Linux.
|
||||
func addHostTranslation(host unix.Errno, trans *Error) {
|
||||
if darwinHostTranslations[host] != nil {
|
||||
panic(fmt.Sprintf("duplicate translation for host errno %q (%d)", host.Error(), host))
|
||||
}
|
||||
darwinHostTranslations[host] = trans
|
||||
}
|
||||
95
pkg/syserr/host_linux.go
Normal file
95
pkg/syserr/host_linux.go
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
// Copyright 2018 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package syserr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/abi/linux/errno"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const maxErrno = 134
|
||||
|
||||
var linuxHostTranslations [maxErrno]*Error
|
||||
|
||||
func getHostTranslation(err unix.Errno) *Error {
|
||||
if uint64(err) >= uint64(len(linuxHostTranslations)) {
|
||||
return nil
|
||||
}
|
||||
return linuxHostTranslations[err]
|
||||
}
|
||||
|
||||
func addHostTranslation(host unix.Errno, trans *Error) {
|
||||
if linuxHostTranslations[host] != nil {
|
||||
panic(fmt.Sprintf("duplicate translation for host errno %q (%d)", host.Error(), host))
|
||||
}
|
||||
linuxHostTranslations[host] = trans
|
||||
}
|
||||
|
||||
// TODO(b/34162363): Remove or replace most of these errors.
|
||||
//
|
||||
// Some of the errors should be replaced with package specific errors and
|
||||
// others should be removed entirely.
|
||||
var (
|
||||
ErrDeadlock = newWithHost("resource deadlock would occur", errno.EDEADLOCK, unix.EDEADLOCK)
|
||||
ErrChannelOutOfRange = newWithHost("channel number out of range", errno.ECHRNG, unix.ECHRNG)
|
||||
ErrLevelTwoNotSynced = newWithHost("level 2 not synchronized", errno.EL2NSYNC, unix.EL2NSYNC)
|
||||
ErrLevelThreeHalted = newWithHost("level 3 halted", errno.EL3HLT, unix.EL3HLT)
|
||||
ErrLevelThreeReset = newWithHost("level 3 reset", errno.EL3RST, unix.EL3RST)
|
||||
ErrLinkNumberOutOfRange = newWithHost("link number out of range", errno.ELNRNG, unix.ELNRNG)
|
||||
ErrProtocolDriverNotAttached = newWithHost("protocol driver not attached", errno.EUNATCH, unix.EUNATCH)
|
||||
ErrNoCSIAvailable = newWithHost("no CSI structure available", errno.ENOCSI, unix.ENOCSI)
|
||||
ErrLevelTwoHalted = newWithHost("level 2 halted", errno.EL2HLT, unix.EL2HLT)
|
||||
ErrInvalidExchange = newWithHost("invalid exchange", errno.EBADE, unix.EBADE)
|
||||
ErrInvalidRequestDescriptor = newWithHost("invalid request descriptor", errno.EBADR, unix.EBADR)
|
||||
ErrExchangeFull = newWithHost("exchange full", errno.EXFULL, unix.EXFULL)
|
||||
ErrNoAnode = newWithHost("no anode", errno.ENOANO, unix.ENOANO)
|
||||
ErrInvalidRequestCode = newWithHost("invalid request code", errno.EBADRQC, unix.EBADRQC)
|
||||
ErrInvalidSlot = newWithHost("invalid slot", errno.EBADSLT, unix.EBADSLT)
|
||||
ErrBadFontFile = newWithHost("bad font file format", errno.EBFONT, unix.EBFONT)
|
||||
ErrMachineNotOnNetwork = newWithHost("machine is not on the network", errno.ENONET, unix.ENONET)
|
||||
ErrPackageNotInstalled = newWithHost("package not installed", errno.ENOPKG, unix.ENOPKG)
|
||||
ErrAdvertise = newWithHost("advertise error", errno.EADV, unix.EADV)
|
||||
ErrSRMount = newWithHost("srmount error", errno.ESRMNT, unix.ESRMNT)
|
||||
ErrSendCommunication = newWithHost("communication error on send", errno.ECOMM, unix.ECOMM)
|
||||
ErrRFS = newWithHost("RFS specific error", errno.EDOTDOT, unix.EDOTDOT)
|
||||
ErrNetworkNameNotUnique = newWithHost("name not unique on network", errno.ENOTUNIQ, unix.ENOTUNIQ)
|
||||
ErrFDInBadState = newWithHost("file descriptor in bad state", errno.EBADFD, unix.EBADFD)
|
||||
ErrRemoteAddressChanged = newWithHost("remote address changed", errno.EREMCHG, unix.EREMCHG)
|
||||
ErrSharedLibraryInaccessible = newWithHost("can not access a needed shared library", errno.ELIBACC, unix.ELIBACC)
|
||||
ErrCorruptedSharedLibrary = newWithHost("accessing a corrupted shared library", errno.ELIBBAD, unix.ELIBBAD)
|
||||
ErrLibSectionCorrupted = newWithHost(".lib section in a.out corrupted", errno.ELIBSCN, unix.ELIBSCN)
|
||||
ErrTooManySharedLibraries = newWithHost("attempting to link in too many shared libraries", errno.ELIBMAX, unix.ELIBMAX)
|
||||
ErrSharedLibraryExeced = newWithHost("cannot exec a shared library directly", errno.ELIBEXEC, unix.ELIBEXEC)
|
||||
ErrShouldRestart = newWithHost("interrupted system call should be restarted", errno.ERESTART, unix.ERESTART)
|
||||
ErrStreamPipe = newWithHost("streams pipe error", errno.ESTRPIPE, unix.ESTRPIPE)
|
||||
ErrStructureNeedsCleaning = newWithHost("structure needs cleaning", errno.EUCLEAN, unix.EUCLEAN)
|
||||
ErrIsNotNamedFile = newWithHost("not a XENIX named type file", errno.ENOTNAM, unix.ENOTNAM)
|
||||
ErrNotAvailable = newWithHost("no XENIX semaphores available", errno.ENAVAIL, unix.ENAVAIL)
|
||||
ErrIsNamedFile = newWithHost("is a named type file", errno.EISNAM, unix.EISNAM)
|
||||
ErrRemoteIO = newWithHost("remote I/O error", errno.EREMOTEIO, unix.EREMOTEIO)
|
||||
ErrNoMedium = newWithHost("no medium found", errno.ENOMEDIUM, unix.ENOMEDIUM)
|
||||
ErrWrongMediumType = newWithHost("wrong medium type", errno.EMEDIUMTYPE, unix.EMEDIUMTYPE)
|
||||
ErrNoKey = newWithHost("required key not available", errno.ENOKEY, unix.ENOKEY)
|
||||
ErrKeyExpired = newWithHost("key has expired", errno.EKEYEXPIRED, unix.EKEYEXPIRED)
|
||||
ErrKeyRevoked = newWithHost("key has been revoked", errno.EKEYREVOKED, unix.EKEYREVOKED)
|
||||
ErrKeyRejected = newWithHost("key was rejected by service", errno.EKEYREJECTED, unix.EKEYREJECTED)
|
||||
ErrRFKill = newWithHost("operation not possible due to RF-kill", errno.ERFKILL, unix.ERFKILL)
|
||||
ErrHwPoison = newWithHost("memory page has hardware error", errno.EHWPOISON, unix.EHWPOISON)
|
||||
)
|
||||
160
pkg/syserr/netstack.go
Normal file
160
pkg/syserr/netstack.go
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright 2018 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package syserr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/abi/linux/errno"
|
||||
"github.com/sagernet/gvisor/pkg/tcpip"
|
||||
)
|
||||
|
||||
// LINT.IfChange
|
||||
|
||||
// Mapping for tcpip.Error types.
|
||||
var (
|
||||
ErrUnknownProtocol = New((&tcpip.ErrUnknownProtocol{}).String(), errno.EINVAL)
|
||||
ErrUnknownNICID = New((&tcpip.ErrUnknownNICID{}).String(), errno.ENODEV)
|
||||
ErrUnknownDevice = New((&tcpip.ErrUnknownDevice{}).String(), errno.ENODEV)
|
||||
ErrUnknownProtocolOption = New((&tcpip.ErrUnknownProtocolOption{}).String(), errno.ENOPROTOOPT)
|
||||
ErrDuplicateNICID = New((&tcpip.ErrDuplicateNICID{}).String(), errno.EEXIST)
|
||||
ErrDuplicateAddress = New((&tcpip.ErrDuplicateAddress{}).String(), errno.EEXIST)
|
||||
ErrAlreadyBound = New((&tcpip.ErrAlreadyBound{}).String(), errno.EINVAL)
|
||||
ErrInvalidEndpointState = New((&tcpip.ErrInvalidEndpointState{}).String(), errno.EINVAL)
|
||||
ErrAlreadyConnecting = New((&tcpip.ErrAlreadyConnecting{}).String(), errno.EALREADY)
|
||||
ErrNoPortAvailable = New((&tcpip.ErrNoPortAvailable{}).String(), errno.EAGAIN)
|
||||
ErrPortInUse = New((&tcpip.ErrPortInUse{}).String(), errno.EADDRINUSE)
|
||||
ErrBadLocalAddress = New((&tcpip.ErrBadLocalAddress{}).String(), errno.EADDRNOTAVAIL)
|
||||
ErrClosedForSend = New((&tcpip.ErrClosedForSend{}).String(), errno.EPIPE)
|
||||
ErrClosedForReceive = New((&tcpip.ErrClosedForReceive{}).String(), errno.NOERRNO)
|
||||
ErrTimeout = New((&tcpip.ErrTimeout{}).String(), errno.ETIMEDOUT)
|
||||
ErrAborted = New((&tcpip.ErrAborted{}).String(), errno.EPIPE)
|
||||
ErrConnectStarted = New((&tcpip.ErrConnectStarted{}).String(), errno.EINPROGRESS)
|
||||
ErrDestinationRequired = New((&tcpip.ErrDestinationRequired{}).String(), errno.EDESTADDRREQ)
|
||||
ErrNotSupported = New((&tcpip.ErrNotSupported{}).String(), errno.EOPNOTSUPP)
|
||||
ErrQueueSizeNotSupported = New((&tcpip.ErrQueueSizeNotSupported{}).String(), errno.ENOTTY)
|
||||
ErrNoSuchFile = New((&tcpip.ErrNoSuchFile{}).String(), errno.ENOENT)
|
||||
ErrInvalidOptionValue = New((&tcpip.ErrInvalidOptionValue{}).String(), errno.EINVAL)
|
||||
ErrBroadcastDisabled = New((&tcpip.ErrBroadcastDisabled{}).String(), errno.EACCES)
|
||||
ErrNotPermittedNet = New((&tcpip.ErrNotPermitted{}).String(), errno.EPERM)
|
||||
ErrBadBuffer = New((&tcpip.ErrBadBuffer{}).String(), errno.EFAULT)
|
||||
ErrMalformedHeader = New((&tcpip.ErrMalformedHeader{}).String(), errno.EINVAL)
|
||||
ErrInvalidPortRange = New((&tcpip.ErrInvalidPortRange{}).String(), errno.EINVAL)
|
||||
ErrMulticastInputCannotBeOutput = New((&tcpip.ErrMulticastInputCannotBeOutput{}).String(), errno.EINVAL)
|
||||
ErrMissingRequiredFields = New((&tcpip.ErrMissingRequiredFields{}).String(), errno.EINVAL)
|
||||
ErrNoNet = New((&tcpip.ErrNoNet{}).String(), errno.ENONET)
|
||||
ErrEndpointBusy = New((&tcpip.ErrEndpointBusy{}).String(), errno.EBUSY)
|
||||
)
|
||||
|
||||
// TranslateNetstackError converts an error from the tcpip package to a sentry
|
||||
// internal error.
|
||||
func TranslateNetstackError(err tcpip.Error) *Error {
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
return nil
|
||||
case *tcpip.ErrUnknownProtocol:
|
||||
return ErrUnknownProtocol
|
||||
case *tcpip.ErrUnknownNICID:
|
||||
return ErrUnknownNICID
|
||||
case *tcpip.ErrUnknownDevice:
|
||||
return ErrUnknownDevice
|
||||
case *tcpip.ErrUnknownProtocolOption:
|
||||
return ErrUnknownProtocolOption
|
||||
case *tcpip.ErrDuplicateNICID:
|
||||
return ErrDuplicateNICID
|
||||
case *tcpip.ErrDuplicateAddress:
|
||||
return ErrDuplicateAddress
|
||||
case *tcpip.ErrHostUnreachable:
|
||||
return ErrHostUnreachable
|
||||
case *tcpip.ErrHostDown:
|
||||
return ErrHostDown
|
||||
case *tcpip.ErrNoNet:
|
||||
return ErrNoNet
|
||||
case *tcpip.ErrAlreadyBound:
|
||||
return ErrAlreadyBound
|
||||
case *tcpip.ErrInvalidEndpointState:
|
||||
return ErrInvalidEndpointState
|
||||
case *tcpip.ErrAlreadyConnecting:
|
||||
return ErrAlreadyConnecting
|
||||
case *tcpip.ErrAlreadyConnected:
|
||||
return ErrAlreadyConnected
|
||||
case *tcpip.ErrNoPortAvailable:
|
||||
return ErrNoPortAvailable
|
||||
case *tcpip.ErrPortInUse:
|
||||
return ErrPortInUse
|
||||
case *tcpip.ErrBadLocalAddress:
|
||||
return ErrBadLocalAddress
|
||||
case *tcpip.ErrClosedForSend:
|
||||
return ErrClosedForSend
|
||||
case *tcpip.ErrClosedForReceive:
|
||||
return ErrClosedForReceive
|
||||
case *tcpip.ErrWouldBlock:
|
||||
return ErrWouldBlock
|
||||
case *tcpip.ErrConnectionRefused:
|
||||
return ErrConnectionRefused
|
||||
case *tcpip.ErrTimeout:
|
||||
return ErrTimeout
|
||||
case *tcpip.ErrAborted:
|
||||
return ErrAborted
|
||||
case *tcpip.ErrConnectStarted:
|
||||
return ErrConnectStarted
|
||||
case *tcpip.ErrDestinationRequired:
|
||||
return ErrDestinationRequired
|
||||
case *tcpip.ErrNotSupported:
|
||||
return ErrNotSupported
|
||||
case *tcpip.ErrQueueSizeNotSupported:
|
||||
return ErrQueueSizeNotSupported
|
||||
case *tcpip.ErrNotConnected:
|
||||
return ErrNotConnected
|
||||
case *tcpip.ErrConnectionReset:
|
||||
return ErrConnectionReset
|
||||
case *tcpip.ErrConnectionAborted:
|
||||
return ErrConnectionAborted
|
||||
case *tcpip.ErrNoSuchFile:
|
||||
return ErrNoSuchFile
|
||||
case *tcpip.ErrInvalidOptionValue:
|
||||
return ErrInvalidOptionValue
|
||||
case *tcpip.ErrBadAddress:
|
||||
return ErrBadAddress
|
||||
case *tcpip.ErrNetworkUnreachable:
|
||||
return ErrNetworkUnreachable
|
||||
case *tcpip.ErrMessageTooLong:
|
||||
return ErrMessageTooLong
|
||||
case *tcpip.ErrNoBufferSpace:
|
||||
return ErrNoBufferSpace
|
||||
case *tcpip.ErrBroadcastDisabled:
|
||||
return ErrBroadcastDisabled
|
||||
case *tcpip.ErrNotPermitted:
|
||||
return ErrNotPermittedNet
|
||||
case *tcpip.ErrAddressFamilyNotSupported:
|
||||
return ErrAddressFamilyNotSupported
|
||||
case *tcpip.ErrBadBuffer:
|
||||
return ErrBadBuffer
|
||||
case *tcpip.ErrMalformedHeader:
|
||||
return ErrMalformedHeader
|
||||
case *tcpip.ErrInvalidPortRange:
|
||||
return ErrInvalidPortRange
|
||||
case *tcpip.ErrMulticastInputCannotBeOutput:
|
||||
return ErrMulticastInputCannotBeOutput
|
||||
case *tcpip.ErrMissingRequiredFields:
|
||||
return ErrMissingRequiredFields
|
||||
case *tcpip.ErrEndpointBusy:
|
||||
return ErrEndpointBusy
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown error %T", err))
|
||||
}
|
||||
}
|
||||
|
||||
// LINT.ThenChange(../tcpip/errors.go)
|
||||
282
pkg/syserr/syserr.go
Normal file
282
pkg/syserr/syserr.go
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
// Copyright 2018 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package syserr contains sandbox-internal errors. These errors are distinct
|
||||
// from both the errors returned by host system calls and the errors returned
|
||||
// to sandboxed applications.
|
||||
package syserr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/abi/linux/errno"
|
||||
"github.com/sagernet/gvisor/pkg/errors"
|
||||
"github.com/sagernet/gvisor/pkg/errors/linuxerr"
|
||||
"github.com/sagernet/gvisor/pkg/safecopy"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Error represents an internal error.
|
||||
type Error struct {
|
||||
// message is the human readable form of this Error.
|
||||
message string
|
||||
|
||||
// noTranslation indicates that this Error cannot be translated to a
|
||||
// errno.Errno.
|
||||
noTranslation bool
|
||||
|
||||
// errno is the errno.Errno this Error should be translated to.
|
||||
errno errno.Errno
|
||||
}
|
||||
|
||||
// New creates a new Error and adds a translation for it.
|
||||
//
|
||||
// New must only be called at init.
|
||||
func New(message string, linuxTranslation errno.Errno) *Error {
|
||||
err := &Error{message: message, errno: linuxTranslation}
|
||||
|
||||
// TODO(b/34162363): Remove this.
|
||||
if int(err.errno) >= len(linuxBackwardsTranslations) {
|
||||
panic(fmt.Sprint("invalid errno: ", err.errno))
|
||||
}
|
||||
|
||||
e := error(unix.Errno(err.errno))
|
||||
// linuxerr.ErrWouldBlock gets translated to linuxerr.EWOULDBLOCK and
|
||||
// enables proper blocking semantics. This should temporary address the
|
||||
// class of blocking bugs that keep popping up with the current state of
|
||||
// the error space.
|
||||
if err.errno == linuxerr.EWOULDBLOCK.Errno() {
|
||||
e = linuxerr.ErrWouldBlock
|
||||
}
|
||||
linuxBackwardsTranslations[err.errno] = linuxBackwardsTranslation{err: e, ok: true}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// NewDynamic creates a new error with a dynamic error message and an errno
|
||||
// translation.
|
||||
//
|
||||
// NewDynamic should only be used sparingly and not be used for static error
|
||||
// messages. Errors with static error messages should be declared with New as
|
||||
// global variables.
|
||||
func NewDynamic(message string, linuxTranslation errno.Errno) *Error {
|
||||
return &Error{message: message, errno: linuxTranslation}
|
||||
}
|
||||
|
||||
func newWithHost(message string, linuxTranslation errno.Errno, hostErrno unix.Errno) *Error {
|
||||
e := New(message, linuxTranslation)
|
||||
addHostTranslation(hostErrno, e)
|
||||
return e
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.String.
|
||||
func (e *Error) String() string {
|
||||
if e == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
return e.message
|
||||
}
|
||||
|
||||
type linuxBackwardsTranslation struct {
|
||||
err error
|
||||
ok bool
|
||||
}
|
||||
|
||||
// TODO(b/34162363): Remove this.
|
||||
var linuxBackwardsTranslations [maxErrno]linuxBackwardsTranslation
|
||||
|
||||
// ToError translates an Error to a corresponding error value.
|
||||
//
|
||||
// TODO(b/34162363): Remove this.
|
||||
func (e *Error) ToError() error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
if e.noTranslation {
|
||||
panic(fmt.Sprintf("error %q does not support translation", e.message))
|
||||
}
|
||||
err := int(e.errno)
|
||||
if err == errno.NOERRNO {
|
||||
return nil
|
||||
}
|
||||
if err >= len(linuxBackwardsTranslations) || !linuxBackwardsTranslations[err].ok {
|
||||
panic(fmt.Sprintf("unknown error %q (%d)", e.message, err))
|
||||
}
|
||||
return linuxBackwardsTranslations[err].err
|
||||
}
|
||||
|
||||
// ToLinux converts the Error to a Linux ABI error that can be returned to the
|
||||
// application.
|
||||
func (e *Error) ToLinux() errno.Errno {
|
||||
if e.noTranslation {
|
||||
panic(fmt.Sprintf("No Linux ABI translation available for %q", e.message))
|
||||
}
|
||||
return e.errno
|
||||
}
|
||||
|
||||
// AnnotatedError represents an error with an additional message.
|
||||
type AnnotatedError struct {
|
||||
error *Error
|
||||
message string
|
||||
}
|
||||
|
||||
// Error implements Error() for the error interface
|
||||
func (e *AnnotatedError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.error.String(), e.message)
|
||||
}
|
||||
|
||||
// NewAnnotatedError creates a new AnnotatedError with the given error and message.
|
||||
func NewAnnotatedError(error *Error, message string) *AnnotatedError {
|
||||
return &AnnotatedError{error: error, message: message}
|
||||
}
|
||||
|
||||
// GetError returns the underlying error.
|
||||
func (e *AnnotatedError) GetError() *Error {
|
||||
return e.error
|
||||
}
|
||||
|
||||
// TODO(b/34162363): Remove or replace most of these errors.
|
||||
//
|
||||
// Some of the errors should be replaced with package specific errors and
|
||||
// others should be removed entirely.
|
||||
//
|
||||
// Note that some errors are declared in platform-specific files.
|
||||
var (
|
||||
ErrNotPermitted = newWithHost("operation not permitted", errno.EPERM, unix.EPERM)
|
||||
ErrNoFileOrDir = newWithHost("no such file or directory", errno.ENOENT, unix.ENOENT)
|
||||
ErrNoProcess = newWithHost("no such process", errno.ESRCH, unix.ESRCH)
|
||||
ErrInterrupted = newWithHost("interrupted system call", errno.EINTR, unix.EINTR)
|
||||
ErrIO = newWithHost("I/O error", errno.EIO, unix.EIO)
|
||||
ErrDeviceOrAddress = newWithHost("no such device or address", errno.ENXIO, unix.ENXIO)
|
||||
ErrTooManyArgs = newWithHost("argument list too long", errno.E2BIG, unix.E2BIG)
|
||||
ErrEcec = newWithHost("exec format error", errno.ENOEXEC, unix.ENOEXEC)
|
||||
ErrBadFD = newWithHost("bad file number", errno.EBADF, unix.EBADF)
|
||||
ErrNoChild = newWithHost("no child processes", errno.ECHILD, unix.ECHILD)
|
||||
ErrTryAgain = newWithHost("try again", errno.EAGAIN, unix.EAGAIN)
|
||||
ErrNoMemory = newWithHost("out of memory", errno.ENOMEM, unix.ENOMEM)
|
||||
ErrPermissionDenied = newWithHost("permission denied", errno.EACCES, unix.EACCES)
|
||||
ErrBadAddress = newWithHost("bad address", errno.EFAULT, unix.EFAULT)
|
||||
ErrNotBlockDevice = newWithHost("block device required", errno.ENOTBLK, unix.ENOTBLK)
|
||||
ErrBusy = newWithHost("device or resource busy", errno.EBUSY, unix.EBUSY)
|
||||
ErrExists = newWithHost("file exists", errno.EEXIST, unix.EEXIST)
|
||||
ErrCrossDeviceLink = newWithHost("cross-device link", errno.EXDEV, unix.EXDEV)
|
||||
ErrNoDevice = newWithHost("no such device", errno.ENODEV, unix.ENODEV)
|
||||
ErrNotDir = newWithHost("not a directory", errno.ENOTDIR, unix.ENOTDIR)
|
||||
ErrIsDir = newWithHost("is a directory", errno.EISDIR, unix.EISDIR)
|
||||
ErrInvalidArgument = newWithHost("invalid argument", errno.EINVAL, unix.EINVAL)
|
||||
ErrFileTableOverflow = newWithHost("file table overflow", errno.ENFILE, unix.ENFILE)
|
||||
ErrTooManyOpenFiles = newWithHost("too many open files", errno.EMFILE, unix.EMFILE)
|
||||
ErrNotTTY = newWithHost("not a typewriter", errno.ENOTTY, unix.ENOTTY)
|
||||
ErrTestFileBusy = newWithHost("text file busy", errno.ETXTBSY, unix.ETXTBSY)
|
||||
ErrFileTooBig = newWithHost("file too large", errno.EFBIG, unix.EFBIG)
|
||||
ErrNoSpace = newWithHost("no space left on device", errno.ENOSPC, unix.ENOSPC)
|
||||
ErrIllegalSeek = newWithHost("illegal seek", errno.ESPIPE, unix.ESPIPE)
|
||||
ErrReadOnlyFS = newWithHost("read-only file system", errno.EROFS, unix.EROFS)
|
||||
ErrTooManyLinks = newWithHost("too many links", errno.EMLINK, unix.EMLINK)
|
||||
ErrBrokenPipe = newWithHost("broken pipe", errno.EPIPE, unix.EPIPE)
|
||||
ErrDomain = newWithHost("math argument out of domain of func", errno.EDOM, unix.EDOM)
|
||||
ErrRange = newWithHost("math result not representable", errno.ERANGE, unix.ERANGE)
|
||||
ErrNameTooLong = newWithHost("file name too long", errno.ENAMETOOLONG, unix.ENAMETOOLONG)
|
||||
ErrNoLocksAvailable = newWithHost("no record locks available", errno.ENOLCK, unix.ENOLCK)
|
||||
ErrInvalidSyscall = newWithHost("invalid system call number", errno.ENOSYS, unix.ENOSYS)
|
||||
ErrDirNotEmpty = newWithHost("directory not empty", errno.ENOTEMPTY, unix.ENOTEMPTY)
|
||||
ErrLinkLoop = newWithHost("too many symbolic links encountered", errno.ELOOP, unix.ELOOP)
|
||||
ErrNoMessage = newWithHost("no message of desired type", errno.ENOMSG, unix.ENOMSG)
|
||||
ErrIdentifierRemoved = newWithHost("identifier removed", errno.EIDRM, unix.EIDRM)
|
||||
ErrNotStream = newWithHost("device not a stream", errno.ENOSTR, unix.ENOSTR)
|
||||
ErrNoDataAvailable = newWithHost("no data available", errno.ENODATA, unix.ENODATA)
|
||||
ErrTimerExpired = newWithHost("timer expired", errno.ETIME, unix.ETIME)
|
||||
ErrStreamsResourceDepleted = newWithHost("out of streams resources", errno.ENOSR, unix.ENOSR)
|
||||
ErrIsRemote = newWithHost("object is remote", errno.EREMOTE, unix.EREMOTE)
|
||||
ErrNoLink = newWithHost("link has been severed", errno.ENOLINK, unix.ENOLINK)
|
||||
ErrProtocol = newWithHost("protocol error", errno.EPROTO, unix.EPROTO)
|
||||
ErrMultihopAttempted = newWithHost("multihop attempted", errno.EMULTIHOP, unix.EMULTIHOP)
|
||||
ErrInvalidDataMessage = newWithHost("not a data message", errno.EBADMSG, unix.EBADMSG)
|
||||
ErrOverflow = newWithHost("value too large for defined data type", errno.EOVERFLOW, unix.EOVERFLOW)
|
||||
ErrIllegalByteSequence = newWithHost("illegal byte sequence", errno.EILSEQ, unix.EILSEQ)
|
||||
ErrTooManyUsers = newWithHost("too many users", errno.EUSERS, unix.EUSERS)
|
||||
ErrNotASocket = newWithHost("socket operation on non-socket", errno.ENOTSOCK, unix.ENOTSOCK)
|
||||
ErrDestinationAddressRequired = newWithHost("destination address required", errno.EDESTADDRREQ, unix.EDESTADDRREQ)
|
||||
ErrMessageTooLong = newWithHost("message too long", errno.EMSGSIZE, unix.EMSGSIZE)
|
||||
ErrWrongProtocolForSocket = newWithHost("protocol wrong type for socket", errno.EPROTOTYPE, unix.EPROTOTYPE)
|
||||
ErrProtocolNotAvailable = newWithHost("protocol not available", errno.ENOPROTOOPT, unix.ENOPROTOOPT)
|
||||
ErrProtocolNotSupported = newWithHost("protocol not supported", errno.EPROTONOSUPPORT, unix.EPROTONOSUPPORT)
|
||||
ErrSocketNotSupported = newWithHost("socket type not supported", errno.ESOCKTNOSUPPORT, unix.ESOCKTNOSUPPORT)
|
||||
ErrEndpointOperation = newWithHost("operation not supported on transport endpoint", errno.EOPNOTSUPP, unix.EOPNOTSUPP)
|
||||
ErrProtocolFamilyNotSupported = newWithHost("protocol family not supported", errno.EPFNOSUPPORT, unix.EPFNOSUPPORT)
|
||||
ErrAddressFamilyNotSupported = newWithHost("address family not supported by protocol", errno.EAFNOSUPPORT, unix.EAFNOSUPPORT)
|
||||
ErrAddressInUse = newWithHost("address already in use", errno.EADDRINUSE, unix.EADDRINUSE)
|
||||
ErrAddressNotAvailable = newWithHost("cannot assign requested address", errno.EADDRNOTAVAIL, unix.EADDRNOTAVAIL)
|
||||
ErrNetworkDown = newWithHost("network is down", errno.ENETDOWN, unix.ENETDOWN)
|
||||
ErrNetworkUnreachable = newWithHost("network is unreachable", errno.ENETUNREACH, unix.ENETUNREACH)
|
||||
ErrNetworkReset = newWithHost("network dropped connection because of reset", errno.ENETRESET, unix.ENETRESET)
|
||||
ErrConnectionAborted = newWithHost("software caused connection abort", errno.ECONNABORTED, unix.ECONNABORTED)
|
||||
ErrConnectionReset = newWithHost("connection reset by peer", errno.ECONNRESET, unix.ECONNRESET)
|
||||
ErrNoBufferSpace = newWithHost("no buffer space available", errno.ENOBUFS, unix.ENOBUFS)
|
||||
ErrAlreadyConnected = newWithHost("transport endpoint is already connected", errno.EISCONN, unix.EISCONN)
|
||||
ErrNotConnected = newWithHost("transport endpoint is not connected", errno.ENOTCONN, unix.ENOTCONN)
|
||||
ErrShutdown = newWithHost("cannot send after transport endpoint shutdown", errno.ESHUTDOWN, unix.ESHUTDOWN)
|
||||
ErrTooManyRefs = newWithHost("too many references: cannot splice", errno.ETOOMANYREFS, unix.ETOOMANYREFS)
|
||||
ErrTimedOut = newWithHost("connection timed out", errno.ETIMEDOUT, unix.ETIMEDOUT)
|
||||
ErrConnectionRefused = newWithHost("connection refused", errno.ECONNREFUSED, unix.ECONNREFUSED)
|
||||
ErrHostDown = newWithHost("host is down", errno.EHOSTDOWN, unix.EHOSTDOWN)
|
||||
ErrHostUnreachable = newWithHost("no route to host", errno.EHOSTUNREACH, unix.EHOSTUNREACH)
|
||||
ErrAlreadyInProgress = newWithHost("operation already in progress", errno.EALREADY, unix.EALREADY)
|
||||
ErrInProgress = newWithHost("operation now in progress", errno.EINPROGRESS, unix.EINPROGRESS)
|
||||
ErrStaleFileHandle = newWithHost("stale file handle", errno.ESTALE, unix.ESTALE)
|
||||
ErrQuotaExceeded = newWithHost("quota exceeded", errno.EDQUOT, unix.EDQUOT)
|
||||
ErrCanceled = newWithHost("operation canceled", errno.ECANCELED, unix.ECANCELED)
|
||||
ErrOwnerDied = newWithHost("owner died", errno.EOWNERDEAD, unix.EOWNERDEAD)
|
||||
ErrNotRecoverable = newWithHost("state not recoverable", errno.ENOTRECOVERABLE, unix.ENOTRECOVERABLE)
|
||||
|
||||
// ErrWouldBlock translates to EWOULDBLOCK which is the same as EAGAIN
|
||||
// on Linux.
|
||||
ErrWouldBlock = New("operation would block", errno.EWOULDBLOCK)
|
||||
)
|
||||
|
||||
// FromHost translates a unix.Errno to a corresponding Error value.
|
||||
func FromHost(err unix.Errno) *Error {
|
||||
got := getHostTranslation(err)
|
||||
if got == nil {
|
||||
panic(fmt.Sprintf("unknown host errno %q (%d)", err.Error(), err))
|
||||
}
|
||||
return got
|
||||
}
|
||||
|
||||
// IsValid checks if the given errno is a valid errno which can be translated
|
||||
// to an Error.
|
||||
func IsValid(err unix.Errno) bool {
|
||||
return getHostTranslation(err) != nil
|
||||
}
|
||||
|
||||
// FromError converts a generic error to an *Error.
|
||||
//
|
||||
// TODO(b/34162363): Remove this function.
|
||||
func FromError(err error) *Error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch e := err.(type) {
|
||||
case unix.Errno:
|
||||
return FromHost(e)
|
||||
case *errors.Error:
|
||||
return FromHost(unix.Errno(e.Errno()))
|
||||
case safecopy.SegvError, safecopy.BusError, safecopy.AlignmentError:
|
||||
return FromHost(unix.EFAULT)
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("err: %s type: %T", err.Error(), err)
|
||||
panic(msg)
|
||||
}
|
||||
6
pkg/syserr/syserr_linux_state_autogen.go
Normal file
6
pkg/syserr/syserr_linux_state_autogen.go
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// automatically generated by stateify.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package syserr
|
||||
6
pkg/syserr/syserr_state_autogen.go
Normal file
6
pkg/syserr/syserr_state_autogen.go
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
// automatically generated by stateify.
|
||||
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package syserr
|
||||
Loading…
Add table
Add a link
Reference in a new issue