darwin: replace custom syscall package with Go native syscall package

This required a few compiler and runtime tricks to work, but I ran a
bunch of tests and it seems fine. (CI will of course do more exhaustive
testing).

The main benefit here is that we don't need to maintain the darwin
version of the syscall package, and reduce extra risks for bugs (because
we reuse the well-tested syscall package). For example, Go 1.23 needed a
bunch of new constants in the syscall package. That would have been
avoided if we had used the native syscall package on MacOS.
This commit is contained in:
Ayke van Laethem
2024-08-18 19:33:04 +02:00
committed by Ron Evans
parent 753f4b38b4
commit 105fe9b25d
19 changed files with 229 additions and 531 deletions
+1
View File
@@ -389,6 +389,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) {
"-platform_version", "macos", platformVersion, platformVersion,
)
spec.ExtraFiles = append(spec.ExtraFiles,
"src/runtime/os_darwin.c",
"src/runtime/runtime_unix.c")
case "linux":
spec.Linker = "ld.lld"
+8 -1
View File
@@ -1847,7 +1847,9 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
case strings.HasPrefix(name, "(device/riscv.CSR)."):
return b.emitCSROperation(instr)
case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall"):
return b.createSyscall(instr)
if b.GOOS != "darwin" {
return b.createSyscall(instr)
}
case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"):
return b.createRawSyscallNoError(instr)
case name == "runtime.supportsRecover":
@@ -1865,6 +1867,11 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil
case name == "runtime/interrupt.New":
return b.createInterruptGlobal(instr)
case name == "internal/abi.FuncPCABI0":
retval := b.createDarwinFuncPCABI0Call(instr)
if !retval.IsNil() {
return retval, nil
}
}
calleeType, callee = b.getFunction(fn)
+62
View File
@@ -5,6 +5,7 @@ package compiler
import (
"strconv"
"strings"
"golang.org/x/tools/go/ssa"
"tinygo.org/x/go-llvm"
@@ -329,3 +330,64 @@ func (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, err
retval = b.CreateInsertValue(retval, llvm.ConstInt(b.uintptrType, 0, false), 1, "")
return retval, nil
}
// Lower a call to internal/abi.FuncPCABI0 on MacOS.
// This function is called like this:
//
// syscall(abi.FuncPCABI0(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
//
// So we'll want to return a function pointer (as uintptr) that points to the
// libc function. Specifically, we _don't_ want to point to the trampoline
// function (which is implemented in Go assembly which we can't read), but
// rather to the actually intended function. For this we're going to assume that
// all the functions follow a specific pattern: libc_<functionname>_trampoline.
//
// The return value is the function pointer as an uintptr, or a nil value if
// this isn't possible (and a regular call should be made as fallback).
func (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value {
if b.GOOS != "darwin" {
// This has only been tested on MacOS (and only seems to be used there).
return llvm.Value{}
}
// Check that it uses a function call like syscall.libc_*_trampoline
itf := instr.Args[0].(*ssa.MakeInterface)
calledFn := itf.X.(*ssa.Function)
if pkgName := calledFn.Pkg.Pkg.Path(); pkgName != "syscall" && pkgName != "internal/syscall/unix" {
return llvm.Value{}
}
if !strings.HasPrefix(calledFn.Name(), "libc_") || !strings.HasSuffix(calledFn.Name(), "_trampoline") {
return llvm.Value{}
}
// Extract the libc function name.
name := strings.TrimPrefix(strings.TrimSuffix(calledFn.Name(), "_trampoline"), "libc_")
if name == "open" {
// Special case: open() is a variadic function and can't be called like
// a regular function. Therefore, we need to use a wrapper implemented
// in C.
name = "syscall_libc_open"
}
if b.GOARCH == "amd64" {
if name == "fdopendir" || name == "readdir_r" {
// Hack to support amd64, which needs the $INODE64 suffix.
// This is also done in upstream Go:
// https://github.com/golang/go/commit/096ab3c21b88ccc7d411379d09fe6274e3159467
name += "$INODE64"
}
}
// Obtain the C function.
// Use a simple function (no parameters or return value) because all we need
// is the address of the function.
llvmFn := b.mod.NamedFunction(name)
if llvmFn.IsNil() {
llvmFnType := llvm.FunctionType(b.ctx.VoidType(), nil, false)
llvmFn = llvm.AddFunction(b.mod, name, llvmFnType)
}
// Cast the function pointer to a uintptr (because that's what
// abi.FuncPCABI0 returns).
return b.CreatePtrToInt(llvmFn, b.uintptrType, "")
}
+1 -1
View File
@@ -218,7 +218,7 @@ func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool)
// with the TinyGo version. This is the case on some targets.
func needsSyscallPackage(buildTags []string) bool {
for _, tag := range buildTags {
if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" || tag == "tinygo.wasm" {
if tag == "baremetal" || tag == "nintendoswitch" || tag == "tinygo.wasm" {
return true
}
}
+4 -6
View File
@@ -4,11 +4,9 @@ package abi
// (in particular internal/syscall/unix on MacOS). They do not currently have an
// implementation, in part because TinyGo doesn't use ABI0 or ABIInternal (it
// uses a C-like calling convention).
// Calls to FuncPCABI0 however are treated specially by the compiler when
// compiling for MacOS.
func FuncPCABI0(f interface{}) uintptr {
panic("unimplemented: internal/abi.FuncPCABI0")
}
func FuncPCABI0(f interface{}) uintptr
func FuncPCABIInternal(f interface{}) uintptr {
panic("unimplemented: internal/abi.FuncPCABIInternal")
}
func FuncPCABIInternal(f interface{}) uintptr
+4 -1
View File
@@ -135,7 +135,7 @@ func darwinOpenDir(fd syscallFd) (uintptr, string, error) {
}
var dir uintptr
for {
dir, err = syscall.Fdopendir(fd2)
dir, err = fdopendir(fd2)
if err != syscall.EINTR {
break
}
@@ -149,6 +149,9 @@ func darwinOpenDir(fd syscallFd) (uintptr, string, error) {
// Implemented in syscall/syscall_libc_darwin_*.go.
//go:linkname fdopendir syscall.fdopendir
func fdopendir(fd int) (dir uintptr, err error)
//go:linkname closedir syscall.closedir
func closedir(dir uintptr) (err error)
+7
View File
@@ -0,0 +1,7 @@
package os
import "syscall"
func pipe(p []int) error {
return syscall.Pipe(p)
}
+9
View File
@@ -0,0 +1,9 @@
//go:build (linux && !baremetal && !wasm_unknown) || wasip1 || wasip2
package os
import "syscall"
func pipe(p []int) error {
return syscall.Pipe2(p, syscall.O_CLOEXEC)
}
+1 -1
View File
@@ -70,7 +70,7 @@ func Truncate(name string, size int64) error {
func Pipe() (r *File, w *File, err error) {
var p [2]int
err = handleSyscallError(syscall.Pipe2(p[:], syscall.O_CLOEXEC))
err = handleSyscallError(pipe(p[:]))
if err != nil {
return
}
+27 -2
View File
@@ -1,7 +1,32 @@
// Wrapper function because 'open' is a variadic function and variadic functions
// use a different (incompatible) calling convention on darwin/arm64.
//go:build none
// This file is included in the build, despite the //go:build line above.
#include <fcntl.h>
// Wrapper function because 'open' is a variadic function and variadic functions
// use a different (incompatible) calling convention on darwin/arm64.
// This function is referenced from the compiler, when it sees a
// syscall.libc_open_trampoline function.
int syscall_libc_open(const char *pathname, int flags, mode_t mode) {
return open(pathname, flags, mode);
}
// The following functions are called by the runtime because Go can't call
// function pointers directly.
int tinygo_syscall(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) {
return fn(a1, a2, a3);
}
uintptr_t tinygo_syscallX(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) {
return fn(a1, a2, a3);
}
int tinygo_syscall6(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) {
return fn(a1, a2, a3, a4, a5, a6);
}
uintptr_t tinygo_syscall6X(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) {
return fn(a1, a2, a3, a4, a5, a6);
}
+100 -2
View File
@@ -4,8 +4,6 @@ package runtime
import "unsafe"
import "C" // dummy import so that os_darwin.c works
const GOOS = "darwin"
const (
@@ -127,7 +125,107 @@ func hardwareRand() (n uint64, ok bool) {
return n, true
}
//go:linkname syscall_Getpagesize syscall.Getpagesize
func syscall_Getpagesize() int {
return int(libc_getpagesize())
}
// Call "system calls" (actually: libc functions) in a special way.
// - Most calls calls return a C int (which is 32-bits), and -1 on failure.
// - syscallX* is for functions that return a 64-bit integer (and also return
// -1 on failure).
// - syscallPtr is for functions that return a pointer on success or NULL on
// failure.
// - rawSyscall seems to avoid some stack modifications, which isn't relevant
// to TinyGo.
//go:linkname syscall_syscall syscall.syscall
func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
// For TinyGo we don't need to do anything special to call C functions.
return syscall_rawSyscall(fn, a1, a2, a3)
}
//go:linkname syscall_rawSyscall syscall.rawSyscall
func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
result := call_syscall(fn, a1, a2, a3)
r1 = uintptr(result)
if result == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
}
return
}
//go:linkname syscall_syscallX syscall.syscallX
func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1 = call_syscallX(fn, a1, a2, a3)
if int64(r1) == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
}
return
}
//go:linkname syscall_syscallPtr syscall.syscallPtr
func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
r1 = call_syscallX(fn, a1, a2, a3)
if r1 == 0 {
// Syscall returns a pointer on success, or NULL on failure.
err = uintptr(*libc___error())
}
return
}
//go:linkname syscall_syscall6 syscall.syscall6
func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
result := call_syscall6(fn, a1, a2, a3, a4, a5, a6)
r1 = uintptr(result)
if result == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
}
return
}
//go:linkname syscall_syscall6X syscall.syscall6X
func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
r1 = call_syscall6X(fn, a1, a2, a3, a4, a5, a6)
if int64(r1) == -1 {
// Syscall returns -1 on failure.
err = uintptr(*libc___error())
}
return
}
// uint32_t arc4random(void);
//
//export arc4random
func libc_arc4random() uint32
// int getpagesize(void);
//
//export getpagesize
func libc_getpagesize() int32
// This function returns the error location in the darwin ABI.
// Discovered by compiling the following code using Clang:
//
// #include <errno.h>
// int getErrno() {
// return errno;
// }
//
//export __error
func libc___error() *int32
//export tinygo_syscall
func call_syscall(fn, a1, a2, a3 uintptr) int32
//export tinygo_syscallX
func call_syscallX(fn, a1, a2, a3 uintptr) uintptr
//export tinygo_syscall6
func call_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) int32
//export tinygo_syscall6X
func call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build darwin || nintendoswitch || wasip1
//go:build nintendoswitch || wasip1
package syscall
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build !wasip1 && !wasip2 && !darwin
//go:build !wasip1 && !wasip2
package syscall
+1 -1
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build darwin || linux
//go:build linux
package syscall_test
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build darwin || nintendoswitch || wasip1 || wasip2
//go:build nintendoswitch || wasip1 || wasip2
package syscall
-432
View File
@@ -1,432 +0,0 @@
//go:build darwin
package syscall
import (
"internal/itoa"
"unsafe"
)
// This file defines errno and constants to match the darwin libsystem ABI.
// Values have been copied from src/syscall/zerrors_darwin_amd64.go.
// This function returns the error location in the darwin ABI.
// Discovered by compiling the following code using Clang:
//
// #include <errno.h>
// int getErrno() {
// return errno;
// }
//
//export __error
func libc___error() *int32
// getErrno returns the current C errno. It may not have been caused by the last
// call, so it should only be relied upon when the last call indicates an error
// (for example, by returning -1).
func getErrno() Errno {
errptr := libc___error()
return Errno(uintptr(*errptr))
}
func (e Errno) Is(target error) bool {
switch target.Error() {
case "permission denied":
return e == EACCES || e == EPERM
case "file already exists":
return e == EEXIST
case "file does not exist":
return e == ENOENT
}
return false
}
// Source: upstream zerrors_darwin_amd64.go
const (
DT_BLK = 0x6
DT_CHR = 0x2
DT_DIR = 0x4
DT_FIFO = 0x1
DT_LNK = 0xa
DT_REG = 0x8
DT_SOCK = 0xc
DT_UNKNOWN = 0x0
DT_WHT = 0xe
F_GETFL = 0x3
F_SETFL = 0x4
O_NONBLOCK = 0x4
TIOCSPGRP = 0x80047476
)
// Source: https://opensource.apple.com/source/xnu/xnu-7195.141.2/bsd/sys/errno.h.auto.html
const (
EPERM Errno = 1
ENOENT Errno = 2
ESRCH Errno = 3
EINTR Errno = 4
EIO Errno = 5
ENXIO Errno = 6
E2BIG Errno = 7
ENOEXEC Errno = 8
EBADF Errno = 9
ECHILD Errno = 10
EDEADLK Errno = 11
ENOMEM Errno = 12
EACCES Errno = 13
EFAULT Errno = 14
ENOTBLK Errno = 15
EBUSY Errno = 16
EEXIST Errno = 17
EXDEV Errno = 18
ENODEV Errno = 19
ENOTDIR Errno = 20
EISDIR Errno = 21
EINVAL Errno = 22
ENFILE Errno = 23
EMFILE Errno = 24
ENOTTY Errno = 25
ETXTBSY Errno = 26
EFBIG Errno = 27
ENOSPC Errno = 28
ESPIPE Errno = 29
EROFS Errno = 30
EMLINK Errno = 31
EPIPE Errno = 32
EDOM Errno = 33
ERANGE Errno = 34
EAGAIN Errno = 35
EWOULDBLOCK Errno = EAGAIN
EINPROGRESS Errno = 36
EALREADY Errno = 37
ENOTSOCK Errno = 38
EDESTADDRREQ Errno = 39
EMSGSIZE Errno = 40
EPROTOTYPE Errno = 41
ENOPROTOOPT Errno = 42
EPROTONOSUPPORT Errno = 43
ESOCKTNOSUPPORT Errno = 44
ENOTSUP Errno = 45
EPFNOSUPPORT Errno = 46
EAFNOSUPPORT Errno = 47
EADDRINUSE Errno = 48
EADDRNOTAVAIL Errno = 49
ENETDOWN Errno = 50
ENETUNREACH Errno = 51
ENETRESET Errno = 52
ECONNABORTED Errno = 53
ECONNRESET Errno = 54
ENOBUFS Errno = 55
EISCONN Errno = 56
ENOTCONN Errno = 57
ESHUTDOWN Errno = 58
ETOOMANYREFS Errno = 59
ETIMEDOUT Errno = 60
ECONNREFUSED Errno = 61
ELOOP Errno = 62
ENAMETOOLONG Errno = 63
EHOSTDOWN Errno = 64
EHOSTUNREACH Errno = 65
ENOTEMPTY Errno = 66
EPROCLIM Errno = 67
EUSERS Errno = 68
EDQUOT Errno = 69
ESTALE Errno = 70
EREMOTE Errno = 71
EBADRPC Errno = 72
ERPCMISMATCH Errno = 73
EPROGUNAVAIL Errno = 74
EPROGMISMATCH Errno = 75
EPROCUNAVAIL Errno = 76
ENOLCK Errno = 77
ENOSYS Errno = 78
EFTYPE Errno = 79
EAUTH Errno = 80
ENEEDAUTH Errno = 81
EPWROFF Errno = 82
EDEVERR Errno = 83
EOVERFLOW Errno = 84
EBADEXEC Errno = 85
EBADARCH Errno = 86
ESHLIBVERS Errno = 87
EBADMACHO Errno = 88
ECANCELED Errno = 89
EIDRM Errno = 90
ENOMSG Errno = 91
EILSEQ Errno = 92
ENOATTR Errno = 93
EBADMSG Errno = 94
EMULTIHOP Errno = 95
ENODATA Errno = 96
ENOLINK Errno = 97
ENOSR Errno = 98
ENOSTR Errno = 99
EPROTO Errno = 100
ETIME Errno = 101
EOPNOTSUPP Errno = 102
ENOPOLICY Errno = 103
ENOTRECOVERABLE Errno = 104
EOWNERDEAD Errno = 105
EQFULL Errno = 106
ELAST Errno = 106
)
type Signal int
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/signal.h
const (
SIGINT Signal = 2 /* interrupt */
SIGQUIT Signal = 3 /* quit */
SIGILL Signal = 4 /* illegal instruction (not reset when caught) */
SIGTRAP Signal = 5 /* trace trap (not reset when caught) */
SIGABRT Signal = 6 /* abort() */
SIGFPE Signal = 8 /* floating point exception */
SIGKILL Signal = 9 /* kill (cannot be caught or ignored) */
SIGBUS Signal = 10 /* bus error */
SIGSEGV Signal = 11 /* segmentation violation */
SIGPIPE Signal = 13 /* write on a pipe with no one to read it */
SIGTERM Signal = 15 /* software termination signal from kill */
SIGCHLD Signal = 20 /* to parent on child stop or exit */
)
func (s Signal) Signal() {}
func (s Signal) String() string {
if 0 <= s && int(s) < len(signals) {
str := signals[s]
if str != "" {
return str
}
}
return "signal " + itoa.Itoa(int(s))
}
var signals = [...]string{}
const (
Stdin = 0
Stdout = 1
Stderr = 2
)
const (
O_RDONLY = 0x0
O_WRONLY = 0x1
O_RDWR = 0x2
O_APPEND = 0x8
O_SYNC = 0x80
O_CREAT = 0x200
O_TRUNC = 0x400
O_EXCL = 0x800
O_CLOEXEC = 0x01000000
)
// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html
const (
PROT_NONE = 0x00 // no permissions
PROT_READ = 0x01 // pages can be read
PROT_WRITE = 0x02 // pages can be written
PROT_EXEC = 0x04 // pages can be executed
MAP_SHARED = 0x0001 // share changes
MAP_PRIVATE = 0x0002 // changes are private
MAP_FILE = 0x0000 // map from file (default)
MAP_ANON = 0x1000 // allocated from memory, swap space
MAP_ANONYMOUS = MAP_ANON
)
type Timespec struct {
Sec int64
Nsec int64
}
// Unix returns the time stored in ts as seconds plus nanoseconds.
func (ts *Timespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
}
// Source: upstream ztypes_darwin_amd64.go
type Dirent struct {
Ino uint64
Seekoff uint64
Reclen uint16
Namlen uint16
Type uint8
Name [1024]int8
Pad_cgo_0 [3]byte
}
type Stat_t struct {
Dev int32
Mode uint16
Nlink uint16
Ino uint64
Uid uint32
Gid uint32
Rdev int32
Pad_cgo_0 [4]byte
Atimespec Timespec
Mtimespec Timespec
Ctimespec Timespec
Btimespec Timespec
Size int64
Blocks int64
Blksize int32
Flags uint32
Gen uint32
Lspare int32
Qspare [2]int64
}
// Source: https://github.com/apple/darwin-xnu/blob/main/bsd/sys/_types/_s_ifmt.h
const (
S_IEXEC = 0x40
S_IFBLK = 0x6000
S_IFCHR = 0x2000
S_IFDIR = 0x4000
S_IFIFO = 0x1000
S_IFLNK = 0xa000
S_IFMT = 0xf000
S_IFREG = 0x8000
S_IFSOCK = 0xc000
S_IFWHT = 0xe000
S_IREAD = 0x100
S_IRGRP = 0x20
S_IROTH = 0x4
S_IRUSR = 0x100
S_IRWXG = 0x38
S_IRWXO = 0x7
S_IRWXU = 0x1c0
S_ISGID = 0x400
S_ISTXT = 0x200
S_ISUID = 0x800
S_ISVTX = 0x200
S_IWGRP = 0x10
S_IWOTH = 0x2
S_IWRITE = 0x80
S_IWUSR = 0x80
S_IXGRP = 0x8
S_IXOTH = 0x1
S_IXUSR = 0x40
)
func Stat(path string, p *Stat_t) (err error) {
data := cstring(path)
n := libc_stat(&data[0], unsafe.Pointer(p))
if n < 0 {
err = getErrno()
}
return
}
func Fstat(fd int, p *Stat_t) (err error) {
n := libc_fstat(int32(fd), unsafe.Pointer(p))
if n < 0 {
err = getErrno()
}
return
}
func Lstat(path string, p *Stat_t) (err error) {
data := cstring(path)
n := libc_lstat(&data[0], unsafe.Pointer(p))
if n < 0 {
err = getErrno()
}
return
}
func Fdopendir(fd int) (dir uintptr, err error) {
r0 := libc_fdopendir(int32(fd))
dir = uintptr(r0)
if dir == 0 {
err = getErrno()
}
return
}
func Pipe2(fds []int, flags int) (err error) {
// Mac only has Pipe, which ignores the flags argument
buf := make([]int32, 2)
fail := int(libc_pipe(&buf[0]))
if fail < 0 {
err = getErrno()
} else {
fds[0] = int(buf[0])
fds[1] = int(buf[1])
}
return
}
func Chmod(path string, mode uint32) (err error) {
data := cstring(path)
fail := int(libc_chmod(&data[0], mode))
if fail < 0 {
err = getErrno()
}
return
}
func closedir(dir uintptr) (err error) {
e := libc_closedir(unsafe.Pointer(dir))
if e != 0 {
err = getErrno()
}
return
}
func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (err error) {
e1 := libc_readdir_r(unsafe.Pointer(dir), unsafe.Pointer(entry), unsafe.Pointer(result))
if e1 != 0 {
err = getErrno()
}
return
}
func Getpagesize() int {
return int(libc_getpagesize())
}
// The following RawSockAddr* types have been copied from the Go source tree and
// are here purely to fix build errors.
type RawSockaddr struct {
Len uint8
Family uint8
Data [14]int8
}
type RawSockaddrInet4 struct {
Len uint8
Family uint8
Port uint16
Addr [4]byte /* in_addr */
Zero [8]int8
}
type RawSockaddrInet6 struct {
Len uint8
Family uint8
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
// int pipe(int32 *fds);
//
//export pipe
func libc_pipe(fds *int32) int32
// int getpagesize();
//
//export getpagesize
func libc_getpagesize() int32
// int open(const char *pathname, int flags, mode_t mode);
//
//export syscall_libc_open
func libc_open(pathname *byte, flags int32, mode uint32) int32
-43
View File
@@ -1,43 +0,0 @@
//go:build darwin
package syscall
import (
"unsafe"
)
// The odd $INODE64 suffix is an Apple compatibility feature, see
// __DARWIN_INODE64 in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h
// and https://assert.cc/posts/darwin_use_64_bit_inode_vs_ctypes/
// Without it, you get the old, smaller struct stat from mac os 10.2 or so.
// It not needed on arm64.
// struct DIR * buf fdopendir(int fd);
//
//export fdopendir$INODE64
func libc_fdopendir(fd int32) unsafe.Pointer
// int closedir(struct DIR * buf);
//
//export closedir
func libc_closedir(unsafe.Pointer) int32
// int readdir_r(struct DIR * buf, struct dirent *entry, struct dirent **result);
//
//export readdir_r$INODE64
func libc_readdir_r(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) int32
// int stat(const char *path, struct stat * buf);
//
//export stat$INODE64
func libc_stat(pathname *byte, ptr unsafe.Pointer) int32
// int fstat(int fd, struct stat * buf);
//
//export fstat$INODE64
func libc_fstat(fd int32, ptr unsafe.Pointer) int32
// int lstat(const char *path, struct stat * buf);
//
//export lstat$INODE64
func libc_lstat(pathname *byte, ptr unsafe.Pointer) int32
-37
View File
@@ -1,37 +0,0 @@
//go:build darwin
package syscall
import (
"unsafe"
)
// struct DIR * buf fdopendir(int fd);
//
//export fdopendir
func libc_fdopendir(fd int32) unsafe.Pointer
// int closedir(struct DIR * buf);
//
//export closedir
func libc_closedir(unsafe.Pointer) int32
// int readdir_r(struct DIR * buf, struct dirent *entry, struct dirent **result);
//
//export readdir_r
func libc_readdir_r(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) int32
// int stat(const char *path, struct stat * buf);
//
//export stat
func libc_stat(pathname *byte, ptr unsafe.Pointer) int32
// int fstat(int fd, struct stat * buf);
//
//export fstat
func libc_fstat(fd int32, ptr unsafe.Pointer) int32
// int lstat(const char *path, struct stat * buf);
//
//export lstat
func libc_lstat(pathname *byte, ptr unsafe.Pointer) int32