Merge pull request #422 from xushiwei/q

patch os, syscall, io/fs: Errno, Stdin/out/err
This commit is contained in:
xushiwei
2024-06-25 16:14:25 +08:00
committed by GitHub
9 changed files with 540 additions and 37 deletions

View File

@@ -19,6 +19,16 @@ package fs
// llgo:skipall
import (
_ "unsafe"
"github.com/goplus/llgo/internal/lib/syscall"
)
var (
ErrInvalid = syscall.ErrInvalid
ErrPermission = syscall.ErrPermission
ErrExist = syscall.ErrExist
ErrNotExist = syscall.ErrNotExist
ErrClosed = syscall.ErrClosed
)
// -----------------------------------------------------------------------------

144
internal/lib/os/error.go Normal file
View 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
}

View File

@@ -4,10 +4,13 @@
package os
import (
"syscall"
)
// Name returns the name of the file as presented to Open.
func (f *File) Name() string { return f.name }
/*
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
//
@@ -44,6 +47,7 @@ const (
SEEK_END int = 2 // seek relative to the end
)
/*
// Read reads up to len(b) bytes from the File and stores them in b.
// It returns the number of bytes read and any error encountered.
// At end of file, Read returns 0, io.EOF.

View File

@@ -19,7 +19,6 @@ package os
// llgo:skipall
import (
"errors"
"io/fs"
"runtime"
_ "unsafe"
@@ -31,38 +30,6 @@ const (
LLGoPackage = true
)
type timeout interface {
Timeout() bool
}
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}
}
// LinkError records an error during a link or symlink or rename
// system call and the paths that caused it.
type LinkError struct {

View File

@@ -7,8 +7,6 @@ package os
import (
"io/fs"
"syscall"
"github.com/goplus/llgo/c"
)
// Getpagesize returns the underlying system's memory page size.
@@ -16,10 +14,32 @@ func Getpagesize() int { return syscall.Getpagesize() }
// File represents an open file descriptor.
type File struct {
fd c.Int
fd uintptr
name string
}
// NewFile returns a new File with the given file descriptor and
// name. The returned value will be nil if fd is not a valid file
// descriptor. On Unix systems, if the file descriptor is in
// non-blocking mode, NewFile will attempt to return a pollable File
// (one for which the SetDeadline methods work).
//
// After passing it to NewFile, fd may become invalid under the same
// conditions described in the comments of the Fd method, and the same
// constraints apply.
func NewFile(fd uintptr, name string) *File {
return &File{fd, name}
}
// checkValid checks whether f is valid for use.
// If not, it returns an appropriate error, perhaps incorporating the operation name op.
func (f *File) checkValid(op string) error {
if f == nil {
return ErrInvalid
}
return nil
}
// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo = fs.FileInfo

View File

@@ -0,0 +1,16 @@
// 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 syscall
import "errors"
// from internal/oserror
var (
ErrInvalid = errors.New("invalid argument")
ErrPermission = errors.New("permission denied")
ErrExist = errors.New("file already exists")
ErrNotExist = errors.New("file does not exist")
ErrClosed = errors.New("file already closed")
)

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* 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 syscall
import (
"unsafe"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/internal/lib/errors"
)
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
type Errno uintptr
func (e Errno) Error() string {
ret := c.Strerror(c.Int(e))
return unsafe.String((*byte)(unsafe.Pointer(ret)), c.Strlen(ret))
}
func (e Errno) Is(target error) bool {
switch target {
case ErrPermission:
return e == EACCES || e == EPERM
case ErrExist:
return e == EEXIST || e == ENOTEMPTY
case ErrNotExist:
return e == ENOENT
case errors.ErrUnsupported:
return e == ENOSYS || e == ENOTSUP || e == EOPNOTSUPP
}
return false
}
func (e Errno) Temporary() bool {
return e == EINTR || e == EMFILE || e == ENFILE || e.Timeout()
}
func (e Errno) Timeout() bool {
return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* 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 syscall
// Errors
const (
E2BIG = Errno(0x7)
EACCES = Errno(0xd)
EADDRINUSE = Errno(0x30)
EADDRNOTAVAIL = Errno(0x31)
EAFNOSUPPORT = Errno(0x2f)
EAGAIN = Errno(0x23)
EALREADY = Errno(0x25)
EAUTH = Errno(0x50)
EBADARCH = Errno(0x56)
EBADEXEC = Errno(0x55)
EBADF = Errno(0x9)
EBADMACHO = Errno(0x58)
EBADMSG = Errno(0x5e)
EBADRPC = Errno(0x48)
EBUSY = Errno(0x10)
ECANCELED = Errno(0x59)
ECHILD = Errno(0xa)
ECONNABORTED = Errno(0x35)
ECONNREFUSED = Errno(0x3d)
ECONNRESET = Errno(0x36)
EDEADLK = Errno(0xb)
EDESTADDRREQ = Errno(0x27)
EDEVERR = Errno(0x53)
EDOM = Errno(0x21)
EDQUOT = Errno(0x45)
EEXIST = Errno(0x11)
EFAULT = Errno(0xe)
EFBIG = Errno(0x1b)
EFTYPE = Errno(0x4f)
EHOSTDOWN = Errno(0x40)
EHOSTUNREACH = Errno(0x41)
EIDRM = Errno(0x5a)
EILSEQ = Errno(0x5c)
EINPROGRESS = Errno(0x24)
EINTR = Errno(0x4)
EINVAL = Errno(0x16)
EIO = Errno(0x5)
EISCONN = Errno(0x38)
EISDIR = Errno(0x15)
ELAST = Errno(0x6a)
ELOOP = Errno(0x3e)
EMFILE = Errno(0x18)
EMLINK = Errno(0x1f)
EMSGSIZE = Errno(0x28)
EMULTIHOP = Errno(0x5f)
ENAMETOOLONG = Errno(0x3f)
ENEEDAUTH = Errno(0x51)
ENETDOWN = Errno(0x32)
ENETRESET = Errno(0x34)
ENETUNREACH = Errno(0x33)
ENFILE = Errno(0x17)
ENOATTR = Errno(0x5d)
ENOBUFS = Errno(0x37)
ENODATA = Errno(0x60)
ENODEV = Errno(0x13)
ENOENT = Errno(0x2)
ENOEXEC = Errno(0x8)
ENOLCK = Errno(0x4d)
ENOLINK = Errno(0x61)
ENOMEM = Errno(0xc)
ENOMSG = Errno(0x5b)
ENOPOLICY = Errno(0x67)
ENOPROTOOPT = Errno(0x2a)
ENOSPC = Errno(0x1c)
ENOSR = Errno(0x62)
ENOSTR = Errno(0x63)
ENOSYS = Errno(0x4e)
ENOTBLK = Errno(0xf)
ENOTCONN = Errno(0x39)
ENOTDIR = Errno(0x14)
ENOTEMPTY = Errno(0x42)
ENOTRECOVERABLE = Errno(0x68)
ENOTSOCK = Errno(0x26)
ENOTSUP = Errno(0x2d)
ENOTTY = Errno(0x19)
ENXIO = Errno(0x6)
EOPNOTSUPP = Errno(0x66)
EOVERFLOW = Errno(0x54)
EOWNERDEAD = Errno(0x69)
EPERM = Errno(0x1)
EPFNOSUPPORT = Errno(0x2e)
EPIPE = Errno(0x20)
EPROCLIM = Errno(0x43)
EPROCUNAVAIL = Errno(0x4c)
EPROGMISMATCH = Errno(0x4b)
EPROGUNAVAIL = Errno(0x4a)
EPROTO = Errno(0x64)
EPROTONOSUPPORT = Errno(0x2b)
EPROTOTYPE = Errno(0x29)
EPWROFF = Errno(0x52)
EQFULL = Errno(0x6a)
ERANGE = Errno(0x22)
EREMOTE = Errno(0x47)
EROFS = Errno(0x1e)
ERPCMISMATCH = Errno(0x49)
ESHLIBVERS = Errno(0x57)
ESHUTDOWN = Errno(0x3a)
ESOCKTNOSUPPORT = Errno(0x2c)
ESPIPE = Errno(0x1d)
ESRCH = Errno(0x3)
ESTALE = Errno(0x46)
ETIME = Errno(0x65)
ETIMEDOUT = Errno(0x3c)
ETOOMANYREFS = Errno(0x3b)
ETXTBSY = Errno(0x1a)
EUSERS = Errno(0x44)
EWOULDBLOCK = Errno(0x23)
EXDEV = Errno(0x12)
)

View File

@@ -0,0 +1,154 @@
/*
* Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
*
* 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 syscall
// Errors
const (
E2BIG = Errno(0x7)
EACCES = Errno(0xd)
EADDRINUSE = Errno(0x62)
EADDRNOTAVAIL = Errno(0x63)
EADV = Errno(0x44)
EAFNOSUPPORT = Errno(0x61)
EAGAIN = Errno(0xb)
EALREADY = Errno(0x72)
EBADE = Errno(0x34)
EBADF = Errno(0x9)
EBADFD = Errno(0x4d)
EBADMSG = Errno(0x4a)
EBADR = Errno(0x35)
EBADRQC = Errno(0x38)
EBADSLT = Errno(0x39)
EBFONT = Errno(0x3b)
EBUSY = Errno(0x10)
ECANCELED = Errno(0x7d)
ECHILD = Errno(0xa)
ECHRNG = Errno(0x2c)
ECOMM = Errno(0x46)
ECONNABORTED = Errno(0x67)
ECONNREFUSED = Errno(0x6f)
ECONNRESET = Errno(0x68)
EDEADLK = Errno(0x23)
EDEADLOCK = Errno(0x23)
EDESTADDRREQ = Errno(0x59)
EDOM = Errno(0x21)
EDOTDOT = Errno(0x49)
EDQUOT = Errno(0x7a)
EEXIST = Errno(0x11)
EFAULT = Errno(0xe)
EFBIG = Errno(0x1b)
EHOSTDOWN = Errno(0x70)
EHOSTUNREACH = Errno(0x71)
EIDRM = Errno(0x2b)
EILSEQ = Errno(0x54)
EINPROGRESS = Errno(0x73)
EINTR = Errno(0x4)
EINVAL = Errno(0x16)
EIO = Errno(0x5)
EISCONN = Errno(0x6a)
EISDIR = Errno(0x15)
EISNAM = Errno(0x78)
EKEYEXPIRED = Errno(0x7f)
EKEYREJECTED = Errno(0x81)
EKEYREVOKED = Errno(0x80)
EL2HLT = Errno(0x33)
EL2NSYNC = Errno(0x2d)
EL3HLT = Errno(0x2e)
EL3RST = Errno(0x2f)
ELIBACC = Errno(0x4f)
ELIBBAD = Errno(0x50)
ELIBEXEC = Errno(0x53)
ELIBMAX = Errno(0x52)
ELIBSCN = Errno(0x51)
ELNRNG = Errno(0x30)
ELOOP = Errno(0x28)
EMEDIUMTYPE = Errno(0x7c)
EMFILE = Errno(0x18)
EMLINK = Errno(0x1f)
EMSGSIZE = Errno(0x5a)
EMULTIHOP = Errno(0x48)
ENAMETOOLONG = Errno(0x24)
ENAVAIL = Errno(0x77)
ENETDOWN = Errno(0x64)
ENETRESET = Errno(0x66)
ENETUNREACH = Errno(0x65)
ENFILE = Errno(0x17)
ENOANO = Errno(0x37)
ENOBUFS = Errno(0x69)
ENOCSI = Errno(0x32)
ENODATA = Errno(0x3d)
ENODEV = Errno(0x13)
ENOENT = Errno(0x2)
ENOEXEC = Errno(0x8)
ENOKEY = Errno(0x7e)
ENOLCK = Errno(0x25)
ENOLINK = Errno(0x43)
ENOMEDIUM = Errno(0x7b)
ENOMEM = Errno(0xc)
ENOMSG = Errno(0x2a)
ENONET = Errno(0x40)
ENOPKG = Errno(0x41)
ENOPROTOOPT = Errno(0x5c)
ENOSPC = Errno(0x1c)
ENOSR = Errno(0x3f)
ENOSTR = Errno(0x3c)
ENOSYS = Errno(0x26)
ENOTBLK = Errno(0xf)
ENOTCONN = Errno(0x6b)
ENOTDIR = Errno(0x14)
ENOTEMPTY = Errno(0x27)
ENOTNAM = Errno(0x76)
ENOTRECOVERABLE = Errno(0x83)
ENOTSOCK = Errno(0x58)
ENOTSUP = Errno(0x5f)
ENOTTY = Errno(0x19)
ENOTUNIQ = Errno(0x4c)
ENXIO = Errno(0x6)
EOPNOTSUPP = Errno(0x5f)
EOVERFLOW = Errno(0x4b)
EOWNERDEAD = Errno(0x82)
EPERM = Errno(0x1)
EPFNOSUPPORT = Errno(0x60)
EPIPE = Errno(0x20)
EPROTO = Errno(0x47)
EPROTONOSUPPORT = Errno(0x5d)
EPROTOTYPE = Errno(0x5b)
ERANGE = Errno(0x22)
EREMCHG = Errno(0x4e)
EREMOTE = Errno(0x42)
EREMOTEIO = Errno(0x79)
ERESTART = Errno(0x55)
ERFKILL = Errno(0x84)
EROFS = Errno(0x1e)
ESHUTDOWN = Errno(0x6c)
ESOCKTNOSUPPORT = Errno(0x5e)
ESPIPE = Errno(0x1d)
ESRCH = Errno(0x3)
ESRMNT = Errno(0x45)
ESTALE = Errno(0x74)
ESTRPIPE = Errno(0x56)
ETIME = Errno(0x3e)
ETIMEDOUT = Errno(0x6e)
ETOOMANYREFS = Errno(0x6d)
ETXTBSY = Errno(0x1a)
EUCLEAN = Errno(0x75)
EUNATCH = Errno(0x31)
EUSERS = Errno(0x57)
EWOULDBLOCK = Errno(0xb)
EXDEV = Errno(0x12)
EXFULL = Errno(0x36)
)