mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
2
vendor/golang.org/x/sys/unix/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
||||
_obj/
|
||||
unix.test
|
173
vendor/golang.org/x/sys/unix/README.md
generated
vendored
173
vendor/golang.org/x/sys/unix/README.md
generated
vendored
@ -1,173 +0,0 @@
|
||||
# Building `sys/unix`
|
||||
|
||||
The sys/unix package provides access to the raw system call interface of the
|
||||
underlying operating system. See: https://godoc.org/golang.org/x/sys/unix
|
||||
|
||||
Porting Go to a new architecture/OS combination or adding syscalls, types, or
|
||||
constants to an existing architecture/OS pair requires some manual effort;
|
||||
however, there are tools that automate much of the process.
|
||||
|
||||
## Build Systems
|
||||
|
||||
There are currently two ways we generate the necessary files. We are currently
|
||||
migrating the build system to use containers so the builds are reproducible.
|
||||
This is being done on an OS-by-OS basis. Please update this documentation as
|
||||
components of the build system change.
|
||||
|
||||
### Old Build System (currently for `GOOS != "linux"`)
|
||||
|
||||
The old build system generates the Go files based on the C header files
|
||||
present on your system. This means that files
|
||||
for a given GOOS/GOARCH pair must be generated on a system with that OS and
|
||||
architecture. This also means that the generated code can differ from system
|
||||
to system, based on differences in the header files.
|
||||
|
||||
To avoid this, if you are using the old build system, only generate the Go
|
||||
files on an installation with unmodified header files. It is also important to
|
||||
keep track of which version of the OS the files were generated from (ex.
|
||||
Darwin 14 vs Darwin 15). This makes it easier to track the progress of changes
|
||||
and have each OS upgrade correspond to a single change.
|
||||
|
||||
To build the files for your current OS and architecture, make sure GOOS and
|
||||
GOARCH are set correctly and run `mkall.sh`. This will generate the files for
|
||||
your specific system. Running `mkall.sh -n` shows the commands that will be run.
|
||||
|
||||
Requirements: bash, perl, go
|
||||
|
||||
### New Build System (currently for `GOOS == "linux"`)
|
||||
|
||||
The new build system uses a Docker container to generate the go files directly
|
||||
from source checkouts of the kernel and various system libraries. This means
|
||||
that on any platform that supports Docker, all the files using the new build
|
||||
system can be generated at once, and generated files will not change based on
|
||||
what the person running the scripts has installed on their computer.
|
||||
|
||||
The OS specific files for the new build system are located in the `${GOOS}`
|
||||
directory, and the build is coordinated by the `${GOOS}/mkall.go` program. When
|
||||
the kernel or system library updates, modify the Dockerfile at
|
||||
`${GOOS}/Dockerfile` to checkout the new release of the source.
|
||||
|
||||
To build all the files under the new build system, you must be on an amd64/Linux
|
||||
system and have your GOOS and GOARCH set accordingly. Running `mkall.sh` will
|
||||
then generate all of the files for all of the GOOS/GOARCH pairs in the new build
|
||||
system. Running `mkall.sh -n` shows the commands that will be run.
|
||||
|
||||
Requirements: bash, perl, go, docker
|
||||
|
||||
## Component files
|
||||
|
||||
This section describes the various files used in the code generation process.
|
||||
It also contains instructions on how to modify these files to add a new
|
||||
architecture/OS or to add additional syscalls, types, or constants. Note that
|
||||
if you are using the new build system, the scripts cannot be called normally.
|
||||
They must be called from within the docker container.
|
||||
|
||||
### asm files
|
||||
|
||||
The hand-written assembly file at `asm_${GOOS}_${GOARCH}.s` implements system
|
||||
call dispatch. There are three entry points:
|
||||
```
|
||||
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr)
|
||||
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr)
|
||||
```
|
||||
The first and second are the standard ones; they differ only in how many
|
||||
arguments can be passed to the kernel. The third is for low-level use by the
|
||||
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
|
||||
let it know that a system call is running.
|
||||
|
||||
When porting Go to an new architecture/OS, this file must be implemented for
|
||||
each GOOS/GOARCH pair.
|
||||
|
||||
### mksysnum
|
||||
|
||||
Mksysnum is a script located at `${GOOS}/mksysnum.pl` (or `mksysnum_${GOOS}.pl`
|
||||
for the old system). This script takes in a list of header files containing the
|
||||
syscall number declarations and parses them to produce the corresponding list of
|
||||
Go numeric constants. See `zsysnum_${GOOS}_${GOARCH}.go` for the generated
|
||||
constants.
|
||||
|
||||
Adding new syscall numbers is mostly done by running the build on a sufficiently
|
||||
new installation of the target OS (or updating the source checkouts for the
|
||||
new build system). However, depending on the OS, you make need to update the
|
||||
parsing in mksysnum.
|
||||
|
||||
### mksyscall.pl
|
||||
|
||||
The `syscall.go`, `syscall_${GOOS}.go`, `syscall_${GOOS}_${GOARCH}.go` are
|
||||
hand-written Go files which implement system calls (for unix, the specific OS,
|
||||
or the specific OS/Architecture pair respectively) that need special handling
|
||||
and list `//sys` comments giving prototypes for ones that can be generated.
|
||||
|
||||
The mksyscall.pl script takes the `//sys` and `//sysnb` comments and converts
|
||||
them into syscalls. This requires the name of the prototype in the comment to
|
||||
match a syscall number in the `zsysnum_${GOOS}_${GOARCH}.go` file. The function
|
||||
prototype can be exported (capitalized) or not.
|
||||
|
||||
Adding a new syscall often just requires adding a new `//sys` function prototype
|
||||
with the desired arguments and a capitalized name so it is exported. However, if
|
||||
you want the interface to the syscall to be different, often one will make an
|
||||
unexported `//sys` prototype, an then write a custom wrapper in
|
||||
`syscall_${GOOS}.go`.
|
||||
|
||||
### types files
|
||||
|
||||
For each OS, there is a hand-written Go file at `${GOOS}/types.go` (or
|
||||
`types_${GOOS}.go` on the old system). This file includes standard C headers and
|
||||
creates Go type aliases to the corresponding C types. The file is then fed
|
||||
through godef to get the Go compatible definitions. Finally, the generated code
|
||||
is fed though mkpost.go to format the code correctly and remove any hidden or
|
||||
private identifiers. This cleaned-up code is written to
|
||||
`ztypes_${GOOS}_${GOARCH}.go`.
|
||||
|
||||
The hardest part about preparing this file is figuring out which headers to
|
||||
include and which symbols need to be `#define`d to get the actual data
|
||||
structures that pass through to the kernel system calls. Some C libraries
|
||||
preset alternate versions for binary compatibility and translate them on the
|
||||
way in and out of system calls, but there is almost always a `#define` that can
|
||||
get the real ones.
|
||||
See `types_darwin.go` and `linux/types.go` for examples.
|
||||
|
||||
To add a new type, add in the necessary include statement at the top of the
|
||||
file (if it is not already there) and add in a type alias line. Note that if
|
||||
your type is significantly different on different architectures, you may need
|
||||
some `#if/#elif` macros in your include statements.
|
||||
|
||||
### mkerrors.sh
|
||||
|
||||
This script is used to generate the system's various constants. This doesn't
|
||||
just include the error numbers and error strings, but also the signal numbers
|
||||
an a wide variety of miscellaneous constants. The constants come from the list
|
||||
of include files in the `includes_${uname}` variable. A regex then picks out
|
||||
the desired `#define` statements, and generates the corresponding Go constants.
|
||||
The error numbers and strings are generated from `#include <errno.h>`, and the
|
||||
signal numbers and strings are generated from `#include <signal.h>`. All of
|
||||
these constants are written to `zerrors_${GOOS}_${GOARCH}.go` via a C program,
|
||||
`_errors.c`, which prints out all the constants.
|
||||
|
||||
To add a constant, add the header that includes it to the appropriate variable.
|
||||
Then, edit the regex (if necessary) to match the desired constant. Avoid making
|
||||
the regex too broad to avoid matching unintended constants.
|
||||
|
||||
|
||||
## Generated files
|
||||
|
||||
### `zerror_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A file containing all of the system's generated error numbers, error strings,
|
||||
signal numbers, and constants. Generated by `mkerrors.sh` (see above).
|
||||
|
||||
### `zsyscall_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A file containing all the generated syscalls for a specific GOOS and GOARCH.
|
||||
Generated by `mksyscall.pl` (see above).
|
||||
|
||||
### `zsysnum_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A list of numeric constants for all the syscall number of the specific GOOS
|
||||
and GOARCH. Generated by mksysnum (see above).
|
||||
|
||||
### `ztypes_${GOOS}_${GOARCH}.go`
|
||||
|
||||
A file containing Go types for passing into (or returning from) syscalls.
|
||||
Generated by godefs and the types file (see above).
|
134
vendor/golang.org/x/sys/unix/creds_test.go
generated
vendored
134
vendor/golang.org/x/sys/unix/creds_test.go
generated
vendored
@ -1,134 +0,0 @@
|
||||
// Copyright 2012 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.
|
||||
|
||||
// +build linux
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/build"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// TestSCMCredentials tests the sending and receiving of credentials
|
||||
// (PID, UID, GID) in an ancillary message between two UNIX
|
||||
// sockets. The SO_PASSCRED socket option is enabled on the sending
|
||||
// socket for this to work.
|
||||
func TestSCMCredentials(t *testing.T) {
|
||||
socketTypeTests := []struct {
|
||||
socketType int
|
||||
dataLen int
|
||||
}{
|
||||
{
|
||||
unix.SOCK_STREAM,
|
||||
1,
|
||||
}, {
|
||||
unix.SOCK_DGRAM,
|
||||
0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range socketTypeTests {
|
||||
if tt.socketType == unix.SOCK_DGRAM && !atLeast1p10() {
|
||||
t.Log("skipping DGRAM test on pre-1.10")
|
||||
continue
|
||||
}
|
||||
|
||||
fds, err := unix.Socketpair(unix.AF_LOCAL, tt.socketType, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Socketpair: %v", err)
|
||||
}
|
||||
defer unix.Close(fds[0])
|
||||
defer unix.Close(fds[1])
|
||||
|
||||
err = unix.SetsockoptInt(fds[0], unix.SOL_SOCKET, unix.SO_PASSCRED, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("SetsockoptInt: %v", err)
|
||||
}
|
||||
|
||||
srvFile := os.NewFile(uintptr(fds[0]), "server")
|
||||
defer srvFile.Close()
|
||||
srv, err := net.FileConn(srvFile)
|
||||
if err != nil {
|
||||
t.Errorf("FileConn: %v", err)
|
||||
return
|
||||
}
|
||||
defer srv.Close()
|
||||
|
||||
cliFile := os.NewFile(uintptr(fds[1]), "client")
|
||||
defer cliFile.Close()
|
||||
cli, err := net.FileConn(cliFile)
|
||||
if err != nil {
|
||||
t.Errorf("FileConn: %v", err)
|
||||
return
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
var ucred unix.Ucred
|
||||
ucred.Pid = int32(os.Getpid())
|
||||
ucred.Uid = uint32(os.Getuid())
|
||||
ucred.Gid = uint32(os.Getgid())
|
||||
oob := unix.UnixCredentials(&ucred)
|
||||
|
||||
// On SOCK_STREAM, this is internally going to send a dummy byte
|
||||
n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("WriteMsgUnix: %v", err)
|
||||
}
|
||||
if n != 0 {
|
||||
t.Fatalf("WriteMsgUnix n = %d, want 0", n)
|
||||
}
|
||||
if oobn != len(oob) {
|
||||
t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
|
||||
}
|
||||
|
||||
oob2 := make([]byte, 10*len(oob))
|
||||
n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadMsgUnix: %v", err)
|
||||
}
|
||||
if flags != 0 {
|
||||
t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
|
||||
}
|
||||
if n != tt.dataLen {
|
||||
t.Fatalf("ReadMsgUnix n = %d, want %d", n, tt.dataLen)
|
||||
}
|
||||
if oobn2 != oobn {
|
||||
// without SO_PASSCRED set on the socket, ReadMsgUnix will
|
||||
// return zero oob bytes
|
||||
t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
|
||||
}
|
||||
oob2 = oob2[:oobn2]
|
||||
if !bytes.Equal(oob, oob2) {
|
||||
t.Fatal("ReadMsgUnix oob bytes don't match")
|
||||
}
|
||||
|
||||
scm, err := unix.ParseSocketControlMessage(oob2)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseSocketControlMessage: %v", err)
|
||||
}
|
||||
newUcred, err := unix.ParseUnixCredentials(&scm[0])
|
||||
if err != nil {
|
||||
t.Fatalf("ParseUnixCredentials: %v", err)
|
||||
}
|
||||
if *newUcred != ucred {
|
||||
t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// atLeast1p10 reports whether we are running on Go 1.10 or later.
|
||||
func atLeast1p10() bool {
|
||||
for _, ver := range build.Default.ReleaseTags {
|
||||
if ver == "go1.10" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
210
vendor/golang.org/x/sys/unix/darwin_test.go
generated
vendored
210
vendor/golang.org/x/sys/unix/darwin_test.go
generated
vendored
@ -1,210 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build darwin,go1.12,amd64 darwin,go1.12,386
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type darwinTest struct {
|
||||
name string
|
||||
f func()
|
||||
}
|
||||
|
||||
// TODO(khr): decide whether to keep this test enabled permanently or
|
||||
// only temporarily.
|
||||
func TestDarwinLoader(t *testing.T) {
|
||||
// Make sure the Darwin dynamic loader can actually resolve
|
||||
// all the system calls into libSystem.dylib. Unfortunately
|
||||
// there is no easy way to test this at compile time. So we
|
||||
// implement a crazy hack here, calling into the syscall
|
||||
// function with all its arguments set to junk, and see what
|
||||
// error we get. We are happy with any error (or none) except
|
||||
// an error from the dynamic loader.
|
||||
//
|
||||
// We have to run each test in a separate subprocess for fault isolation.
|
||||
//
|
||||
// Hopefully the junk args won't accidentally ask the system to do "rm -fr /".
|
||||
//
|
||||
// In an ideal world each syscall would have its own test, so this test
|
||||
// would be unnecessary. Unfortunately, we do not live in that world.
|
||||
for _, test := range darwinTests {
|
||||
// Call the test binary recursively, giving it a magic argument
|
||||
// (see init below) and the name of the test to run.
|
||||
cmd := exec.Command(os.Args[0], "testDarwinLoader", test.name)
|
||||
|
||||
// Run subprocess, collect results. Note that we expect the subprocess
|
||||
// to fail somehow, so the error is irrelevant.
|
||||
out, _ := cmd.CombinedOutput()
|
||||
|
||||
if strings.Contains(string(out), "dyld: Symbol not found:") {
|
||||
t.Errorf("can't resolve %s in libSystem.dylib", test.name)
|
||||
}
|
||||
if !strings.Contains(string(out), "success") {
|
||||
// Not really an error. Might be a syscall that never returns,
|
||||
// like exit, or one that segfaults, like gettimeofday.
|
||||
t.Logf("test never finished: %s: %s", test.name, string(out))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// The test binary execs itself with the "testDarwinLoader" argument.
|
||||
// Run the test specified by os.Args[2], then panic.
|
||||
if len(os.Args) >= 3 && os.Args[1] == "testDarwinLoader" {
|
||||
for _, test := range darwinTests {
|
||||
if test.name == os.Args[2] {
|
||||
test.f()
|
||||
}
|
||||
}
|
||||
// Panic with a "success" label, so the parent process can check it.
|
||||
panic("success")
|
||||
}
|
||||
}
|
||||
|
||||
// All the _trampoline functions in zsyscall_darwin_$ARCH.s
|
||||
var darwinTests = [...]darwinTest{
|
||||
{"getgroups", libc_getgroups_trampoline},
|
||||
{"setgroups", libc_setgroups_trampoline},
|
||||
{"wait4", libc_wait4_trampoline},
|
||||
{"accept", libc_accept_trampoline},
|
||||
{"bind", libc_bind_trampoline},
|
||||
{"connect", libc_connect_trampoline},
|
||||
{"socket", libc_socket_trampoline},
|
||||
{"getsockopt", libc_getsockopt_trampoline},
|
||||
{"setsockopt", libc_setsockopt_trampoline},
|
||||
{"getpeername", libc_getpeername_trampoline},
|
||||
{"getsockname", libc_getsockname_trampoline},
|
||||
{"shutdown", libc_shutdown_trampoline},
|
||||
{"socketpair", libc_socketpair_trampoline},
|
||||
{"recvfrom", libc_recvfrom_trampoline},
|
||||
{"sendto", libc_sendto_trampoline},
|
||||
{"recvmsg", libc_recvmsg_trampoline},
|
||||
{"sendmsg", libc_sendmsg_trampoline},
|
||||
{"kevent", libc_kevent_trampoline},
|
||||
{"__sysctl", libc___sysctl_trampoline},
|
||||
{"utimes", libc_utimes_trampoline},
|
||||
{"futimes", libc_futimes_trampoline},
|
||||
{"fcntl", libc_fcntl_trampoline},
|
||||
{"poll", libc_poll_trampoline},
|
||||
{"madvise", libc_madvise_trampoline},
|
||||
{"mlock", libc_mlock_trampoline},
|
||||
{"mlockall", libc_mlockall_trampoline},
|
||||
{"mprotect", libc_mprotect_trampoline},
|
||||
{"msync", libc_msync_trampoline},
|
||||
{"munlock", libc_munlock_trampoline},
|
||||
{"munlockall", libc_munlockall_trampoline},
|
||||
{"ptrace", libc_ptrace_trampoline},
|
||||
{"pipe", libc_pipe_trampoline},
|
||||
{"getxattr", libc_getxattr_trampoline},
|
||||
{"fgetxattr", libc_fgetxattr_trampoline},
|
||||
{"setxattr", libc_setxattr_trampoline},
|
||||
{"fsetxattr", libc_fsetxattr_trampoline},
|
||||
{"removexattr", libc_removexattr_trampoline},
|
||||
{"fremovexattr", libc_fremovexattr_trampoline},
|
||||
{"listxattr", libc_listxattr_trampoline},
|
||||
{"flistxattr", libc_flistxattr_trampoline},
|
||||
{"kill", libc_kill_trampoline},
|
||||
{"ioctl", libc_ioctl_trampoline},
|
||||
{"access", libc_access_trampoline},
|
||||
{"adjtime", libc_adjtime_trampoline},
|
||||
{"chdir", libc_chdir_trampoline},
|
||||
{"chflags", libc_chflags_trampoline},
|
||||
{"chmod", libc_chmod_trampoline},
|
||||
{"chown", libc_chown_trampoline},
|
||||
{"chroot", libc_chroot_trampoline},
|
||||
{"close", libc_close_trampoline},
|
||||
{"dup", libc_dup_trampoline},
|
||||
{"dup2", libc_dup2_trampoline},
|
||||
{"exchangedata", libc_exchangedata_trampoline},
|
||||
{"exit", libc_exit_trampoline},
|
||||
{"faccessat", libc_faccessat_trampoline},
|
||||
{"fchdir", libc_fchdir_trampoline},
|
||||
{"fchflags", libc_fchflags_trampoline},
|
||||
{"fchmod", libc_fchmod_trampoline},
|
||||
{"fchmodat", libc_fchmodat_trampoline},
|
||||
{"fchown", libc_fchown_trampoline},
|
||||
{"fchownat", libc_fchownat_trampoline},
|
||||
{"flock", libc_flock_trampoline},
|
||||
{"fpathconf", libc_fpathconf_trampoline},
|
||||
{"fstat64", libc_fstat64_trampoline},
|
||||
{"fstatat64", libc_fstatat64_trampoline},
|
||||
{"fstatfs64", libc_fstatfs64_trampoline},
|
||||
{"fsync", libc_fsync_trampoline},
|
||||
{"ftruncate", libc_ftruncate_trampoline},
|
||||
{"__getdirentries64", libc___getdirentries64_trampoline},
|
||||
{"getdtablesize", libc_getdtablesize_trampoline},
|
||||
{"getegid", libc_getegid_trampoline},
|
||||
{"geteuid", libc_geteuid_trampoline},
|
||||
{"getgid", libc_getgid_trampoline},
|
||||
{"getpgid", libc_getpgid_trampoline},
|
||||
{"getpgrp", libc_getpgrp_trampoline},
|
||||
{"getpid", libc_getpid_trampoline},
|
||||
{"getppid", libc_getppid_trampoline},
|
||||
{"getpriority", libc_getpriority_trampoline},
|
||||
{"getrlimit", libc_getrlimit_trampoline},
|
||||
{"getrusage", libc_getrusage_trampoline},
|
||||
{"getsid", libc_getsid_trampoline},
|
||||
{"getuid", libc_getuid_trampoline},
|
||||
{"issetugid", libc_issetugid_trampoline},
|
||||
{"kqueue", libc_kqueue_trampoline},
|
||||
{"lchown", libc_lchown_trampoline},
|
||||
{"link", libc_link_trampoline},
|
||||
{"linkat", libc_linkat_trampoline},
|
||||
{"listen", libc_listen_trampoline},
|
||||
{"lstat64", libc_lstat64_trampoline},
|
||||
{"mkdir", libc_mkdir_trampoline},
|
||||
{"mkdirat", libc_mkdirat_trampoline},
|
||||
{"mkfifo", libc_mkfifo_trampoline},
|
||||
{"mknod", libc_mknod_trampoline},
|
||||
{"open", libc_open_trampoline},
|
||||
{"openat", libc_openat_trampoline},
|
||||
{"pathconf", libc_pathconf_trampoline},
|
||||
{"pread", libc_pread_trampoline},
|
||||
{"pwrite", libc_pwrite_trampoline},
|
||||
{"read", libc_read_trampoline},
|
||||
{"readlink", libc_readlink_trampoline},
|
||||
{"readlinkat", libc_readlinkat_trampoline},
|
||||
{"rename", libc_rename_trampoline},
|
||||
{"renameat", libc_renameat_trampoline},
|
||||
{"revoke", libc_revoke_trampoline},
|
||||
{"rmdir", libc_rmdir_trampoline},
|
||||
{"lseek", libc_lseek_trampoline},
|
||||
{"select", libc_select_trampoline},
|
||||
{"setegid", libc_setegid_trampoline},
|
||||
{"seteuid", libc_seteuid_trampoline},
|
||||
{"setgid", libc_setgid_trampoline},
|
||||
{"setlogin", libc_setlogin_trampoline},
|
||||
{"setpgid", libc_setpgid_trampoline},
|
||||
{"setpriority", libc_setpriority_trampoline},
|
||||
{"setprivexec", libc_setprivexec_trampoline},
|
||||
{"setregid", libc_setregid_trampoline},
|
||||
{"setreuid", libc_setreuid_trampoline},
|
||||
{"setrlimit", libc_setrlimit_trampoline},
|
||||
{"setsid", libc_setsid_trampoline},
|
||||
{"settimeofday", libc_settimeofday_trampoline},
|
||||
{"setuid", libc_setuid_trampoline},
|
||||
{"stat64", libc_stat64_trampoline},
|
||||
{"statfs64", libc_statfs64_trampoline},
|
||||
{"symlink", libc_symlink_trampoline},
|
||||
{"symlinkat", libc_symlinkat_trampoline},
|
||||
{"sync", libc_sync_trampoline},
|
||||
{"truncate", libc_truncate_trampoline},
|
||||
{"umask", libc_umask_trampoline},
|
||||
{"undelete", libc_undelete_trampoline},
|
||||
{"unlink", libc_unlink_trampoline},
|
||||
{"unlinkat", libc_unlinkat_trampoline},
|
||||
{"unmount", libc_unmount_trampoline},
|
||||
{"write", libc_write_trampoline},
|
||||
{"mmap", libc_mmap_trampoline},
|
||||
{"munmap", libc_munmap_trampoline},
|
||||
{"gettimeofday", libc_gettimeofday_trampoline},
|
||||
{"getfsstat64", libc_getfsstat64_trampoline},
|
||||
}
|
56
vendor/golang.org/x/sys/unix/dev_linux_test.go
generated
vendored
56
vendor/golang.org/x/sys/unix/dev_linux_test.go
generated
vendored
@ -1,56 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// +build go1.7
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestDevices(t *testing.T) {
|
||||
testCases := []struct {
|
||||
path string
|
||||
major uint32
|
||||
minor uint32
|
||||
}{
|
||||
// well known major/minor numbers according to
|
||||
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/admin-guide/devices.txt
|
||||
{"/dev/null", 1, 3},
|
||||
{"/dev/zero", 1, 5},
|
||||
{"/dev/random", 1, 8},
|
||||
{"/dev/full", 1, 7},
|
||||
{"/dev/urandom", 1, 9},
|
||||
{"/dev/tty", 5, 0},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("%s %v:%v", tc.path, tc.major, tc.minor), func(t *testing.T) {
|
||||
var stat unix.Stat_t
|
||||
err := unix.Stat(tc.path, &stat)
|
||||
if err != nil {
|
||||
if err == unix.EACCES {
|
||||
t.Skip("no permission to stat device, skipping test")
|
||||
}
|
||||
t.Errorf("failed to stat device: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
dev := uint64(stat.Rdev)
|
||||
if unix.Major(dev) != tc.major {
|
||||
t.Errorf("for %s Major(%#x) == %d, want %d", tc.path, dev, unix.Major(dev), tc.major)
|
||||
}
|
||||
if unix.Minor(dev) != tc.minor {
|
||||
t.Errorf("for %s Minor(%#x) == %d, want %d", tc.path, dev, unix.Minor(dev), tc.minor)
|
||||
}
|
||||
if unix.Mkdev(tc.major, tc.minor) != dev {
|
||||
t.Errorf("for %s Mkdev(%d, %d) == %#x, want %#x", tc.path, tc.major, tc.minor, unix.Mkdev(tc.major, tc.minor), dev)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
19
vendor/golang.org/x/sys/unix/example_exec_test.go
generated
vendored
19
vendor/golang.org/x/sys/unix/example_exec_test.go
generated
vendored
@ -1,19 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func ExampleExec() {
|
||||
err := unix.Exec("/bin/ls", []string{"ls", "-al"}, os.Environ())
|
||||
log.Fatal(err)
|
||||
}
|
25
vendor/golang.org/x/sys/unix/example_flock_test.go
generated
vendored
25
vendor/golang.org/x/sys/unix/example_flock_test.go
generated
vendored
@ -1,25 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func ExampleFlock() {
|
||||
f, _ := os.Create("example.lock")
|
||||
if err := unix.Flock(int(f.Fd()), unix.LOCK_EX); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Do work here that requires the lock. When finished, release the lock:
|
||||
if err := unix.Flock(int(f.Fd()), unix.LOCK_UN); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
9
vendor/golang.org/x/sys/unix/export_test.go
generated
vendored
9
vendor/golang.org/x/sys/unix/export_test.go
generated
vendored
@ -1,9 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix
|
||||
|
||||
var Itoa = itoa
|
53
vendor/golang.org/x/sys/unix/linux/Dockerfile
generated
vendored
53
vendor/golang.org/x/sys/unix/linux/Dockerfile
generated
vendored
@ -1,53 +0,0 @@
|
||||
FROM ubuntu:18.10
|
||||
|
||||
# Dependencies to get the git sources and go binaries
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Get the git sources. If not cached, this takes O(5 minutes).
|
||||
WORKDIR /git
|
||||
RUN git config --global advice.detachedHead false
|
||||
# Linux Kernel: Released 23 Dec 2018
|
||||
RUN git clone --branch v4.20 --depth 1 https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
|
||||
# GNU C library: Released 01 Aug 2018 (we should try to get a secure way to clone this)
|
||||
RUN git clone --branch glibc-2.28 --depth 1 git://sourceware.org/git/glibc.git
|
||||
|
||||
# Get Go
|
||||
ENV GOLANG_VERSION 1.12beta1
|
||||
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
|
||||
ENV GOLANG_DOWNLOAD_SHA256 65bfd4a99925f1f85d712f4c1109977aa24ee4c6e198162bf8e819fdde19e875
|
||||
|
||||
RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
|
||||
&& echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \
|
||||
&& tar -C /usr/local -xzf golang.tar.gz \
|
||||
&& rm golang.tar.gz
|
||||
|
||||
ENV PATH /usr/local/go/bin:$PATH
|
||||
|
||||
# Linux and Glibc build dependencies and emulator
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
bison gawk make python \
|
||||
gcc gcc-multilib \
|
||||
gettext texinfo \
|
||||
qemu-user \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
# Cross compilers (install recommended packages to get cross libc-dev)
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc-aarch64-linux-gnu gcc-arm-linux-gnueabi \
|
||||
gcc-mips-linux-gnu gcc-mips64-linux-gnuabi64 \
|
||||
gcc-mips64el-linux-gnuabi64 gcc-mipsel-linux-gnu \
|
||||
gcc-powerpc64-linux-gnu gcc-powerpc64le-linux-gnu \
|
||||
gcc-riscv64-linux-gnu \
|
||||
gcc-s390x-linux-gnu gcc-sparc64-linux-gnu \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Let the scripts know they are in the docker environment
|
||||
ENV GOLANG_SYS_BUILD docker
|
||||
WORKDIR /build
|
||||
ENTRYPOINT ["go", "run", "linux/mkall.go", "/git/linux", "/git/glibc"]
|
775
vendor/golang.org/x/sys/unix/linux/mkall.go
generated
vendored
775
vendor/golang.org/x/sys/unix/linux/mkall.go
generated
vendored
@ -1,775 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// linux/mkall.go - Generates all Linux zsysnum, zsyscall, zerror, and ztype
|
||||
// files for all Linux architectures supported by the go compiler. See
|
||||
// README.md for more information about the build system.
|
||||
|
||||
// To run it you must have a git checkout of the Linux kernel and glibc. Once
|
||||
// the appropriate sources are ready, the program is run as:
|
||||
// go run linux/mkall.go <linux_dir> <glibc_dir>
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// These will be paths to the appropriate source directories.
|
||||
var LinuxDir string
|
||||
var GlibcDir string
|
||||
|
||||
const TempDir = "/tmp"
|
||||
const IncludeDir = TempDir + "/include" // To hold our C headers
|
||||
const BuildDir = TempDir + "/build" // To hold intermediate build files
|
||||
|
||||
const GOOS = "linux" // Only for Linux targets
|
||||
const BuildArch = "amd64" // Must be built on this architecture
|
||||
const MinKernel = "2.6.23" // https://golang.org/doc/install#requirements
|
||||
|
||||
type target struct {
|
||||
GoArch string // Architecture name according to Go
|
||||
LinuxArch string // Architecture name according to the Linux Kernel
|
||||
GNUArch string // Architecture name according to GNU tools (https://wiki.debian.org/Multiarch/Tuples)
|
||||
BigEndian bool // Default Little Endian
|
||||
SignedChar bool // Is -fsigned-char needed (default no)
|
||||
Bits int
|
||||
}
|
||||
|
||||
// List of all Linux targets supported by the go compiler. Currently, riscv64
|
||||
// and sparc64 are not fully supported, but there is enough support already to
|
||||
// generate Go type and error definitions.
|
||||
var targets = []target{
|
||||
{
|
||||
GoArch: "386",
|
||||
LinuxArch: "x86",
|
||||
GNUArch: "i686-linux-gnu", // Note "i686" not "i386"
|
||||
Bits: 32,
|
||||
},
|
||||
{
|
||||
GoArch: "amd64",
|
||||
LinuxArch: "x86",
|
||||
GNUArch: "x86_64-linux-gnu",
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "arm64",
|
||||
LinuxArch: "arm64",
|
||||
GNUArch: "aarch64-linux-gnu",
|
||||
SignedChar: true,
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "arm",
|
||||
LinuxArch: "arm",
|
||||
GNUArch: "arm-linux-gnueabi",
|
||||
Bits: 32,
|
||||
},
|
||||
{
|
||||
GoArch: "mips",
|
||||
LinuxArch: "mips",
|
||||
GNUArch: "mips-linux-gnu",
|
||||
BigEndian: true,
|
||||
Bits: 32,
|
||||
},
|
||||
{
|
||||
GoArch: "mipsle",
|
||||
LinuxArch: "mips",
|
||||
GNUArch: "mipsel-linux-gnu",
|
||||
Bits: 32,
|
||||
},
|
||||
{
|
||||
GoArch: "mips64",
|
||||
LinuxArch: "mips",
|
||||
GNUArch: "mips64-linux-gnuabi64",
|
||||
BigEndian: true,
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "mips64le",
|
||||
LinuxArch: "mips",
|
||||
GNUArch: "mips64el-linux-gnuabi64",
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "ppc64",
|
||||
LinuxArch: "powerpc",
|
||||
GNUArch: "powerpc64-linux-gnu",
|
||||
BigEndian: true,
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "ppc64le",
|
||||
LinuxArch: "powerpc",
|
||||
GNUArch: "powerpc64le-linux-gnu",
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "riscv64",
|
||||
LinuxArch: "riscv",
|
||||
GNUArch: "riscv64-linux-gnu",
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "s390x",
|
||||
LinuxArch: "s390",
|
||||
GNUArch: "s390x-linux-gnu",
|
||||
BigEndian: true,
|
||||
SignedChar: true,
|
||||
Bits: 64,
|
||||
},
|
||||
{
|
||||
GoArch: "sparc64",
|
||||
LinuxArch: "sparc",
|
||||
GNUArch: "sparc64-linux-gnu",
|
||||
BigEndian: true,
|
||||
Bits: 64,
|
||||
},
|
||||
}
|
||||
|
||||
// ptracePairs is a list of pairs of targets that can, in some cases,
|
||||
// run each other's binaries.
|
||||
var ptracePairs = []struct{ a1, a2 string }{
|
||||
{"386", "amd64"},
|
||||
{"arm", "arm64"},
|
||||
{"mips", "mips64"},
|
||||
{"mipsle", "mips64le"},
|
||||
}
|
||||
|
||||
func main() {
|
||||
if runtime.GOOS != GOOS || runtime.GOARCH != BuildArch {
|
||||
fmt.Printf("Build system has GOOS_GOARCH = %s_%s, need %s_%s\n",
|
||||
runtime.GOOS, runtime.GOARCH, GOOS, BuildArch)
|
||||
return
|
||||
}
|
||||
|
||||
// Check that we are using the new build system if we should
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
fmt.Println("In the new build system, mkall.go should not be called directly.")
|
||||
fmt.Println("See README.md")
|
||||
return
|
||||
}
|
||||
|
||||
// Parse the command line options
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Println("USAGE: go run linux/mkall.go <linux_dir> <glibc_dir>")
|
||||
return
|
||||
}
|
||||
LinuxDir = os.Args[1]
|
||||
GlibcDir = os.Args[2]
|
||||
|
||||
for _, t := range targets {
|
||||
fmt.Printf("----- GENERATING: %s -----\n", t.GoArch)
|
||||
if err := t.generateFiles(); err != nil {
|
||||
fmt.Printf("%v\n***** FAILURE: %s *****\n\n", err, t.GoArch)
|
||||
} else {
|
||||
fmt.Printf("----- SUCCESS: %s -----\n\n", t.GoArch)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("----- GENERATING ptrace pairs -----\n")
|
||||
ok := true
|
||||
for _, p := range ptracePairs {
|
||||
if err := generatePtracePair(p.a1, p.a2); err != nil {
|
||||
fmt.Printf("%v\n***** FAILURE: %s/%s *****\n\n", err, p.a1, p.a2)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
fmt.Printf("----- SUCCESS ptrace pairs -----\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
// Makes an exec.Cmd with Stderr attached to os.Stderr
|
||||
func makeCommand(name string, args ...string) *exec.Cmd {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Set GOARCH for target and build environments.
|
||||
func (t *target) setTargetBuildArch(cmd *exec.Cmd) {
|
||||
// Set GOARCH_TARGET so command knows what GOARCH is..
|
||||
cmd.Env = append(os.Environ(), "GOARCH_TARGET="+t.GoArch)
|
||||
// Set GOARCH to host arch for command, so it can run natively.
|
||||
for i, s := range cmd.Env {
|
||||
if strings.HasPrefix(s, "GOARCH=") {
|
||||
cmd.Env[i] = "GOARCH=" + BuildArch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Runs the command, pipes output to a formatter, pipes that to an output file.
|
||||
func (t *target) commandFormatOutput(formatter string, outputFile string,
|
||||
name string, args ...string) (err error) {
|
||||
mainCmd := makeCommand(name, args...)
|
||||
if name == "mksyscall" {
|
||||
args = append([]string{"run", "mksyscall.go"}, args...)
|
||||
mainCmd = makeCommand("go", args...)
|
||||
t.setTargetBuildArch(mainCmd)
|
||||
} else if name == "mksysnum" {
|
||||
args = append([]string{"run", "linux/mksysnum.go"}, args...)
|
||||
mainCmd = makeCommand("go", args...)
|
||||
t.setTargetBuildArch(mainCmd)
|
||||
}
|
||||
|
||||
fmtCmd := makeCommand(formatter)
|
||||
if formatter == "mkpost" {
|
||||
fmtCmd = makeCommand("go", "run", "mkpost.go")
|
||||
t.setTargetBuildArch(fmtCmd)
|
||||
}
|
||||
|
||||
// mainCmd | fmtCmd > outputFile
|
||||
if fmtCmd.Stdin, err = mainCmd.StdoutPipe(); err != nil {
|
||||
return
|
||||
}
|
||||
if fmtCmd.Stdout, err = os.Create(outputFile); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure the formatter eventually closes
|
||||
if err = fmtCmd.Start(); err != nil {
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
fmtErr := fmtCmd.Wait()
|
||||
if err == nil {
|
||||
err = fmtErr
|
||||
}
|
||||
}()
|
||||
|
||||
return mainCmd.Run()
|
||||
}
|
||||
|
||||
// Generates all the files for a Linux target
|
||||
func (t *target) generateFiles() error {
|
||||
// Setup environment variables
|
||||
os.Setenv("GOOS", GOOS)
|
||||
os.Setenv("GOARCH", t.GoArch)
|
||||
|
||||
// Get appropriate compiler and emulator (unless on x86)
|
||||
if t.LinuxArch != "x86" {
|
||||
// Check/Setup cross compiler
|
||||
compiler := t.GNUArch + "-gcc"
|
||||
if _, err := exec.LookPath(compiler); err != nil {
|
||||
return err
|
||||
}
|
||||
os.Setenv("CC", compiler)
|
||||
|
||||
// Check/Setup emulator (usually first component of GNUArch)
|
||||
qemuArchName := t.GNUArch[:strings.Index(t.GNUArch, "-")]
|
||||
if t.LinuxArch == "powerpc" {
|
||||
qemuArchName = t.GoArch
|
||||
}
|
||||
// Fake uname for QEMU to allow running on Host kernel version < 4.15
|
||||
if t.LinuxArch == "riscv" {
|
||||
os.Setenv("QEMU_UNAME", "4.15")
|
||||
}
|
||||
os.Setenv("GORUN", "qemu-"+qemuArchName)
|
||||
} else {
|
||||
os.Setenv("CC", "gcc")
|
||||
}
|
||||
|
||||
// Make the include directory and fill it with headers
|
||||
if err := os.MkdirAll(IncludeDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(IncludeDir)
|
||||
if err := t.makeHeaders(); err != nil {
|
||||
return fmt.Errorf("could not make header files: %v", err)
|
||||
}
|
||||
fmt.Println("header files generated")
|
||||
|
||||
// Make each of the four files
|
||||
if err := t.makeZSysnumFile(); err != nil {
|
||||
return fmt.Errorf("could not make zsysnum file: %v", err)
|
||||
}
|
||||
fmt.Println("zsysnum file generated")
|
||||
|
||||
if err := t.makeZSyscallFile(); err != nil {
|
||||
return fmt.Errorf("could not make zsyscall file: %v", err)
|
||||
}
|
||||
fmt.Println("zsyscall file generated")
|
||||
|
||||
if err := t.makeZTypesFile(); err != nil {
|
||||
return fmt.Errorf("could not make ztypes file: %v", err)
|
||||
}
|
||||
fmt.Println("ztypes file generated")
|
||||
|
||||
if err := t.makeZErrorsFile(); err != nil {
|
||||
return fmt.Errorf("could not make zerrors file: %v", err)
|
||||
}
|
||||
fmt.Println("zerrors file generated")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create the Linux, glibc and ABI (C compiler convention) headers in the include directory.
|
||||
func (t *target) makeHeaders() error {
|
||||
// Make the Linux headers we need for this architecture
|
||||
linuxMake := makeCommand("make", "headers_install", "ARCH="+t.LinuxArch, "INSTALL_HDR_PATH="+TempDir)
|
||||
linuxMake.Dir = LinuxDir
|
||||
if err := linuxMake.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// A Temporary build directory for glibc
|
||||
if err := os.MkdirAll(BuildDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(BuildDir)
|
||||
|
||||
// Make the glibc headers we need for this architecture
|
||||
confScript := filepath.Join(GlibcDir, "configure")
|
||||
glibcConf := makeCommand(confScript, "--prefix="+TempDir, "--host="+t.GNUArch, "--enable-kernel="+MinKernel)
|
||||
glibcConf.Dir = BuildDir
|
||||
if err := glibcConf.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
glibcMake := makeCommand("make", "install-headers")
|
||||
glibcMake.Dir = BuildDir
|
||||
if err := glibcMake.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
// We only need an empty stubs file
|
||||
stubsFile := filepath.Join(IncludeDir, "gnu/stubs.h")
|
||||
if file, err := os.Create(stubsFile); err != nil {
|
||||
return err
|
||||
} else {
|
||||
file.Close()
|
||||
}
|
||||
|
||||
// ABI headers will specify C compiler behavior for the target platform.
|
||||
return t.makeABIHeaders()
|
||||
}
|
||||
|
||||
// makeABIHeaders generates C header files based on the platform's calling convention.
|
||||
// While many platforms have formal Application Binary Interfaces, in practice, whatever the
|
||||
// dominant C compilers generate is the de-facto calling convention.
|
||||
//
|
||||
// We generate C headers instead of a Go file, so as to enable references to the ABI from Cgo.
|
||||
func (t *target) makeABIHeaders() (err error) {
|
||||
abiDir := filepath.Join(IncludeDir, "abi")
|
||||
if err = os.Mkdir(abiDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cc := os.Getenv("CC")
|
||||
if cc == "" {
|
||||
return errors.New("CC (compiler) env var not set")
|
||||
}
|
||||
|
||||
// Build a sacrificial ELF file, to mine for C compiler behavior.
|
||||
binPath := filepath.Join(TempDir, "tmp_abi.o")
|
||||
bin, err := t.buildELF(cc, cCode, binPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot build ELF to analyze: %v", err)
|
||||
}
|
||||
defer bin.Close()
|
||||
defer os.Remove(binPath)
|
||||
|
||||
// Right now, we put everything in abi.h, but we may change this later.
|
||||
abiFile, err := os.Create(filepath.Join(abiDir, "abi.h"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if cerr := abiFile.Close(); cerr != nil && err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
|
||||
if err = t.writeBitFieldMasks(bin, abiFile); err != nil {
|
||||
return fmt.Errorf("cannot write bitfield masks: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *target) buildELF(cc, src, path string) (*elf.File, error) {
|
||||
// Compile the cCode source using the set compiler - we will need its .data section.
|
||||
// Do not link the binary, so that we can find .data section offsets from the symbol values.
|
||||
ccCmd := makeCommand(cc, "-o", path, "-gdwarf", "-x", "c", "-c", "-")
|
||||
ccCmd.Stdin = strings.NewReader(src)
|
||||
ccCmd.Stdout = os.Stdout
|
||||
if err := ccCmd.Run(); err != nil {
|
||||
return nil, fmt.Errorf("compiler error: %v", err)
|
||||
}
|
||||
|
||||
bin, err := elf.Open(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read ELF file %s: %v", path, err)
|
||||
}
|
||||
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
func (t *target) writeBitFieldMasks(bin *elf.File, out io.Writer) error {
|
||||
symbols, err := bin.Symbols()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting ELF symbols: %v", err)
|
||||
}
|
||||
var masksSym *elf.Symbol
|
||||
|
||||
for _, sym := range symbols {
|
||||
if sym.Name == "masks" {
|
||||
masksSym = &sym
|
||||
}
|
||||
}
|
||||
|
||||
if masksSym == nil {
|
||||
return errors.New("could not find the 'masks' symbol in ELF symtab")
|
||||
}
|
||||
|
||||
dataSection := bin.Section(".data")
|
||||
if dataSection == nil {
|
||||
return errors.New("ELF file has no .data section")
|
||||
}
|
||||
|
||||
data, err := dataSection.Data()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not read .data section: %v\n", err)
|
||||
}
|
||||
|
||||
var bo binary.ByteOrder
|
||||
if t.BigEndian {
|
||||
bo = binary.BigEndian
|
||||
} else {
|
||||
bo = binary.LittleEndian
|
||||
}
|
||||
|
||||
// 64 bit masks of type uint64 are stored in the data section starting at masks.Value.
|
||||
// Here we are running on AMD64, but these values may be big endian or little endian,
|
||||
// depending on target architecture.
|
||||
for i := uint64(0); i < 64; i++ {
|
||||
off := masksSym.Value + i*8
|
||||
// Define each mask in native by order, so as to match target endian.
|
||||
fmt.Fprintf(out, "#define BITFIELD_MASK_%d %dULL\n", i, bo.Uint64(data[off:off+8]))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// makes the zsysnum_linux_$GOARCH.go file
|
||||
func (t *target) makeZSysnumFile() error {
|
||||
zsysnumFile := fmt.Sprintf("zsysnum_linux_%s.go", t.GoArch)
|
||||
unistdFile := filepath.Join(IncludeDir, "asm/unistd.h")
|
||||
|
||||
args := append(t.cFlags(), unistdFile)
|
||||
return t.commandFormatOutput("gofmt", zsysnumFile, "mksysnum", args...)
|
||||
}
|
||||
|
||||
// makes the zsyscall_linux_$GOARCH.go file
|
||||
func (t *target) makeZSyscallFile() error {
|
||||
zsyscallFile := fmt.Sprintf("zsyscall_linux_%s.go", t.GoArch)
|
||||
// Find the correct architecture syscall file (might end with x.go)
|
||||
archSyscallFile := fmt.Sprintf("syscall_linux_%s.go", t.GoArch)
|
||||
if _, err := os.Stat(archSyscallFile); os.IsNotExist(err) {
|
||||
shortArch := strings.TrimSuffix(t.GoArch, "le")
|
||||
archSyscallFile = fmt.Sprintf("syscall_linux_%sx.go", shortArch)
|
||||
}
|
||||
|
||||
args := append(t.mksyscallFlags(), "-tags", "linux,"+t.GoArch,
|
||||
"syscall_linux.go", archSyscallFile)
|
||||
return t.commandFormatOutput("gofmt", zsyscallFile, "mksyscall", args...)
|
||||
}
|
||||
|
||||
// makes the zerrors_linux_$GOARCH.go file
|
||||
func (t *target) makeZErrorsFile() error {
|
||||
zerrorsFile := fmt.Sprintf("zerrors_linux_%s.go", t.GoArch)
|
||||
|
||||
return t.commandFormatOutput("gofmt", zerrorsFile, "./mkerrors.sh", t.cFlags()...)
|
||||
}
|
||||
|
||||
// makes the ztypes_linux_$GOARCH.go file
|
||||
func (t *target) makeZTypesFile() error {
|
||||
ztypesFile := fmt.Sprintf("ztypes_linux_%s.go", t.GoArch)
|
||||
|
||||
args := []string{"tool", "cgo", "-godefs", "--"}
|
||||
args = append(args, t.cFlags()...)
|
||||
args = append(args, "linux/types.go")
|
||||
return t.commandFormatOutput("mkpost", ztypesFile, "go", args...)
|
||||
}
|
||||
|
||||
// Flags that should be given to gcc and cgo for this target
|
||||
func (t *target) cFlags() []string {
|
||||
// Compile statically to avoid cross-architecture dynamic linking.
|
||||
flags := []string{"-Wall", "-Werror", "-static", "-I" + IncludeDir}
|
||||
|
||||
// Architecture-specific flags
|
||||
if t.SignedChar {
|
||||
flags = append(flags, "-fsigned-char")
|
||||
}
|
||||
if t.LinuxArch == "x86" {
|
||||
flags = append(flags, fmt.Sprintf("-m%d", t.Bits))
|
||||
}
|
||||
|
||||
return flags
|
||||
}
|
||||
|
||||
// Flags that should be given to mksyscall for this target
|
||||
func (t *target) mksyscallFlags() (flags []string) {
|
||||
if t.Bits == 32 {
|
||||
if t.BigEndian {
|
||||
flags = append(flags, "-b32")
|
||||
} else {
|
||||
flags = append(flags, "-l32")
|
||||
}
|
||||
}
|
||||
|
||||
// This flag means a 64-bit value should use (even, odd)-pair.
|
||||
if t.GoArch == "arm" || (t.LinuxArch == "mips" && t.Bits == 32) {
|
||||
flags = append(flags, "-arm")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// generatePtracePair takes a pair of GOARCH values that can run each
|
||||
// other's binaries, such as 386 and amd64. It extracts the PtraceRegs
|
||||
// type for each one. It writes a new file defining the types
|
||||
// PtraceRegsArch1 and PtraceRegsArch2 and the corresponding functions
|
||||
// Ptrace{Get,Set}Regs{arch1,arch2}. This permits debugging the other
|
||||
// binary on a native system.
|
||||
func generatePtracePair(arch1, arch2 string) error {
|
||||
def1, err := ptraceDef(arch1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
def2, err := ptraceDef(arch2)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
f, err := os.Create(fmt.Sprintf("zptrace%s_linux.go", arch1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
buf := bufio.NewWriter(f)
|
||||
fmt.Fprintf(buf, "// Code generated by linux/mkall.go generatePtracePair(%s, %s). DO NOT EDIT.\n", arch1, arch2)
|
||||
fmt.Fprintf(buf, "\n")
|
||||
fmt.Fprintf(buf, "// +build linux\n")
|
||||
fmt.Fprintf(buf, "// +build %s %s\n", arch1, arch2)
|
||||
fmt.Fprintf(buf, "\n")
|
||||
fmt.Fprintf(buf, "package unix\n")
|
||||
fmt.Fprintf(buf, "\n")
|
||||
fmt.Fprintf(buf, "%s\n", `import "unsafe"`)
|
||||
fmt.Fprintf(buf, "\n")
|
||||
writeOnePtrace(buf, arch1, def1)
|
||||
fmt.Fprintf(buf, "\n")
|
||||
writeOnePtrace(buf, arch2, def2)
|
||||
if err := buf.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ptraceDef returns the definition of PtraceRegs for arch.
|
||||
func ptraceDef(arch string) (string, error) {
|
||||
filename := fmt.Sprintf("ztypes_linux_%s.go", arch)
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("reading %s: %v", filename, err)
|
||||
}
|
||||
start := bytes.Index(data, []byte("type PtraceRegs struct"))
|
||||
if start < 0 {
|
||||
return "", fmt.Errorf("%s: no definition of PtraceRegs", filename)
|
||||
}
|
||||
data = data[start:]
|
||||
end := bytes.Index(data, []byte("\n}\n"))
|
||||
if end < 0 {
|
||||
return "", fmt.Errorf("%s: can't find end of PtraceRegs definition", filename)
|
||||
}
|
||||
return string(data[:end+2]), nil
|
||||
}
|
||||
|
||||
// writeOnePtrace writes out the ptrace definitions for arch.
|
||||
func writeOnePtrace(w io.Writer, arch, def string) {
|
||||
uarch := string(unicode.ToUpper(rune(arch[0]))) + arch[1:]
|
||||
fmt.Fprintf(w, "// PtraceRegs%s is the registers used by %s binaries.\n", uarch, arch)
|
||||
fmt.Fprintf(w, "%s\n", strings.Replace(def, "PtraceRegs", "PtraceRegs"+uarch, 1))
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, "// PtraceGetRegs%s fetches the registers used by %s binaries.\n", uarch, arch)
|
||||
fmt.Fprintf(w, "func PtraceGetRegs%s(pid int, regsout *PtraceRegs%s) error {\n", uarch, uarch)
|
||||
fmt.Fprintf(w, "\treturn ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))\n")
|
||||
fmt.Fprintf(w, "}\n")
|
||||
fmt.Fprintf(w, "\n")
|
||||
fmt.Fprintf(w, "// PtraceSetRegs%s sets the registers used by %s binaries.\n", uarch, arch)
|
||||
fmt.Fprintf(w, "func PtraceSetRegs%s(pid int, regs *PtraceRegs%s) error {\n", uarch, uarch)
|
||||
fmt.Fprintf(w, "\treturn ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))\n")
|
||||
fmt.Fprintf(w, "}\n")
|
||||
}
|
||||
|
||||
// cCode is compiled for the target architecture, and the resulting data section is carved for
|
||||
// the statically initialized bit masks.
|
||||
const cCode = `
|
||||
// Bit fields are used in some system calls and other ABIs, but their memory layout is
|
||||
// implementation-defined [1]. Even with formal ABIs, bit fields are a source of subtle bugs [2].
|
||||
// Here we generate the offsets for all 64 bits in an uint64.
|
||||
// 1: http://en.cppreference.com/w/c/language/bit_field
|
||||
// 2: https://lwn.net/Articles/478657/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct bitfield {
|
||||
union {
|
||||
uint64_t val;
|
||||
struct {
|
||||
uint64_t u64_bit_0 : 1;
|
||||
uint64_t u64_bit_1 : 1;
|
||||
uint64_t u64_bit_2 : 1;
|
||||
uint64_t u64_bit_3 : 1;
|
||||
uint64_t u64_bit_4 : 1;
|
||||
uint64_t u64_bit_5 : 1;
|
||||
uint64_t u64_bit_6 : 1;
|
||||
uint64_t u64_bit_7 : 1;
|
||||
uint64_t u64_bit_8 : 1;
|
||||
uint64_t u64_bit_9 : 1;
|
||||
uint64_t u64_bit_10 : 1;
|
||||
uint64_t u64_bit_11 : 1;
|
||||
uint64_t u64_bit_12 : 1;
|
||||
uint64_t u64_bit_13 : 1;
|
||||
uint64_t u64_bit_14 : 1;
|
||||
uint64_t u64_bit_15 : 1;
|
||||
uint64_t u64_bit_16 : 1;
|
||||
uint64_t u64_bit_17 : 1;
|
||||
uint64_t u64_bit_18 : 1;
|
||||
uint64_t u64_bit_19 : 1;
|
||||
uint64_t u64_bit_20 : 1;
|
||||
uint64_t u64_bit_21 : 1;
|
||||
uint64_t u64_bit_22 : 1;
|
||||
uint64_t u64_bit_23 : 1;
|
||||
uint64_t u64_bit_24 : 1;
|
||||
uint64_t u64_bit_25 : 1;
|
||||
uint64_t u64_bit_26 : 1;
|
||||
uint64_t u64_bit_27 : 1;
|
||||
uint64_t u64_bit_28 : 1;
|
||||
uint64_t u64_bit_29 : 1;
|
||||
uint64_t u64_bit_30 : 1;
|
||||
uint64_t u64_bit_31 : 1;
|
||||
uint64_t u64_bit_32 : 1;
|
||||
uint64_t u64_bit_33 : 1;
|
||||
uint64_t u64_bit_34 : 1;
|
||||
uint64_t u64_bit_35 : 1;
|
||||
uint64_t u64_bit_36 : 1;
|
||||
uint64_t u64_bit_37 : 1;
|
||||
uint64_t u64_bit_38 : 1;
|
||||
uint64_t u64_bit_39 : 1;
|
||||
uint64_t u64_bit_40 : 1;
|
||||
uint64_t u64_bit_41 : 1;
|
||||
uint64_t u64_bit_42 : 1;
|
||||
uint64_t u64_bit_43 : 1;
|
||||
uint64_t u64_bit_44 : 1;
|
||||
uint64_t u64_bit_45 : 1;
|
||||
uint64_t u64_bit_46 : 1;
|
||||
uint64_t u64_bit_47 : 1;
|
||||
uint64_t u64_bit_48 : 1;
|
||||
uint64_t u64_bit_49 : 1;
|
||||
uint64_t u64_bit_50 : 1;
|
||||
uint64_t u64_bit_51 : 1;
|
||||
uint64_t u64_bit_52 : 1;
|
||||
uint64_t u64_bit_53 : 1;
|
||||
uint64_t u64_bit_54 : 1;
|
||||
uint64_t u64_bit_55 : 1;
|
||||
uint64_t u64_bit_56 : 1;
|
||||
uint64_t u64_bit_57 : 1;
|
||||
uint64_t u64_bit_58 : 1;
|
||||
uint64_t u64_bit_59 : 1;
|
||||
uint64_t u64_bit_60 : 1;
|
||||
uint64_t u64_bit_61 : 1;
|
||||
uint64_t u64_bit_62 : 1;
|
||||
uint64_t u64_bit_63 : 1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct bitfield masks[] = {
|
||||
{.u64_bit_0 = 1},
|
||||
{.u64_bit_1 = 1},
|
||||
{.u64_bit_2 = 1},
|
||||
{.u64_bit_3 = 1},
|
||||
{.u64_bit_4 = 1},
|
||||
{.u64_bit_5 = 1},
|
||||
{.u64_bit_6 = 1},
|
||||
{.u64_bit_7 = 1},
|
||||
{.u64_bit_8 = 1},
|
||||
{.u64_bit_9 = 1},
|
||||
{.u64_bit_10 = 1},
|
||||
{.u64_bit_11 = 1},
|
||||
{.u64_bit_12 = 1},
|
||||
{.u64_bit_13 = 1},
|
||||
{.u64_bit_14 = 1},
|
||||
{.u64_bit_15 = 1},
|
||||
{.u64_bit_16 = 1},
|
||||
{.u64_bit_17 = 1},
|
||||
{.u64_bit_18 = 1},
|
||||
{.u64_bit_19 = 1},
|
||||
{.u64_bit_20 = 1},
|
||||
{.u64_bit_21 = 1},
|
||||
{.u64_bit_22 = 1},
|
||||
{.u64_bit_23 = 1},
|
||||
{.u64_bit_24 = 1},
|
||||
{.u64_bit_25 = 1},
|
||||
{.u64_bit_26 = 1},
|
||||
{.u64_bit_27 = 1},
|
||||
{.u64_bit_28 = 1},
|
||||
{.u64_bit_29 = 1},
|
||||
{.u64_bit_30 = 1},
|
||||
{.u64_bit_31 = 1},
|
||||
{.u64_bit_32 = 1},
|
||||
{.u64_bit_33 = 1},
|
||||
{.u64_bit_34 = 1},
|
||||
{.u64_bit_35 = 1},
|
||||
{.u64_bit_36 = 1},
|
||||
{.u64_bit_37 = 1},
|
||||
{.u64_bit_38 = 1},
|
||||
{.u64_bit_39 = 1},
|
||||
{.u64_bit_40 = 1},
|
||||
{.u64_bit_41 = 1},
|
||||
{.u64_bit_42 = 1},
|
||||
{.u64_bit_43 = 1},
|
||||
{.u64_bit_44 = 1},
|
||||
{.u64_bit_45 = 1},
|
||||
{.u64_bit_46 = 1},
|
||||
{.u64_bit_47 = 1},
|
||||
{.u64_bit_48 = 1},
|
||||
{.u64_bit_49 = 1},
|
||||
{.u64_bit_50 = 1},
|
||||
{.u64_bit_51 = 1},
|
||||
{.u64_bit_52 = 1},
|
||||
{.u64_bit_53 = 1},
|
||||
{.u64_bit_54 = 1},
|
||||
{.u64_bit_55 = 1},
|
||||
{.u64_bit_56 = 1},
|
||||
{.u64_bit_57 = 1},
|
||||
{.u64_bit_58 = 1},
|
||||
{.u64_bit_59 = 1},
|
||||
{.u64_bit_60 = 1},
|
||||
{.u64_bit_61 = 1},
|
||||
{.u64_bit_62 = 1},
|
||||
{.u64_bit_63 = 1}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct bitfield *mask_ptr = &masks[0];
|
||||
return mask_ptr->val;
|
||||
}
|
||||
|
||||
`
|
143
vendor/golang.org/x/sys/unix/linux/mksysnum.go
generated
vendored
143
vendor/golang.org/x/sys/unix/linux/mksysnum.go
generated
vendored
@ -1,143 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
goos, goarch string
|
||||
)
|
||||
|
||||
// cmdLine returns this programs's commandline arguments
|
||||
func cmdLine() string {
|
||||
return "go run linux/mksysnum.go " + strings.Join(os.Args[1:], " ")
|
||||
}
|
||||
|
||||
// buildTags returns build tags
|
||||
func buildTags() string {
|
||||
return fmt.Sprintf("%s,%s", goarch, goos)
|
||||
}
|
||||
|
||||
func format(name string, num int, offset int) string {
|
||||
if num > 999 {
|
||||
// ignore deprecated syscalls that are no longer implemented
|
||||
// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/asm-generic/unistd.h?id=refs/heads/master#n716
|
||||
return ""
|
||||
}
|
||||
name = strings.ToUpper(name)
|
||||
num = num + offset
|
||||
return fmt.Sprintf(" SYS_%s = %d;\n", name, num)
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// source string and substring slice for regexp
|
||||
type re struct {
|
||||
str string // source string
|
||||
sub []string // matched sub-string
|
||||
}
|
||||
|
||||
// Match performs regular expression match
|
||||
func (r *re) Match(exp string) bool {
|
||||
r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
|
||||
if r.sub != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the OS and architecture (using GOARCH_TARGET if it exists)
|
||||
goos = os.Getenv("GOOS")
|
||||
goarch = os.Getenv("GOARCH_TARGET")
|
||||
if goarch == "" {
|
||||
goarch = os.Getenv("GOARCH")
|
||||
}
|
||||
// Check if GOOS and GOARCH environment variables are defined
|
||||
if goarch == "" || goos == "" {
|
||||
fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
// Check that we are using the new build system if we should
|
||||
if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
|
||||
fmt.Fprintf(os.Stderr, "In the new build system, mksysnum should not be called directly.\n")
|
||||
fmt.Fprintf(os.Stderr, "See README.md\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cc := os.Getenv("CC")
|
||||
if cc == "" {
|
||||
fmt.Fprintf(os.Stderr, "CC is not defined in environment\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
args := os.Args[1:]
|
||||
args = append([]string{"-E", "-dD"}, args...)
|
||||
cmd, err := exec.Command(cc, args...).Output() // execute command and capture output
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "can't run %s", cc)
|
||||
os.Exit(1)
|
||||
}
|
||||
text := ""
|
||||
s := bufio.NewScanner(strings.NewReader(string(cmd)))
|
||||
var offset, prev int
|
||||
for s.Scan() {
|
||||
t := re{str: s.Text()}
|
||||
if t.Match(`^#define __NR_Linux\s+([0-9]+)`) {
|
||||
// mips/mips64: extract offset
|
||||
offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
|
||||
} else if t.Match(`^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)`) {
|
||||
// arm: extract offset
|
||||
offset, _ = strconv.Atoi(t.sub[1]) // Make offset=0 if empty or non-numeric
|
||||
} else if t.Match(`^#define __NR_syscalls\s+`) {
|
||||
// ignore redefinitions of __NR_syscalls
|
||||
} else if t.Match(`^#define __NR_(\w*)Linux_syscalls\s+`) {
|
||||
// mips/mips64: ignore definitions about the number of syscalls
|
||||
} else if t.Match(`^#define __NR_(\w+)\s+([0-9]+)`) {
|
||||
prev, err = strconv.Atoi(t.sub[2])
|
||||
checkErr(err)
|
||||
text += format(t.sub[1], prev, offset)
|
||||
} else if t.Match(`^#define __NR3264_(\w+)\s+([0-9]+)`) {
|
||||
prev, err = strconv.Atoi(t.sub[2])
|
||||
checkErr(err)
|
||||
text += format(t.sub[1], prev, offset)
|
||||
} else if t.Match(`^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)`) {
|
||||
r2, err := strconv.Atoi(t.sub[2])
|
||||
checkErr(err)
|
||||
text += format(t.sub[1], prev+r2, offset)
|
||||
} else if t.Match(`^#define __NR_(\w+)\s+\(__NR_(?:SYSCALL_BASE|Linux) \+ ([0-9]+)`) {
|
||||
r2, err := strconv.Atoi(t.sub[2])
|
||||
checkErr(err)
|
||||
text += format(t.sub[1], r2, offset)
|
||||
}
|
||||
}
|
||||
err = s.Err()
|
||||
checkErr(err)
|
||||
fmt.Printf(template, cmdLine(), buildTags(), text)
|
||||
}
|
||||
|
||||
const template = `// %s
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build %s
|
||||
|
||||
package unix
|
||||
|
||||
const(
|
||||
%s)`
|
1667
vendor/golang.org/x/sys/unix/linux/types.go
generated
vendored
1667
vendor/golang.org/x/sys/unix/linux/types.go
generated
vendored
File diff suppressed because it is too large
Load Diff
214
vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
214
vendor/golang.org/x/sys/unix/mkall.sh
generated
vendored
@ -1,214 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# 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.
|
||||
|
||||
# This script runs or (given -n) prints suggested commands to generate files for
|
||||
# the Architecture/OS specified by the GOARCH and GOOS environment variables.
|
||||
# See README.md for more information about how the build system works.
|
||||
|
||||
GOOSARCH="${GOOS}_${GOARCH}"
|
||||
|
||||
# defaults
|
||||
mksyscall="go run mksyscall.go"
|
||||
mkerrors="./mkerrors.sh"
|
||||
zerrors="zerrors_$GOOSARCH.go"
|
||||
mksysctl=""
|
||||
zsysctl="zsysctl_$GOOSARCH.go"
|
||||
mksysnum=
|
||||
mktypes=
|
||||
mkasm=
|
||||
run="sh"
|
||||
cmd=""
|
||||
|
||||
case "$1" in
|
||||
-syscalls)
|
||||
for i in zsyscall*go
|
||||
do
|
||||
# Run the command line that appears in the first line
|
||||
# of the generated file to regenerate it.
|
||||
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
|
||||
rm _$i
|
||||
done
|
||||
exit 0
|
||||
;;
|
||||
-n)
|
||||
run="cat"
|
||||
cmd="echo"
|
||||
shift
|
||||
esac
|
||||
|
||||
case "$#" in
|
||||
0)
|
||||
;;
|
||||
*)
|
||||
echo 'usage: mkall.sh [-n]' 1>&2
|
||||
exit 2
|
||||
esac
|
||||
|
||||
if [[ "$GOOS" = "linux" ]]; then
|
||||
# Use the Docker-based build system
|
||||
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
|
||||
$cmd docker build --tag generate:$GOOS $GOOS
|
||||
$cmd docker run --interactive --tty --volume $(dirname "$(readlink -f "$0")"):/build generate:$GOOS
|
||||
exit
|
||||
fi
|
||||
|
||||
GOOSARCH_in=syscall_$GOOSARCH.go
|
||||
case "$GOOSARCH" in
|
||||
_* | *_ | _)
|
||||
echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
aix_ppc)
|
||||
mkerrors="$mkerrors -maix32"
|
||||
mksyscall="go run mksyscall_aix_ppc.go -aix"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
aix_ppc64)
|
||||
mkerrors="$mkerrors -maix64"
|
||||
mksyscall="./mksyscall_aix_ppc64.pl -aix"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
darwin_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="go run mksyscall.go -l32"
|
||||
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
mkasm="go run mkasm_darwin.go"
|
||||
;;
|
||||
darwin_amd64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk macosx)/usr/include/sys/syscall.h"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
mkasm="go run mkasm_darwin.go"
|
||||
;;
|
||||
darwin_arm)
|
||||
mkerrors="$mkerrors"
|
||||
mksyscall="go run mksyscall.go -l32"
|
||||
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
mkasm="go run mkasm_darwin.go"
|
||||
;;
|
||||
darwin_arm64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go $(xcrun --show-sdk-path --sdk iphoneos)/usr/include/sys/syscall.h"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
mkasm="go run mkasm_darwin.go"
|
||||
;;
|
||||
dragonfly_amd64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksyscall="go run mksyscall.go -dragonfly"
|
||||
mksysnum="go run mksysnum.go 'https://gitweb.dragonflybsd.org/dragonfly.git/blob_plain/HEAD:/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
freebsd_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="go run mksyscall.go -l32"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
freebsd_amd64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
freebsd_arm)
|
||||
mkerrors="$mkerrors"
|
||||
mksyscall="go run mksyscall.go -l32 -arm"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
||||
# Let the type of C char be signed for making the bare syscall
|
||||
# API consistent across platforms.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
freebsd_arm64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum="go run mksysnum.go 'https://svn.freebsd.org/base/stable/10/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
netbsd_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="go run mksyscall.go -l32 -netbsd"
|
||||
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
netbsd_amd64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksyscall="go run mksyscall.go -netbsd"
|
||||
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
netbsd_arm)
|
||||
mkerrors="$mkerrors"
|
||||
mksyscall="go run mksyscall.go -l32 -netbsd -arm"
|
||||
mksysnum="go run mksysnum.go 'http://cvsweb.netbsd.org/bsdweb.cgi/~checkout~/src/sys/kern/syscalls.master'"
|
||||
# Let the type of C char be signed for making the bare syscall
|
||||
# API consistent across platforms.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
openbsd_386)
|
||||
mkerrors="$mkerrors -m32"
|
||||
mksyscall="go run mksyscall.go -l32 -openbsd"
|
||||
mksysctl="./mksysctl_openbsd.pl"
|
||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
openbsd_amd64)
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksyscall="go run mksyscall.go -openbsd"
|
||||
mksysctl="./mksysctl_openbsd.pl"
|
||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
openbsd_arm)
|
||||
mkerrors="$mkerrors"
|
||||
mksyscall="go run mksyscall.go -l32 -openbsd -arm"
|
||||
mksysctl="./mksysctl_openbsd.pl"
|
||||
mksysnum="go run mksysnum.go 'https://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/kern/syscalls.master'"
|
||||
# Let the type of C char be signed for making the bare syscall
|
||||
# API consistent across platforms.
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs -- -fsigned-char"
|
||||
;;
|
||||
solaris_amd64)
|
||||
mksyscall="./mksyscall_solaris.pl"
|
||||
mkerrors="$mkerrors -m64"
|
||||
mksysnum=
|
||||
mktypes="GOARCH=$GOARCH go tool cgo -godefs"
|
||||
;;
|
||||
*)
|
||||
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
(
|
||||
if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
|
||||
case "$GOOS" in
|
||||
*)
|
||||
syscall_goos="syscall_$GOOS.go"
|
||||
case "$GOOS" in
|
||||
darwin | dragonfly | freebsd | netbsd | openbsd)
|
||||
syscall_goos="syscall_bsd.go $syscall_goos"
|
||||
;;
|
||||
esac
|
||||
if [ -n "$mksyscall" ]; then
|
||||
if [ "$GOOSARCH" == "aix_ppc64" ]; then
|
||||
# aix/ppc64 script generates files instead of writing to stdin.
|
||||
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
|
||||
elif [ "$GOOS" == "darwin" ]; then
|
||||
# pre-1.12, direct syscalls
|
||||
echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
|
||||
# 1.12 and later, syscalls via libSystem
|
||||
echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
|
||||
else
|
||||
echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
|
||||
fi
|
||||
fi
|
||||
esac
|
||||
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
|
||||
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
|
||||
if [ -n "$mktypes" ]; then
|
||||
echo "$mktypes types_$GOOS.go | go run mkpost.go > ztypes_$GOOSARCH.go";
|
||||
if [ -n "$mkasm" ]; then echo "$mkasm $GOARCH"; fi
|
||||
fi
|
||||
) | $run
|
665
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
665
vendor/golang.org/x/sys/unix/mkerrors.sh
generated
vendored
@ -1,665 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# 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.
|
||||
|
||||
# Generate Go code listing errors and other #defined constant
|
||||
# values (ENAMETOOLONG etc.), by asking the preprocessor
|
||||
# about the definitions.
|
||||
|
||||
unset LANG
|
||||
export LC_ALL=C
|
||||
export LC_CTYPE=C
|
||||
|
||||
if test -z "$GOARCH" -o -z "$GOOS"; then
|
||||
echo 1>&2 "GOARCH or GOOS not defined in environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that we are using the new build system if we should
|
||||
if [[ "$GOOS" = "linux" ]] && [[ "$GOLANG_SYS_BUILD" != "docker" ]]; then
|
||||
echo 1>&2 "In the Docker based build system, mkerrors should not be called directly."
|
||||
echo 1>&2 "See README.md"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$GOOS" = "aix" ]]; then
|
||||
CC=${CC:-gcc}
|
||||
else
|
||||
CC=${CC:-cc}
|
||||
fi
|
||||
|
||||
if [[ "$GOOS" = "solaris" ]]; then
|
||||
# Assumes GNU versions of utilities in PATH.
|
||||
export PATH=/usr/gnu/bin:$PATH
|
||||
fi
|
||||
|
||||
uname=$(uname)
|
||||
|
||||
includes_AIX='
|
||||
#include <net/if.h>
|
||||
#include <net/netopt.h>
|
||||
#include <netinet/ip_mroute.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/stropts.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/termio.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define AF_LOCAL AF_UNIX
|
||||
'
|
||||
|
||||
includes_Darwin='
|
||||
#define _DARWIN_C_SOURCE
|
||||
#define KERNEL
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#include <stdint.h>
|
||||
#include <sys/attr.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <termios.h>
|
||||
'
|
||||
|
||||
includes_DragonFly='
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <termios.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <net/ip_mroute/ip_mroute.h>
|
||||
'
|
||||
|
||||
includes_FreeBSD='
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <termios.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_mroute.h>
|
||||
#include <sys/extattr.h>
|
||||
|
||||
#if __FreeBSD__ >= 10
|
||||
#define IFT_CARP 0xf8 // IFT_CARP is deprecated in FreeBSD 10
|
||||
#undef SIOCAIFADDR
|
||||
#define SIOCAIFADDR _IOW(105, 26, struct oifaliasreq) // ifaliasreq contains if_data
|
||||
#undef SIOCSIFPHYADDR
|
||||
#define SIOCSIFPHYADDR _IOW(105, 70, struct oifaliasreq) // ifaliasreq contains if_data
|
||||
#endif
|
||||
'
|
||||
|
||||
includes_Linux='
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#ifndef __LP64__
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
#define _GNU_SOURCE
|
||||
|
||||
// <sys/ioctl.h> is broken on powerpc64, as it fails to include definitions of
|
||||
// these structures. We just include them copied from <bits/termios.h>.
|
||||
#if defined(__powerpc__)
|
||||
struct sgttyb {
|
||||
char sg_ispeed;
|
||||
char sg_ospeed;
|
||||
char sg_erase;
|
||||
char sg_kill;
|
||||
short sg_flags;
|
||||
};
|
||||
|
||||
struct tchars {
|
||||
char t_intrc;
|
||||
char t_quitc;
|
||||
char t_startc;
|
||||
char t_stopc;
|
||||
char t_eofc;
|
||||
char t_brkc;
|
||||
};
|
||||
|
||||
struct ltchars {
|
||||
char t_suspc;
|
||||
char t_dsuspc;
|
||||
char t_rprntc;
|
||||
char t_flushc;
|
||||
char t_werasc;
|
||||
char t_lnextc;
|
||||
};
|
||||
#endif
|
||||
|
||||
#include <bits/sockaddr.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_alg.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_ppp.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/falloc.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/memfd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/net_namespace.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/vm_sockets.h>
|
||||
#include <linux/taskstats.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/if_xdp.h>
|
||||
#include <mtd/ubi-user.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#if defined(__sparc__)
|
||||
// On sparc{,64}, the kernel defines struct termios2 itself which clashes with the
|
||||
// definition in glibc. As only the error constants are needed here, include the
|
||||
// generic termibits.h (which is included by termbits.h on sparc).
|
||||
#include <asm-generic/termbits.h>
|
||||
#else
|
||||
#include <asm/termbits.h>
|
||||
#endif
|
||||
|
||||
#ifndef MSG_FASTOPEN
|
||||
#define MSG_FASTOPEN 0x20000000
|
||||
#endif
|
||||
|
||||
#ifndef PTRACE_GETREGS
|
||||
#define PTRACE_GETREGS 0xc
|
||||
#endif
|
||||
|
||||
#ifndef PTRACE_SETREGS
|
||||
#define PTRACE_SETREGS 0xd
|
||||
#endif
|
||||
|
||||
#ifndef SOL_NETLINK
|
||||
#define SOL_NETLINK 270
|
||||
#endif
|
||||
|
||||
#ifdef SOL_BLUETOOTH
|
||||
// SPARC includes this in /usr/include/sparc64-linux-gnu/bits/socket.h
|
||||
// but it is already in bluetooth_linux.go
|
||||
#undef SOL_BLUETOOTH
|
||||
#endif
|
||||
|
||||
// Certain constants are missing from the fs/crypto UAPI
|
||||
#define FS_KEY_DESC_PREFIX "fscrypt:"
|
||||
#define FS_KEY_DESC_PREFIX_SIZE 8
|
||||
#define FS_MAX_KEY_SIZE 64
|
||||
|
||||
// XDP socket constants do not appear to be picked up otherwise.
|
||||
// Copied from samples/bpf/xdpsock_user.c.
|
||||
#ifndef SOL_XDP
|
||||
#define SOL_XDP 283
|
||||
#endif
|
||||
|
||||
#ifndef AF_XDP
|
||||
#define AF_XDP 44
|
||||
#endif
|
||||
'
|
||||
|
||||
includes_NetBSD='
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/extattr.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_mroute.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
// Needed since <sys/param.h> refers to it...
|
||||
#define schedppq 1
|
||||
'
|
||||
|
||||
includes_OpenBSD='
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/termios.h>
|
||||
#include <sys/ttycom.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_mroute.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/if_bridge.h>
|
||||
|
||||
// We keep some constants not supported in OpenBSD 5.5 and beyond for
|
||||
// the promise of compatibility.
|
||||
#define EMUL_ENABLED 0x1
|
||||
#define EMUL_NATIVE 0x2
|
||||
#define IPV6_FAITH 0x1d
|
||||
#define IPV6_OPTIONS 0x1
|
||||
#define IPV6_RTHDR_STRICT 0x1
|
||||
#define IPV6_SOCKOPT_RESERVED1 0x3
|
||||
#define SIOCGIFGENERIC 0xc020693a
|
||||
#define SIOCSIFGENERIC 0x80206939
|
||||
#define WALTSIG 0x4
|
||||
'
|
||||
|
||||
includes_SunOS='
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mkdev.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <termios.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_mroute.h>
|
||||
'
|
||||
|
||||
|
||||
includes='
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <errno.h>
|
||||
#include <sys/signal.h>
|
||||
#include <signal.h>
|
||||
#include <sys/resource.h>
|
||||
#include <time.h>
|
||||
'
|
||||
ccflags="$@"
|
||||
|
||||
# Write go tool cgo -godefs input.
|
||||
(
|
||||
echo package unix
|
||||
echo
|
||||
echo '/*'
|
||||
indirect="includes_$(uname)"
|
||||
echo "${!indirect} $includes"
|
||||
echo '*/'
|
||||
echo 'import "C"'
|
||||
echo 'import "syscall"'
|
||||
echo
|
||||
echo 'const ('
|
||||
|
||||
# The gcc command line prints all the #defines
|
||||
# it encounters while processing the input
|
||||
echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags |
|
||||
awk '
|
||||
$1 != "#define" || $2 ~ /\(/ || $3 == "" {next}
|
||||
|
||||
$2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers
|
||||
$2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next}
|
||||
$2 ~ /^(SCM_SRCRT)$/ {next}
|
||||
$2 ~ /^(MAP_FAILED)$/ {next}
|
||||
$2 ~ /^ELF_.*$/ {next}# <asm/elf.h> contains ELF_ARCH, etc.
|
||||
|
||||
$2 ~ /^EXTATTR_NAMESPACE_NAMES/ ||
|
||||
$2 ~ /^EXTATTR_NAMESPACE_[A-Z]+_STRING/ {next}
|
||||
|
||||
$2 !~ /^ECCAPBITS/ &&
|
||||
$2 !~ /^ETH_/ &&
|
||||
$2 !~ /^EPROC_/ &&
|
||||
$2 !~ /^EQUIV_/ &&
|
||||
$2 !~ /^EXPR_/ &&
|
||||
$2 ~ /^E[A-Z0-9_]+$/ ||
|
||||
$2 ~ /^B[0-9_]+$/ ||
|
||||
$2 ~ /^(OLD|NEW)DEV$/ ||
|
||||
$2 == "BOTHER" ||
|
||||
$2 ~ /^CI?BAUD(EX)?$/ ||
|
||||
$2 == "IBSHIFT" ||
|
||||
$2 ~ /^V[A-Z0-9]+$/ ||
|
||||
$2 ~ /^CS[A-Z0-9]/ ||
|
||||
$2 ~ /^I(SIG|CANON|CRNL|UCLC|EXTEN|MAXBEL|STRIP|UTF8)$/ ||
|
||||
$2 ~ /^IGN/ ||
|
||||
$2 ~ /^IX(ON|ANY|OFF)$/ ||
|
||||
$2 ~ /^IN(LCR|PCK)$/ ||
|
||||
$2 !~ "X86_CR3_PCID_NOFLUSH" &&
|
||||
$2 ~ /(^FLU?SH)|(FLU?SH$)/ ||
|
||||
$2 ~ /^C(LOCAL|READ|MSPAR|RTSCTS)$/ ||
|
||||
$2 == "BRKINT" ||
|
||||
$2 == "HUPCL" ||
|
||||
$2 == "PENDIN" ||
|
||||
$2 == "TOSTOP" ||
|
||||
$2 == "XCASE" ||
|
||||
$2 == "ALTWERASE" ||
|
||||
$2 == "NOKERNINFO" ||
|
||||
$2 ~ /^PAR/ ||
|
||||
$2 ~ /^SIG[^_]/ ||
|
||||
$2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ ||
|
||||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ ||
|
||||
$2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ ||
|
||||
$2 ~ /^O?XTABS$/ ||
|
||||
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
||||
$2 ~ /^IN_/ ||
|
||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ ||
|
||||
$2 ~ /^TP_STATUS_/ ||
|
||||
$2 ~ /^FALLOC_/ ||
|
||||
$2 == "ICMPV6_FILTER" ||
|
||||
$2 == "SOMAXCONN" ||
|
||||
$2 == "NAME_MAX" ||
|
||||
$2 == "IFNAMSIZ" ||
|
||||
$2 ~ /^CTL_(HW|KERN|MAXNAME|NET|QUERY)$/ ||
|
||||
$2 ~ /^KERN_(HOSTNAME|OS(RELEASE|TYPE)|VERSION)$/ ||
|
||||
$2 ~ /^HW_MACHINE$/ ||
|
||||
$2 ~ /^SYSCTL_VERS/ ||
|
||||
$2 !~ "MNT_BITS" &&
|
||||
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
||||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT)_/ ||
|
||||
$2 ~ /^KEXEC_/ ||
|
||||
$2 ~ /^LINUX_REBOOT_CMD_/ ||
|
||||
$2 ~ /^LINUX_REBOOT_MAGIC[12]$/ ||
|
||||
$2 ~ /^MODULE_INIT_/ ||
|
||||
$2 !~ "NLA_TYPE_MASK" &&
|
||||
$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
|
||||
$2 ~ /^SIOC/ ||
|
||||
$2 ~ /^TIOC/ ||
|
||||
$2 ~ /^TCGET/ ||
|
||||
$2 ~ /^TCSET/ ||
|
||||
$2 ~ /^TC(FLSH|SBRKP?|XONC)$/ ||
|
||||
$2 !~ "RTF_BITS" &&
|
||||
$2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ ||
|
||||
$2 ~ /^BIOC/ ||
|
||||
$2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ ||
|
||||
$2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|LOCKS|MEMLOCK|MSGQUEUE|NICE|NOFILE|NPROC|RSS|RTPRIO|RTTIME|SIGPENDING|STACK)|RLIM_INFINITY/ ||
|
||||
$2 ~ /^PRIO_(PROCESS|PGRP|USER)/ ||
|
||||
$2 ~ /^CLONE_[A-Z_]+/ ||
|
||||
$2 !~ /^(BPF_TIMEVAL)$/ &&
|
||||
$2 ~ /^(BPF|DLT)_/ ||
|
||||
$2 ~ /^(CLOCK|TIMER)_/ ||
|
||||
$2 ~ /^CAN_/ ||
|
||||
$2 ~ /^CAP_/ ||
|
||||
$2 ~ /^ALG_/ ||
|
||||
$2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE|IOC_(GET|SET)_ENCRYPTION)/ ||
|
||||
$2 ~ /^GRND_/ ||
|
||||
$2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ ||
|
||||
$2 ~ /^KEYCTL_/ ||
|
||||
$2 ~ /^PERF_EVENT_IOC_/ ||
|
||||
$2 ~ /^SECCOMP_MODE_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||
$2 !~ /^AUDIT_RECORD_MAGIC/ &&
|
||||
$2 !~ /IOC_MAGIC/ &&
|
||||
$2 ~ /^[A-Z][A-Z0-9_]+_MAGIC2?$/ ||
|
||||
$2 ~ /^(VM|VMADDR)_/ ||
|
||||
$2 ~ /^IOCTL_VM_SOCKETS_/ ||
|
||||
$2 ~ /^(TASKSTATS|TS)_/ ||
|
||||
$2 ~ /^CGROUPSTATS_/ ||
|
||||
$2 ~ /^GENL_/ ||
|
||||
$2 ~ /^STATX_/ ||
|
||||
$2 ~ /^RENAME/ ||
|
||||
$2 ~ /^UBI_IOC[A-Z]/ ||
|
||||
$2 ~ /^UTIME_/ ||
|
||||
$2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ ||
|
||||
$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
|
||||
$2 ~ /^FSOPT_/ ||
|
||||
$2 ~ /^WDIOC_/ ||
|
||||
$2 ~ /^NFN/ ||
|
||||
$2 ~ /^XDP_/ ||
|
||||
$2 ~ /^(HDIO|WIN|SMART)_/ ||
|
||||
$2 !~ "WMESGLEN" &&
|
||||
$2 ~ /^W[A-Z0-9]+$/ ||
|
||||
$2 ~/^PPPIOC/ ||
|
||||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
|
||||
$2 ~ /^__WCOREFLAG$/ {next}
|
||||
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}
|
||||
|
||||
{next}
|
||||
' | sort
|
||||
|
||||
echo ')'
|
||||
) >_const.go
|
||||
|
||||
# Pull out the error names for later.
|
||||
errors=$(
|
||||
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' |
|
||||
sort
|
||||
)
|
||||
|
||||
# Pull out the signal names for later.
|
||||
signals=$(
|
||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
||||
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||
sort
|
||||
)
|
||||
|
||||
# Again, writing regexps to a file.
|
||||
echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||
awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||
sort >_error.grep
|
||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||
egrep -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||
sort >_signal.grep
|
||||
|
||||
echo '// mkerrors.sh' "$@"
|
||||
echo '// Code generated by the command above; see README.md. DO NOT EDIT.'
|
||||
echo
|
||||
echo "// +build ${GOARCH},${GOOS}"
|
||||
echo
|
||||
go tool cgo -godefs -- "$@" _const.go >_error.out
|
||||
cat _error.out | grep -vf _error.grep | grep -vf _signal.grep
|
||||
echo
|
||||
echo '// Errors'
|
||||
echo 'const ('
|
||||
cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= syscall.Errno(\1)/'
|
||||
echo ')'
|
||||
|
||||
echo
|
||||
echo '// Signals'
|
||||
echo 'const ('
|
||||
cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= syscall.Signal(\1)/'
|
||||
echo ')'
|
||||
|
||||
# Run C program to print error and syscall strings.
|
||||
(
|
||||
echo -E "
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below
|
||||
|
||||
struct tuple {
|
||||
int num;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct tuple errors[] = {
|
||||
"
|
||||
for i in $errors
|
||||
do
|
||||
echo -E ' {'$i', "'$i'" },'
|
||||
done
|
||||
|
||||
echo -E "
|
||||
};
|
||||
|
||||
struct tuple signals[] = {
|
||||
"
|
||||
for i in $signals
|
||||
do
|
||||
echo -E ' {'$i', "'$i'" },'
|
||||
done
|
||||
|
||||
# Use -E because on some systems bash builtin interprets \n itself.
|
||||
echo -E '
|
||||
};
|
||||
|
||||
static int
|
||||
tuplecmp(const void *a, const void *b)
|
||||
{
|
||||
return ((struct tuple *)a)->num - ((struct tuple *)b)->num;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int i, e;
|
||||
char buf[1024], *p;
|
||||
|
||||
printf("\n\n// Error table\n");
|
||||
printf("var errorList = [...]struct {\n");
|
||||
printf("\tnum syscall.Errno\n");
|
||||
printf("\tname string\n");
|
||||
printf("\tdesc string\n");
|
||||
printf("} {\n");
|
||||
qsort(errors, nelem(errors), sizeof errors[0], tuplecmp);
|
||||
for(i=0; i<nelem(errors); i++) {
|
||||
e = errors[i].num;
|
||||
if(i > 0 && errors[i-1].num == e)
|
||||
continue;
|
||||
strcpy(buf, strerror(e));
|
||||
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
|
||||
buf[0] += a - A;
|
||||
printf("\t{ %d, \"%s\", \"%s\" },\n", e, errors[i].name, buf);
|
||||
}
|
||||
printf("}\n\n");
|
||||
|
||||
printf("\n\n// Signal table\n");
|
||||
printf("var signalList = [...]struct {\n");
|
||||
printf("\tnum syscall.Signal\n");
|
||||
printf("\tname string\n");
|
||||
printf("\tdesc string\n");
|
||||
printf("} {\n");
|
||||
qsort(signals, nelem(signals), sizeof signals[0], tuplecmp);
|
||||
for(i=0; i<nelem(signals); i++) {
|
||||
e = signals[i].num;
|
||||
if(i > 0 && signals[i-1].num == e)
|
||||
continue;
|
||||
strcpy(buf, strsignal(e));
|
||||
// lowercase first letter: Bad -> bad, but STREAM -> STREAM.
|
||||
if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z)
|
||||
buf[0] += a - A;
|
||||
// cut trailing : number.
|
||||
p = strrchr(buf, ":"[0]);
|
||||
if(p)
|
||||
*p = '\0';
|
||||
printf("\t{ %d, \"%s\", \"%s\" },\n", e, signals[i].name, buf);
|
||||
}
|
||||
printf("}\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
'
|
||||
) >_errors.c
|
||||
|
||||
$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out
|
579
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl
generated
vendored
579
vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl
generated
vendored
@ -1,579 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright 2018 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.
|
||||
|
||||
# This program reads a file containing function prototypes
|
||||
# (like syscall_aix.go) and generates system call bodies.
|
||||
# The prototypes are marked by lines beginning with "//sys"
|
||||
# and read like func declarations if //sys is replaced by func, but:
|
||||
# * The parameter lists must give a name for each argument.
|
||||
# This includes return parameters.
|
||||
# * The parameter lists must give a type for each argument:
|
||||
# the (x, y, z int) shorthand is not allowed.
|
||||
# * If the return parameter is an error number, it must be named err.
|
||||
# * If go func name needs to be different than its libc name,
|
||||
# * or the function is not in libc, name could be specified
|
||||
# * at the end, after "=" sign, like
|
||||
# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
||||
# This program will generate three files and handle both gc and gccgo implementation:
|
||||
# - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
|
||||
# - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
|
||||
# - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
|
||||
|
||||
# The generated code looks like this
|
||||
#
|
||||
# zsyscall_aix_ppc64.go
|
||||
# func asyscall(...) (n int, err error) {
|
||||
# // Pointer Creation
|
||||
# r1, e1 := callasyscall(...)
|
||||
# // Type Conversion
|
||||
# // Error Handler
|
||||
# return
|
||||
# }
|
||||
#
|
||||
# zsyscall_aix_ppc64_gc.go
|
||||
# //go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
|
||||
# //go:linkname libc_asyscall libc_asyscall
|
||||
# var asyscall syscallFunc
|
||||
#
|
||||
# func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
# r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
|
||||
# return
|
||||
# }
|
||||
#
|
||||
# zsyscall_aix_ppc64_ggcgo.go
|
||||
# /*
|
||||
# int asyscall(...)
|
||||
#
|
||||
# */
|
||||
# import "C"
|
||||
#
|
||||
# func callasyscall(...) (r1 uintptr, e1 Errno) {
|
||||
# r1 = uintptr(C.asyscall(...))
|
||||
# e1 = syscall.GetErrno()
|
||||
# return
|
||||
# }
|
||||
|
||||
|
||||
|
||||
use strict;
|
||||
|
||||
my $cmdline = "mksyscall_aix_ppc64.pl " . join(' ', @ARGV);
|
||||
my $errors = 0;
|
||||
my $_32bit = "";
|
||||
my $tags = ""; # build tags
|
||||
my $aix = 0;
|
||||
my $solaris = 0;
|
||||
|
||||
binmode STDOUT;
|
||||
|
||||
if($ARGV[0] eq "-b32") {
|
||||
$_32bit = "big-endian";
|
||||
shift;
|
||||
} elsif($ARGV[0] eq "-l32") {
|
||||
$_32bit = "little-endian";
|
||||
shift;
|
||||
}
|
||||
if($ARGV[0] eq "-aix") {
|
||||
$aix = 1;
|
||||
shift;
|
||||
}
|
||||
if($ARGV[0] eq "-tags") {
|
||||
shift;
|
||||
$tags = $ARGV[0];
|
||||
shift;
|
||||
}
|
||||
|
||||
if($ARGV[0] =~ /^-/) {
|
||||
print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub parseparamlist($) {
|
||||
my ($list) = @_;
|
||||
$list =~ s/^\s*//;
|
||||
$list =~ s/\s*$//;
|
||||
if($list eq "") {
|
||||
return ();
|
||||
}
|
||||
return split(/\s*,\s*/, $list);
|
||||
}
|
||||
|
||||
sub parseparam($) {
|
||||
my ($p) = @_;
|
||||
if($p !~ /^(\S*) (\S*)$/) {
|
||||
print STDERR "$ARGV:$.: malformed parameter: $p\n";
|
||||
$errors = 1;
|
||||
return ("xx", "int");
|
||||
}
|
||||
return ($1, $2);
|
||||
}
|
||||
|
||||
my $package = "";
|
||||
# GCCGO
|
||||
my $textgccgo = "";
|
||||
my $c_extern = "/*\n#include <stdint.h>\n";
|
||||
# GC
|
||||
my $textgc = "";
|
||||
my $dynimports = "";
|
||||
my $linknames = "";
|
||||
my @vars = ();
|
||||
# COMMUN
|
||||
my $textcommon = "";
|
||||
|
||||
while(<>) {
|
||||
chomp;
|
||||
s/\s+/ /g;
|
||||
s/^\s+//;
|
||||
s/\s+$//;
|
||||
$package = $1 if !$package && /^package (\S+)$/;
|
||||
my $nonblock = /^\/\/sysnb /;
|
||||
next if !/^\/\/sys / && !$nonblock;
|
||||
|
||||
# Line must be of the form
|
||||
# func Open(path string, mode int, perm int) (fd int, err error)
|
||||
# Split into name, in params, out params.
|
||||
if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
|
||||
print STDERR "$ARGV:$.: malformed //sys declaration\n";
|
||||
$errors = 1;
|
||||
next;
|
||||
}
|
||||
my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
|
||||
|
||||
# Split argument lists on comma.
|
||||
my @in = parseparamlist($in);
|
||||
my @out = parseparamlist($out);
|
||||
|
||||
$in = join(', ', @in);
|
||||
$out = join(', ', @out);
|
||||
|
||||
if($sysname eq "") {
|
||||
$sysname = "$func";
|
||||
}
|
||||
|
||||
my $onlyCommon = 0;
|
||||
if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") {
|
||||
# This function call another syscall which is already implemented.
|
||||
# Therefore, the gc and gccgo part must not be generated.
|
||||
$onlyCommon = 1
|
||||
}
|
||||
|
||||
# Try in vain to keep people from editing this file.
|
||||
# The theory is that they jump into the middle of the file
|
||||
# without reading the header.
|
||||
|
||||
$textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
|
||||
if (!$onlyCommon) {
|
||||
$textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
|
||||
$textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
|
||||
}
|
||||
|
||||
|
||||
# Check if value return, err return available
|
||||
my $errvar = "";
|
||||
my $retvar = "";
|
||||
my $rettype = "";
|
||||
foreach my $p (@out) {
|
||||
my ($name, $type) = parseparam($p);
|
||||
if($type eq "error") {
|
||||
$errvar = $name;
|
||||
} else {
|
||||
$retvar = $name;
|
||||
$rettype = $type;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$sysname =~ s/([a-z])([A-Z])/${1}_$2/g;
|
||||
$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
|
||||
|
||||
# GCCGO Prototype return type
|
||||
my $C_rettype = "";
|
||||
if($rettype eq "unsafe.Pointer") {
|
||||
$C_rettype = "uintptr_t";
|
||||
} elsif($rettype eq "uintptr") {
|
||||
$C_rettype = "uintptr_t";
|
||||
} elsif($rettype =~ /^_/) {
|
||||
$C_rettype = "uintptr_t";
|
||||
} elsif($rettype eq "int") {
|
||||
$C_rettype = "int";
|
||||
} elsif($rettype eq "int32") {
|
||||
$C_rettype = "int";
|
||||
} elsif($rettype eq "int64") {
|
||||
$C_rettype = "long long";
|
||||
} elsif($rettype eq "uint32") {
|
||||
$C_rettype = "unsigned int";
|
||||
} elsif($rettype eq "uint64") {
|
||||
$C_rettype = "unsigned long long";
|
||||
} else {
|
||||
$C_rettype = "int";
|
||||
}
|
||||
if($sysname eq "exit") {
|
||||
$C_rettype = "void";
|
||||
}
|
||||
|
||||
# GCCGO Prototype arguments type
|
||||
my @c_in = ();
|
||||
foreach my $i (0 .. $#in) {
|
||||
my ($name, $type) = parseparam($in[$i]);
|
||||
if($type =~ /^\*/) {
|
||||
push @c_in, "uintptr_t";
|
||||
} elsif($type eq "string") {
|
||||
push @c_in, "uintptr_t";
|
||||
} elsif($type =~ /^\[\](.*)/) {
|
||||
push @c_in, "uintptr_t", "size_t";
|
||||
} elsif($type eq "unsafe.Pointer") {
|
||||
push @c_in, "uintptr_t";
|
||||
} elsif($type eq "uintptr") {
|
||||
push @c_in, "uintptr_t";
|
||||
} elsif($type =~ /^_/) {
|
||||
push @c_in, "uintptr_t";
|
||||
} elsif($type eq "int") {
|
||||
if (($i == 0 || $i == 2) && $func eq "fcntl"){
|
||||
# These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
push @c_in, "uintptr_t";
|
||||
} else {
|
||||
push @c_in, "int";
|
||||
}
|
||||
} elsif($type eq "int32") {
|
||||
push @c_in, "int";
|
||||
} elsif($type eq "int64") {
|
||||
push @c_in, "long long";
|
||||
} elsif($type eq "uint32") {
|
||||
push @c_in, "unsigned int";
|
||||
} elsif($type eq "uint64") {
|
||||
push @c_in, "unsigned long long";
|
||||
} else {
|
||||
push @c_in, "int";
|
||||
}
|
||||
}
|
||||
|
||||
if (!$onlyCommon){
|
||||
# GCCGO Prototype Generation
|
||||
# Imports of system calls from libc
|
||||
$c_extern .= "$C_rettype $sysname";
|
||||
my $c_in = join(', ', @c_in);
|
||||
$c_extern .= "($c_in);\n";
|
||||
}
|
||||
|
||||
# GC Library name
|
||||
if($modname eq "") {
|
||||
$modname = "libc.a/shr_64.o";
|
||||
} else {
|
||||
print STDERR "$func: only syscall using libc are available\n";
|
||||
$errors = 1;
|
||||
next;
|
||||
}
|
||||
my $sysvarname = "libc_${sysname}";
|
||||
|
||||
if (!$onlyCommon){
|
||||
# GC Runtime import of function to allow cross-platform builds.
|
||||
$dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n";
|
||||
# GC Link symbol to proc address variable.
|
||||
$linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n";
|
||||
# GC Library proc address variable.
|
||||
push @vars, $sysvarname;
|
||||
}
|
||||
|
||||
my $strconvfunc ="BytePtrFromString";
|
||||
my $strconvtype = "*byte";
|
||||
|
||||
# Go function header.
|
||||
if($out ne "") {
|
||||
$out = " ($out)";
|
||||
}
|
||||
if($textcommon ne "") {
|
||||
$textcommon .= "\n"
|
||||
}
|
||||
|
||||
$textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ;
|
||||
|
||||
# Prepare arguments to call.
|
||||
my @argscommun = (); # Arguments in the commun part
|
||||
my @argscall = (); # Arguments for call prototype
|
||||
my @argsgc = (); # Arguments for gc call (with syscall6)
|
||||
my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall)
|
||||
my $n = 0;
|
||||
my $arg_n = 0;
|
||||
foreach my $p (@in) {
|
||||
my ($name, $type) = parseparam($p);
|
||||
if($type =~ /^\*/) {
|
||||
push @argscommun, "uintptr(unsafe.Pointer($name))";
|
||||
push @argscall, "$name uintptr";
|
||||
push @argsgc, "$name";
|
||||
push @argsgccgo, "C.uintptr_t($name)";
|
||||
} elsif($type eq "string" && $errvar ne "") {
|
||||
$textcommon .= "\tvar _p$n $strconvtype\n";
|
||||
$textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n";
|
||||
$textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||
|
||||
push @argscommun, "uintptr(unsafe.Pointer(_p$n))";
|
||||
push @argscall, "_p$n uintptr ";
|
||||
push @argsgc, "_p$n";
|
||||
push @argsgccgo, "C.uintptr_t(_p$n)";
|
||||
$n++;
|
||||
} elsif($type eq "string") {
|
||||
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
||||
$textcommon .= "\tvar _p$n $strconvtype\n";
|
||||
$textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n";
|
||||
$textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||
|
||||
push @argscommun, "uintptr(unsafe.Pointer(_p$n))";
|
||||
push @argscall, "_p$n uintptr";
|
||||
push @argsgc, "_p$n";
|
||||
push @argsgccgo, "C.uintptr_t(_p$n)";
|
||||
$n++;
|
||||
} elsif($type =~ /^\[\](.*)/) {
|
||||
# Convert slice into pointer, length.
|
||||
# Have to be careful not to take address of &a[0] if len == 0:
|
||||
# pass nil in that case.
|
||||
$textcommon .= "\tvar _p$n *$1\n";
|
||||
$textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
|
||||
push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)";
|
||||
push @argscall, "_p$n uintptr", "_lenp$n int";
|
||||
push @argsgc, "_p$n", "uintptr(_lenp$n)";
|
||||
push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)";
|
||||
$n++;
|
||||
} elsif($type eq "int64" && $_32bit ne "") {
|
||||
print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n";
|
||||
# if($_32bit eq "big-endian") {
|
||||
# push @args, "uintptr($name >> 32)", "uintptr($name)";
|
||||
# } else {
|
||||
# push @args, "uintptr($name)", "uintptr($name >> 32)";
|
||||
# }
|
||||
# $n++;
|
||||
} elsif($type eq "bool") {
|
||||
print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n";
|
||||
# $text .= "\tvar _p$n uint32\n";
|
||||
# $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
|
||||
# push @args, "_p$n";
|
||||
# $n++;
|
||||
} elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") {
|
||||
push @argscommun, "uintptr($name)";
|
||||
push @argscall, "$name uintptr";
|
||||
push @argsgc, "$name";
|
||||
push @argsgccgo, "C.uintptr_t($name)";
|
||||
} elsif($type eq "int") {
|
||||
if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) {
|
||||
# These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
|
||||
push @argscommun, "uintptr($name)";
|
||||
push @argscall, "$name uintptr";
|
||||
push @argsgc, "$name";
|
||||
push @argsgccgo, "C.uintptr_t($name)";
|
||||
} else {
|
||||
push @argscommun, "$name";
|
||||
push @argscall, "$name int";
|
||||
push @argsgc, "uintptr($name)";
|
||||
push @argsgccgo, "C.int($name)";
|
||||
}
|
||||
} elsif($type eq "int32") {
|
||||
push @argscommun, "$name";
|
||||
push @argscall, "$name int32";
|
||||
push @argsgc, "uintptr($name)";
|
||||
push @argsgccgo, "C.int($name)";
|
||||
} elsif($type eq "int64") {
|
||||
push @argscommun, "$name";
|
||||
push @argscall, "$name int64";
|
||||
push @argsgc, "uintptr($name)";
|
||||
push @argsgccgo, "C.longlong($name)";
|
||||
} elsif($type eq "uint32") {
|
||||
push @argscommun, "$name";
|
||||
push @argscall, "$name uint32";
|
||||
push @argsgc, "uintptr($name)";
|
||||
push @argsgccgo, "C.uint($name)";
|
||||
} elsif($type eq "uint64") {
|
||||
push @argscommun, "$name";
|
||||
push @argscall, "$name uint64";
|
||||
push @argsgc, "uintptr($name)";
|
||||
push @argsgccgo, "C.ulonglong($name)";
|
||||
} elsif($type eq "uintptr") {
|
||||
push @argscommun, "$name";
|
||||
push @argscall, "$name uintptr";
|
||||
push @argsgc, "$name";
|
||||
push @argsgccgo, "C.uintptr_t($name)";
|
||||
} else {
|
||||
push @argscommun, "int($name)";
|
||||
push @argscall, "$name int";
|
||||
push @argsgc, "uintptr($name)";
|
||||
push @argsgccgo, "C.int($name)";
|
||||
}
|
||||
$arg_n++;
|
||||
}
|
||||
my $nargs = @argsgc;
|
||||
|
||||
# COMMUN function generation
|
||||
my $argscommun = join(', ', @argscommun);
|
||||
my $callcommun = "call$sysname($argscommun)";
|
||||
my @ret = ("_", "_");
|
||||
my $body = "";
|
||||
my $do_errno = 0;
|
||||
for(my $i=0; $i<@out; $i++) {
|
||||
my $p = $out[$i];
|
||||
my ($name, $type) = parseparam($p);
|
||||
my $reg = "";
|
||||
if($name eq "err") {
|
||||
$reg = "e1";
|
||||
$ret[1] = $reg;
|
||||
$do_errno = 1;
|
||||
} else {
|
||||
$reg = "r0";
|
||||
$ret[0] = $reg;
|
||||
}
|
||||
if($type eq "bool") {
|
||||
$reg = "$reg != 0";
|
||||
}
|
||||
if($reg ne "e1") {
|
||||
$body .= "\t$name = $type($reg)\n";
|
||||
}
|
||||
}
|
||||
if ($ret[0] eq "_" && $ret[1] eq "_") {
|
||||
$textcommon .= "\t$callcommun\n";
|
||||
} else {
|
||||
$textcommon .= "\t$ret[0], $ret[1] := $callcommun\n";
|
||||
}
|
||||
$textcommon .= $body;
|
||||
|
||||
if ($do_errno) {
|
||||
$textcommon .= "\tif e1 != 0 {\n";
|
||||
$textcommon .= "\t\terr = errnoErr(e1)\n";
|
||||
$textcommon .= "\t}\n";
|
||||
}
|
||||
$textcommon .= "\treturn\n";
|
||||
$textcommon .= "}\n";
|
||||
|
||||
if ($onlyCommon){
|
||||
next
|
||||
}
|
||||
# CALL Prototype
|
||||
my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall);
|
||||
|
||||
# GC function generation
|
||||
my $asm = "syscall6";
|
||||
if ($nonblock) {
|
||||
$asm = "rawSyscall6";
|
||||
}
|
||||
|
||||
if(@argsgc <= 6) {
|
||||
while(@argsgc < 6) {
|
||||
push @argsgc, "0";
|
||||
}
|
||||
} else {
|
||||
print STDERR "$ARGV:$.: too many arguments to system call\n";
|
||||
}
|
||||
my $argsgc = join(', ', @argsgc);
|
||||
my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)";
|
||||
|
||||
$textgc .= $callProto;
|
||||
$textgc .= "\tr1, _, e1 = $callgc\n";
|
||||
$textgc .= "\treturn\n}\n";
|
||||
|
||||
# GCCGO function generation
|
||||
my $argsgccgo = join(', ', @argsgccgo);
|
||||
my $callgccgo = "C.$sysname($argsgccgo)";
|
||||
$textgccgo .= $callProto;
|
||||
$textgccgo .= "\tr1 = uintptr($callgccgo)\n";
|
||||
$textgccgo .= "\te1 = syscall.GetErrno()\n";
|
||||
$textgccgo .= "\treturn\n}\n";
|
||||
}
|
||||
|
||||
if($errors) {
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Print zsyscall_aix_ppc64.go
|
||||
open(my $fcommun, '>', 'zsyscall_aix_ppc64.go');
|
||||
my $tofcommun = <<EOF;
|
||||
// $cmdline
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build $tags
|
||||
|
||||
package $package
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
EOF
|
||||
|
||||
$tofcommun .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
|
||||
|
||||
$tofcommun .=<<EOF;
|
||||
|
||||
$textcommon
|
||||
EOF
|
||||
print $fcommun $tofcommun;
|
||||
|
||||
|
||||
# Print zsyscall_aix_ppc64_gc.go
|
||||
open(my $fgc, '>', 'zsyscall_aix_ppc64_gc.go');
|
||||
my $tofgc = <<EOF;
|
||||
// $cmdline
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build $tags
|
||||
// +build !gccgo
|
||||
|
||||
package $package
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
$tofgc .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
|
||||
|
||||
my $vardecls = "\t" . join(",\n\t", @vars);
|
||||
$vardecls .= " syscallFunc";
|
||||
|
||||
$tofgc .=<<EOF;
|
||||
$dynimports
|
||||
$linknames
|
||||
type syscallFunc uintptr
|
||||
|
||||
var (
|
||||
$vardecls
|
||||
)
|
||||
|
||||
// Implemented in runtime/syscall_aix.go.
|
||||
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
|
||||
|
||||
$textgc
|
||||
EOF
|
||||
print $fgc $tofgc;
|
||||
|
||||
# Print zsyscall_aix_ppc64_gc.go
|
||||
open(my $fgccgo, '>', 'zsyscall_aix_ppc64_gccgo.go');
|
||||
my $tofgccgo = <<EOF;
|
||||
// $cmdline
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build $tags
|
||||
// +build gccgo
|
||||
|
||||
package $package
|
||||
|
||||
|
||||
$c_extern
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
|
||||
EOF
|
||||
|
||||
$tofgccgo .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
|
||||
|
||||
$tofgccgo .=<<EOF;
|
||||
|
||||
$textgccgo
|
||||
EOF
|
||||
print $fgccgo $tofgccgo;
|
||||
exit 0;
|
294
vendor/golang.org/x/sys/unix/mksyscall_solaris.pl
generated
vendored
294
vendor/golang.org/x/sys/unix/mksyscall_solaris.pl
generated
vendored
@ -1,294 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# 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.
|
||||
|
||||
# This program reads a file containing function prototypes
|
||||
# (like syscall_solaris.go) and generates system call bodies.
|
||||
# The prototypes are marked by lines beginning with "//sys"
|
||||
# and read like func declarations if //sys is replaced by func, but:
|
||||
# * The parameter lists must give a name for each argument.
|
||||
# This includes return parameters.
|
||||
# * The parameter lists must give a type for each argument:
|
||||
# the (x, y, z int) shorthand is not allowed.
|
||||
# * If the return parameter is an error number, it must be named err.
|
||||
# * If go func name needs to be different than its libc name,
|
||||
# * or the function is not in libc, name could be specified
|
||||
# * at the end, after "=" sign, like
|
||||
# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
|
||||
|
||||
use strict;
|
||||
|
||||
my $cmdline = "mksyscall_solaris.pl " . join(' ', @ARGV);
|
||||
my $errors = 0;
|
||||
my $_32bit = "";
|
||||
my $tags = ""; # build tags
|
||||
|
||||
binmode STDOUT;
|
||||
|
||||
if($ARGV[0] eq "-b32") {
|
||||
$_32bit = "big-endian";
|
||||
shift;
|
||||
} elsif($ARGV[0] eq "-l32") {
|
||||
$_32bit = "little-endian";
|
||||
shift;
|
||||
}
|
||||
if($ARGV[0] eq "-tags") {
|
||||
shift;
|
||||
$tags = $ARGV[0];
|
||||
shift;
|
||||
}
|
||||
|
||||
if($ARGV[0] =~ /^-/) {
|
||||
print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub parseparamlist($) {
|
||||
my ($list) = @_;
|
||||
$list =~ s/^\s*//;
|
||||
$list =~ s/\s*$//;
|
||||
if($list eq "") {
|
||||
return ();
|
||||
}
|
||||
return split(/\s*,\s*/, $list);
|
||||
}
|
||||
|
||||
sub parseparam($) {
|
||||
my ($p) = @_;
|
||||
if($p !~ /^(\S*) (\S*)$/) {
|
||||
print STDERR "$ARGV:$.: malformed parameter: $p\n";
|
||||
$errors = 1;
|
||||
return ("xx", "int");
|
||||
}
|
||||
return ($1, $2);
|
||||
}
|
||||
|
||||
my $package = "";
|
||||
my $text = "";
|
||||
my $dynimports = "";
|
||||
my $linknames = "";
|
||||
my @vars = ();
|
||||
while(<>) {
|
||||
chomp;
|
||||
s/\s+/ /g;
|
||||
s/^\s+//;
|
||||
s/\s+$//;
|
||||
$package = $1 if !$package && /^package (\S+)$/;
|
||||
my $nonblock = /^\/\/sysnb /;
|
||||
next if !/^\/\/sys / && !$nonblock;
|
||||
|
||||
# Line must be of the form
|
||||
# func Open(path string, mode int, perm int) (fd int, err error)
|
||||
# Split into name, in params, out params.
|
||||
if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
|
||||
print STDERR "$ARGV:$.: malformed //sys declaration\n";
|
||||
$errors = 1;
|
||||
next;
|
||||
}
|
||||
my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
|
||||
|
||||
# Split argument lists on comma.
|
||||
my @in = parseparamlist($in);
|
||||
my @out = parseparamlist($out);
|
||||
|
||||
# Try in vain to keep people from editing this file.
|
||||
# The theory is that they jump into the middle of the file
|
||||
# without reading the header.
|
||||
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
|
||||
|
||||
# So file name.
|
||||
if($modname eq "") {
|
||||
$modname = "libc";
|
||||
}
|
||||
|
||||
# System call name.
|
||||
if($sysname eq "") {
|
||||
$sysname = "$func";
|
||||
}
|
||||
|
||||
# System call pointer variable name.
|
||||
my $sysvarname = "proc$sysname";
|
||||
|
||||
my $strconvfunc = "BytePtrFromString";
|
||||
my $strconvtype = "*byte";
|
||||
|
||||
$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
|
||||
|
||||
# Runtime import of function to allow cross-platform builds.
|
||||
$dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n";
|
||||
# Link symbol to proc address variable.
|
||||
$linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n";
|
||||
# Library proc address variable.
|
||||
push @vars, $sysvarname;
|
||||
|
||||
# Go function header.
|
||||
$out = join(', ', @out);
|
||||
if($out ne "") {
|
||||
$out = " ($out)";
|
||||
}
|
||||
if($text ne "") {
|
||||
$text .= "\n"
|
||||
}
|
||||
$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
|
||||
|
||||
# Check if err return available
|
||||
my $errvar = "";
|
||||
foreach my $p (@out) {
|
||||
my ($name, $type) = parseparam($p);
|
||||
if($type eq "error") {
|
||||
$errvar = $name;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
# Prepare arguments to Syscall.
|
||||
my @args = ();
|
||||
my $n = 0;
|
||||
foreach my $p (@in) {
|
||||
my ($name, $type) = parseparam($p);
|
||||
if($type =~ /^\*/) {
|
||||
push @args, "uintptr(unsafe.Pointer($name))";
|
||||
} elsif($type eq "string" && $errvar ne "") {
|
||||
$text .= "\tvar _p$n $strconvtype\n";
|
||||
$text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
|
||||
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||
$n++;
|
||||
} elsif($type eq "string") {
|
||||
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
|
||||
$text .= "\tvar _p$n $strconvtype\n";
|
||||
$text .= "\t_p$n, _ = $strconvfunc($name)\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))";
|
||||
$n++;
|
||||
} elsif($type =~ /^\[\](.*)/) {
|
||||
# Convert slice into pointer, length.
|
||||
# Have to be careful not to take address of &a[0] if len == 0:
|
||||
# pass nil in that case.
|
||||
$text .= "\tvar _p$n *$1\n";
|
||||
$text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
|
||||
push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
|
||||
$n++;
|
||||
} elsif($type eq "int64" && $_32bit ne "") {
|
||||
if($_32bit eq "big-endian") {
|
||||
push @args, "uintptr($name >> 32)", "uintptr($name)";
|
||||
} else {
|
||||
push @args, "uintptr($name)", "uintptr($name >> 32)";
|
||||
}
|
||||
} elsif($type eq "bool") {
|
||||
$text .= "\tvar _p$n uint32\n";
|
||||
$text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
|
||||
push @args, "uintptr(_p$n)";
|
||||
$n++;
|
||||
} else {
|
||||
push @args, "uintptr($name)";
|
||||
}
|
||||
}
|
||||
my $nargs = @args;
|
||||
|
||||
# Determine which form to use; pad args with zeros.
|
||||
my $asm = "sysvicall6";
|
||||
if ($nonblock) {
|
||||
$asm = "rawSysvicall6";
|
||||
}
|
||||
if(@args <= 6) {
|
||||
while(@args < 6) {
|
||||
push @args, "0";
|
||||
}
|
||||
} else {
|
||||
print STDERR "$ARGV:$.: too many arguments to system call\n";
|
||||
}
|
||||
|
||||
# Actual call.
|
||||
my $args = join(', ', @args);
|
||||
my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)";
|
||||
|
||||
# Assign return values.
|
||||
my $body = "";
|
||||
my $failexpr = "";
|
||||
my @ret = ("_", "_", "_");
|
||||
my @pout= ();
|
||||
my $do_errno = 0;
|
||||
for(my $i=0; $i<@out; $i++) {
|
||||
my $p = $out[$i];
|
||||
my ($name, $type) = parseparam($p);
|
||||
my $reg = "";
|
||||
if($name eq "err") {
|
||||
$reg = "e1";
|
||||
$ret[2] = $reg;
|
||||
$do_errno = 1;
|
||||
} else {
|
||||
$reg = sprintf("r%d", $i);
|
||||
$ret[$i] = $reg;
|
||||
}
|
||||
if($type eq "bool") {
|
||||
$reg = "$reg != 0";
|
||||
}
|
||||
if($type eq "int64" && $_32bit ne "") {
|
||||
# 64-bit number in r1:r0 or r0:r1.
|
||||
if($i+2 > @out) {
|
||||
print STDERR "$ARGV:$.: not enough registers for int64 return\n";
|
||||
}
|
||||
if($_32bit eq "big-endian") {
|
||||
$reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
|
||||
} else {
|
||||
$reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
|
||||
}
|
||||
$ret[$i] = sprintf("r%d", $i);
|
||||
$ret[$i+1] = sprintf("r%d", $i+1);
|
||||
}
|
||||
if($reg ne "e1") {
|
||||
$body .= "\t$name = $type($reg)\n";
|
||||
}
|
||||
}
|
||||
if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
|
||||
$text .= "\t$call\n";
|
||||
} else {
|
||||
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
|
||||
}
|
||||
$text .= $body;
|
||||
|
||||
if ($do_errno) {
|
||||
$text .= "\tif e1 != 0 {\n";
|
||||
$text .= "\t\terr = e1\n";
|
||||
$text .= "\t}\n";
|
||||
}
|
||||
$text .= "\treturn\n";
|
||||
$text .= "}\n";
|
||||
}
|
||||
|
||||
if($errors) {
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
// $cmdline
|
||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||
|
||||
// +build $tags
|
||||
|
||||
package $package
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
EOF
|
||||
|
||||
print "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
|
||||
|
||||
my $vardecls = "\t" . join(",\n\t", @vars);
|
||||
$vardecls .= " syscallFunc";
|
||||
|
||||
chomp($_=<<EOF);
|
||||
|
||||
$dynimports
|
||||
$linknames
|
||||
var (
|
||||
$vardecls
|
||||
)
|
||||
|
||||
$text
|
||||
EOF
|
||||
print $_;
|
||||
exit 0;
|
265
vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl
generated
vendored
265
vendor/golang.org/x/sys/unix/mksysctl_openbsd.pl
generated
vendored
@ -1,265 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# Copyright 2011 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.
|
||||
|
||||
#
|
||||
# Parse the header files for OpenBSD and generate a Go usable sysctl MIB.
|
||||
#
|
||||
# Build a MIB with each entry being an array containing the level, type and
|
||||
# a hash that will contain additional entries if the current entry is a node.
|
||||
# We then walk this MIB and create a flattened sysctl name to OID hash.
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
|
||||
print STDERR "GOARCH or GOOS not defined in environment\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $debug = 0;
|
||||
my %ctls = ();
|
||||
|
||||
my @headers = qw (
|
||||
sys/sysctl.h
|
||||
sys/socket.h
|
||||
sys/tty.h
|
||||
sys/malloc.h
|
||||
sys/mount.h
|
||||
sys/namei.h
|
||||
sys/sem.h
|
||||
sys/shm.h
|
||||
sys/vmmeter.h
|
||||
uvm/uvmexp.h
|
||||
uvm/uvm_param.h
|
||||
uvm/uvm_swap_encrypt.h
|
||||
ddb/db_var.h
|
||||
net/if.h
|
||||
net/if_pfsync.h
|
||||
net/pipex.h
|
||||
netinet/in.h
|
||||
netinet/icmp_var.h
|
||||
netinet/igmp_var.h
|
||||
netinet/ip_ah.h
|
||||
netinet/ip_carp.h
|
||||
netinet/ip_divert.h
|
||||
netinet/ip_esp.h
|
||||
netinet/ip_ether.h
|
||||
netinet/ip_gre.h
|
||||
netinet/ip_ipcomp.h
|
||||
netinet/ip_ipip.h
|
||||
netinet/pim_var.h
|
||||
netinet/tcp_var.h
|
||||
netinet/udp_var.h
|
||||
netinet6/in6.h
|
||||
netinet6/ip6_divert.h
|
||||
netinet6/pim6_var.h
|
||||
netinet/icmp6.h
|
||||
netmpls/mpls.h
|
||||
);
|
||||
|
||||
my @ctls = qw (
|
||||
kern
|
||||
vm
|
||||
fs
|
||||
net
|
||||
#debug # Special handling required
|
||||
hw
|
||||
#machdep # Arch specific
|
||||
user
|
||||
ddb
|
||||
#vfs # Special handling required
|
||||
fs.posix
|
||||
kern.forkstat
|
||||
kern.intrcnt
|
||||
kern.malloc
|
||||
kern.nchstats
|
||||
kern.seminfo
|
||||
kern.shminfo
|
||||
kern.timecounter
|
||||
kern.tty
|
||||
kern.watchdog
|
||||
net.bpf
|
||||
net.ifq
|
||||
net.inet
|
||||
net.inet.ah
|
||||
net.inet.carp
|
||||
net.inet.divert
|
||||
net.inet.esp
|
||||
net.inet.etherip
|
||||
net.inet.gre
|
||||
net.inet.icmp
|
||||
net.inet.igmp
|
||||
net.inet.ip
|
||||
net.inet.ip.ifq
|
||||
net.inet.ipcomp
|
||||
net.inet.ipip
|
||||
net.inet.mobileip
|
||||
net.inet.pfsync
|
||||
net.inet.pim
|
||||
net.inet.tcp
|
||||
net.inet.udp
|
||||
net.inet6
|
||||
net.inet6.divert
|
||||
net.inet6.ip6
|
||||
net.inet6.icmp6
|
||||
net.inet6.pim6
|
||||
net.inet6.tcp6
|
||||
net.inet6.udp6
|
||||
net.mpls
|
||||
net.mpls.ifq
|
||||
net.key
|
||||
net.pflow
|
||||
net.pfsync
|
||||
net.pipex
|
||||
net.rt
|
||||
vm.swapencrypt
|
||||
#vfsgenctl # Special handling required
|
||||
);
|
||||
|
||||
# Node name "fixups"
|
||||
my %ctl_map = (
|
||||
"ipproto" => "net.inet",
|
||||
"net.inet.ipproto" => "net.inet",
|
||||
"net.inet6.ipv6proto" => "net.inet6",
|
||||
"net.inet6.ipv6" => "net.inet6.ip6",
|
||||
"net.inet.icmpv6" => "net.inet6.icmp6",
|
||||
"net.inet6.divert6" => "net.inet6.divert",
|
||||
"net.inet6.tcp6" => "net.inet.tcp",
|
||||
"net.inet6.udp6" => "net.inet.udp",
|
||||
"mpls" => "net.mpls",
|
||||
"swpenc" => "vm.swapencrypt"
|
||||
);
|
||||
|
||||
# Node mappings
|
||||
my %node_map = (
|
||||
"net.inet.ip.ifq" => "net.ifq",
|
||||
"net.inet.pfsync" => "net.pfsync",
|
||||
"net.mpls.ifq" => "net.ifq"
|
||||
);
|
||||
|
||||
my $ctlname;
|
||||
my %mib = ();
|
||||
my %sysctl = ();
|
||||
my $node;
|
||||
|
||||
sub debug() {
|
||||
print STDERR "$_[0]\n" if $debug;
|
||||
}
|
||||
|
||||
# Walk the MIB and build a sysctl name to OID mapping.
|
||||
sub build_sysctl() {
|
||||
my ($node, $name, $oid) = @_;
|
||||
my %node = %{$node};
|
||||
my @oid = @{$oid};
|
||||
|
||||
foreach my $key (sort keys %node) {
|
||||
my @node = @{$node{$key}};
|
||||
my $nodename = $name.($name ne '' ? '.' : '').$key;
|
||||
my @nodeoid = (@oid, $node[0]);
|
||||
if ($node[1] eq 'CTLTYPE_NODE') {
|
||||
if (exists $node_map{$nodename}) {
|
||||
$node = \%mib;
|
||||
$ctlname = $node_map{$nodename};
|
||||
foreach my $part (split /\./, $ctlname) {
|
||||
$node = \%{@{$$node{$part}}[2]};
|
||||
}
|
||||
} else {
|
||||
$node = $node[2];
|
||||
}
|
||||
&build_sysctl($node, $nodename, \@nodeoid);
|
||||
} elsif ($node[1] ne '') {
|
||||
$sysctl{$nodename} = \@nodeoid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $ctl (@ctls) {
|
||||
$ctls{$ctl} = $ctl;
|
||||
}
|
||||
|
||||
# Build MIB
|
||||
foreach my $header (@headers) {
|
||||
&debug("Processing $header...");
|
||||
open HEADER, "/usr/include/$header" ||
|
||||
print STDERR "Failed to open $header\n";
|
||||
while (<HEADER>) {
|
||||
if ($_ =~ /^#define\s+(CTL_NAMES)\s+{/ ||
|
||||
$_ =~ /^#define\s+(CTL_(.*)_NAMES)\s+{/ ||
|
||||
$_ =~ /^#define\s+((.*)CTL_NAMES)\s+{/) {
|
||||
if ($1 eq 'CTL_NAMES') {
|
||||
# Top level.
|
||||
$node = \%mib;
|
||||
} else {
|
||||
# Node.
|
||||
my $nodename = lc($2);
|
||||
if ($header =~ /^netinet\//) {
|
||||
$ctlname = "net.inet.$nodename";
|
||||
} elsif ($header =~ /^netinet6\//) {
|
||||
$ctlname = "net.inet6.$nodename";
|
||||
} elsif ($header =~ /^net\//) {
|
||||
$ctlname = "net.$nodename";
|
||||
} else {
|
||||
$ctlname = "$nodename";
|
||||
$ctlname =~ s/^(fs|net|kern)_/$1\./;
|
||||
}
|
||||
if (exists $ctl_map{$ctlname}) {
|
||||
$ctlname = $ctl_map{$ctlname};
|
||||
}
|
||||
if (not exists $ctls{$ctlname}) {
|
||||
&debug("Ignoring $ctlname...");
|
||||
next;
|
||||
}
|
||||
|
||||
# Walk down from the top of the MIB.
|
||||
$node = \%mib;
|
||||
foreach my $part (split /\./, $ctlname) {
|
||||
if (not exists $$node{$part}) {
|
||||
&debug("Missing node $part");
|
||||
$$node{$part} = [ 0, '', {} ];
|
||||
}
|
||||
$node = \%{@{$$node{$part}}[2]};
|
||||
}
|
||||
}
|
||||
|
||||
# Populate current node with entries.
|
||||
my $i = -1;
|
||||
while (defined($_) && $_ !~ /^}/) {
|
||||
$_ = <HEADER>;
|
||||
$i++ if $_ =~ /{.*}/;
|
||||
next if $_ !~ /{\s+"(\w+)",\s+(CTLTYPE_[A-Z]+)\s+}/;
|
||||
$$node{$1} = [ $i, $2, {} ];
|
||||
}
|
||||
}
|
||||
}
|
||||
close HEADER;
|
||||
}
|
||||
|
||||
&build_sysctl(\%mib, "", []);
|
||||
|
||||
print <<EOF;
|
||||
// mksysctl_openbsd.pl
|
||||
// Code generated by the command above; DO NOT EDIT.
|
||||
|
||||
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
|
||||
|
||||
package unix;
|
||||
|
||||
type mibentry struct {
|
||||
ctlname string
|
||||
ctloid []_C_int
|
||||
}
|
||||
|
||||
var sysctlMib = []mibentry {
|
||||
EOF
|
||||
|
||||
foreach my $name (sort keys %sysctl) {
|
||||
my @oid = @{$sysctl{$name}};
|
||||
print "\t{ \"$name\", []_C_int{ ", join(', ', @oid), " } }, \n";
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
}
|
||||
EOF
|
41
vendor/golang.org/x/sys/unix/mmap_unix_test.go
generated
vendored
41
vendor/golang.org/x/sys/unix/mmap_unix_test.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestMmap(t *testing.T) {
|
||||
b, err := unix.Mmap(-1, 0, unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE)
|
||||
if err != nil {
|
||||
t.Fatalf("Mmap: %v", err)
|
||||
}
|
||||
if err := unix.Mprotect(b, unix.PROT_READ|unix.PROT_WRITE); err != nil {
|
||||
t.Fatalf("Mprotect: %v", err)
|
||||
}
|
||||
|
||||
b[0] = 42
|
||||
|
||||
if runtime.GOOS == "aix" {
|
||||
t.Skip("msync returns invalid argument for AIX, skipping msync test")
|
||||
} else {
|
||||
if err := unix.Msync(b, unix.MS_SYNC); err != nil {
|
||||
t.Fatalf("Msync: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := unix.Madvise(b, unix.MADV_DONTNEED); err != nil {
|
||||
t.Fatalf("Madvise: %v", err)
|
||||
}
|
||||
if err := unix.Munmap(b); err != nil {
|
||||
t.Fatalf("Munmap: %v", err)
|
||||
}
|
||||
}
|
113
vendor/golang.org/x/sys/unix/openbsd_test.go
generated
vendored
113
vendor/golang.org/x/sys/unix/openbsd_test.go
generated
vendored
@ -1,113 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// +build openbsd
|
||||
|
||||
// This, on the face of it, bizarre testing mechanism is necessary because
|
||||
// the only reliable way to gauge whether or not a pledge(2) call has succeeded
|
||||
// is that the program has been killed as a result of breaking its pledge.
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
type testProc struct {
|
||||
fn func() // should always exit instead of returning
|
||||
cleanup func() error // for instance, delete coredumps from testing pledge
|
||||
success bool // whether zero-exit means success or failure
|
||||
}
|
||||
|
||||
var (
|
||||
testProcs = map[string]testProc{}
|
||||
procName = ""
|
||||
)
|
||||
|
||||
const (
|
||||
optName = "sys-unix-internal-procname"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&procName, optName, "", "internal use only")
|
||||
}
|
||||
|
||||
// testCmd generates a proper command that, when executed, runs the test
|
||||
// corresponding to the given key.
|
||||
func testCmd(procName string) (*exec.Cmd, error) {
|
||||
exe, err := filepath.Abs(os.Args[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := exec.Command(exe, "-"+optName+"="+procName)
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing
|
||||
// a testProc with a key.
|
||||
func ExitsCorrectly(procName string, t *testing.T) {
|
||||
s := testProcs[procName]
|
||||
c, err := testCmd(procName)
|
||||
defer func() {
|
||||
if s.cleanup() != nil {
|
||||
t.Fatalf("Failed to run cleanup for %s", procName)
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct command for %s", procName)
|
||||
}
|
||||
if (c.Run() == nil) != s.success {
|
||||
result := "succeed"
|
||||
if !s.success {
|
||||
result = "fail"
|
||||
}
|
||||
t.Fatalf("Process did not %s when it was supposed to", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if procName != "" {
|
||||
testProcs[procName].fn()
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// For example, add a test for pledge.
|
||||
func init() {
|
||||
testProcs["pledge"] = testProc{
|
||||
func() {
|
||||
fmt.Println(unix.Pledge("", ""))
|
||||
os.Exit(0)
|
||||
},
|
||||
func() error {
|
||||
files, err := ioutil.ReadDir(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
if filepath.Ext(file.Name()) == ".core" {
|
||||
if err := os.Remove(file.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
false,
|
||||
}
|
||||
}
|
||||
|
||||
func TestPledge(t *testing.T) {
|
||||
ExitsCorrectly("pledge", t)
|
||||
}
|
98
vendor/golang.org/x/sys/unix/sendfile_test.go
generated
vendored
98
vendor/golang.org/x/sys/unix/sendfile_test.go
generated
vendored
@ -1,98 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build darwin,amd64 darwin,386 dragonfly freebsd linux solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestSendfile(t *testing.T) {
|
||||
// Set up source data file.
|
||||
tempDir, err := ioutil.TempDir("", "TestSendfile")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
name := filepath.Join(tempDir, "source")
|
||||
const contents = "contents"
|
||||
err = ioutil.WriteFile(name, []byte(contents), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
done := make(chan bool)
|
||||
|
||||
// Start server listening on a socket.
|
||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Skipf("listen failed: %s\n", err)
|
||||
}
|
||||
defer ln.Close()
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
b, err := ioutil.ReadAll(conn)
|
||||
if string(b) != contents {
|
||||
t.Errorf("contents not transmitted: got %s (len=%d), want %s", string(b), len(b), contents)
|
||||
}
|
||||
done <- true
|
||||
}()
|
||||
|
||||
// Open source file.
|
||||
src, err := os.Open(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Send source file to server.
|
||||
conn, err := net.Dial("tcp", ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
file, err := conn.(*net.TCPConn).File()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var off int64
|
||||
n, err := unix.Sendfile(int(file.Fd()), int(src.Fd()), &off, len(contents))
|
||||
if err != nil {
|
||||
t.Errorf("Sendfile failed %s\n", err)
|
||||
}
|
||||
if n != len(contents) {
|
||||
t.Errorf("written count wrong: want %d, got %d", len(contents), n)
|
||||
}
|
||||
// Note: off is updated on some systems and not others. Oh well.
|
||||
// Linux: increments off by the amount sent.
|
||||
// Darwin: leaves off unchanged.
|
||||
// It would be nice to fix Darwin if we can.
|
||||
if off != 0 && off != int64(len(contents)) {
|
||||
t.Errorf("offset wrong: god %d, want %d or %d", off, 0, len(contents))
|
||||
}
|
||||
// The cursor position should be unchanged.
|
||||
pos, err := src.Seek(0, 1)
|
||||
if err != nil {
|
||||
t.Errorf("can't get cursor position %s\n", err)
|
||||
}
|
||||
if pos != 0 {
|
||||
t.Errorf("cursor position wrong: got %d, want 0", pos)
|
||||
}
|
||||
|
||||
file.Close() // Note: required to have the close below really send EOF to the server.
|
||||
conn.Close()
|
||||
|
||||
// Wait for server to close.
|
||||
<-done
|
||||
}
|
162
vendor/golang.org/x/sys/unix/syscall_aix_test.go
generated
vendored
162
vendor/golang.org/x/sys/unix/syscall_aix_test.go
generated
vendored
@ -1,162 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build aix
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestIoctlGetInt(t *testing.T) {
|
||||
f, err := os.Open("/dev/random")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open device: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to perform ioctl: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("%d bits of entropy available", v)
|
||||
}
|
||||
|
||||
func TestTime(t *testing.T) {
|
||||
var ut unix.Time_t
|
||||
ut2, err := unix.Time(&ut)
|
||||
if err != nil {
|
||||
t.Fatalf("Time: %v", err)
|
||||
}
|
||||
if ut != ut2 {
|
||||
t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut)
|
||||
}
|
||||
|
||||
var now time.Time
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
ut, err = unix.Time(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Time: %v", err)
|
||||
}
|
||||
|
||||
now = time.Now()
|
||||
|
||||
if int64(ut) == now.Unix() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix())
|
||||
}
|
||||
|
||||
func TestUtime(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
touch(t, "file1")
|
||||
|
||||
buf := &unix.Utimbuf{
|
||||
Modtime: 12345,
|
||||
}
|
||||
|
||||
err := unix.Utime("file1", buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Utime: %v", err)
|
||||
}
|
||||
|
||||
fi, err := os.Stat("file1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if fi.ModTime().Unix() != 12345 {
|
||||
t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUtimesNanoAt(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
symlink := "symlink1"
|
||||
defer os.Remove(symlink)
|
||||
err := os.Symlink("nonexisting", symlink)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ts := []unix.Timespec{
|
||||
{Sec: 1111, Nsec: 2222},
|
||||
{Sec: 3333, Nsec: 4444},
|
||||
}
|
||||
err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
t.Fatalf("UtimesNanoAt: %v", err)
|
||||
}
|
||||
|
||||
var st unix.Stat_t
|
||||
err = unix.Lstat(symlink, &st)
|
||||
if err != nil {
|
||||
t.Fatalf("Lstat: %v", err)
|
||||
}
|
||||
if runtime.GOARCH == "ppc64" {
|
||||
if int64(st.Atim.Sec) != int64(ts[0].Sec) || st.Atim.Nsec != int32(ts[0].Nsec) {
|
||||
t.Errorf("UtimesNanoAt: wrong atime: %v", st.Atim)
|
||||
}
|
||||
if int64(st.Mtim.Sec) != int64(ts[1].Sec) || st.Mtim.Nsec != int32(ts[1].Nsec) {
|
||||
t.Errorf("UtimesNanoAt: wrong mtime: %v", st.Mtim)
|
||||
}
|
||||
} else {
|
||||
if int32(st.Atim.Sec) != int32(ts[0].Sec) || int32(st.Atim.Nsec) != int32(ts[0].Nsec) {
|
||||
t.Errorf("UtimesNanoAt: wrong atime: %v", st.Atim)
|
||||
}
|
||||
if int32(st.Mtim.Sec) != int32(ts[1].Sec) || int32(st.Mtim.Nsec) != int32(ts[1].Nsec) {
|
||||
t.Errorf("UtimesNanoAt: wrong mtime: %v", st.Mtim)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPselect(t *testing.T) {
|
||||
if runtime.GOARCH == "ppc64" {
|
||||
t.Skip("pselect issue with structure timespec on AIX 7.2 tl0, skipping test")
|
||||
}
|
||||
|
||||
_, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Pselect: %v", err)
|
||||
}
|
||||
|
||||
dur := 2500 * time.Microsecond
|
||||
ts := unix.NsecToTimespec(int64(dur))
|
||||
start := time.Now()
|
||||
_, err = unix.Pselect(0, nil, nil, nil, &ts, nil)
|
||||
took := time.Since(start)
|
||||
if err != nil {
|
||||
t.Fatalf("Pselect: %v", err)
|
||||
}
|
||||
|
||||
if took < dur {
|
||||
t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took)
|
||||
}
|
||||
}
|
||||
|
||||
// stringsFromByteSlice converts a sequence of attributes to a []string.
|
||||
// On Linux, each entry is a NULL-terminated string.
|
||||
func stringsFromByteSlice(buf []byte) []string {
|
||||
var result []string
|
||||
off := 0
|
||||
for i, b := range buf {
|
||||
if b == 0 {
|
||||
result = append(result, string(buf[off:i]))
|
||||
off = i + 1
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
89
vendor/golang.org/x/sys/unix/syscall_bsd_test.go
generated
vendored
89
vendor/golang.org/x/sys/unix/syscall_bsd_test.go
generated
vendored
@ -1,89 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// +build darwin dragonfly freebsd openbsd
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestGetfsstat(t *testing.T) {
|
||||
n, err := unix.Getfsstat(nil, unix.MNT_NOWAIT)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := make([]unix.Statfs_t, n)
|
||||
n2, err := unix.Getfsstat(data, unix.MNT_NOWAIT)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != n2 {
|
||||
t.Errorf("Getfsstat(nil) = %d, but subsequent Getfsstat(slice) = %d", n, n2)
|
||||
}
|
||||
for i, stat := range data {
|
||||
if stat == (unix.Statfs_t{}) {
|
||||
t.Errorf("index %v is an empty Statfs_t struct", i)
|
||||
}
|
||||
}
|
||||
if t.Failed() {
|
||||
for i, stat := range data[:n2] {
|
||||
t.Logf("data[%v] = %+v", i, stat)
|
||||
}
|
||||
mount, err := exec.Command("mount").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("mount: %v\n%s", err, mount)
|
||||
} else {
|
||||
t.Logf("mount: %s", mount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
|
||||
if err != nil {
|
||||
t.Fatalf("Select: %v", err)
|
||||
}
|
||||
|
||||
dur := 250 * time.Millisecond
|
||||
tv := unix.NsecToTimeval(int64(dur))
|
||||
start := time.Now()
|
||||
err = unix.Select(0, nil, nil, nil, &tv)
|
||||
took := time.Since(start)
|
||||
if err != nil {
|
||||
t.Fatalf("Select: %v", err)
|
||||
}
|
||||
|
||||
// On some BSDs the actual timeout might also be slightly less than the requested.
|
||||
// Add an acceptable margin to avoid flaky tests.
|
||||
if took < dur*2/3 {
|
||||
t.Errorf("Select: timeout should have been at least %v, got %v", dur, took)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysctlRaw(t *testing.T) {
|
||||
if runtime.GOOS == "openbsd" {
|
||||
t.Skip("kern.proc.pid does not exist on OpenBSD")
|
||||
}
|
||||
|
||||
_, err := unix.SysctlRaw("kern.proc.pid", unix.Getpid())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysctlUint32(t *testing.T) {
|
||||
maxproc, err := unix.SysctlUint32("kern.maxproc")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("kern.maxproc: %v", maxproc)
|
||||
}
|
63
vendor/golang.org/x/sys/unix/syscall_darwin_test.go
generated
vendored
63
vendor/golang.org/x/sys/unix/syscall_darwin_test.go
generated
vendored
@ -1,63 +0,0 @@
|
||||
// Copyright 2018 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 unix_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// stringsFromByteSlice converts a sequence of attributes to a []string.
|
||||
// On Darwin, each entry is a NULL-terminated string.
|
||||
func stringsFromByteSlice(buf []byte) []string {
|
||||
var result []string
|
||||
off := 0
|
||||
for i, b := range buf {
|
||||
if b == 0 {
|
||||
result = append(result, string(buf[off:i]))
|
||||
off = i + 1
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func TestUtimesNanoAt(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
symlink := "symlink1"
|
||||
os.Remove(symlink)
|
||||
err := os.Symlink("nonexisting", symlink)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ts := []unix.Timespec{
|
||||
{Sec: 1111, Nsec: 2222},
|
||||
{Sec: 3333, Nsec: 4444},
|
||||
}
|
||||
err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
t.Fatalf("UtimesNanoAt: %v", err)
|
||||
}
|
||||
|
||||
var st unix.Stat_t
|
||||
err = unix.Lstat(symlink, &st)
|
||||
if err != nil {
|
||||
t.Fatalf("Lstat: %v", err)
|
||||
}
|
||||
|
||||
// Only check Mtimespec, Atimespec might not be supported by the underlying filesystem
|
||||
expected := ts[1]
|
||||
if st.Mtimespec.Nsec == 0 {
|
||||
// Some filesystems only support 1-second time stamp resolution
|
||||
// and will always set Nsec to 0.
|
||||
expected.Nsec = 0
|
||||
}
|
||||
if st.Mtimespec != expected {
|
||||
t.Errorf("UtimesNanoAt: wrong mtime: got %v, expected %v", st.Mtimespec, expected)
|
||||
}
|
||||
}
|
312
vendor/golang.org/x/sys/unix/syscall_freebsd_test.go
generated
vendored
312
vendor/golang.org/x/sys/unix/syscall_freebsd_test.go
generated
vendored
@ -1,312 +0,0 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// +build freebsd
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestSysctlUint64(t *testing.T) {
|
||||
_, err := unix.SysctlUint64("vm.swap_total")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Infrastructure for launching tests in subprocesses stolen from openbsd_test.go - refactor?
|
||||
// testCmd generates a proper command that, when executed, runs the test
|
||||
// corresponding to the given key.
|
||||
|
||||
type testProc struct {
|
||||
fn func() // should always exit instead of returning
|
||||
arg func(t *testing.T) string // generate argument for test
|
||||
cleanup func(arg string) error // for instance, delete coredumps from testing pledge
|
||||
success bool // whether zero-exit means success or failure
|
||||
}
|
||||
|
||||
var (
|
||||
testProcs = map[string]testProc{}
|
||||
procName = ""
|
||||
procArg = ""
|
||||
)
|
||||
|
||||
const (
|
||||
optName = "sys-unix-internal-procname"
|
||||
optArg = "sys-unix-internal-arg"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&procName, optName, "", "internal use only")
|
||||
flag.StringVar(&procArg, optArg, "", "internal use only")
|
||||
|
||||
}
|
||||
|
||||
func testCmd(procName string, procArg string) (*exec.Cmd, error) {
|
||||
exe, err := filepath.Abs(os.Args[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cmd := exec.Command(exe, "-"+optName+"="+procName, "-"+optArg+"="+procArg)
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// ExitsCorrectly is a comprehensive, one-line-of-use wrapper for testing
|
||||
// a testProc with a key.
|
||||
func ExitsCorrectly(t *testing.T, procName string) {
|
||||
s := testProcs[procName]
|
||||
arg := "-"
|
||||
if s.arg != nil {
|
||||
arg = s.arg(t)
|
||||
}
|
||||
c, err := testCmd(procName, arg)
|
||||
defer func(arg string) {
|
||||
if err := s.cleanup(arg); err != nil {
|
||||
t.Fatalf("Failed to run cleanup for %s %s %#v", procName, err, err)
|
||||
}
|
||||
}(arg)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to construct command for %s", procName)
|
||||
}
|
||||
if (c.Run() == nil) != s.success {
|
||||
result := "succeed"
|
||||
if !s.success {
|
||||
result = "fail"
|
||||
}
|
||||
t.Fatalf("Process did not %s when it was supposed to", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if procName != "" {
|
||||
t := testProcs[procName]
|
||||
t.fn()
|
||||
os.Stderr.WriteString("test function did not exit\n")
|
||||
if t.success {
|
||||
os.Exit(1)
|
||||
} else {
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
// end of infrastructure
|
||||
|
||||
const testfile = "gocapmodetest"
|
||||
const testfile2 = testfile + "2"
|
||||
|
||||
func CapEnterTest() {
|
||||
_, err := os.OpenFile(path.Join(procArg, testfile), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("OpenFile: %s", err))
|
||||
}
|
||||
|
||||
err = unix.CapEnter()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapEnter: %s", err))
|
||||
}
|
||||
|
||||
_, err = os.OpenFile(path.Join(procArg, testfile2), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err == nil {
|
||||
panic("OpenFile works!")
|
||||
}
|
||||
if err.(*os.PathError).Err != unix.ECAPMODE {
|
||||
panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err))
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func makeTempDir(t *testing.T) string {
|
||||
d, err := ioutil.TempDir("", "go_openat_test")
|
||||
if err != nil {
|
||||
t.Fatalf("TempDir failed: %s", err)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
func removeTempDir(arg string) error {
|
||||
err := os.RemoveAll(arg)
|
||||
if err != nil && err.(*os.PathError).Err == unix.ENOENT {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func init() {
|
||||
testProcs["cap_enter"] = testProc{
|
||||
CapEnterTest,
|
||||
makeTempDir,
|
||||
removeTempDir,
|
||||
true,
|
||||
}
|
||||
}
|
||||
|
||||
func TestCapEnter(t *testing.T) {
|
||||
if runtime.GOARCH != "amd64" {
|
||||
t.Skipf("skipping test on %s", runtime.GOARCH)
|
||||
}
|
||||
ExitsCorrectly(t, "cap_enter")
|
||||
}
|
||||
|
||||
func OpenatTest() {
|
||||
f, err := os.Open(procArg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = unix.CapEnter()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapEnter: %s", err))
|
||||
}
|
||||
|
||||
fxx, err := unix.Openat(int(f.Fd()), "xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
unix.Close(fxx)
|
||||
|
||||
// The right to open BASE/xx is not ambient
|
||||
_, err = os.OpenFile(procArg+"/xx", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err == nil {
|
||||
panic("OpenFile succeeded")
|
||||
}
|
||||
if err.(*os.PathError).Err != unix.ECAPMODE {
|
||||
panic(fmt.Sprintf("OpenFile failed wrong: %s %#v", err, err))
|
||||
}
|
||||
|
||||
// Can't make a new directory either
|
||||
err = os.Mkdir(procArg+"2", 0777)
|
||||
if err == nil {
|
||||
panic("MKdir succeeded")
|
||||
}
|
||||
if err.(*os.PathError).Err != unix.ECAPMODE {
|
||||
panic(fmt.Sprintf("Mkdir failed wrong: %s %#v", err, err))
|
||||
}
|
||||
|
||||
// Remove all caps except read and lookup.
|
||||
r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_LOOKUP})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapRightsInit failed: %s %#v", err, err))
|
||||
}
|
||||
err = unix.CapRightsLimit(f.Fd(), r)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapRightsLimit failed: %s %#v", err, err))
|
||||
}
|
||||
|
||||
// Check we can get the rights back again
|
||||
r, err = unix.CapRightsGet(f.Fd())
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapRightsGet failed: %s %#v", err, err))
|
||||
}
|
||||
b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err))
|
||||
}
|
||||
if !b {
|
||||
panic(fmt.Sprintf("Unexpected rights"))
|
||||
}
|
||||
b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_LOOKUP, unix.CAP_WRITE})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("CapRightsIsSet failed: %s %#v", err, err))
|
||||
}
|
||||
if b {
|
||||
panic(fmt.Sprintf("Unexpected rights (2)"))
|
||||
}
|
||||
|
||||
// Can no longer create a file
|
||||
_, err = unix.Openat(int(f.Fd()), "xx2", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err == nil {
|
||||
panic("Openat succeeded")
|
||||
}
|
||||
if err != unix.ENOTCAPABLE {
|
||||
panic(fmt.Sprintf("OpenFileAt failed wrong: %s %#v", err, err))
|
||||
}
|
||||
|
||||
// But can read an existing one
|
||||
_, err = unix.Openat(int(f.Fd()), "xx", os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Openat failed: %s %#v", err, err))
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func init() {
|
||||
testProcs["openat"] = testProc{
|
||||
OpenatTest,
|
||||
makeTempDir,
|
||||
removeTempDir,
|
||||
true,
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenat(t *testing.T) {
|
||||
if runtime.GOARCH != "amd64" {
|
||||
t.Skipf("skipping test on %s", runtime.GOARCH)
|
||||
}
|
||||
ExitsCorrectly(t, "openat")
|
||||
}
|
||||
|
||||
func TestCapRightsSetAndClear(t *testing.T) {
|
||||
r, err := unix.CapRightsInit([]uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT})
|
||||
if err != nil {
|
||||
t.Fatalf("CapRightsInit failed: %s", err)
|
||||
}
|
||||
|
||||
err = unix.CapRightsSet(r, []uint64{unix.CAP_EVENT, unix.CAP_LISTEN})
|
||||
if err != nil {
|
||||
t.Fatalf("CapRightsSet failed: %s", err)
|
||||
}
|
||||
|
||||
b, err := unix.CapRightsIsSet(r, []uint64{unix.CAP_READ, unix.CAP_WRITE, unix.CAP_PDWAIT, unix.CAP_EVENT, unix.CAP_LISTEN})
|
||||
if err != nil {
|
||||
t.Fatalf("CapRightsIsSet failed: %s", err)
|
||||
}
|
||||
if !b {
|
||||
t.Fatalf("Wrong rights set")
|
||||
}
|
||||
|
||||
err = unix.CapRightsClear(r, []uint64{unix.CAP_READ, unix.CAP_PDWAIT})
|
||||
if err != nil {
|
||||
t.Fatalf("CapRightsClear failed: %s", err)
|
||||
}
|
||||
|
||||
b, err = unix.CapRightsIsSet(r, []uint64{unix.CAP_WRITE, unix.CAP_EVENT, unix.CAP_LISTEN})
|
||||
if err != nil {
|
||||
t.Fatalf("CapRightsIsSet failed: %s", err)
|
||||
}
|
||||
if !b {
|
||||
t.Fatalf("Wrong rights set")
|
||||
}
|
||||
}
|
||||
|
||||
// stringsFromByteSlice converts a sequence of attributes to a []string.
|
||||
// On FreeBSD, each entry consists of a single byte containing the length
|
||||
// of the attribute name, followed by the attribute name.
|
||||
// The name is _not_ NULL-terminated.
|
||||
func stringsFromByteSlice(buf []byte) []string {
|
||||
var result []string
|
||||
i := 0
|
||||
for i < len(buf) {
|
||||
next := i + 1 + int(buf[i])
|
||||
result = append(result, string(buf[i+1:next]))
|
||||
i = next
|
||||
}
|
||||
return result
|
||||
}
|
517
vendor/golang.org/x/sys/unix/syscall_linux_test.go
generated
vendored
517
vendor/golang.org/x/sys/unix/syscall_linux_test.go
generated
vendored
@ -1,517 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
// +build linux
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestIoctlGetInt(t *testing.T) {
|
||||
f, err := os.Open("/dev/random")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to open device: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
v, err := unix.IoctlGetInt(int(f.Fd()), unix.RNDGETENTCNT)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to perform ioctl: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("%d bits of entropy available", v)
|
||||
}
|
||||
|
||||
func TestPpoll(t *testing.T) {
|
||||
if runtime.GOOS == "android" {
|
||||
t.Skip("mkfifo syscall is not available on android, skipping test")
|
||||
}
|
||||
|
||||
f, cleanup := mktmpfifo(t)
|
||||
defer cleanup()
|
||||
|
||||
const timeout = 100 * time.Millisecond
|
||||
|
||||
ok := make(chan bool, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(10 * timeout):
|
||||
t.Errorf("Ppoll: failed to timeout after %d", 10*timeout)
|
||||
case <-ok:
|
||||
}
|
||||
}()
|
||||
|
||||
fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
|
||||
timeoutTs := unix.NsecToTimespec(int64(timeout))
|
||||
n, err := unix.Ppoll(fds, &timeoutTs, nil)
|
||||
ok <- true
|
||||
if err != nil {
|
||||
t.Errorf("Ppoll: unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestTime(t *testing.T) {
|
||||
var ut unix.Time_t
|
||||
ut2, err := unix.Time(&ut)
|
||||
if err != nil {
|
||||
t.Fatalf("Time: %v", err)
|
||||
}
|
||||
if ut != ut2 {
|
||||
t.Errorf("Time: return value %v should be equal to argument %v", ut2, ut)
|
||||
}
|
||||
|
||||
var now time.Time
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
ut, err = unix.Time(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Time: %v", err)
|
||||
}
|
||||
|
||||
now = time.Now()
|
||||
|
||||
if int64(ut) == now.Unix() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
t.Errorf("Time: return value %v should be nearly equal to time.Now().Unix() %v", ut, now.Unix())
|
||||
}
|
||||
|
||||
func TestUtime(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
touch(t, "file1")
|
||||
|
||||
buf := &unix.Utimbuf{
|
||||
Modtime: 12345,
|
||||
}
|
||||
|
||||
err := unix.Utime("file1", buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Utime: %v", err)
|
||||
}
|
||||
|
||||
fi, err := os.Stat("file1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if fi.ModTime().Unix() != 12345 {
|
||||
t.Errorf("Utime: failed to change modtime: expected %v, got %v", 12345, fi.ModTime().Unix())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUtimesNanoAt(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
symlink := "symlink1"
|
||||
os.Remove(symlink)
|
||||
err := os.Symlink("nonexisting", symlink)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ts := []unix.Timespec{
|
||||
{Sec: 1111, Nsec: 2222},
|
||||
{Sec: 3333, Nsec: 4444},
|
||||
}
|
||||
err = unix.UtimesNanoAt(unix.AT_FDCWD, symlink, ts, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
t.Fatalf("UtimesNanoAt: %v", err)
|
||||
}
|
||||
|
||||
var st unix.Stat_t
|
||||
err = unix.Lstat(symlink, &st)
|
||||
if err != nil {
|
||||
t.Fatalf("Lstat: %v", err)
|
||||
}
|
||||
|
||||
// Only check Mtim, Atim might not be supported by the underlying filesystem
|
||||
expected := ts[1]
|
||||
if st.Mtim.Nsec == 0 {
|
||||
// Some filesystems only support 1-second time stamp resolution
|
||||
// and will always set Nsec to 0.
|
||||
expected.Nsec = 0
|
||||
}
|
||||
if st.Mtim != expected {
|
||||
t.Errorf("UtimesNanoAt: wrong mtime: expected %v, got %v", expected, st.Mtim)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRlimitAs(t *testing.T) {
|
||||
// disable GC during to avoid flaky test
|
||||
defer debug.SetGCPercent(debug.SetGCPercent(-1))
|
||||
|
||||
var rlim unix.Rlimit
|
||||
err := unix.Getrlimit(unix.RLIMIT_AS, &rlim)
|
||||
if err != nil {
|
||||
t.Fatalf("Getrlimit: %v", err)
|
||||
}
|
||||
var zero unix.Rlimit
|
||||
if zero == rlim {
|
||||
t.Fatalf("Getrlimit: got zero value %#v", rlim)
|
||||
}
|
||||
set := rlim
|
||||
set.Cur = uint64(unix.Getpagesize())
|
||||
err = unix.Setrlimit(unix.RLIMIT_AS, &set)
|
||||
if err != nil {
|
||||
t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
|
||||
}
|
||||
|
||||
// RLIMIT_AS was set to the page size, so mmap()'ing twice the page size
|
||||
// should fail. See 'man 2 getrlimit'.
|
||||
_, err = unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE)
|
||||
if err == nil {
|
||||
t.Fatal("Mmap: unexpectedly succeeded after setting RLIMIT_AS")
|
||||
}
|
||||
|
||||
err = unix.Setrlimit(unix.RLIMIT_AS, &rlim)
|
||||
if err != nil {
|
||||
t.Fatalf("Setrlimit: restore failed: %#v %v", rlim, err)
|
||||
}
|
||||
|
||||
b, err := unix.Mmap(-1, 0, 2*unix.Getpagesize(), unix.PROT_NONE, unix.MAP_ANON|unix.MAP_PRIVATE)
|
||||
if err != nil {
|
||||
t.Fatalf("Mmap: %v", err)
|
||||
}
|
||||
err = unix.Munmap(b)
|
||||
if err != nil {
|
||||
t.Fatalf("Munmap: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
_, err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
|
||||
if err != nil {
|
||||
t.Fatalf("Select: %v", err)
|
||||
}
|
||||
|
||||
dur := 150 * time.Millisecond
|
||||
tv := unix.NsecToTimeval(int64(dur))
|
||||
start := time.Now()
|
||||
_, err = unix.Select(0, nil, nil, nil, &tv)
|
||||
took := time.Since(start)
|
||||
if err != nil {
|
||||
t.Fatalf("Select: %v", err)
|
||||
}
|
||||
|
||||
if took < dur {
|
||||
t.Errorf("Select: timeout should have been at least %v, got %v", dur, took)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPselect(t *testing.T) {
|
||||
_, err := unix.Pselect(0, nil, nil, nil, &unix.Timespec{Sec: 0, Nsec: 0}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Pselect: %v", err)
|
||||
}
|
||||
|
||||
dur := 2500 * time.Microsecond
|
||||
ts := unix.NsecToTimespec(int64(dur))
|
||||
start := time.Now()
|
||||
_, err = unix.Pselect(0, nil, nil, nil, &ts, nil)
|
||||
took := time.Since(start)
|
||||
if err != nil {
|
||||
t.Fatalf("Pselect: %v", err)
|
||||
}
|
||||
|
||||
if took < dur {
|
||||
t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchedSetaffinity(t *testing.T) {
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
var oldMask unix.CPUSet
|
||||
err := unix.SchedGetaffinity(0, &oldMask)
|
||||
if err != nil {
|
||||
t.Fatalf("SchedGetaffinity: %v", err)
|
||||
}
|
||||
|
||||
var newMask unix.CPUSet
|
||||
newMask.Zero()
|
||||
if newMask.Count() != 0 {
|
||||
t.Errorf("CpuZero: didn't zero CPU set: %v", newMask)
|
||||
}
|
||||
cpu := 1
|
||||
newMask.Set(cpu)
|
||||
if newMask.Count() != 1 || !newMask.IsSet(cpu) {
|
||||
t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask)
|
||||
}
|
||||
cpu = 5
|
||||
newMask.Set(cpu)
|
||||
if newMask.Count() != 2 || !newMask.IsSet(cpu) {
|
||||
t.Errorf("CpuSet: didn't set CPU %d in set: %v", cpu, newMask)
|
||||
}
|
||||
newMask.Clear(cpu)
|
||||
if newMask.Count() != 1 || newMask.IsSet(cpu) {
|
||||
t.Errorf("CpuClr: didn't clear CPU %d in set: %v", cpu, newMask)
|
||||
}
|
||||
|
||||
if runtime.NumCPU() < 2 {
|
||||
t.Skip("skipping setaffinity tests on single CPU system")
|
||||
}
|
||||
if runtime.GOOS == "android" {
|
||||
t.Skip("skipping setaffinity tests on android")
|
||||
}
|
||||
|
||||
// On a system like ppc64x where some cores can be disabled using ppc64_cpu,
|
||||
// setaffinity should only be called with enabled cores. The valid cores
|
||||
// are found from the oldMask, but if none are found then the setaffinity
|
||||
// tests are skipped. Issue #27875.
|
||||
if !oldMask.IsSet(cpu) {
|
||||
newMask.Zero()
|
||||
for i := 0; i < len(oldMask); i++ {
|
||||
if oldMask.IsSet(i) {
|
||||
newMask.Set(i)
|
||||
break
|
||||
}
|
||||
}
|
||||
if newMask.Count() == 0 {
|
||||
t.Skip("skipping setaffinity tests if CPU not available")
|
||||
}
|
||||
}
|
||||
|
||||
err = unix.SchedSetaffinity(0, &newMask)
|
||||
if err != nil {
|
||||
t.Fatalf("SchedSetaffinity: %v", err)
|
||||
}
|
||||
|
||||
var gotMask unix.CPUSet
|
||||
err = unix.SchedGetaffinity(0, &gotMask)
|
||||
if err != nil {
|
||||
t.Fatalf("SchedGetaffinity: %v", err)
|
||||
}
|
||||
|
||||
if gotMask != newMask {
|
||||
t.Errorf("SchedSetaffinity: returned affinity mask does not match set affinity mask")
|
||||
}
|
||||
|
||||
// Restore old mask so it doesn't affect successive tests
|
||||
err = unix.SchedSetaffinity(0, &oldMask)
|
||||
if err != nil {
|
||||
t.Fatalf("SchedSetaffinity: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatx(t *testing.T) {
|
||||
var stx unix.Statx_t
|
||||
err := unix.Statx(unix.AT_FDCWD, ".", 0, 0, &stx)
|
||||
if err == unix.ENOSYS || err == unix.EPERM {
|
||||
t.Skip("statx syscall is not available, skipping test")
|
||||
} else if err != nil {
|
||||
t.Fatalf("Statx: %v", err)
|
||||
}
|
||||
|
||||
defer chtmpdir(t)()
|
||||
touch(t, "file1")
|
||||
|
||||
var st unix.Stat_t
|
||||
err = unix.Stat("file1", &st)
|
||||
if err != nil {
|
||||
t.Fatalf("Stat: %v", err)
|
||||
}
|
||||
|
||||
flags := unix.AT_STATX_SYNC_AS_STAT
|
||||
err = unix.Statx(unix.AT_FDCWD, "file1", flags, unix.STATX_ALL, &stx)
|
||||
if err != nil {
|
||||
t.Fatalf("Statx: %v", err)
|
||||
}
|
||||
|
||||
if uint32(stx.Mode) != st.Mode {
|
||||
t.Errorf("Statx: returned stat mode does not match Stat")
|
||||
}
|
||||
|
||||
ctime := unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)}
|
||||
mtime := unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)}
|
||||
|
||||
if stx.Ctime != ctime {
|
||||
t.Errorf("Statx: returned stat ctime does not match Stat")
|
||||
}
|
||||
if stx.Mtime != mtime {
|
||||
t.Errorf("Statx: returned stat mtime does not match Stat")
|
||||
}
|
||||
|
||||
err = os.Symlink("file1", "symlink1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = unix.Lstat("symlink1", &st)
|
||||
if err != nil {
|
||||
t.Fatalf("Lstat: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Statx(unix.AT_FDCWD, "symlink1", flags, unix.STATX_BASIC_STATS, &stx)
|
||||
if err != nil {
|
||||
t.Fatalf("Statx: %v", err)
|
||||
}
|
||||
|
||||
// follow symlink, expect a regulat file
|
||||
if stx.Mode&unix.S_IFREG == 0 {
|
||||
t.Errorf("Statx: didn't follow symlink")
|
||||
}
|
||||
|
||||
err = unix.Statx(unix.AT_FDCWD, "symlink1", flags|unix.AT_SYMLINK_NOFOLLOW, unix.STATX_ALL, &stx)
|
||||
if err != nil {
|
||||
t.Fatalf("Statx: %v", err)
|
||||
}
|
||||
|
||||
// follow symlink, expect a symlink
|
||||
if stx.Mode&unix.S_IFLNK == 0 {
|
||||
t.Errorf("Statx: unexpectedly followed symlink")
|
||||
}
|
||||
if uint32(stx.Mode) != st.Mode {
|
||||
t.Errorf("Statx: returned stat mode does not match Lstat")
|
||||
}
|
||||
|
||||
ctime = unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)}
|
||||
mtime = unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)}
|
||||
|
||||
if stx.Ctime != ctime {
|
||||
t.Errorf("Statx: returned stat ctime does not match Lstat")
|
||||
}
|
||||
if stx.Mtime != mtime {
|
||||
t.Errorf("Statx: returned stat mtime does not match Lstat")
|
||||
}
|
||||
}
|
||||
|
||||
// stringsFromByteSlice converts a sequence of attributes to a []string.
|
||||
// On Linux, each entry is a NULL-terminated string.
|
||||
func stringsFromByteSlice(buf []byte) []string {
|
||||
var result []string
|
||||
off := 0
|
||||
for i, b := range buf {
|
||||
if b == 0 {
|
||||
result = append(result, string(buf[off:i]))
|
||||
off = i + 1
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func TestFaccessat(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
touch(t, "file1")
|
||||
|
||||
err := unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 0)
|
||||
if err != nil {
|
||||
t.Errorf("Faccessat: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, 2)
|
||||
if err != unix.EINVAL {
|
||||
t.Errorf("Faccessat: unexpected error: %v, want EINVAL", err)
|
||||
}
|
||||
|
||||
err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_EACCESS)
|
||||
if err != nil {
|
||||
t.Errorf("Faccessat: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = os.Symlink("file1", "symlink1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = unix.Faccessat(unix.AT_FDCWD, "symlink1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
t.Errorf("Faccessat SYMLINK_NOFOLLOW: unexpected error %v", err)
|
||||
}
|
||||
|
||||
// We can't really test AT_SYMLINK_NOFOLLOW, because there
|
||||
// doesn't seem to be any way to change the mode of a symlink.
|
||||
// We don't test AT_EACCESS because such tests are only
|
||||
// meaningful if run as root.
|
||||
|
||||
err = unix.Fchmodat(unix.AT_FDCWD, "file1", 0, 0)
|
||||
if err != nil {
|
||||
t.Errorf("Fchmodat: unexpected error %v", err)
|
||||
}
|
||||
|
||||
err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.F_OK, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
t.Errorf("Faccessat: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Faccessat(unix.AT_FDCWD, "file1", unix.R_OK, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != unix.EACCES {
|
||||
if unix.Getuid() != 0 {
|
||||
t.Errorf("Faccessat: unexpected error: %v, want EACCES", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncFileRange(t *testing.T) {
|
||||
file, err := ioutil.TempFile("", "TestSyncFileRange")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
defer file.Close()
|
||||
|
||||
err = unix.SyncFileRange(int(file.Fd()), 0, 0, 0)
|
||||
if err == unix.ENOSYS || err == unix.EPERM {
|
||||
t.Skip("sync_file_range syscall is not available, skipping test")
|
||||
} else if err != nil {
|
||||
t.Fatalf("SyncFileRange: %v", err)
|
||||
}
|
||||
|
||||
// invalid flags
|
||||
flags := 0xf00
|
||||
err = unix.SyncFileRange(int(file.Fd()), 0, 0, flags)
|
||||
if err != unix.EINVAL {
|
||||
t.Fatalf("SyncFileRange: unexpected error: %v, want EINVAL", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClockNanosleep(t *testing.T) {
|
||||
delay := 100 * time.Millisecond
|
||||
|
||||
// Relative timespec.
|
||||
start := time.Now()
|
||||
rel := unix.NsecToTimespec(delay.Nanoseconds())
|
||||
err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, nil)
|
||||
if err == unix.ENOSYS || err == unix.EPERM {
|
||||
t.Skip("clock_nanosleep syscall is not available, skipping test")
|
||||
} else if err != nil {
|
||||
t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) = %v", &rel, err)
|
||||
} else if slept := time.Now().Sub(start); slept < delay {
|
||||
t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) slept only %v", &rel, slept)
|
||||
}
|
||||
|
||||
// Absolute timespec.
|
||||
start = time.Now()
|
||||
until := start.Add(delay)
|
||||
abs := unix.NsecToTimespec(until.UnixNano())
|
||||
err = unix.ClockNanosleep(unix.CLOCK_REALTIME, unix.TIMER_ABSTIME, &abs, nil)
|
||||
if err != nil {
|
||||
t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) = %v", &abs, until, err)
|
||||
} else if slept := time.Now().Sub(start); slept < delay {
|
||||
t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) slept only %v", &abs, until, slept)
|
||||
}
|
||||
|
||||
// Invalid clock. clock_nanosleep(2) says EINVAL, but it’s actually EOPNOTSUPP.
|
||||
err = unix.ClockNanosleep(unix.CLOCK_THREAD_CPUTIME_ID, 0, &rel, nil)
|
||||
if err != unix.EINVAL && err != unix.EOPNOTSUPP {
|
||||
t.Errorf("ClockNanosleep(CLOCK_THREAD_CPUTIME_ID, 0, %#v, nil) = %v, want EINVAL or EOPNOTSUPP", &rel, err)
|
||||
}
|
||||
}
|
51
vendor/golang.org/x/sys/unix/syscall_netbsd_test.go
generated
vendored
51
vendor/golang.org/x/sys/unix/syscall_netbsd_test.go
generated
vendored
@ -1,51 +0,0 @@
|
||||
// Copyright 2018 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 unix_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// stringsFromByteSlice converts a sequence of attributes to a []string.
|
||||
// On NetBSD, each entry consists of a single byte containing the length
|
||||
// of the attribute name, followed by the attribute name.
|
||||
// The name is _not_ NULL-terminated.
|
||||
func stringsFromByteSlice(buf []byte) []string {
|
||||
var result []string
|
||||
i := 0
|
||||
for i < len(buf) {
|
||||
next := i + 1 + int(buf[i])
|
||||
result = append(result, string(buf[i+1:next]))
|
||||
i = next
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func TestSysctlClockinfo(t *testing.T) {
|
||||
ci, err := unix.SysctlClockinfo("kern.clockrate")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("tick = %v, tickadj = %v, hz = %v, profhz = %v, stathz = %v",
|
||||
ci.Tick, ci.Tickadj, ci.Hz, ci.Profhz, ci.Stathz)
|
||||
}
|
||||
|
||||
func TestIoctlPtmget(t *testing.T) {
|
||||
fd, err := unix.Open("/dev/ptmx", unix.O_NOCTTY|unix.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
t.Skip("failed to open /dev/ptmx, skipping test")
|
||||
}
|
||||
defer unix.Close(fd)
|
||||
|
||||
ptm, err := unix.IoctlGetPtmget(fd, unix.TIOCPTSNAME)
|
||||
if err != nil {
|
||||
t.Fatalf("IoctlGetPtmget: %v\n", err)
|
||||
}
|
||||
|
||||
t.Logf("sfd = %v, ptsname = %v", ptm.Sfd, string(ptm.Sn[:bytes.IndexByte(ptm.Sn[:], 0)]))
|
||||
}
|
49
vendor/golang.org/x/sys/unix/syscall_openbsd_test.go
generated
vendored
49
vendor/golang.org/x/sys/unix/syscall_openbsd_test.go
generated
vendored
@ -1,49 +0,0 @@
|
||||
// Copyright 2018 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 unix_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestPpoll(t *testing.T) {
|
||||
f, cleanup := mktmpfifo(t)
|
||||
defer cleanup()
|
||||
|
||||
const timeout = 100 * time.Millisecond
|
||||
|
||||
ok := make(chan bool, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(10 * timeout):
|
||||
t.Errorf("Ppoll: failed to timeout after %d", 10*timeout)
|
||||
case <-ok:
|
||||
}
|
||||
}()
|
||||
|
||||
fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
|
||||
timeoutTs := unix.NsecToTimespec(int64(timeout))
|
||||
n, err := unix.Ppoll(fds, &timeoutTs, nil)
|
||||
ok <- true
|
||||
if err != nil {
|
||||
t.Errorf("Ppoll: unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("Ppoll: wrong number of events: got %v, expected %v", n, 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysctlUvmexp(t *testing.T) {
|
||||
uvm, err := unix.SysctlUvmexp("vm.uvmexp")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("free = %v", uvm.Free)
|
||||
}
|
55
vendor/golang.org/x/sys/unix/syscall_solaris_test.go
generated
vendored
55
vendor/golang.org/x/sys/unix/syscall_solaris_test.go
generated
vendored
@ -1,55 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
// +build solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
err := unix.Select(0, nil, nil, nil, &unix.Timeval{Sec: 0, Usec: 0})
|
||||
if err != nil {
|
||||
t.Fatalf("Select: %v", err)
|
||||
}
|
||||
|
||||
dur := 150 * time.Millisecond
|
||||
tv := unix.NsecToTimeval(int64(dur))
|
||||
start := time.Now()
|
||||
err = unix.Select(0, nil, nil, nil, &tv)
|
||||
took := time.Since(start)
|
||||
if err != nil {
|
||||
t.Fatalf("Select: %v", err)
|
||||
}
|
||||
|
||||
if took < dur {
|
||||
t.Errorf("Select: timeout should have been at least %v, got %v", dur, took)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatvfs(t *testing.T) {
|
||||
if err := unix.Statvfs("", nil); err == nil {
|
||||
t.Fatal(`Statvfs("") expected failure`)
|
||||
}
|
||||
|
||||
statvfs := unix.Statvfs_t{}
|
||||
if err := unix.Statvfs("/", &statvfs); err != nil {
|
||||
t.Errorf(`Statvfs("/") failed: %v`, err)
|
||||
}
|
||||
|
||||
if t.Failed() {
|
||||
mount, err := exec.Command("mount").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("mount: %v\n%s", err, mount)
|
||||
} else {
|
||||
t.Logf("mount: %s", mount)
|
||||
}
|
||||
}
|
||||
}
|
60
vendor/golang.org/x/sys/unix/syscall_test.go
generated
vendored
60
vendor/golang.org/x/sys/unix/syscall_test.go
generated
vendored
@ -1,60 +0,0 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func testSetGetenv(t *testing.T, key, value string) {
|
||||
err := unix.Setenv(key, value)
|
||||
if err != nil {
|
||||
t.Fatalf("Setenv failed to set %q: %v", value, err)
|
||||
}
|
||||
newvalue, found := unix.Getenv(key)
|
||||
if !found {
|
||||
t.Fatalf("Getenv failed to find %v variable (want value %q)", key, value)
|
||||
}
|
||||
if newvalue != value {
|
||||
t.Fatalf("Getenv(%v) = %q; want %q", key, newvalue, value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnv(t *testing.T) {
|
||||
testSetGetenv(t, "TESTENV", "AVALUE")
|
||||
// make sure TESTENV gets set to "", not deleted
|
||||
testSetGetenv(t, "TESTENV", "")
|
||||
}
|
||||
|
||||
func TestItoa(t *testing.T) {
|
||||
// Make most negative integer: 0x8000...
|
||||
i := 1
|
||||
for i<<1 != 0 {
|
||||
i <<= 1
|
||||
}
|
||||
if i >= 0 {
|
||||
t.Fatal("bad math")
|
||||
}
|
||||
s := unix.Itoa(i)
|
||||
f := fmt.Sprint(i)
|
||||
if s != f {
|
||||
t.Fatalf("itoa(%d) = %s, want %s", i, s, f)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUname(t *testing.T) {
|
||||
var utsname unix.Utsname
|
||||
err := unix.Uname(&utsname)
|
||||
if err != nil {
|
||||
t.Fatalf("Uname: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("OS: %s/%s %s", utsname.Sysname[:], utsname.Machine[:], utsname.Release[:])
|
||||
}
|
677
vendor/golang.org/x/sys/unix/syscall_unix_test.go
generated
vendored
677
vendor/golang.org/x/sys/unix/syscall_unix_test.go
generated
vendored
@ -1,677 +0,0 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// Tests that below functions, structures and constants are consistent
|
||||
// on all Unix-like systems.
|
||||
func _() {
|
||||
// program scheduling priority functions and constants
|
||||
var (
|
||||
_ func(int, int, int) error = unix.Setpriority
|
||||
_ func(int, int) (int, error) = unix.Getpriority
|
||||
)
|
||||
const (
|
||||
_ int = unix.PRIO_USER
|
||||
_ int = unix.PRIO_PROCESS
|
||||
_ int = unix.PRIO_PGRP
|
||||
)
|
||||
|
||||
// termios constants
|
||||
const (
|
||||
_ int = unix.TCIFLUSH
|
||||
_ int = unix.TCIOFLUSH
|
||||
_ int = unix.TCOFLUSH
|
||||
)
|
||||
|
||||
// fcntl file locking structure and constants
|
||||
var (
|
||||
_ = unix.Flock_t{
|
||||
Type: int16(0),
|
||||
Whence: int16(0),
|
||||
Start: int64(0),
|
||||
Len: int64(0),
|
||||
Pid: int32(0),
|
||||
}
|
||||
)
|
||||
const (
|
||||
_ = unix.F_GETLK
|
||||
_ = unix.F_SETLK
|
||||
_ = unix.F_SETLKW
|
||||
)
|
||||
}
|
||||
|
||||
func TestErrnoSignalName(t *testing.T) {
|
||||
testErrors := []struct {
|
||||
num syscall.Errno
|
||||
name string
|
||||
}{
|
||||
{syscall.EPERM, "EPERM"},
|
||||
{syscall.EINVAL, "EINVAL"},
|
||||
{syscall.ENOENT, "ENOENT"},
|
||||
}
|
||||
|
||||
for _, te := range testErrors {
|
||||
t.Run(fmt.Sprintf("%d/%s", te.num, te.name), func(t *testing.T) {
|
||||
e := unix.ErrnoName(te.num)
|
||||
if e != te.name {
|
||||
t.Errorf("ErrnoName(%d) returned %s, want %s", te.num, e, te.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
testSignals := []struct {
|
||||
num syscall.Signal
|
||||
name string
|
||||
}{
|
||||
{syscall.SIGHUP, "SIGHUP"},
|
||||
{syscall.SIGPIPE, "SIGPIPE"},
|
||||
{syscall.SIGSEGV, "SIGSEGV"},
|
||||
}
|
||||
|
||||
for _, ts := range testSignals {
|
||||
t.Run(fmt.Sprintf("%d/%s", ts.num, ts.name), func(t *testing.T) {
|
||||
s := unix.SignalName(ts.num)
|
||||
if s != ts.name {
|
||||
t.Errorf("SignalName(%d) returned %s, want %s", ts.num, s, ts.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFcntlInt(t *testing.T) {
|
||||
t.Parallel()
|
||||
file, err := ioutil.TempFile("", "TestFnctlInt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
defer file.Close()
|
||||
f := file.Fd()
|
||||
flags, err := unix.FcntlInt(f, unix.F_GETFD, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if flags&unix.FD_CLOEXEC == 0 {
|
||||
t.Errorf("flags %#x do not include FD_CLOEXEC", flags)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFcntlFlock tests whether the file locking structure matches
|
||||
// the calling convention of each kernel.
|
||||
func TestFcntlFlock(t *testing.T) {
|
||||
name := filepath.Join(os.TempDir(), "TestFcntlFlock")
|
||||
fd, err := unix.Open(name, unix.O_CREAT|unix.O_RDWR|unix.O_CLOEXEC, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Open failed: %v", err)
|
||||
}
|
||||
defer unix.Unlink(name)
|
||||
defer unix.Close(fd)
|
||||
flock := unix.Flock_t{
|
||||
Type: unix.F_RDLCK,
|
||||
Start: 0, Len: 0, Whence: 1,
|
||||
}
|
||||
if err := unix.FcntlFlock(uintptr(fd), unix.F_GETLK, &flock); err != nil {
|
||||
t.Fatalf("FcntlFlock failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestPassFD tests passing a file descriptor over a Unix socket.
|
||||
//
|
||||
// This test involved both a parent and child process. The parent
|
||||
// process is invoked as a normal test, with "go test", which then
|
||||
// runs the child process by running the current test binary with args
|
||||
// "-test.run=^TestPassFD$" and an environment variable used to signal
|
||||
// that the test should become the child process instead.
|
||||
func TestPassFD(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
|
||||
t.Skip("cannot exec subprocess on iOS, skipping test")
|
||||
}
|
||||
if runtime.GOOS == "aix" {
|
||||
t.Skip("getsockname issue on AIX 7.2 tl1, skipping test")
|
||||
}
|
||||
|
||||
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
|
||||
passFDChild()
|
||||
return
|
||||
}
|
||||
|
||||
tempDir, err := ioutil.TempDir("", "TestPassFD")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Socketpair: %v", err)
|
||||
}
|
||||
defer unix.Close(fds[0])
|
||||
defer unix.Close(fds[1])
|
||||
writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
|
||||
readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
|
||||
defer writeFile.Close()
|
||||
defer readFile.Close()
|
||||
|
||||
cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
|
||||
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
||||
if lp := os.Getenv("LD_LIBRARY_PATH"); lp != "" {
|
||||
cmd.Env = append(cmd.Env, "LD_LIBRARY_PATH="+lp)
|
||||
}
|
||||
cmd.ExtraFiles = []*os.File{writeFile}
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
if len(out) > 0 || err != nil {
|
||||
t.Fatalf("child process: %q, %v", out, err)
|
||||
}
|
||||
|
||||
c, err := net.FileConn(readFile)
|
||||
if err != nil {
|
||||
t.Fatalf("FileConn: %v", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
uc, ok := c.(*net.UnixConn)
|
||||
if !ok {
|
||||
t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
|
||||
}
|
||||
|
||||
buf := make([]byte, 32) // expect 1 byte
|
||||
oob := make([]byte, 32) // expect 24 bytes
|
||||
closeUnix := time.AfterFunc(5*time.Second, func() {
|
||||
t.Logf("timeout reading from unix socket")
|
||||
uc.Close()
|
||||
})
|
||||
_, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadMsgUnix: %v", err)
|
||||
}
|
||||
closeUnix.Stop()
|
||||
|
||||
scms, err := unix.ParseSocketControlMessage(oob[:oobn])
|
||||
if err != nil {
|
||||
t.Fatalf("ParseSocketControlMessage: %v", err)
|
||||
}
|
||||
if len(scms) != 1 {
|
||||
t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
|
||||
}
|
||||
scm := scms[0]
|
||||
gotFds, err := unix.ParseUnixRights(&scm)
|
||||
if err != nil {
|
||||
t.Fatalf("unix.ParseUnixRights: %v", err)
|
||||
}
|
||||
if len(gotFds) != 1 {
|
||||
t.Fatalf("wanted 1 fd; got %#v", gotFds)
|
||||
}
|
||||
|
||||
f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
|
||||
defer f.Close()
|
||||
|
||||
got, err := ioutil.ReadAll(f)
|
||||
want := "Hello from child process!\n"
|
||||
if string(got) != want {
|
||||
t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
|
||||
}
|
||||
}
|
||||
|
||||
// passFDChild is the child process used by TestPassFD.
|
||||
func passFDChild() {
|
||||
defer os.Exit(0)
|
||||
|
||||
// Look for our fd. It should be fd 3, but we work around an fd leak
|
||||
// bug here (http://golang.org/issue/2603) to let it be elsewhere.
|
||||
var uc *net.UnixConn
|
||||
for fd := uintptr(3); fd <= 10; fd++ {
|
||||
f := os.NewFile(fd, "unix-conn")
|
||||
var ok bool
|
||||
netc, _ := net.FileConn(f)
|
||||
uc, ok = netc.(*net.UnixConn)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
if uc == nil {
|
||||
fmt.Println("failed to find unix fd")
|
||||
return
|
||||
}
|
||||
|
||||
// Make a file f to send to our parent process on uc.
|
||||
// We make it in tempDir, which our parent will clean up.
|
||||
flag.Parse()
|
||||
tempDir := flag.Arg(0)
|
||||
f, err := ioutil.TempFile(tempDir, "")
|
||||
if err != nil {
|
||||
fmt.Printf("TempFile: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
f.Write([]byte("Hello from child process!\n"))
|
||||
f.Seek(0, 0)
|
||||
|
||||
rights := unix.UnixRights(int(f.Fd()))
|
||||
dummyByte := []byte("x")
|
||||
n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("WriteMsgUnix: %v", err)
|
||||
return
|
||||
}
|
||||
if n != 1 || oobn != len(rights) {
|
||||
fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnixRightsRoundtrip tests that UnixRights, ParseSocketControlMessage,
|
||||
// and ParseUnixRights are able to successfully round-trip lists of file descriptors.
|
||||
func TestUnixRightsRoundtrip(t *testing.T) {
|
||||
testCases := [...][][]int{
|
||||
{{42}},
|
||||
{{1, 2}},
|
||||
{{3, 4, 5}},
|
||||
{{}},
|
||||
{{1, 2}, {3, 4, 5}, {}, {7}},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
b := []byte{}
|
||||
var n int
|
||||
for _, fds := range testCase {
|
||||
// Last assignment to n wins
|
||||
n = len(b) + unix.CmsgLen(4*len(fds))
|
||||
b = append(b, unix.UnixRights(fds...)...)
|
||||
}
|
||||
// Truncate b
|
||||
b = b[:n]
|
||||
|
||||
scms, err := unix.ParseSocketControlMessage(b)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseSocketControlMessage: %v", err)
|
||||
}
|
||||
if len(scms) != len(testCase) {
|
||||
t.Fatalf("expected %v SocketControlMessage; got scms = %#v", len(testCase), scms)
|
||||
}
|
||||
for i, scm := range scms {
|
||||
gotFds, err := unix.ParseUnixRights(&scm)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseUnixRights: %v", err)
|
||||
}
|
||||
wantFds := testCase[i]
|
||||
if len(gotFds) != len(wantFds) {
|
||||
t.Fatalf("expected %v fds, got %#v", len(wantFds), gotFds)
|
||||
}
|
||||
for j, fd := range gotFds {
|
||||
if fd != wantFds[j] {
|
||||
t.Fatalf("expected fd %v, got %v", wantFds[j], fd)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRlimit(t *testing.T) {
|
||||
var rlimit, zero unix.Rlimit
|
||||
err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit)
|
||||
if err != nil {
|
||||
t.Fatalf("Getrlimit: save failed: %v", err)
|
||||
}
|
||||
if zero == rlimit {
|
||||
t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
|
||||
}
|
||||
set := rlimit
|
||||
set.Cur = set.Max - 1
|
||||
if runtime.GOOS == "darwin" && set.Cur > 10240 {
|
||||
// The max file limit is 10240, even though
|
||||
// the max returned by Getrlimit is 1<<63-1.
|
||||
// This is OPEN_MAX in sys/syslimits.h.
|
||||
set.Cur = 10240
|
||||
}
|
||||
err = unix.Setrlimit(unix.RLIMIT_NOFILE, &set)
|
||||
if err != nil {
|
||||
t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
|
||||
}
|
||||
var get unix.Rlimit
|
||||
err = unix.Getrlimit(unix.RLIMIT_NOFILE, &get)
|
||||
if err != nil {
|
||||
t.Fatalf("Getrlimit: get failed: %v", err)
|
||||
}
|
||||
set = rlimit
|
||||
set.Cur = set.Max - 1
|
||||
if set != get {
|
||||
// Seems like Darwin requires some privilege to
|
||||
// increase the soft limit of rlimit sandbox, though
|
||||
// Setrlimit never reports an error.
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
default:
|
||||
t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
|
||||
}
|
||||
}
|
||||
err = unix.Setrlimit(unix.RLIMIT_NOFILE, &rlimit)
|
||||
if err != nil {
|
||||
t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeekFailure(t *testing.T) {
|
||||
_, err := unix.Seek(-1, 0, 0)
|
||||
if err == nil {
|
||||
t.Fatalf("Seek(-1, 0, 0) did not fail")
|
||||
}
|
||||
str := err.Error() // used to crash on Linux
|
||||
t.Logf("Seek: %v", str)
|
||||
if str == "" {
|
||||
t.Fatalf("Seek(-1, 0, 0) return error with empty message")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDup(t *testing.T) {
|
||||
file, err := ioutil.TempFile("", "TestDup")
|
||||
if err != nil {
|
||||
t.Fatalf("Tempfile failed: %v", err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
defer file.Close()
|
||||
f := int(file.Fd())
|
||||
|
||||
newFd, err := unix.Dup(f)
|
||||
if err != nil {
|
||||
t.Fatalf("Dup: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Dup2(newFd, newFd+1)
|
||||
if err != nil {
|
||||
t.Fatalf("Dup2: %v", err)
|
||||
}
|
||||
|
||||
b1 := []byte("Test123")
|
||||
b2 := make([]byte, 7)
|
||||
_, err = unix.Write(newFd+1, b1)
|
||||
if err != nil {
|
||||
t.Fatalf("Write to dup2 fd failed: %v", err)
|
||||
}
|
||||
_, err = unix.Seek(f, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Seek failed: %v", err)
|
||||
}
|
||||
_, err = unix.Read(f, b2)
|
||||
if err != nil {
|
||||
t.Fatalf("Read back failed: %v", err)
|
||||
}
|
||||
if string(b1) != string(b2) {
|
||||
t.Errorf("Dup: stdout write not in file, expected %v, got %v", string(b1), string(b2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoll(t *testing.T) {
|
||||
if runtime.GOOS == "android" ||
|
||||
(runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64")) {
|
||||
t.Skip("mkfifo syscall is not available on android and iOS, skipping test")
|
||||
}
|
||||
|
||||
f, cleanup := mktmpfifo(t)
|
||||
defer cleanup()
|
||||
|
||||
const timeout = 100
|
||||
|
||||
ok := make(chan bool, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-time.After(10 * timeout * time.Millisecond):
|
||||
t.Errorf("Poll: failed to timeout after %d milliseconds", 10*timeout)
|
||||
case <-ok:
|
||||
}
|
||||
}()
|
||||
|
||||
fds := []unix.PollFd{{Fd: int32(f.Fd()), Events: unix.POLLIN}}
|
||||
n, err := unix.Poll(fds, timeout)
|
||||
ok <- true
|
||||
if err != nil {
|
||||
t.Errorf("Poll: unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if n != 0 {
|
||||
t.Errorf("Poll: wrong number of events: got %v, expected %v", n, 0)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetwd(t *testing.T) {
|
||||
fd, err := os.Open(".")
|
||||
if err != nil {
|
||||
t.Fatalf("Open .: %s", err)
|
||||
}
|
||||
defer fd.Close()
|
||||
// Directory list for test. Do not worry if any are symlinks or do not
|
||||
// exist on some common unix desktop environments. That will be checked.
|
||||
dirs := []string{"/", "/usr/bin", "/etc", "/var", "/opt"}
|
||||
switch runtime.GOOS {
|
||||
case "android":
|
||||
dirs = []string{"/", "/system/bin"}
|
||||
case "darwin":
|
||||
switch runtime.GOARCH {
|
||||
case "arm", "arm64":
|
||||
d1, err := ioutil.TempDir("", "d1")
|
||||
if err != nil {
|
||||
t.Fatalf("TempDir: %v", err)
|
||||
}
|
||||
d2, err := ioutil.TempDir("", "d2")
|
||||
if err != nil {
|
||||
t.Fatalf("TempDir: %v", err)
|
||||
}
|
||||
dirs = []string{d1, d2}
|
||||
}
|
||||
}
|
||||
oldwd := os.Getenv("PWD")
|
||||
for _, d := range dirs {
|
||||
// Check whether d exists, is a dir and that d's path does not contain a symlink
|
||||
fi, err := os.Stat(d)
|
||||
if err != nil || !fi.IsDir() {
|
||||
t.Logf("Test dir %s stat error (%v) or not a directory, skipping", d, err)
|
||||
continue
|
||||
}
|
||||
check, err := filepath.EvalSymlinks(d)
|
||||
if err != nil || check != d {
|
||||
t.Logf("Test dir %s (%s) is symlink or other error (%v), skipping", d, check, err)
|
||||
continue
|
||||
}
|
||||
err = os.Chdir(d)
|
||||
if err != nil {
|
||||
t.Fatalf("Chdir: %v", err)
|
||||
}
|
||||
pwd, err := unix.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("Getwd in %s: %s", d, err)
|
||||
}
|
||||
os.Setenv("PWD", oldwd)
|
||||
err = fd.Chdir()
|
||||
if err != nil {
|
||||
// We changed the current directory and cannot go back.
|
||||
// Don't let the tests continue; they'll scribble
|
||||
// all over some other directory.
|
||||
fmt.Fprintf(os.Stderr, "fchdir back to dot failed: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if pwd != d {
|
||||
t.Fatalf("Getwd returned %q want %q", pwd, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFstatat(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
touch(t, "file1")
|
||||
|
||||
var st1 unix.Stat_t
|
||||
err := unix.Stat("file1", &st1)
|
||||
if err != nil {
|
||||
t.Fatalf("Stat: %v", err)
|
||||
}
|
||||
|
||||
var st2 unix.Stat_t
|
||||
err = unix.Fstatat(unix.AT_FDCWD, "file1", &st2, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Fstatat: %v", err)
|
||||
}
|
||||
|
||||
if st1 != st2 {
|
||||
t.Errorf("Fstatat: returned stat does not match Stat")
|
||||
}
|
||||
|
||||
err = os.Symlink("file1", "symlink1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = unix.Lstat("symlink1", &st1)
|
||||
if err != nil {
|
||||
t.Fatalf("Lstat: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Fstatat(unix.AT_FDCWD, "symlink1", &st2, unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
t.Fatalf("Fstatat: %v", err)
|
||||
}
|
||||
|
||||
if st1 != st2 {
|
||||
t.Errorf("Fstatat: returned stat does not match Lstat")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFchmodat(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
touch(t, "file1")
|
||||
err := os.Symlink("file1", "symlink1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
mode := os.FileMode(0444)
|
||||
err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Fchmodat: unexpected error: %v", err)
|
||||
}
|
||||
|
||||
fi, err := os.Stat("file1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if fi.Mode() != mode {
|
||||
t.Errorf("Fchmodat: failed to change file mode: expected %v, got %v", mode, fi.Mode())
|
||||
}
|
||||
|
||||
mode = os.FileMode(0644)
|
||||
didChmodSymlink := true
|
||||
err = unix.Fchmodat(unix.AT_FDCWD, "symlink1", uint32(mode), unix.AT_SYMLINK_NOFOLLOW)
|
||||
if err != nil {
|
||||
if (runtime.GOOS == "android" || runtime.GOOS == "linux" || runtime.GOOS == "solaris") && err == unix.EOPNOTSUPP {
|
||||
// Linux and Illumos don't support flags != 0
|
||||
didChmodSymlink = false
|
||||
} else {
|
||||
t.Fatalf("Fchmodat: unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if !didChmodSymlink {
|
||||
// Didn't change mode of the symlink. On Linux, the permissions
|
||||
// of a symbolic link are always 0777 according to symlink(7)
|
||||
mode = os.FileMode(0777)
|
||||
}
|
||||
|
||||
var st unix.Stat_t
|
||||
err = unix.Lstat("symlink1", &st)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got := os.FileMode(st.Mode & 0777)
|
||||
if got != mode {
|
||||
t.Errorf("Fchmodat: failed to change symlink mode: expected %v, got %v", mode, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMkdev(t *testing.T) {
|
||||
major := uint32(42)
|
||||
minor := uint32(7)
|
||||
dev := unix.Mkdev(major, minor)
|
||||
|
||||
if unix.Major(dev) != major {
|
||||
t.Errorf("Major(%#x) == %d, want %d", dev, unix.Major(dev), major)
|
||||
}
|
||||
if unix.Minor(dev) != minor {
|
||||
t.Errorf("Minor(%#x) == %d, want %d", dev, unix.Minor(dev), minor)
|
||||
}
|
||||
}
|
||||
|
||||
// mktmpfifo creates a temporary FIFO and provides a cleanup function.
|
||||
func mktmpfifo(t *testing.T) (*os.File, func()) {
|
||||
err := unix.Mkfifo("fifo", 0666)
|
||||
if err != nil {
|
||||
t.Fatalf("mktmpfifo: failed to create FIFO: %v", err)
|
||||
}
|
||||
|
||||
f, err := os.OpenFile("fifo", os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
os.Remove("fifo")
|
||||
t.Fatalf("mktmpfifo: failed to open FIFO: %v", err)
|
||||
}
|
||||
|
||||
return f, func() {
|
||||
f.Close()
|
||||
os.Remove("fifo")
|
||||
}
|
||||
}
|
||||
|
||||
// utilities taken from os/os_test.go
|
||||
|
||||
func touch(t *testing.T, name string) {
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// chtmpdir changes the working directory to a new temporary directory and
|
||||
// provides a cleanup function. Used when PWD is read-only.
|
||||
func chtmpdir(t *testing.T) func() {
|
||||
oldwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("chtmpdir: %v", err)
|
||||
}
|
||||
d, err := ioutil.TempDir("", "test")
|
||||
if err != nil {
|
||||
t.Fatalf("chtmpdir: %v", err)
|
||||
}
|
||||
if err := os.Chdir(d); err != nil {
|
||||
t.Fatalf("chtmpdir: %v", err)
|
||||
}
|
||||
return func() {
|
||||
if err := os.Chdir(oldwd); err != nil {
|
||||
t.Fatalf("chtmpdir: %v", err)
|
||||
}
|
||||
os.RemoveAll(d)
|
||||
}
|
||||
}
|
54
vendor/golang.org/x/sys/unix/timestruct_test.go
generated
vendored
54
vendor/golang.org/x/sys/unix/timestruct_test.go
generated
vendored
@ -1,54 +0,0 @@
|
||||
// Copyright 2017 The Go Authors. All right reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestTimeToTimespec(t *testing.T) {
|
||||
timeTests := []struct {
|
||||
time time.Time
|
||||
valid bool
|
||||
}{
|
||||
{time.Unix(0, 0), true},
|
||||
{time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), true},
|
||||
{time.Date(2262, time.December, 31, 23, 0, 0, 0, time.UTC), false},
|
||||
{time.Unix(0x7FFFFFFF, 0), true},
|
||||
{time.Unix(0x80000000, 0), false},
|
||||
{time.Unix(0x7FFFFFFF, 1000000000), false},
|
||||
{time.Unix(0x7FFFFFFF, 999999999), true},
|
||||
{time.Unix(-0x80000000, 0), true},
|
||||
{time.Unix(-0x80000001, 0), false},
|
||||
{time.Date(2038, time.January, 19, 3, 14, 7, 0, time.UTC), true},
|
||||
{time.Date(2038, time.January, 19, 3, 14, 8, 0, time.UTC), false},
|
||||
{time.Date(1901, time.December, 13, 20, 45, 52, 0, time.UTC), true},
|
||||
{time.Date(1901, time.December, 13, 20, 45, 51, 0, time.UTC), false},
|
||||
}
|
||||
|
||||
// Currently all targets have either int32 or int64 for Timespec.Sec.
|
||||
// If there were a new target with unsigned or floating point type for
|
||||
// it, this test must be adjusted.
|
||||
have64BitTime := (unsafe.Sizeof(unix.Timespec{}.Sec) == 8)
|
||||
for _, tt := range timeTests {
|
||||
ts, err := unix.TimeToTimespec(tt.time)
|
||||
tt.valid = tt.valid || have64BitTime
|
||||
if tt.valid && err != nil {
|
||||
t.Errorf("TimeToTimespec(%v): %v", tt.time, err)
|
||||
}
|
||||
if err == nil {
|
||||
tstime := time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
||||
if !tstime.Equal(tt.time) {
|
||||
t.Errorf("TimeToTimespec(%v) is the time %v", tt.time, tstime)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
207
vendor/golang.org/x/sys/unix/xattr_test.go
generated
vendored
207
vendor/golang.org/x/sys/unix/xattr_test.go
generated
vendored
@ -1,207 +0,0 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// +build darwin freebsd linux netbsd
|
||||
|
||||
package unix_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func TestXattr(t *testing.T) {
|
||||
defer chtmpdir(t)()
|
||||
|
||||
f := "xattr1"
|
||||
touch(t, f)
|
||||
|
||||
xattrName := "user.test"
|
||||
xattrDataSet := "gopher"
|
||||
|
||||
err := unix.Setxattr(f, xattrName, []byte{}, 0)
|
||||
if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
|
||||
t.Skip("filesystem does not support extended attributes, skipping test")
|
||||
} else if err != nil {
|
||||
t.Fatalf("Setxattr: %v", err)
|
||||
}
|
||||
|
||||
err = unix.Setxattr(f, xattrName, []byte(xattrDataSet), 0)
|
||||
if err != nil {
|
||||
t.Fatalf("Setxattr: %v", err)
|
||||
}
|
||||
|
||||
// find size
|
||||
size, err := unix.Listxattr(f, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Listxattr: %v", err)
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
t.Fatalf("Listxattr returned an empty list of attributes")
|
||||
}
|
||||
|
||||
buf := make([]byte, size)
|
||||
read, err := unix.Listxattr(f, buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Listxattr: %v", err)
|
||||
}
|
||||
|
||||
xattrs := stringsFromByteSlice(buf[:read])
|
||||
|
||||
xattrWant := xattrName
|
||||
if runtime.GOOS == "freebsd" {
|
||||
// On FreeBSD, the namespace is stored separately from the xattr
|
||||
// name and Listxattr doesn't return the namespace prefix.
|
||||
xattrWant = strings.TrimPrefix(xattrWant, "user.")
|
||||
}
|
||||
found := false
|
||||
for _, name := range xattrs {
|
||||
if name == xattrWant {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Errorf("Listxattr did not return previously set attribute '%s'", xattrName)
|
||||
}
|
||||
|
||||
// find size
|
||||
size, err = unix.Getxattr(f, xattrName, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Getxattr: %v", err)
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
t.Fatalf("Getxattr returned an empty attribute")
|
||||
}
|
||||
|
||||
xattrDataGet := make([]byte, size)
|
||||
_, err = unix.Getxattr(f, xattrName, xattrDataGet)
|
||||
if err != nil {
|
||||
t.Fatalf("Getxattr: %v", err)
|
||||
}
|
||||
|
||||
got := string(xattrDataGet)
|
||||
if got != xattrDataSet {
|
||||
t.Errorf("Getxattr: expected attribute value %s, got %s", xattrDataSet, got)
|
||||
}
|
||||
|
||||
err = unix.Removexattr(f, xattrName)
|
||||
if err != nil {
|
||||
t.Fatalf("Removexattr: %v", err)
|
||||
}
|
||||
|
||||
n := "nonexistent"
|
||||
err = unix.Lsetxattr(n, xattrName, []byte(xattrDataSet), 0)
|
||||
if err != unix.ENOENT {
|
||||
t.Errorf("Lsetxattr: expected %v on non-existent file, got %v", unix.ENOENT, err)
|
||||
}
|
||||
|
||||
_, err = unix.Lgetxattr(n, xattrName, nil)
|
||||
if err != unix.ENOENT {
|
||||
t.Errorf("Lgetxattr: %v", err)
|
||||
}
|
||||
|
||||
s := "symlink1"
|
||||
err = os.Symlink(n, s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = unix.Lsetxattr(s, xattrName, []byte(xattrDataSet), 0)
|
||||
if err != nil {
|
||||
// Linux and Android doen't support xattrs on symlinks according
|
||||
// to xattr(7), so just test that we get the proper error.
|
||||
if (runtime.GOOS != "linux" && runtime.GOOS != "android") || err != unix.EPERM {
|
||||
t.Fatalf("Lsetxattr: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFdXattr(t *testing.T) {
|
||||
file, err := ioutil.TempFile("", "TestFdXattr")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(file.Name())
|
||||
defer file.Close()
|
||||
|
||||
fd := int(file.Fd())
|
||||
xattrName := "user.test"
|
||||
xattrDataSet := "gopher"
|
||||
|
||||
err = unix.Fsetxattr(fd, xattrName, []byte(xattrDataSet), 0)
|
||||
if err == unix.ENOTSUP || err == unix.EOPNOTSUPP {
|
||||
t.Skip("filesystem does not support extended attributes, skipping test")
|
||||
} else if err != nil {
|
||||
t.Fatalf("Fsetxattr: %v", err)
|
||||
}
|
||||
|
||||
// find size
|
||||
size, err := unix.Flistxattr(fd, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Flistxattr: %v", err)
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
t.Fatalf("Flistxattr returned an empty list of attributes")
|
||||
}
|
||||
|
||||
buf := make([]byte, size)
|
||||
read, err := unix.Flistxattr(fd, buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Flistxattr: %v", err)
|
||||
}
|
||||
|
||||
xattrs := stringsFromByteSlice(buf[:read])
|
||||
|
||||
xattrWant := xattrName
|
||||
if runtime.GOOS == "freebsd" {
|
||||
// On FreeBSD, the namespace is stored separately from the xattr
|
||||
// name and Listxattr doesn't return the namespace prefix.
|
||||
xattrWant = strings.TrimPrefix(xattrWant, "user.")
|
||||
}
|
||||
found := false
|
||||
for _, name := range xattrs {
|
||||
if name == xattrWant {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Errorf("Flistxattr did not return previously set attribute '%s'", xattrName)
|
||||
}
|
||||
|
||||
// find size
|
||||
size, err = unix.Fgetxattr(fd, xattrName, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Fgetxattr: %v", err)
|
||||
}
|
||||
|
||||
if size <= 0 {
|
||||
t.Fatalf("Fgetxattr returned an empty attribute")
|
||||
}
|
||||
|
||||
xattrDataGet := make([]byte, size)
|
||||
_, err = unix.Fgetxattr(fd, xattrName, xattrDataGet)
|
||||
if err != nil {
|
||||
t.Fatalf("Fgetxattr: %v", err)
|
||||
}
|
||||
|
||||
got := string(xattrDataGet)
|
||||
if got != xattrDataSet {
|
||||
t.Errorf("Fgetxattr: expected attribute value %s, got %s", xattrDataSet, got)
|
||||
}
|
||||
|
||||
err = unix.Fremovexattr(fd, xattrName)
|
||||
if err != nil {
|
||||
t.Fatalf("Fremovexattr: %v", err)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user