Commit de27caac by Ian Lance Taylor

Implement new syscall package.

Calls to library functions now use entersyscall and
exitsyscall as appropriate.  This is a first step toward
multiplexing goroutines onto threads.

From-SVN: r180345
parent 7b45b87f
...@@ -1392,128 +1392,142 @@ go_testing_script_files = \ ...@@ -1392,128 +1392,142 @@ go_testing_script_files = \
# Define Syscall and Syscall6. # Define Syscall and Syscall6.
if LIBGO_IS_RTEMS if LIBGO_IS_RTEMS
syscall_syscall_file = syscalls/syscall_stubs.go syscall_syscall_file = go/syscall/syscall_stubs.go
else else
syscall_syscall_file = syscalls/syscall.go syscall_syscall_file = go/syscall/syscall_unix.go
endif endif
# Declare libc functions that vary for largefile systems. # Define ForkExec and Exec.
if LIBGO_IS_LINUX
# Always use lseek64 on GNU/Linux.
syscall_filesize_file = syscalls/sysfile_largefile.go
syscall_stat_file = syscalls/sysfile_stat_largefile.go
else # !LIBGO_IS_LINUX
if LIBGO_IS_SOLARIS
if LIBGO_IS_386
# Use lseek64 on 32-bit Solaris/x86.
syscall_filesize_file = syscalls/sysfile_largefile.go
syscall_stat_file = syscalls/sysfile_stat_largefile.go
else # !LIBGO_IS_386
if LIBGO_IS_SPARC
# Use lseek64 on 32-bit Solaris/SPARC.
syscall_filesize_file = syscalls/sysfile_largefile.go
syscall_stat_file = syscalls/sysfile_stat_largefile.go
else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
# Use lseek on 64-bit Solaris.
syscall_filesize_file = syscalls/sysfile_regfile.go
syscall_stat_file = syscalls/sysfile_stat_regfile.go
endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
endif # !LIBGO_IS_SOLARIS
else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
# Use lseek by default.
syscall_filesize_file = syscalls/sysfile_regfile.go
syscall_stat_file = syscalls/sysfile_stat_regfile.go
endif # !LIBGO_IS_SOLARIS
endif # !LIBGO_IS_LINUX
# Define ForkExec, PtraceForkExec, and Exec.
if LIBGO_IS_RTEMS if LIBGO_IS_RTEMS
syscall_exec_os_file = syscalls/exec_stubs.go syscall_exec_file = go/syscall/exec_stubs.go
else else
syscall_exec_os_file = syscalls/exec.go syscall_exec_file = go/syscall/exec_unix.go
endif endif
# Define Wait4. # Define Wait4.
if HAVE_WAIT4 if HAVE_WAIT4
syscall_wait_file = syscalls/wait4.go syscall_wait_file = go/syscall/libcall_wait4.go
else else
syscall_wait_file = syscalls/waitpid.go syscall_wait_file = go/syscall/libcall_waitpid.go
endif endif
# Define Sleep. # Define Sleep.
if LIBGO_IS_RTEMS if LIBGO_IS_RTEMS
syscall_sleep_file = syscalls/sleep_rtems.go syscall_sleep_file = go/syscall/sleep_rtems.go
else else
syscall_sleep_file = syscalls/sleep_select.go syscall_sleep_file = go/syscall/sleep_select.go
endif endif
# Define Errstr. # Define Errstr.
if LIBGO_IS_LINUX
syscall_errstr_file = go/syscall/errstr_linux.go
else
if LIBGO_IS_RTEMS if LIBGO_IS_RTEMS
syscall_errstr_file = syscalls/errstr_rtems.go syscall_errstr_file = go/syscall/errstr_linux.go
else else
if HAVE_STRERROR_R if HAVE_STRERROR_R
syscall_errstr_file = syscalls/errstr.go syscall_errstr_file = go/syscall/errstr.go
else else
syscall_errstr_file = syscalls/errstr_nor.go syscall_errstr_file = go/syscall/errstr_nor.go
endif
endif endif
endif endif
# Declare libc_strerror_r which is the Go name for strerror_r. # Declare libc functions that vary for largefile systems.
if LIBGO_IS_RTEMS
# RTEMS uses newlib in which strerror_r returns char *.
syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go
else
if LIBGO_IS_LINUX if LIBGO_IS_LINUX
# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r. # Always use lseek64 on GNU/Linux.
syscall_errstr_decl_file = syscalls/errstr_decl_linux.go syscall_size_file = go/syscall/libcall_posix_largefile.go
else else # !LIBGO_IS_LINUX
# On other systems we hope strerror_r is just strerror_r. if LIBGO_IS_SOLARIS
syscall_errstr_decl_file = syscalls/errstr_decl.go if LIBGO_IS_386
endif # Use lseek64 on 32-bit Solaris/x86.
endif syscall_size_file = go/syscall/libcall_posix_largefile.go
else # !LIBGO_IS_386
if LIBGO_IS_SPARC
# Use lseek64 on 32-bit Solaris/SPARC.
syscall_size_file = go/syscall/libcall_posix_largefile.go
else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
# Use lseek on 64-bit Solaris.
syscall_size_file = go/syscall/libcall_posix_regfile.go
endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
endif # !LIBGO_IS_SOLARIS
else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
# Use lseek by default.
syscall_size_file = go/syscall/libcall_posix_regfile.go
endif # !LIBGO_IS_SOLARIS
endif # !LIBGO_IS_LINUX
# Define socket sizes and types. # Define socket sizes and types.
if LIBGO_IS_LINUX if LIBGO_IS_LINUX
syscall_socket_os_file = syscalls/socket_linux.go syscall_socket_file = go/syscall/socket_linux.go
else else
if LIBGO_IS_SOLARIS if LIBGO_IS_SOLARIS
syscall_socket_os_file = syscalls/socket_solaris.go syscall_socket_file = go/syscall/socket_solaris.go
else else
if LIBGO_IS_IRIX if LIBGO_IS_IRIX
syscall_socket_os_file = syscalls/socket_irix.go syscall_socket_file = go/syscall/socket_irix.go
else else
syscall_socket_os_file = syscalls/socket_bsd.go syscall_socket_file = go/syscall/socket_bsd.go
endif endif
endif endif
endif endif
# Support for epoll.
if LIBGO_IS_LINUX
syscall_socket_epoll_file = syscalls/socket_epoll.go
else
syscall_socket_epoll_file =
endif
# Support for uname. # Support for uname.
if LIBGO_IS_SOLARIS if LIBGO_IS_SOLARIS
if LIBGO_IS_386 if LIBGO_IS_386
# 32-bit Solaris 2/x86 needs _nuname, handled in syscall_solaris_386.go. # 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go.
syscall_uname_file = syscall_uname_file =
else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS
syscall_uname_file = syscalls/syscall_uname.go syscall_uname_file = go/syscall/libcall_uname.go
endif endif
else # !LIBGO_IS_SOLARIS else # !LIBGO_IS_SOLARIS
syscall_uname_file = syscalls/syscall_uname.go syscall_uname_file = go/syscall/libcall_uname.go
endif endif
# Support for netlink sockets and messages. # Support for netlink sockets and messages.
if LIBGO_IS_LINUX if LIBGO_IS_LINUX
syscall_netlink_file = syscalls/netlink_linux.go syscall_netlink_file = go/syscall/netlink_linux.go
else else
syscall_netlink_file = syscall_netlink_file =
endif endif
go_base_syscall_files = \
go/syscall/libcall_support.go \
go/syscall/libcall_posix.go \
go/syscall/socket.go \
go/syscall/str.go \
go/syscall/syscall.go \
$(syscall_syscall_file) \
$(syscall_exec_file) \
$(syscall_wait_file) \
$(syscall_sleep_file) \
$(syscall_errstr_file) \
$(syscall_size_file) \
$(syscall_socket_file) \
$(syscall_uname_file) \
$(syscall_netlink_file) \
$(GO_LIBCALL_OS_FILE) \
$(GO_LIBCALL_OS_ARCH_FILE) \
$(GO_SYSCALL_OS_FILE) \
$(GO_SYSCALL_OS_ARCH_FILE)
go_syscall_files = \
$(go_base_syscall_files) \
libcalls.go \
sysinfo.go \
syscall_arch.go
go_syscall_c_files = \
go/syscall/errno.c \
go/syscall/wait.c
libcalls.go: s-libcalls; @true
s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files)
rm -f libcalls.go.tmp
files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \
$(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp
$(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go
$(STAMP) $@
syscall_arch.go: s-syscall_arch; @true syscall_arch.go: s-syscall_arch; @true
s-syscall_arch: Makefile s-syscall_arch: Makefile
rm -f syscall_arch.go.tmp rm -f syscall_arch.go.tmp
...@@ -1523,30 +1537,11 @@ s-syscall_arch: Makefile ...@@ -1523,30 +1537,11 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go $(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@ $(STAMP) $@
go_syscall_files = \ sysinfo.go: s-sysinfo; @true
$(syscall_errstr_file) \ s-sysinfo: $(srcdir)/mksysinfo.sh config.h
$(syscall_errstr_decl_file) \ CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
syscalls/exec_helpers.go \ $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
$(syscall_exec_os_file) \ $(STAMP) $@
$(syscall_wait_file) \
$(syscall_filesize_file) \
$(syscall_netlink_file) \
$(syscall_stat_file) \
$(syscall_sleep_file) \
syscalls/socket.go \
$(syscall_socket_os_file) \
$(syscall_socket_epoll_file) \
$(syscall_syscall_file) \
$(syscall_uname_file) \
syscalls/syscall_unix.go \
syscalls/stringbyte.go \
syscalls/syscall_$(GOOS).go \
$(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \
syscalls/sysfile_posix.go \
sysinfo.go \
syscall_arch.go
go_syscall_c_files = \
syscalls/errno.c
if LIBGO_IS_LINUX if LIBGO_IS_LINUX
# os_lib_inotify_lo = os/inotify.lo # os_lib_inotify_lo = os/inotify.lo
...@@ -1708,8 +1703,9 @@ libgo_go_objs = \ ...@@ -1708,8 +1703,9 @@ libgo_go_objs = \
runtime/pprof.lo \ runtime/pprof.lo \
sync/atomic.lo \ sync/atomic.lo \
sync/atomic_c.lo \ sync/atomic_c.lo \
syscalls/syscall.lo \ syscall/syscall.lo \
syscalls/errno.lo \ syscall/errno.lo \
syscall/wait.lo \
template/parse.lo \ template/parse.lo \
testing/testing.lo \ testing/testing.lo \
testing/iotest.lo \ testing/iotest.lo \
...@@ -2983,16 +2979,12 @@ testing/script/check: $(CHECK_DEPS) ...@@ -2983,16 +2979,12 @@ testing/script/check: $(CHECK_DEPS)
@$(CHECK) @$(CHECK)
.PHONY: testing/script/check .PHONY: testing/script/check
sysinfo.go: s-sysinfo; @true syscall/syscall.lo: $(go_syscall_files) sync.gox
s-sysinfo: $(srcdir)/mksysinfo.sh config.h
CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
$(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
$(STAMP) $@
syscalls/syscall.lo: $(go_syscall_files) sync.gox
$(BUILDPACKAGE) $(BUILDPACKAGE)
syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo syscall/errno.lo: go/syscall/errno.c
$(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c $(LTCOMPILE) -c -o $@ $<
syscall/wait.lo: go/syscall/wait.c
$(LTCOMPILE) -c -o $@ $<
# How to build a .gox file from a .lo file. # How to build a .gox file from a .lo file.
BUILDGOX = \ BUILDGOX = \
...@@ -3079,7 +3071,7 @@ sync.gox: sync/sync.lo ...@@ -3079,7 +3071,7 @@ sync.gox: sync/sync.lo
$(BUILDGOX) $(BUILDGOX)
syslog.gox: syslog/syslog.lo syslog.gox: syslog/syslog.lo
$(BUILDGOX) $(BUILDGOX)
syscall.gox: syscalls/syscall.lo syscall.gox: syscall/syscall.lo
$(BUILDGOX) $(BUILDGOX)
tabwriter.gox: tabwriter/tabwriter.lo tabwriter.gox: tabwriter/tabwriter.lo
$(BUILDGOX) $(BUILDGOX)
......
...@@ -617,7 +617,10 @@ USING_SPLIT_STACK_FALSE ...@@ -617,7 +617,10 @@ USING_SPLIT_STACK_FALSE
USING_SPLIT_STACK_TRUE USING_SPLIT_STACK_TRUE
SPLIT_STACK SPLIT_STACK
OSCFLAGS OSCFLAGS
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE GO_SYSCALL_OS_ARCH_FILE
GO_SYSCALL_OS_FILE
GO_LIBCALL_OS_ARCH_FILE
GO_LIBCALL_OS_FILE
GOARCH GOARCH
LIBGO_IS_X86_64_FALSE LIBGO_IS_X86_64_FALSE
LIBGO_IS_X86_64_TRUE LIBGO_IS_X86_64_TRUE
...@@ -10913,7 +10916,7 @@ else ...@@ -10913,7 +10916,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 10916 "configure" #line 10919 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -11019,7 +11022,7 @@ else ...@@ -11019,7 +11022,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF cat > conftest.$ac_ext <<_LT_EOF
#line 11022 "configure" #line 11025 "configure"
#include "confdefs.h" #include "confdefs.h"
#if HAVE_DLFCN_H #if HAVE_DLFCN_H
...@@ -13151,6 +13154,49 @@ CC="$lt_save_CC" ...@@ -13151,6 +13154,49 @@ CC="$lt_save_CC"
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc} CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if test "${ac_cv_prog_AWK+set}" = set; then :
$as_echo_n "(cached) " >&6
else
if test -n "$AWK"; then
ac_cv_prog_AWK="$AWK" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
ac_cv_prog_AWK="$ac_prog"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
AWK=$ac_cv_prog_AWK
if test -n "$AWK"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
$as_echo "$AWK" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
test -n "$AWK" && break
done
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual' WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
...@@ -13551,10 +13597,25 @@ fi ...@@ -13551,10 +13597,25 @@ fi
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE= GO_LIBCALL_OS_FILE=
if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then GO_LIBCALL_OS_ARCH_FILE=
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go GO_SYSCALL_OS_FILE=
GO_SYSCALL_OS_ARCH_FILE=
if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then
GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go
fi fi
if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then
GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go
fi
if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then
GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go
fi
if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then
GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go
fi
case "$target" in case "$target" in
......
...@@ -45,6 +45,8 @@ AC_SUBST(enable_static) ...@@ -45,6 +45,8 @@ AC_SUBST(enable_static)
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc} CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
AC_SUBST(CC_FOR_BUILD) AC_SUBST(CC_FOR_BUILD)
AC_PROG_AWK
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual' WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
AC_SUBST(WARN_FLAGS) AC_SUBST(WARN_FLAGS)
...@@ -249,11 +251,26 @@ AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes) ...@@ -249,11 +251,26 @@ AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes)
AC_SUBST(GOARCH) AC_SUBST(GOARCH)
dnl Some files are only present when needed for specific architectures. dnl Some files are only present when needed for specific architectures.
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE= GO_LIBCALL_OS_FILE=
if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then GO_LIBCALL_OS_ARCH_FILE=
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go GO_SYSCALL_OS_FILE=
GO_SYSCALL_OS_ARCH_FILE=
if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then
GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go
fi
if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then
GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go
fi
if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then
GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go
fi
if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then
GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go
fi fi
AC_SUBST(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) AC_SUBST(GO_LIBCALL_OS_FILE)
AC_SUBST(GO_LIBCALL_OS_ARCH_FILE)
AC_SUBST(GO_SYSCALL_OS_FILE)
AC_SUBST(GO_SYSCALL_OS_ARCH_FILE)
dnl Some targets need special flags to build sysinfo.go. dnl Some targets need special flags to build sysinfo.go.
case "$target" in case "$target" in
......
...@@ -24,6 +24,17 @@ func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res ** ...@@ -24,6 +24,17 @@ func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **
func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo") func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo")
func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror") func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror")
// bytePtrToString takes a NUL-terminated array of bytes and convert
// it to a Go string.
func bytePtrToString(p *byte) string {
a := (*[10000]byte)(unsafe.Pointer(p))
i := 0
for a[i] != 0 {
i++
}
return string(a[:i])
}
func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) { func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
ip, err, completed := cgoLookupIP(name) ip, err, completed := cgoLookupIP(name)
for _, p := range ip { for _, p := range ip {
...@@ -99,13 +110,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp ...@@ -99,13 +110,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
} else if gerrno == syscall.EAI_SYSTEM { } else if gerrno == syscall.EAI_SYSTEM {
str = syscall.Errstr(syscall.GetErrno()) str = syscall.Errstr(syscall.GetErrno())
} else { } else {
str = syscall.BytePtrToString(libc_gai_strerror(gerrno)) str = bytePtrToString(libc_gai_strerror(gerrno))
} }
return nil, "", &DNSError{Error: str, Name: name}, true return nil, "", &DNSError{Error: str, Name: name}, true
} }
defer libc_freeaddrinfo(res) defer libc_freeaddrinfo(res)
if res != nil { if res != nil {
cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname))) cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
if cname == "" { if cname == "" {
cname = name cname = name
} }
......
...@@ -12,20 +12,20 @@ import ( ...@@ -12,20 +12,20 @@ import (
) )
type pollster struct { type pollster struct {
readFds, writeFds, repeatFds *syscall.FdSet_t readFds, writeFds, repeatFds *syscall.FdSet
maxFd int maxFd int
readyReadFds, readyWriteFds *syscall.FdSet_t readyReadFds, readyWriteFds *syscall.FdSet
nReady int nReady int
lastFd int lastFd int
} }
func newpollster() (p *pollster, err os.Error) { func newpollster() (p *pollster, err os.Error) {
p = new(pollster) p = new(pollster)
p.readFds = new(syscall.FdSet_t) p.readFds = new(syscall.FdSet)
p.writeFds = new(syscall.FdSet_t) p.writeFds = new(syscall.FdSet)
p.repeatFds = new(syscall.FdSet_t) p.repeatFds = new(syscall.FdSet)
p.readyReadFds = new(syscall.FdSet_t) p.readyReadFds = new(syscall.FdSet)
p.readyWriteFds = new(syscall.FdSet_t) p.readyWriteFds = new(syscall.FdSet)
p.maxFd = -1 p.maxFd = -1
p.nReady = 0 p.nReady = 0
p.lastFd = 0 p.lastFd = 0
...@@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E ...@@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
} }
var n, e int var n, e int
var tmpReadFds, tmpWriteFds syscall.FdSet_t var tmpReadFds, tmpWriteFds syscall.FdSet
for { for {
// Temporary syscall.FdSet_ts into which the values are copied // Temporary syscall.FdSet's into which the values are copied
// because select mutates the values. // because select mutates the values.
tmpReadFds = *p.readFds tmpReadFds = *p.readFds
tmpWriteFds = *p.writeFds tmpWriteFds = *p.writeFds
......
...@@ -27,6 +27,17 @@ static int mygetpwuid_r(int uid, struct passwd *pwd, ...@@ -27,6 +27,17 @@ static int mygetpwuid_r(int uid, struct passwd *pwd,
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r") func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r")
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r") func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r")
// bytePtrToString takes a NUL-terminated array of bytes and convert
// it to a Go string.
func bytePtrToString(p *byte) string {
a := (*[10000]byte)(unsafe.Pointer(p))
i := 0
for a[i] != 0 {
i++
}
return string(a[:i])
}
func init() { func init() {
implemented = true implemented = true
} }
...@@ -78,9 +89,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) { ...@@ -78,9 +89,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
u := &User{ u := &User{
Uid: int(pwd.Pw_uid), Uid: int(pwd.Pw_uid),
Gid: int(pwd.Pw_gid), Gid: int(pwd.Pw_gid),
Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))), Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))), Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))), HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
} }
// The pw_gecos field isn't quite standardized. Some docs // The pw_gecos field isn't quite standardized. Some docs
// say: "It is expected to be a comma separated list of // say: "It is expected to be a comma separated list of
......
// 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.
// +build darwin freebsd openbsd
// Berkeley packet filter for BSD variants
package syscall
import (
"unsafe"
)
func BpfStmt(code, k int) *BpfInsn {
return &BpfInsn{Code: uint16(code), K: uint32(k)}
}
func BpfJump(code, k, jt, jf int) *BpfInsn {
return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
}
func BpfBuflen(fd int) (int, int) {
var l int
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
if e := int(ep); e != 0 {
return 0, e
}
return l, 0
}
func SetBpfBuflen(fd, l int) (int, int) {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
if e := int(ep); e != 0 {
return 0, e
}
return l, 0
}
func BpfDatalink(fd int) (int, int) {
var t int
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
if e := int(ep); e != 0 {
return 0, e
}
return t, 0
}
func SetBpfDatalink(fd, t int) (int, int) {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
if e := int(ep); e != 0 {
return 0, e
}
return t, 0
}
func SetBpfPromisc(fd, m int) int {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
if e := int(ep); e != 0 {
return e
}
return 0
}
func FlushBpf(fd int) int {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
if e := int(ep); e != 0 {
return e
}
return 0
}
type ivalue struct {
name [IFNAMSIZ]byte
value int16
}
func BpfInterface(fd int, name string) (string, int) {
var iv ivalue
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
if e := int(ep); e != 0 {
return "", e
}
return name, 0
}
func SetBpfInterface(fd int, name string) int {
var iv ivalue
copy(iv.name[:], []byte(name))
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
if e := int(ep); e != 0 {
return e
}
return 0
}
func BpfTimeout(fd int) (*Timeval, int) {
var tv Timeval
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
if e := int(ep); e != 0 {
return nil, e
}
return &tv, 0
}
func SetBpfTimeout(fd int, tv *Timeval) int {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
if e := int(ep); e != 0 {
return e
}
return 0
}
func BpfStats(fd int) (*BpfStat, int) {
var s BpfStat
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
if e := int(ep); e != 0 {
return nil, e
}
return &s, 0
}
func SetBpfImmediate(fd, m int) int {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
if e := int(ep); e != 0 {
return e
}
return 0
}
func SetBpf(fd int, i []BpfInsn) int {
var p BpfProgram
p.Len = uint32(len(i))
p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0]))
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
if e := int(ep); e != 0 {
return e
}
return 0
}
func CheckBpfVersion(fd int) int {
var v BpfVersion
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
if e := int(ep); e != 0 {
return e
}
if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION {
return EINVAL
}
return 0
}
func BpfHeadercmpl(fd int) (int, int) {
var f int
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
if e := int(ep); e != 0 {
return 0, e
}
return f, 0
}
func SetBpfHeadercmpl(fd, f int) int {
_, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
if e := int(ep); e != 0 {
return e
}
return 0
}
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
/* errno is typically a macro. These functions set /* errno is typically a macro. These functions set
and get errno specific to the libc being used. */ and get errno specific to the libc being used. */
int GetErrno() asm ("libgo_syscalls.syscall.GetErrno"); int GetErrno() asm ("libgo_syscall.syscall.GetErrno");
void SetErrno(int) asm ("libgo_syscalls.syscall.SetErrno"); void SetErrno(int) asm ("libgo_syscall.syscall.SetErrno");
int int
GetErrno() GetErrno()
......
...@@ -6,18 +6,21 @@ ...@@ -6,18 +6,21 @@
package syscall package syscall
func Errstr(errno int) string { //sysnb strerror_r(errnum int, buf []byte) (errno int)
for len := Size_t(128); ; len *= 2 { //strerror_r(errnum int, buf *byte, buflen Size_t) int
func Errstr(errnum int) string {
for len := 128; ; len *= 2 {
b := make([]byte, len) b := make([]byte, len)
r := libc_strerror_r(errno, &b[0], len) err := strerror_r(errnum, b)
if r >= 0 { if err == 0 {
i := 0 i := 0
for b[i] != 0 { for b[i] != 0 {
i++ i++
} }
return string(b[:i]) return string(b[:i])
} }
if GetErrno() != ERANGE { if err != ERANGE {
return "Errstr failure" return "Errstr failure"
} }
} }
......
...@@ -6,21 +6,18 @@ ...@@ -6,21 +6,18 @@
package syscall package syscall
func Errstr(errno int) string { import "unsafe"
for len := Size_t(128); ; len *= 2 {
b := make([]byte, len+1)
// The newlib strerror_r always returns the string in buffer. //sysnb strerror_r(errnum int, b []byte) (errstr *byte)
libc_strerror_r(errno, &b[0], len) //strerror_r(errnum int, b *byte, len Size_t) *byte
b[len] = 0
i := 0 func Errstr(errnum int) string {
for b[i] != 0 { a := make([]byte, 128)
i++ p := strerror_r(errnum, a)
} b := (*[1000]byte)(unsafe.Pointer(p))
i := 0
if Size_t(i) < len { for b[i] != 0 {
return string(b[0:i]) i++
}
} }
return string(b[:i])
} }
...@@ -11,7 +11,8 @@ import ( ...@@ -11,7 +11,8 @@ import (
"unsafe" "unsafe"
) )
func libc_strerror(int) *byte __asm__ ("strerror") //sysnb strerror(errnum int) *byte
//strerror(errnum int) *byte
var errstr_lock sync.Mutex var errstr_lock sync.Mutex
......
// exec_stubs.go -- fork/exec stubs.
// Copyright 2010 The Go Authors. All rights reserved. // Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
...@@ -12,10 +10,6 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) ...@@ -12,10 +10,6 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int)
return -1, ENOSYS; return -1, ENOSYS;
} }
func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
return -1, ENOSYS;
}
func Exec(argv0 string, argv []string, envv []string) (err int) { func Exec(argv0 string, argv []string, envv []string) (err int) {
return ENOSYS; return ENOSYS;
} }
......
// 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.
// Fork, exec, wait, etc.
package syscall
import (
"sync"
"unsafe"
"utf16"
)
var ForkLock sync.RWMutex
// EscapeArg rewrites command line argument s as prescribed
// in http://msdn.microsoft.com/en-us/library/ms880421.
// This function returns "" (2 double quotes) if s is empty.
// Alternatively, these transformations are done:
// - every back slash (\) is doubled, but only if immediately
// followed by double quote (");
// - every double quote (") is escaped by back slash (\);
// - finally, s is wrapped with double quotes (arg -> "arg"),
// but only if there is space or tab inside s.
func EscapeArg(s string) string {
if len(s) == 0 {
return "\"\""
}
n := len(s)
hasSpace := false
for i := 0; i < len(s); i++ {
switch s[i] {
case '"', '\\':
n++
case ' ', '\t':
hasSpace = true
}
}
if hasSpace {
n += 2
}
if n == len(s) {
return s
}
qs := make([]byte, n)
j := 0
if hasSpace {
qs[j] = '"'
j++
}
slashes := 0
for i := 0; i < len(s); i++ {
switch s[i] {
default:
slashes = 0
qs[j] = s[i]
case '\\':
slashes++
qs[j] = s[i]
case '"':
for ; slashes > 0; slashes-- {
qs[j] = '\\'
j++
}
qs[j] = '\\'
j++
qs[j] = s[i]
}
j++
}
if hasSpace {
for ; slashes > 0; slashes-- {
qs[j] = '\\'
j++
}
qs[j] = '"'
j++
}
return string(qs[:j])
}
// makeCmdLine builds a command line out of args by escaping "special"
// characters and joining the arguments with spaces.
func makeCmdLine(args []string) string {
var s string
for _, v := range args {
if s != "" {
s += " "
}
s += EscapeArg(v)
}
return s
}
// createEnvBlock converts an array of environment strings into
// the representation required by CreateProcess: a sequence of NUL
// terminated strings followed by a nil.
// Last bytes are two UCS-2 NULs, or four NUL bytes.
func createEnvBlock(envv []string) *uint16 {
if len(envv) == 0 {
return &utf16.Encode([]int("\x00\x00"))[0]
}
length := 0
for _, s := range envv {
length += len(s) + 1
}
length += 1
b := make([]byte, length)
i := 0
for _, s := range envv {
l := len(s)
copy(b[i:i+l], []byte(s))
copy(b[i+l:i+l+1], []byte{0})
i = i + l + 1
}
copy(b[i:i+1], []byte{0})
return &utf16.Encode([]int(string(b)))[0]
}
func CloseOnExec(fd Handle) {
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}
func SetNonblock(fd Handle, nonblocking bool) (errno int) {
return 0
}
// getFullPath retrieves the full path of the specified file.
// Just a wrapper for Windows GetFullPathName api.
func getFullPath(name string) (path string, err int) {
p := StringToUTF16Ptr(name)
buf := make([]uint16, 100)
n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
if err != 0 {
return "", err
}
if n > uint32(len(buf)) {
// Windows is asking for bigger buffer.
buf = make([]uint16, n)
n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
if err != 0 {
return "", err
}
if n > uint32(len(buf)) {
return "", EINVAL
}
}
return UTF16ToString(buf[:n]), 0
}
func isSlash(c uint8) bool {
return c == '\\' || c == '/'
}
func normalizeDir(dir string) (name string, err int) {
ndir, err := getFullPath(dir)
if err != 0 {
return "", err
}
if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
// dir cannot have \\server\share\path form
return "", EINVAL
}
return ndir, 0
}
func volToUpper(ch int) int {
if 'a' <= ch && ch <= 'z' {
ch += 'A' - 'a'
}
return ch
}
func joinExeDirAndFName(dir, p string) (name string, err int) {
if len(p) == 0 {
return "", EINVAL
}
if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
// \\server\share\path form
return p, 0
}
if len(p) > 1 && p[1] == ':' {
// has drive letter
if len(p) == 2 {
return "", EINVAL
}
if isSlash(p[2]) {
return p, 0
} else {
d, err := normalizeDir(dir)
if err != 0 {
return "", err
}
if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
return getFullPath(d + "\\" + p[2:])
} else {
return getFullPath(p)
}
}
} else {
// no drive letter
d, err := normalizeDir(dir)
if err != 0 {
return "", err
}
if isSlash(p[0]) {
return getFullPath(d[:2] + p)
} else {
return getFullPath(d + "\\" + p)
}
}
// we shouldn't be here
return "", EINVAL
}
type ProcAttr struct {
Dir string
Env []string
Files []Handle
Sys *SysProcAttr
}
type SysProcAttr struct {
HideWindow bool
CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
}
var zeroProcAttr ProcAttr
var zeroSysProcAttr SysProcAttr
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
if len(argv0) == 0 {
return 0, 0, EWINDOWS
}
if attr == nil {
attr = &zeroProcAttr
}
sys := attr.Sys
if sys == nil {
sys = &zeroSysProcAttr
}
if len(attr.Files) > 3 {
return 0, 0, EWINDOWS
}
if len(attr.Dir) != 0 {
// StartProcess assumes that argv0 is relative to attr.Dir,
// because it implies Chdir(attr.Dir) before executing argv0.
// Windows CreateProcess assumes the opposite: it looks for
// argv0 relative to the current directory, and, only once the new
// process is started, it does Chdir(attr.Dir). We are adjusting
// for that difference here by making argv0 absolute.
var err int
argv0, err = joinExeDirAndFName(attr.Dir, argv0)
if err != 0 {
return 0, 0, err
}
}
argv0p := StringToUTF16Ptr(argv0)
var cmdline string
// Windows CreateProcess takes the command line as a single string:
// use attr.CmdLine if set, else build the command line by escaping
// and joining each argument with spaces
if sys.CmdLine != "" {
cmdline = sys.CmdLine
} else {
cmdline = makeCmdLine(argv)
}
var argvp *uint16
if len(cmdline) != 0 {
argvp = StringToUTF16Ptr(cmdline)
}
var dirp *uint16
if len(attr.Dir) != 0 {
dirp = StringToUTF16Ptr(attr.Dir)
}
// Acquire the fork lock so that no other threads
// create new fds that are not yet close-on-exec
// before we fork.
ForkLock.Lock()
defer ForkLock.Unlock()
p, _ := GetCurrentProcess()
fd := make([]Handle, len(attr.Files))
for i := range attr.Files {
if attr.Files[i] > 0 {
err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
if err != 0 {
return 0, 0, err
}
defer CloseHandle(Handle(fd[i]))
}
}
si := new(StartupInfo)
si.Cb = uint32(unsafe.Sizeof(*si))
si.Flags = STARTF_USESTDHANDLES
if sys.HideWindow {
si.Flags |= STARTF_USESHOWWINDOW
si.ShowWindow = SW_HIDE
}
si.StdInput = fd[0]
si.StdOutput = fd[1]
si.StdErr = fd[2]
pi := new(ProcessInformation)
err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
if err != 0 {
return 0, 0, err
}
defer CloseHandle(Handle(pi.Thread))
return int(pi.ProcessId), int(pi.Process), 0
}
func Exec(argv0 string, argv []string, envv []string) (err int) {
return EWINDOWS
}
// 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.
// POSIX library calls.
// This file is compiled as ordinary Go code,
// but it is also input to mksyscall,
// which parses the //sys lines and generates library call stubs.
// Note that sometimes we use a lowercase //sys name and
// wrap it in our own nicer implementation.
package syscall
import "unsafe"
/*
* Wrapped
*/
//sysnb pipe(p *[2]int) (errno int)
//pipe(p *[2]int) int
func Pipe(p []int) (errno int) {
if len(p) != 2 {
return EINVAL
}
var pp [2]int
errno = pipe(&pp)
p[0] = pp[0]
p[1] = pp[1]
return
}
//sys utimes(path string, times *[2]Timeval) (errno int)
//utimes(path *byte, times *[2]Timeval) int
func Utimes(path string, tv []Timeval) (errno int) {
if len(tv) != 2 {
return EINVAL
}
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
//sys getcwd(buf *byte, size Size_t) (errno int)
//getcwd(buf *byte, size Size_t) *byte
const ImplementsGetwd = true
func Getwd() (ret string, errno int) {
for len := Size_t(4096); ; len *= 2 {
b := make([]byte, len)
err := getcwd(&b[0], len)
if err == 0 {
i := 0;
for b[i] != 0 {
i++;
}
return string(b[0:i]), 0;
}
if err != ERANGE {
return "", err
}
}
}
//sysnb getgroups(size int, list *Gid_t) (nn int, errno int)
//getgroups(size int, list *Gid_t) int
func Getgroups() (gids []int, errno int) {
n, err := getgroups(0, nil)
if err != 0 {
return nil, errno
}
if n == 0 {
return nil, 0
}
// Sanity check group count. Max is 1<<16 on Linux.
if n < 0 || n > 1<<20 {
return nil, EINVAL
}
a := make([]Gid_t, n)
n, err = getgroups(n, &a[0])
if err != 0 {
return nil, errno
}
gids = make([]int, n)
for i, v := range a[0:n] {
gids[i] = int(v)
}
return
}
//sysnb setgroups(n int, list *Gid_t) (errno int)
//setgroups(n Size_t, list *Gid_t) int
func Setgroups(gids []int) (errno int) {
if len(gids) == 0 {
return setgroups(0, nil)
}
a := make([]Gid_t, len(gids))
for i, v := range gids {
a[i] = Gid_t(v)
}
return setgroups(len(a), &a[0])
}
type WaitStatus uint32
// The WaitStatus methods are implemented in C, to pick up the macros
// #defines in <sys/wait.h>.
func (w WaitStatus) Exited() bool
func (w WaitStatus) Signaled() bool
func (w WaitStatus) Stopped() bool
func (w WaitStatus) Continued() bool
func (w WaitStatus) CoreDump() bool
func (w WaitStatus) ExitStatus() int
func (w WaitStatus) Signal() int
func (w WaitStatus) StopSignal() int
func (w WaitStatus) TrapCause() int
//sys Mkfifo(path string, mode uint32) (errno int)
//mkfifo(path *byte, mode Mode_t) int
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int)
//select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) int
const nfdbits = unsafe.Sizeof(fds_bits_type) * 8
type FdSet struct {
Bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type
}
func FDSet(fd int, set *FdSet) {
set.Bits[fd / nfdbits] |= (1 << (uint)(fd % nfdbits))
}
func FDClr(fd int, set *FdSet) {
set.Bits[fd / nfdbits] &^= (1 << (uint)(fd % nfdbits))
}
func FDIsSet(fd int, set *FdSet) bool {
if set.Bits[fd / nfdbits] & (1 << (uint)(fd % nfdbits)) != 0 {
return true
} else {
return false
}
}
func FDZero(set *FdSet) {
for i := range set.Bits {
set.Bits[i] = 0
}
}
//sys Access(path string, mode uint32) (errno int)
//access(path *byte, mode int) int
//sys Chdir(path string) (errno int)
//chdir(path *byte) int
//sys Chmod(path string, mode uint32) (errno int)
//chmod(path *byte, mode Mode_t) int
//sys Chown(path string, uid int, gid int) (errno int)
//chown(path *byte, uid Uid_t, gid Gid_t) int
//sys Chroot(path string) (errno int)
//chroot(path *byte) int
//sys Close(fd int) (errno int)
//close(fd int) int
//sys Creat(path string, mode uint32) (fd int, errno int)
//creat(path *byte, mode Mode_t) int
//sysnb Dup(oldfd int) (fd int, errno int)
//dup(oldfd int) int
//sysnb Dup2(oldfd int, newfd int) (fd int, errno int)
//dup2(oldfd int, newfd int) int
//sys Exit(code int)
//exit(code int)
//sys Fchdir(fd int) (errno int)
//fchdir(fd int) int
//sys Fchmod(fd int, mode uint32) (errno int)
//fchmod(fd int, mode Mode_t) int
//sys Fchown(fd int, uid int, gid int) (errno int)
//fchown(fd int, uid Uid_t, gid Gid_t) int
//sys fcntl(fd int, cmd int, arg int) (val int, errno int)
//fcntl(fd int, cmd int, arg int) int
//sys Fdatasync(fd int) (errno int)
//fdatasync(fd int) int
//sys Flock(fd int, how int) (errno int)
//flock(fd int, how int) int
//sys Fsync(fd int) (errno int)
//fsync(fd int) int
//sysnb Getegid() (egid int)
//getegid() Gid_t
//sysnb Geteuid() (euid int)
//geteuid() Uid_t
//sysnb Getgid() (gid int)
//getgid() Gid_t
//sysnb Getpagesize() (pagesize int)
//getpagesize() int
//sysnb Getpgid(pid int) (pgid int, errno int)
//getpgid(pid Pid_t) Pid_t
//sysnb Getpgrp() (pid int)
//getpgrp() Pid_t
//sysnb Getpid() (pid int)
//getpid() Pid_t
//sysnb Getppid() (ppid int)
//getppid() Pid_t
// FIXME: mksysinfo Rlimit
// //sysnb Getrlimit(resource int, rlim *Rlimit) (errno int)
// //getrlimit(resource int, rlim *Rlimit) int
//sysnb Getrusage(who int, rusage *Rusage) (errno int)
//getrusage(who int, rusage *Rusage) int
//sysnb Gettid() (tid int)
//gettid() Pid_t
//sysnb gettimeofday(tv *Timeval, tz *byte) (errno int)
//gettimeofday(tv *Timeval, tz *byte) int
func Gettimeofday(tv *Timeval) (errno int) {
return gettimeofday(tv, nil)
}
//sysnb Getuid() (uid int)
//getuid() Uid_t
//sysnb Kill(pid int, sig int) (errno int)
//kill(pid Pid_t, sig int) int
//sys Lchown(path string, uid int, gid int) (errno int)
//lchown(path *byte, uid Uid_t, gid Gid_t) int
//sys Link(oldpath string, newpath string) (errno int)
//link(oldpath *byte, newpath *byte) int
//sys Mkdir(path string, mode uint32) (errno int)
//mkdir(path *byte, mode Mode_t) int
//sys Mknod(path string, mode uint32, dev int) (errno int)
//mknod(path *byte, mode Mode_t, dev _dev_t) int
//sys Mount(source string, target string, fstype string, flags int, data string) (errno int)
//mount(source *byte, target *byte, fstype *byte, flags _C_long, data *byte) int
//sys Nanosleep(time *Timespec, leftover *Timespec) (errno int)
//nanosleep(time *Timespec, leftover *Timespec) int
//sys Pause() (errno int)
//pause() int
//sys Read(fd int, p []byte) (n int, errno int)
//read(fd int, buf *byte, count Size_t) Ssize_t
//sys Readlink(path string, buf []byte) (n int, errno int)
//readlink(path *byte, buf *byte, bufsiz Size_t) Ssize_t
//sys Rename(oldpath string, newpath string) (errno int)
//rename(oldpath *byte, newpath *byte) int
//sys Rmdir(path string) (errno int)
//rmdir(path *byte) int
//sys Setdomainname(p []byte) (errno int)
//setdomainname(name *byte, len Size_t) int
//sys Sethostname(p []byte) (errno int)
//sethostname(name *byte, len Size_t) int
//sysnb Setgid(gid int) (errno int)
//setgid(gid Gid_t) int
//sysnb Setregid(rgid int, egid int) (errno int)
//setregid(rgid Gid_t, egid Gid_t) int
//sysnb Setpgid(pid int, pgid int) (errno int)
//setpgid(pid Pid_t, pgid Pid_t) int
//sysnb Setreuid(ruid int, euid int) (errno int)
//setreuid(ruid Uid_t, euid Uid_t) int
// FIXME: mksysinfo Rlimit
// //sysnb Setrlimit(resource int, rlim *Rlimit) (errno int)
// //setrlimit(resource int, rlim *Rlimit) int
//sysnb Setsid() (pid int, errno int)
//setsid() Pid_t
//sysnb settimeofday(tv *Timeval, tz *byte) (errno int)
//settimeofday(tv *Timeval, tz *byte) int
func Settimeofday(tv *Timeval) (errno int) {
return settimeofday(tv, nil)
}
//sysnb Setuid(uid int) (errno int)
//setuid(uid Uid_t) int
//sys Symlink(oldpath string, newpath string) (errno int)
//symlink(oldpath *byte, newpath *byte) int
//sys Sync()
//sync()
// FIXME: mksysinfo Time_t
// //sysnb Time(t *Time_t) (tt Time_t, errno int)
// //time(t *Time_t) Time_t
// FIXME: mksysinfo Tms
// //sysnb Times(tms *Tms) (ticks uintptr, errno int)
// //times(tms *Tms) _clock_t
//sysnb Umask(mask int) (oldmask int)
//umark(mask Mode_t) Mode_t
//sys Unlink(path string) (errno int)
//unlink(path *byte) int
// FIXME: mksysinfo Utimbuf
// //sys Utime(path string, buf *Utimbuf) (errno int)
// //utime(path *byte, buf *Utimbuf) int
//sys Write(fd int, p []byte) (n int, errno int)
//write(fd int, buf *byte, count Size_t) Ssize_t
//sys munmap(addr uintptr, length uintptr) (errno int)
//munmap(addr *byte, length Size_t) int
//sys Madvise(b []byte, advice int) (errno int)
//madvise(addr *byte, len Size_t, advice int) int
//sys Mprotect(b []byte, prot int) (errno int)
//mprotect(addr *byte, len Size_t, prot int) int
//sys Mlock(b []byte) (errno int)
//mlock(addr *byte, len Size_t) int
//sys Munlock(b []byte) (errno int)
//munlock(addr *byte, len Size_t) int
//sys Mlockall(flags int) (errno int)
//mlockall(flags int) int
//sys Munlockall() (errno int)
//munlockall() int
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = Timespec_sec_t(nsec / 1e9)
ts.Nsec = Timespec_nsec_t(nsec % 1e9)
return
}
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Sec = Timeval_sec_t(nsec / 1e9)
tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3)
return
}
// 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.
// POSIX library calls on systems which use the largefile interface.
package syscall
//sys Fstat(fd int, stat *Stat_t) (errno int)
//fstat64(fd int, stat *Stat_t) int
//sys Ftruncate(fd int, length int64) (errno int)
//ftruncate64(fd int, length Offset_t) int
//sys Lstat(path string, stat *Stat_t) (errno int)
//lstat64(path *byte, stat *Stat_t) int
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
//mmap64(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte
//sys Open(path string, mode int, perm uint32) (fd int, errno int)
//open64(path *byte, mode int, perm Mode_t) int
//sys Pread(fd int, p []byte, offset int64) (n int, errno int)
//pread64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
//sys Pwrite(fd int, p []byte, offset int64) (n int, errno int)
//pwrite64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
//sys Seek(fd int, offset int64, whence int) (off int64, errno int)
//lseek64(fd int, offset Offset_t, whence int) Offset_t
//sys Stat(path string, stat *Stat_t) (errno int)
//stat64(path *byte, stat *Stat_t) int
//sys Truncate(path string, length int64) (errno int)
//truncate64(path *byte, length Offset_t) int
// 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.
// POSIX library calls on systems which do not use the largefile
// interface.
package syscall
//sys Fstat(fd int, stat *Stat_t) (errno int)
//fstat(fd int, stat *Stat_t) int
//sys Ftruncate(fd int, length int64) (errno int)
//ftruncate(fd int, length Offset_t) int
//sys Lstat(path string, stat *Stat_t) (errno int)
//lstat(path *byte, stat *Stat_t) int
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
//mmap(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte
//sys Open(path string, mode int, perm uint32) (fd int, errno int)
//open(path *byte, mode int, perm Mode_t) int
//sys Pread(fd int, p []byte, offset int64) (n int, errno int)
//pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
//sys Pwrite(fd int, p []byte, offset int64) (n int, errno int)
//pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
//sys Seek(fd int, offset int64, whence int) (off int64, errno int)
//lseek(fd int, offset Offset_t, whence int) Offset_t
//sys Stat(path string, stat *Stat_t) (errno int)
//stat(path *byte, stat *Stat_t) int
//sys Truncate(path string, length int64) (errno int)
//truncate(path *byte, length Offset_t) int
// syscall_solaris.go -- Solaris 2 specific syscall interface.
// Copyright 2011 The Go Authors. All rights reserved. // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package syscall package syscall
// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
//sysnb Uname(buf *Utsname) (errno int)
//_nuname(buf *Utsname) int
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Declarations for functions which are actually written in C.
package syscall package syscall
func libc_uname(buf *Utsname) (errno int) __asm__("uname") func entersyscall()
func exitsyscall()
func GetErrno() int
func SetErrno(int)
// syscall_rtems.go -- RTEMS specific syscall interface.
// Copyright 2011 The Go Authors. All rights reserved. // Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package syscall package syscall
//sysnb Uname(buf *Utsname) (errno int)
//uname(buf *Utsname) int
// waitpid.go -- Wait4 for systems without wait4, but with waitpid. // Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// For systems with the wait4 library call.
package syscall package syscall
func libc_waitpid(Pid_t, *int, int) Pid_t __asm__ ("waitpid") //sys wait4(pid Pid_t, status *int, options int, rusage *Rusage) (wpid Pid_t, errno int)
//wait4(pid Pid_t, status *int, options int, rusage *Rusage) Pid_t
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status int var status int
r := libc_waitpid(Pid_t(pid), &status, options) r, err := wait4(Pid_t(pid), &status, options, rusage)
wpid = int(r) wpid = int(r)
if r < 0 { errno = err
errno = GetErrno()
}
if wstatus != nil { if wstatus != nil {
*wstatus = WaitStatus(status) *wstatus = WaitStatus(status)
} }
......
// wait4.go -- Wait4 for systems with wait4. // Copyright 2009 The Go Authors. All rights reserved.
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// For systems with the waitpid library call.
package syscall package syscall
func libc_wait4(Pid_t, *int, int, *Rusage) Pid_t __asm__ ("wait4") //sys waitpid(pid Pid_t, status *int, options int) (wpid Pid_t, errno int)
//waitpid(pid Pid_t, status *int, options int) Pid_t
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status int var status int
r := libc_wait4(Pid_t(pid), &status, options, rusage) r, err := waitpid(Pid_t(pid), &status, options)
wpid = int(r) wpid = int(r)
if r < 0 { errno = err
errno = GetErrno()
}
if wstatus != nil { if wstatus != nil {
*wstatus = WaitStatus(status) *wstatus = WaitStatus(status)
} }
......
// 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.
// Linux socket filter
package syscall
import (
"unsafe"
)
func LsfStmt(code, k int) *SockFilter {
return &SockFilter{Code: uint16(code), K: uint32(k)}
}
func LsfJump(code, k, jt, jf int) *SockFilter {
return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
}
func LsfSocket(ifindex, proto int) (int, int) {
var lsall SockaddrLinklayer
s, e := Socket(AF_PACKET, SOCK_RAW, proto)
if e != 0 {
return 0, e
}
p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol))
p[0] = byte(proto >> 8)
p[1] = byte(proto)
lsall.Ifindex = ifindex
e = Bind(s, &lsall)
if e != 0 {
Close(s)
return 0, e
}
return s, 0
}
type iflags struct {
name [IFNAMSIZ]byte
flags uint16
}
func SetLsfPromisc(name string, m bool) int {
s, e := Socket(AF_INET, SOCK_DGRAM, 0)
if e != 0 {
return e
}
defer Close(s)
var ifl iflags
copy(ifl.name[:], []byte(name))
_, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
if e := int(ep); e != 0 {
return e
}
if m {
ifl.flags |= uint16(IFF_PROMISC)
} else {
ifl.flags &= ^uint16(IFF_PROMISC)
}
_, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
if e := int(ep); e != 0 {
return e
}
return 0
}
func AttachLsf(fd int, i []SockFilter) int {
var p SockFprog
p.Len = uint16(len(i))
p.Filter = (*SockFilter)(unsafe.Pointer(&i[0]))
return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, uintptr(unsafe.Pointer(&p)), unsafe.Sizeof(p))
}
func DetachLsf(fd int) int {
var dummy int
return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, uintptr(unsafe.Pointer(&dummy)), unsafe.Sizeof(dummy))
}
# 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.
# This AWK script reads a Go file with comments describing syscall
# functions and the C routines they map to. It generates the Go code
# which calls the C routines.
# The syscall functins 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 errno.
# A line beginning with //sysnb is like //sys, except that the
# goroutine will not be suspended during the execution of the library
# call. This must only be used for library calls which can never
# block, as otherwise the library call could cause all goroutines to
# hang.
# After the //sys or //sysnb line comes a second line which describes
# the C function. The name must be the name of the function in the C
# library, and may be the same as the Go function. The limitations on
# the argument list are the same as for the //sys line, but there must
# be at most one result parameter, and it must be given as just a
# type, without a name.
BEGIN {
print "// This file was automatically generated by mksyscall.awk"
print ""
print "package syscall"
print ""
print "import \"unsafe\""
print ""
status = 0
}
/^\/\/sys/ {
if ($1 == "//sysnb") {
blocking = 0
} else {
blocking = 1
}
if (match($0, "//sys(nb)?[ ]*([a-zA-Z0-9_]+)\\(([^()]*)\\) *(\\(([^()]+)\\))?", gosig) == 0) {
print "unmatched line:", $0 | "cat 1>&2"
status = 1
next
}
gofnname = gosig[2]
gofnparams = gosig[3]
gofnresults = gosig[5]
getline
if (match($0, "//([a-zA-Z0-9_]+)\\(([^()]*)\\) *(.*)$", csig) == 0) {
print "unmatched C line", $0, "after", gofnname | "cat 1>&2"
status = 1
next
}
cfnname = csig[1]
cfnparams = csig[2]
cfnresult = csig[3]
printf("// Automatically generated wrapper for %s/%s\n", gofnname, cfnname)
printf("func c_%s(%s) %s%s__asm__(\"%s\")\n",
cfnname, cfnparams, cfnresult, cfnresult == "" ? "" : " ", cfnname)
printf("func %s(%s) %s%s{\n",
gofnname, gofnparams, gosig[4], gosig[4] == "" ? "" : " ")
if (blocking) {
print "\tentersyscall()"
}
loc = gofnname "/" cfnname ":"
split(gofnparams, goargs, ", *")
split(cfnparams, cargs, ", *")
args = ""
carg = 1
for (goarg = 1; goargs[goarg] != ""; goarg++) {
if (cargs[carg] == "") {
print loc, "not enough C parameters"
}
if (args != "") {
args = args ", "
}
if (match(goargs[goarg], "^([^ ]*) ([^ ]*)$", goparam) == 0) {
print loc, "bad parameter:", goargs[goarg] | "cat 1>&2"
status = 1
next
}
goname = goparam[1]
gotype = goparam[2]
if (match(cargs[carg], "^([^ ]*) ([^ ]*)$", cparam) == 0) {
print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
status = 1
next
}
ctype = cparam[2]
if (gotype ~ /^\*/) {
if (gotype != ctype) {
print loc, "Go/C pointer type mismatch:", gotype, ctype | "cat 1>&2"
status = 1
next
}
args = args goname
} else if (gotype == "string") {
if (ctype != "*byte") {
print loc, "Go string not matched to C *byte:", gotype, ctype | "cat 1>&2"
status = 1
next
}
args = args "StringBytePtr(" goname ")"
} else if (gotype ~ /^\[\](.*)/) {
if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
print loc, "bad C type for slice:", gotype, ctype | "cat 1>&2"
status = 1
next
}
# Convert a slice into a pair of pointer, length.
# Don't try to take the address of the zeroth element of a
# nil slice.
printf("\tvar _p%d %s\n", goarg, ctype)
printf("\tif len(%s) > 0 {\n", goname)
printf("\t\t_p%d = (%s)(unsafe.Pointer(&%s[0]))\n", goarg, ctype, goname)
printf("\t} else {\n")
printf("\t\t_p%d = (%s)(unsafe.Pointer(&_zero))\n", goarg, ctype)
printf("\t}\n")
++carg
if (match(cargs[carg], "^([^ ]*) ([^ ]*)$", cparam) == 0) {
print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
status = 1
next
}
args = sprintf("%s_p%d, %s(len(%s))", args, goarg, cparam[2], goname)
} else if (gotype == "uintptr" && ctype ~ /^\*/) {
args = sprintf("%s(%s)(unsafe.Pointer(%s))", args, ctype, goname)
} else {
args = sprintf("%s%s(%s)", args, ctype, goname)
}
carg++
}
if (cargs[carg] != "") {
print loc, "too many C parameters" | "cat 1>&2"
status = 1
next
}
printf("\t")
if (gofnresults != "") {
printf("_r := ")
}
printf("c_%s(%s)\n", cfnname, args)
if (gofnresults != "") {
fields = split(gofnresults, goresults, ", *")
if (fields > 2) {
print loc, "too many Go results" | "cat 1>&2"
status = 1
next
}
usedr = 0
for (goresult = 1; goresults[goresult] != ""; goresult++) {
if (match(goresults[goresult], "^([^ ]*) ([^ ]*)$", goparam) == 0) {
print loc, "bad result:", goresults[goresult] | "cat 1>&2"
status = 1
next
}
goname = goparam[1]
gotype = goparam[2]
if (goname == "errno") {
if (cfnresult ~ /^\*/) {
print "\tif _r == nil {"
} else {
print "\tif _r < 0 {"
}
print "\t\terrno = GetErrno()"
print "\t}"
} else if (gotype == "uintptr" && cfnresult ~ /^\*/) {
printf("\t%s = (%s)(unsafe.Pointer(_r))\n", goname, gotype)
} else {
if (usedr) {
print loc, "two parameters but no errno parameter" | "cat 1>&2"
status = 1
next
}
printf("\t%s = (%s)(_r)\n", goname, gotype)
usedr = 1
}
}
}
if (blocking) {
print "\texitsyscall()"
}
if (gofnresults != "") {
print "\treturn"
}
print "}"
print ""
next
}
{ next }
END {
if (status != 0) {
print "*** mksyscall.awk failed" | "cat 1>&2"
exit status
}
}
...@@ -195,10 +195,12 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) { ...@@ -195,10 +195,12 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
) )
switch msg.Header.Type { switch msg.Header.Type {
case RTM_NEWLINK: case RTM_NEWLINK, RTM_DELLINK:
buf = msg.Data[SizeofIfInfomsg:] buf = msg.Data[SizeofIfInfomsg:]
case RTM_NEWADDR: case RTM_NEWADDR, RTM_DELADDR:
buf = msg.Data[SizeofIfAddrmsg:] buf = msg.Data[SizeofIfAddrmsg:]
case RTM_NEWROUTE, RTM_DELROUTE:
buf = msg.Data[SizeofRtMsg:]
default: default:
return nil, EINVAL return nil, EINVAL
} }
......
// 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.
// +build darwin freebsd openbsd
// Routing sockets and messages
package syscall
import (
"unsafe"
)
// Round the length of a raw sockaddr up to align it properly.
func rsaAlignOf(salen int) int {
salign := sizeofPtr
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
// aligned access to BSD subsystem.
if darwinAMD64 {
salign = 4
}
if salen == 0 {
return salign
}
return (salen + salign - 1) & ^(salign - 1)
}
// RouteRIB returns routing information base, as known as RIB,
// which consists of network facility information, states and
// parameters.
func RouteRIB(facility, param int) ([]byte, int) {
var (
tab []byte
e int
)
mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
// Find size.
n := uintptr(0)
if e = sysctl(mib, nil, &n, nil, 0); e != 0 {
return nil, e
}
if n == 0 {
return nil, 0
}
tab = make([]byte, n)
if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 {
return nil, e
}
return tab[:n], 0
}
// RoutingMessage represents a routing message.
type RoutingMessage interface {
sockaddr() []Sockaddr
}
const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
type anyMessage struct {
Msglen uint16
Version uint8
Type uint8
}
// RouteMessage represents a routing message containing routing
// entries.
type RouteMessage struct {
Header RtMsghdr
Data []byte
}
const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
func (m *RouteMessage) sockaddr() []Sockaddr {
var (
af int
sas [4]Sockaddr
)
buf := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
switch i {
case RTAX_DST, RTAX_GATEWAY:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != 0 {
return nil
}
if i == RTAX_DST {
af = int(rsa.Family)
}
sas[i] = sa
case RTAX_NETMASK, RTAX_GENMASK:
switch af {
case AF_INET:
rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&buf[0]))
sa := new(SockaddrInet4)
for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
sa.Addr[j] = rsa4.Addr[j]
}
sas[i] = sa
case AF_INET6:
rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&buf[0]))
sa := new(SockaddrInet6)
for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
sa.Addr[j] = rsa6.Addr[j]
}
sas[i] = sa
}
}
buf = buf[rsaAlignOf(int(rsa.Len)):]
}
return sas[:]
}
// InterfaceMessage represents a routing message containing
// network interface entries.
type InterfaceMessage struct {
Header IfMsghdr
Data []byte
}
func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&RTA_IFP == 0 {
return nil
}
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
if e != 0 {
return nil
}
return append(sas, sa)
}
// InterfaceAddrMessage represents a routing message containing
// network interface address entries.
type InterfaceAddrMessage struct {
Header IfaMsghdr
Data []byte
}
const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfaMask == 0 {
return nil
}
buf := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
switch i {
case RTAX_IFA:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != 0 {
return nil
}
sas = append(sas, sa)
case RTAX_NETMASK, RTAX_BRD:
// nothing to do
}
buf = buf[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// ParseRoutingMessage parses buf as routing messages and returns
// the slice containing the RoutingMessage interfaces.
func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
for len(buf) >= anyMessageLen {
any := (*anyMessage)(unsafe.Pointer(&buf[0]))
if any.Version != RTM_VERSION {
return nil, EINVAL
}
msgs = append(msgs, any.toRoutingMessage(buf))
buf = buf[any.Msglen:]
}
return msgs, 0
}
// ParseRoutingMessage parses msg's payload as raw sockaddrs and
// returns the slice containing the Sockaddr interfaces.
func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, errno int) {
return append(sas, msg.sockaddr()...), 0
}
// 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.
// Routing sockets and messages for Darwin
package syscall
import (
"unsafe"
)
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
rtm := &RouteMessage{}
rtm.Header = p.Header
rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
return rtm
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
ifm := &InterfaceMessage{}
ifm.Header = p.Header
ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
return ifm
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
ifam := &InterfaceAddrMessage{}
ifam.Header = p.Header
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
return ifam
case RTM_NEWMADDR2, RTM_DELMADDR:
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
ifmam := &InterfaceMulticastAddrMessage{}
ifmam.Header = p.Header
ifmam.Data = buf[SizeofIfmaMsghdr2:any.Msglen]
return ifmam
}
return nil
}
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr2
Data []byte
}
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfmaMask == 0 {
return nil
}
buf := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
switch i {
case RTAX_IFA:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != 0 {
return nil
}
sas = append(sas, sa)
case RTAX_GATEWAY, RTAX_IFP:
// nothing to do
}
buf = buf[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// 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.
// Routing sockets and messages for FreeBSD
package syscall
import (
"unsafe"
)
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
rtm := &RouteMessage{}
rtm.Header = p.Header
rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
return rtm
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
ifm := &InterfaceMessage{}
ifm.Header = p.Header
ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
return ifm
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
ifam := &InterfaceAddrMessage{}
ifam.Header = p.Header
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
return ifam
case RTM_NEWMADDR, RTM_DELMADDR:
p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
ifmam := &InterfaceMulticastAddrMessage{}
ifmam.Header = p.Header
ifmam.Data = buf[SizeofIfmaMsghdr:any.Msglen]
return ifmam
}
return nil
}
// InterfaceMulticastAddrMessage represents a routing message
// containing network interface address entries.
type InterfaceMulticastAddrMessage struct {
Header IfmaMsghdr
Data []byte
}
const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
if m.Header.Addrs&rtaIfmaMask == 0 {
return nil
}
buf := m.Data[:]
for i := uint(0); i < RTAX_MAX; i++ {
if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
continue
}
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
switch i {
case RTAX_IFA:
sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
if e != 0 {
return nil
}
sas = append(sas, sa)
case RTAX_GATEWAY, RTAX_IFP:
// nothing to do
}
buf = buf[rsaAlignOf(int(rsa.Len)):]
}
return sas
}
// 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.
// Routing sockets and messages for OpenBSD
package syscall
import (
"unsafe"
)
func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
rtm := &RouteMessage{}
rtm.Header = p.Header
rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
return rtm
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
ifm := &InterfaceMessage{}
ifm.Header = p.Header
ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
return ifm
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
ifam := &InterfaceAddrMessage{}
ifam.Header = p.Header
ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
return ifam
}
return nil
}
...@@ -6,14 +6,8 @@ ...@@ -6,14 +6,8 @@
package syscall package syscall
func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
func Sleep(nsec int64) (errno int) { func Sleep(nsec int64) (errno int) {
errno = 0
ts := NsecToTimespec(nsec) ts := NsecToTimespec(nsec)
r := libc_nanosleep(&ts, nil) errno = Nanosleep(&ts, nil)
if r < 0 {
errno = GetErrno()
}
return return
} }
...@@ -8,6 +8,6 @@ package syscall ...@@ -8,6 +8,6 @@ package syscall
func Sleep(nsec int64) (errno int) { func Sleep(nsec int64) (errno int) {
tv := NsecToTimeval(nsec); tv := NsecToTimeval(nsec);
n, err := Select(0, nil, nil, nil, &tv); _, err := Select(0, nil, nil, nil, &tv);
return err; return err;
} }
// 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.
// Socket control messages
package syscall
import (
"unsafe"
)
// UnixCredentials encodes credentials into a socket control message
// for sending to another process. This can be used for
// authentication.
func UnixCredentials(ucred *Ucred) []byte {
buf := make([]byte, CmsgSpace(SizeofUcred))
cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
cmsg.Level = SOL_SOCKET
cmsg.Type = SCM_CREDENTIALS
cmsg.SetLen(CmsgLen(SizeofUcred))
*((*Ucred)(cmsgData(cmsg))) = *ucred
return buf
}
// ParseUnixCredentials decodes a socket control message that contains
// credentials in a Ucred structure. To receive such a message, the
// SO_PASSCRED option must be enabled on the socket.
func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, int) {
if msg.Header.Level != SOL_SOCKET {
return nil, EINVAL
}
if msg.Header.Type != SCM_CREDENTIALS {
return nil, EINVAL
}
ucred := *(*Ucred)(unsafe.Pointer(&msg.Data[0]))
return &ucred, 0
}
// 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.
// +build darwin freebsd linux openbsd
// Socket control messages
package syscall
import (
"unsafe"
)
// Round the length of a raw sockaddr up to align it propery.
func cmsgAlignOf(salen int) int {
salign := sizeofPtr
// NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
// aligned access to BSD subsystem.
if darwinAMD64 {
salign = 4
}
if salen == 0 {
return salign
}
return (salen + salign - 1) & ^(salign - 1)
}
// CmsgLen returns the value to store in the Len field of the Cmsghdr
// structure, taking into account any necessary alignment.
func CmsgLen(datalen int) int {
return cmsgAlignOf(SizeofCmsghdr) + datalen
}
// CmsgSpace returns the number of bytes an ancillary element with
// payload of the passed data length occupies.
func CmsgSpace(datalen int) int {
return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
}
func cmsgData(cmsg *Cmsghdr) unsafe.Pointer {
return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr)
}
type SocketControlMessage struct {
Header Cmsghdr
Data []byte
}
func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) {
var (
h *Cmsghdr
dbuf []byte
e int
cmsgs []SocketControlMessage
)
for len(buf) >= CmsgLen(0) {
h, dbuf, e = socketControlMessageHeaderAndData(buf)
if e != 0 {
break
}
m := SocketControlMessage{}
m.Header = *h
m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]
cmsgs = append(cmsgs, m)
buf = buf[cmsgAlignOf(int(h.Len)):]
}
return cmsgs, e
}
func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) {
h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) {
return nil, nil, EINVAL
}
return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0
}
// UnixRights encodes a set of open file descriptors into a socket
// control message for sending to another process.
func UnixRights(fds ...int) []byte {
datalen := len(fds) * 4
buf := make([]byte, CmsgSpace(datalen))
cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
cmsg.Level = SOL_SOCKET
cmsg.Type = SCM_RIGHTS
cmsg.SetLen(CmsgLen(datalen))
data := uintptr(cmsgData(cmsg))
for _, fd := range fds {
*(*int32)(unsafe.Pointer(data)) = int32(fd)
data += 4
}
return buf
}
// ParseUnixRights decodes a socket control message that contains an
// integer array of open file descriptors from another process.
func ParseUnixRights(msg *SocketControlMessage) ([]int, int) {
if msg.Header.Level != SOL_SOCKET {
return nil, EINVAL
}
if msg.Header.Type != SCM_RIGHTS {
return nil, EINVAL
}
fds := make([]int, len(msg.Data)>>2)
for i, j := 0, 0; i < len(msg.Data); i += 4 {
fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i])))
j++
}
return fds, 0
}
...@@ -57,10 +57,10 @@ func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) { ...@@ -57,10 +57,10 @@ func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
} }
type RawSockaddrInet4 struct { type RawSockaddrInet4 struct {
Family uint16; Family uint16
Port uint16; Port uint16
Addr [4]byte /* in_addr */; Addr [4]byte /* in_addr */
Zero [8]uint8; Zero [8]uint8
} }
func (sa *RawSockaddrInet4) setLen() Socklen_t { func (sa *RawSockaddrInet4) setLen() Socklen_t {
...@@ -68,11 +68,11 @@ func (sa *RawSockaddrInet4) setLen() Socklen_t { ...@@ -68,11 +68,11 @@ func (sa *RawSockaddrInet4) setLen() Socklen_t {
} }
type RawSockaddrInet6 struct { type RawSockaddrInet6 struct {
Family uint16; Family uint16
Port uint16; Port uint16
Flowinfo uint32; Flowinfo uint32
Addr [16]byte /* in6_addr */; Addr [16]byte /* in6_addr */
Scope_id uint32; Scope_id uint32
} }
func (sa *RawSockaddrInet6) setLen() Socklen_t { func (sa *RawSockaddrInet6) setLen() Socklen_t {
...@@ -80,8 +80,8 @@ func (sa *RawSockaddrInet6) setLen() Socklen_t { ...@@ -80,8 +80,8 @@ func (sa *RawSockaddrInet6) setLen() Socklen_t {
} }
type RawSockaddrUnix struct { type RawSockaddrUnix struct {
Family uint16; Family uint16
Path [108]int8; Path [108]int8
} }
func (sa *RawSockaddrUnix) setLen(int) { func (sa *RawSockaddrUnix) setLen(int) {
...@@ -94,7 +94,7 @@ func (sa *RawSockaddrUnix) getLen() (int, int) { ...@@ -94,7 +94,7 @@ func (sa *RawSockaddrUnix) getLen() (int, int) {
// (This is the standard convention.) // (This is the standard convention.)
// Not friendly to overwrite in place, // Not friendly to overwrite in place,
// but the callers below don't care. // but the callers below don't care.
sa.Path[0] = '@'; sa.Path[0] = '@'
} }
// Assume path ends at NUL. // Assume path ends at NUL.
...@@ -102,9 +102,9 @@ func (sa *RawSockaddrUnix) getLen() (int, int) { ...@@ -102,9 +102,9 @@ func (sa *RawSockaddrUnix) getLen() (int, int) {
// abstract Unix domain sockets--they are supposed // abstract Unix domain sockets--they are supposed
// to be uninterpreted fixed-size binary blobs--but // to be uninterpreted fixed-size binary blobs--but
// everyone uses this convention. // everyone uses this convention.
n := 0; n := 0
for n < len(sa.Path) - 3 && sa.Path[n] != 0 { for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
n++; n++
} }
return n, 0 return n, 0
...@@ -128,8 +128,8 @@ type RawSockaddrNetlink struct { ...@@ -128,8 +128,8 @@ type RawSockaddrNetlink struct {
} }
type RawSockaddr struct { type RawSockaddr struct {
Family uint16; Family uint16
Data [14]int8; Data [14]int8
} }
// BindToDevice binds the socket associated with fd to device. // BindToDevice binds the socket associated with fd to device.
...@@ -161,5 +161,23 @@ func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) { ...@@ -161,5 +161,23 @@ func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
} }
return sa, 0 return sa, 0
} }
return nil, EAFNOSUPPORT; return nil, EAFNOSUPPORT
}
// We don't take this type directly from the header file because it
// uses a union. FIXME.
type EpollEvent struct {
Events uint32
Fd int32
Pad int32
} }
//sysnb EpollCreate(size int) (fd int, errno int)
//epoll_create(size int) int
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int)
//epoll_ctl(epfd int, op int, fd int, event *EpollEvent) int
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int)
//epoll_wait(epfd int, events *EpollEvent, maxevents int, timeout int) int
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
if val < 0 {
return "-" + itoa(-val)
}
var buf [32]byte // big enough for int64
i := len(buf) - 1
for val >= 10 {
buf[i] = byte(val%10 + '0')
i--
val /= 10
}
buf[i] = byte(val + '0')
return string(buf[i:])
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package syscall contains an interface to the low-level operating system
// primitives. The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net". Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
// These calls return errno == 0 to indicate success; otherwise
// errno is an operating system error number describing the failure.
package syscall
import "unsafe"
// StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s.
func StringByteSlice(s string) []byte {
a := make([]byte, len(s)+1)
copy(a, s)
return a
}
// StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
// Single-word zero for use when we need a valid pointer to 0 bytes.
// See mksyscall.pl.
var _zero uintptr
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
// Copyright 2010 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.
// These are stubs.
package syscall
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
z := -1
return uintptr(z), 0, uintptr(ENOSYS)
}
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
z := -1
return uintptr(z), 0, uintptr(ENOSYS)
}
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
z := -1
return uintptr(z), 0, uintptr(ENOSYS)
}
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
z := -1
return uintptr(z), 0, uintptr(ENOSYS)
}
// syscall.go -- Basic syscall interface.
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This package contains an interface to the low-level operating system // +build darwin freebsd linux openbsd
// primitives. The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net". Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
package syscall package syscall
import ( import (
...@@ -18,39 +11,80 @@ import ( ...@@ -18,39 +11,80 @@ import (
"unsafe" "unsafe"
) )
func libc_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall"); var (
func libc_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall"); Stdin = 0
Stdout = 1
Stderr = 2
)
func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall");
// Do a system call. We look at the size of uintptr to see how to pass // Do a system call. We look at the size of uintptr to see how to pass
// the arguments, so that we don't pass a 64-bit value when the function // the arguments, so that we don't pass a 64-bit value when the function
// expects a 32-bit one. // expects a 32-bit one.
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
var r uintptr; entersyscall()
if unsafe.Sizeof(r) == 4 { var r uintptr
r1 := libc_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0); if unsafe.Sizeof(r) == 4 {
r = uintptr(r1); r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
} else { r = uintptr(r1)
r1 := libc_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0); } else {
r = uintptr(r1); r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
} r = uintptr(r1)
return r, 0, uintptr(GetErrno()); }
errno := GetErrno()
exitsyscall()
return r, 0, uintptr(errno)
} }
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
var r uintptr; entersyscall()
if unsafe.Sizeof(r) == 4 { var r uintptr
r1 := libc_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), if unsafe.Sizeof(r) == 4 {
int32(a4), int32(a5), int32(a6)); r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
r = uintptr(r1); int32(a4), int32(a5), int32(a6))
} else { r = uintptr(r1)
r1 := libc_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), } else {
int64(a4), int64(a5), int64(a6)); r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
r = uintptr(r1); int64(a4), int64(a5), int64(a6))
} r = uintptr(r1)
return r, 0, uintptr(GetErrno()); }
errno := GetErrno()
exitsyscall()
return r, 0, uintptr(errno)
}
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
var r uintptr
if unsafe.Sizeof(r) == 4 {
r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
r = uintptr(r1)
} else {
r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
r = uintptr(r1)
}
errno := GetErrno()
return r, 0, uintptr(errno)
}
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
var r uintptr
if unsafe.Sizeof(r) == 4 {
r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
int32(a4), int32(a5), int32(a6))
r = uintptr(r1)
} else {
r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
int64(a4), int64(a5), int64(a6))
r = uintptr(r1)
}
errno := GetErrno()
return r, 0, uintptr(errno)
} }
// Mmap manager, for use by operating system-specific implementations. // Mmap manager, for use by operating system-specific implementations.
// Gccgo only has one implementation but we do this to correspond to gc.
type mmapper struct { type mmapper struct {
sync.Mutex sync.Mutex
...@@ -109,3 +143,17 @@ func (m *mmapper) Munmap(data []byte) (errno int) { ...@@ -109,3 +143,17 @@ func (m *mmapper) Munmap(data []byte) (errno int) {
m.active[p] = nil, false m.active[p] = nil, false
return 0 return 0
} }
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (errno int) {
return mapper.Munmap(b)
}
/* wait.c -- functions for getting wait status values.
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.
We use C code to extract the wait status so that we can easily be
OS-independent. */
#define _GNU_SOURCE
#define __EXTENSIONS__
#include <stdint.h>
#include <sys/wait.h>
extern _Bool Exited (uint32_t *w)
__asm__ ("libgo_syscall.syscall.Exited.N32_libgo_syscall.syscall.WaitStatus");
_Bool
Exited (uint32_t *w)
{
return WIFEXITED (*w) != 0;
}
extern _Bool Signaled (uint32_t *w)
__asm__ ("libgo_syscall.syscall.Signaled.N32_libgo_syscall.syscall.WaitStatus");
_Bool
Signaled (uint32_t *w)
{
return WIFSIGNALED (*w) != 0;
}
extern _Bool Stopped (uint32_t *w)
__asm__ ("libgo_syscall.syscall.Stopped.N32_libgo_syscall.syscall.WaitStatus");
_Bool
Stopped (uint32_t *w)
{
return WIFSTOPPED (*w) != 0;
}
extern _Bool Continued (uint32_t *w)
__asm__ ("libgo_syscall.syscall.Continued.N32_libgo_syscall.syscall.WaitStatus");
_Bool
Continued (uint32_t *w)
{
return WIFCONTINUED (*w) != 0;
}
extern _Bool CoreDump (uint32_t *w)
__asm__ ("libgo_syscall.syscall.CoreDump.N32_libgo_syscall.syscall.WaitStatus");
_Bool
CoreDump (uint32_t *w)
{
return WCOREDUMP (*w) != 0;
}
extern int ExitStatus (uint32_t *w)
__asm__ ("libgo_syscall.syscall.ExitStatus.N32_libgo_syscall.syscall.WaitStatus");
int
ExitStatus (uint32_t *w)
{
if (!WIFEXITED (*w))
return -1;
return WEXITSTATUS (*w);
}
extern int Signal (uint32_t *w)
__asm__ ("libgo_syscall.syscall.Signal.N32_libgo_syscall.syscall.WaitStatus");
int
Signal (uint32_t *w)
{
if (!WIFSIGNALED (*w))
return -1;
return WTERMSIG (*w);
}
extern int StopSignal (uint32_t *w)
__asm__ ("libgo_syscall.syscall.StopSignal.N32_libgo_syscall.syscall.WaitStatus");
int
StopSignal (uint32_t *w)
{
if (!WIFSTOPPED (*w))
return -1;
return WSTOPSIG (*w);
}
extern int TrapCause (uint32_t *w)
__asm__ ("libgo_syscall.syscall.TrapCause.N32_libgo_syscall.syscall.WaitStatus");
int
TrapCause (uint32_t *w)
{
#ifndef __linux__
return -1;
#else
if (!WIFSTOPPED (*w) || WSTOPSIG (*w) != SIGTRAP)
return -1;
return *w >> 16;
#endif
}
...@@ -197,16 +197,13 @@ if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then ...@@ -197,16 +197,13 @@ if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then
echo "const EPOLLRDHUP = 0x2000" >> ${OUT} echo "const EPOLLRDHUP = 0x2000" >> ${OUT}
fi fi
# Ptrace constants. We don't expose all the PTRACE flags, just the # Ptrace constants.
# PTRACE_O_xxx and PTRACE_EVENT_xxx ones. grep '^const _PTRACE' gen-sysinfo.go |
grep '^const _PTRACE_O' gen-sysinfo.go | sed -e 's/^\(const \)_\(PTRACE[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
sed -e 's/^\(const \)_\(PTRACE_O[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} # We need some ptrace options that are not defined in older versions
grep '^const _PTRACE_EVENT' gen-sysinfo.go | # of glibc.
sed -e 's/^\(const \)_\(PTRACE_EVENT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} if ! grep '^const PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
# We need PTRACE_SETOPTIONS and PTRACE_GETEVENTMSG, but they are not echo "const PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
# defined in older versions of glibc.
if ! grep '^const _PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
echo "const _PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
fi fi
if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then
echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT} echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT}
...@@ -254,7 +251,7 @@ if ! grep '^const PTRACE_EVENT_EXIT' ${OUT} > /dev/null 2>&1; then ...@@ -254,7 +251,7 @@ if ! grep '^const PTRACE_EVENT_EXIT' ${OUT} > /dev/null 2>&1; then
echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT} echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT}
fi fi
if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then
echo "const _PTRACE_TRACEME = 0" >> ${OUT} echo "const PTRACE_TRACEME = 0" >> ${OUT}
fi fi
# The registers returned by PTRACE_GETREGS. This is probably # The registers returned by PTRACE_GETREGS. This is probably
...@@ -474,6 +471,11 @@ grep '^type _ip_mreq ' gen-sysinfo.go | \ ...@@ -474,6 +471,11 @@ grep '^type _ip_mreq ' gen-sysinfo.go | \
-e 's/_in_addr/[4]byte/g' \ -e 's/_in_addr/[4]byte/g' \
>> ${OUT} >> ${OUT}
# The size of the ip_mreq struct.
if grep 'type IPMreq ' ${OUT} > /dev/null 2>&1; then
echo 'var SizeofIPMreq = int(unsafe.Sizeof(IPMreq{}))' >> ${OUT}
fi
# Try to guess the type to use for fd_set. # Try to guess the type to use for fd_set.
fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true` fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
fds_bits_type="_C_long" fds_bits_type="_C_long"
...@@ -531,6 +533,25 @@ if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then ...@@ -531,6 +533,25 @@ if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then
fi fi
fi fi
# The rtmsg struct.
grep '^type _rtmsg ' gen-sysinfo.go | \
sed -e 's/_rtmsg/RtMsg/' \
-e 's/rtm_family/Family/' \
-e 's/rtm_dst_len/Dst_len/' \
-e 's/rtm_src_len/Src_len/' \
-e 's/rtm_tos/Tos/' \
-e 's/rtm_table/Table/' \
-e 's/rtm_protocol/Procotol/' \
-e 's/rtm_scope/Scope/' \
-e 's/rtm_type/Type/' \
-e 's/rtm_flags/Flags/' \
>> ${OUT}
# The size of the rtmsg struct.
if grep 'type RtMsg ' ${OUT} > /dev/null 2>&1; then
echo 'var SizeofRtMsg = int(unsafe.Sizeof(RtMsg{}))' >> ${OUT}
fi
# The rtgenmsg struct. # The rtgenmsg struct.
grep '^type _rtgenmsg ' gen-sysinfo.go | \ grep '^type _rtgenmsg ' gen-sysinfo.go | \
sed -e 's/_rtgenmsg/RtGenmsg/' \ sed -e 's/_rtgenmsg/RtGenmsg/' \
......
...@@ -71,3 +71,21 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz) ...@@ -71,3 +71,21 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
if(hz != 0) if(hz != 0)
runtime_resetcpuprofiler(hz); runtime_resetcpuprofiler(hz);
} }
/* The entersyscall and exitsyscall functions aren't used for anything
yet. Eventually they will be used to switch to a new OS thread
when making a potentially-blocking library call. */
void runtime_entersyscall() __asm__("libgo_syscall.syscall.entersyscall");
void
runtime_entersyscall()
{
}
void runtime_exitsyscall() __asm__("libgo_syscall.syscall.exitsyscall");
void
runtime_exitsyscall()
{
}
// errstr.go -- Declare strerror_r.
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
func libc_strerror_r(int, *byte, Size_t) int __asm__ ("strerror_r")
// errstr_decl_linux.go -- Declare strerror_r for GNU/Linux.
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
func libc_strerror_r(int, *byte, Size_t) int __asm__ ("__xpg_strerror_r")
// errstr.go -- Declare strerror_r for RTEMS.
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
// RTEMS uses strerror_r in newlib, which is a GNU extension returning a char *.
func libc_strerror_r(int, *byte, Size_t) *byte __asm__ ("strerror_r")
// exec.go -- fork/exec syscall support.
// 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.
// Fork, exec, wait, etc.
package syscall
import "unsafe"
func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl")
func libc_fork() Pid_t __asm__ ("fork")
func libc_setsid() Pid_t __asm__ ("setsid")
func libc_setpgid(Pid_t, Pid_t) int __asm__ ("setpgid")
func libc_chroot(path *byte) int __asm__ ("chroot")
func libc_setuid(Uid_t) int __asm__ ("setuid")
func libc_setgid(Gid_t) int __asm__ ("setgid")
func libc_setgroups(Size_t, *Gid_t) int __asm__ ("setgroups")
func libc_chdir(name *byte) int __asm__ ("chdir")
func libc_dup2(int, int) int __asm__ ("dup2")
func libc_ioctl(int, int) int __asm__ ("ioctl")
func libc_execve(*byte, **byte, **byte) int __asm__ ("execve")
func libc_sysexit(int) __asm__ ("_exit")
// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
// If a dup or exec fails, write the errno int to pipe.
// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
// In the child, this function must not acquire any locks, because
// they might have been locked at the time of the fork. This means
// no rescheduling, no malloc calls, and no new stack segments.
func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
// Declare all variables at top in case any
// declarations require heap allocation (e.g., err1).
var r1, r2, err1 uintptr
var nextfd int
var i int
// guard against side effects of shuffling fds below.
fd := append([]int(nil), attr.Files...)
darwin := OS == "darwin"
// About to call fork.
// No more allocation or calls of non-assembly functions.
child := libc_fork()
if child == -1 {
return 0, GetErrno()
}
if child != 0 {
// parent; return PID
return int(child), 0
}
// Fork succeeded, now in child.
// Enable tracing if requested.
if sys.Ptrace {
if libc_ptrace(_PTRACE_TRACEME, 0, 0, nil) < 0 {
goto childerror
}
}
// Session ID
if sys.Setsid {
if libc_setsid() == Pid_t(-1) {
goto childerror
}
}
// Set process group
if sys.Setpgid {
if libc_setpgid(0, 0) < 0 {
goto childerror
}
}
// Chroot
if chroot != nil {
if libc_chroot(chroot) < 0 {
goto childerror
}
}
// User and groups
if cred := sys.Credential; cred != nil {
ngroups := uintptr(len(cred.Groups))
var groups *Gid_t
if ngroups > 0 {
groups = (*Gid_t)(unsafe.Pointer(&cred.Groups[0]))
}
if libc_setgroups(Size_t(ngroups), groups) < 0 {
goto childerror
}
if libc_setgid(Gid_t(cred.Gid)) < 0 {
goto childerror
}
if libc_setuid(Uid_t(cred.Uid)) < 0 {
goto childerror
}
}
// Chdir
if dir != nil {
if libc_chdir(dir) < 0 {
goto childerror
}
}
// Pass 1: look for fd[i] < i and move those up above len(fd)
// so that pass 2 won't stomp on an fd it needs later.
nextfd = int(len(fd))
if pipe < nextfd {
r := libc_dup2(pipe, nextfd)
if r == -1 {
goto childerror
}
libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
pipe = nextfd
nextfd++
}
for i = 0; i < len(fd); i++ {
if fd[i] >= 0 && fd[i] < int(i) {
r := libc_dup2(fd[i], nextfd)
if r == -1 {
goto childerror
}
libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
fd[i] = nextfd
nextfd++
if nextfd == pipe { // don't stomp on pipe
nextfd++
}
}
}
// Pass 2: dup fd[i] down onto i.
for i = 0; i < len(fd); i++ {
if fd[i] == -1 {
libc_close(i)
continue
}
if fd[i] == int(i) {
// dup2(i, i) won't clear close-on-exec flag on Linux,
// probably not elsewhere either.
r := libc_fcntl(fd[i], F_SETFD, 0)
if r != 0 {
goto childerror
}
continue
}
// The new fd is created NOT close-on-exec,
// which is exactly what we want.
r := libc_dup2(fd[i], i)
if r == -1 {
goto childerror
}
}
// By convention, we don't close-on-exec the fds we are
// started with, so if len(fd) < 3, close 0, 1, 2 as needed.
// Programs that know they inherit fds >= 3 will need
// to set them close-on-exec.
for i = len(fd); i < 3; i++ {
libc_close(i)
}
// Detach fd 0 from tty
if sys.Noctty {
if libc_ioctl(0, TIOCNOTTY) < 0 {
goto childerror
}
}
// Make fd 0 the tty
if sys.Setctty {
if libc_ioctl(0, TIOCSCTTY) < 0 {
goto childerror
}
}
// Time to exec.
libc_execve(argv0, &argv[0], &envv[0])
childerror:
// send error code on pipe
var e uintptr = uintptr(GetErrno())
libc_write(pipe, (*byte)(unsafe.Pointer(&e)),
Size_t(unsafe.Sizeof(err1)))
for {
libc_sysexit(253)
}
// Calling panic is not actually safe,
// but the for loop above won't break
// and this shuts up the compiler.
panic("unreached")
}
// Credential holds user and group identities to be assumed
// by a child process started by StartProcess.
type Credential struct {
Uid uint32 // User ID.
Gid uint32 // Group ID.
Groups []uint32 // Supplementary group IDs.
}
// ProcAttr holds attributes that will be applied to a new process started
// by StartProcess.
type ProcAttr struct {
Dir string // Current working directory.
Env []string // Environment.
Files []int // File descriptors.
Sys *SysProcAttr
}
type SysProcAttr struct {
Chroot string // Chroot.
Credential *Credential // Credential.
Ptrace bool // Enable tracing.
Setsid bool // Create session.
Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
Setctty bool // Set controlling terminal to fd 0
Noctty bool // Detach fd 0 from controlling terminal
}
var zeroProcAttr ProcAttr
var zeroSysProcAttr SysProcAttr
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
var p [2]int
var n Ssize_t
var r1 int
var err1 uintptr
var wstatus WaitStatus
if attr == nil {
attr = &zeroProcAttr
}
sys := attr.Sys
if sys == nil {
sys = &zeroSysProcAttr
}
p[0] = -1
p[1] = -1
// Convert args to C form.
argv0p := StringBytePtr(argv0)
argvp := StringArrayPtr(argv)
envvp := StringArrayPtr(attr.Env)
if OS == "freebsd" && len(argv[0]) > len(argv0) {
argvp[0] = argv0p
}
var chroot *byte
if sys.Chroot != "" {
chroot = StringBytePtr(sys.Chroot)
}
var dir *byte
if attr.Dir != "" {
dir = StringBytePtr(attr.Dir)
}
// Acquire the fork lock so that no other threads
// create new fds that are not yet close-on-exec
// before we fork.
ForkLock.Lock()
// Allocate child status pipe close on exec.
if err = Pipe(p[0:]); err != 0 {
goto error
}
if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
goto error
}
if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
goto error
}
// Kick off child.
pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
if err != 0 {
goto error
}
ForkLock.Unlock()
// Read child error status from pipe.
Close(p[1])
n = libc_read(p[0], (*byte)(unsafe.Pointer(&err1)),
Size_t(unsafe.Sizeof(err1)))
err = 0
if n < 0 {
err = GetErrno()
}
Close(p[0])
if err != 0 || n != 0 {
if int(n) == unsafe.Sizeof(err1) {
err = int(err1)
}
if err == 0 {
err = EPIPE
}
// Child failed; wait for it to exit, to make sure
// the zombies don't accumulate.
_, err1 := Wait4(pid, &wstatus, 0, nil)
for err1 == EINTR {
_, err1 = Wait4(pid, &wstatus, 0, nil)
}
return 0, err
}
// Read got EOF, so pipe closed on exec, so exec succeeded.
return pid, 0
error:
if p[0] >= 0 {
Close(p[0])
Close(p[1])
}
ForkLock.Unlock()
return 0, err
}
// Combination of fork and exec, careful to be thread safe.
func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
return forkExec(argv0, argv, attr)
}
// StartProcess wraps ForkExec for package os.
func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
pid, err = forkExec(argv0, argv, attr)
return pid, 0, err
}
// Ordinary exec.
func Exec(argv0 string, argv []string, envv []string) (err int) {
argv_arg := StringArrayPtr(argv)
envv_arg := StringArrayPtr(envv)
libc_execve(StringBytePtr(argv0), &argv_arg[0], &envv_arg[0])
return GetErrno()
}
// exec_helpers.go -- helper functions used with fork, exec, wait.
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
import "sync"
// Lock synchronizing creation of new file descriptors with fork.
//
// We want the child in a fork/exec sequence to inherit only the
// file descriptors we intend. To do that, we mark all file
// descriptors close-on-exec and then, in the child, explicitly
// unmark the ones we want the exec'ed program to keep.
// Unix doesn't make this easy: there is, in general, no way to
// allocate a new file descriptor close-on-exec. Instead you
// have to allocate the descriptor and then mark it close-on-exec.
// If a fork happens between those two events, the child's exec
// will inherit an unwanted file descriptor.
//
// This lock solves that race: the create new fd/mark close-on-exec
// operation is done holding ForkLock for reading, and the fork itself
// is done holding ForkLock for writing. At least, that's the idea.
// There are some complications.
//
// Some system calls that create new file descriptors can block
// for arbitrarily long times: open on a hung NFS server or named
// pipe, accept on a socket, and so on. We can't reasonably grab
// the lock across those operations.
//
// It is worse to inherit some file descriptors than others.
// If a non-malicious child accidentally inherits an open ordinary file,
// that's not a big deal. On the other hand, if a long-lived child
// accidentally inherits the write end of a pipe, then the reader
// of that pipe will not see EOF until that child exits, potentially
// causing the parent program to hang. This is a common problem
// in threaded C programs that use popen.
//
// Luckily, the file descriptors that are most important not to
// inherit are not the ones that can take an arbitrarily long time
// to create: pipe returns instantly, and the net package uses
// non-blocking I/O to accept on a listening socket.
// The rules for which file descriptor-creating operations use the
// ForkLock are as follows:
//
// 1) Pipe. Does not block. Use the ForkLock.
// 2) Socket. Does not block. Use the ForkLock.
// 3) Accept. If using non-blocking mode, use the ForkLock.
// Otherwise, live with the race.
// 4) Open. Can block. Use O_CLOEXEC if available (Linux).
// Otherwise, live with the race.
// 5) Dup. Does not block. Use the ForkLock.
// On Linux, could use fcntl F_DUPFD_CLOEXEC
// instead of the ForkLock, but only for dup(fd, -1).
type WaitStatus int
var ForkLock sync.RWMutex
// Convert array of string to array
// of NUL-terminated byte pointer.
func StringArrayPtr(ss []string) []*byte {
bb := make([]*byte, len(ss)+1);
for i := 0; i < len(ss); i++ {
bb[i] = StringBytePtr(ss[i]);
}
bb[len(ss)] = nil;
return bb;
}
func CloseOnExec(fd int) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
}
func SetNonblock(fd int, nonblocking bool) (errno int) {
flag, err := fcntl(fd, F_GETFL, 0);
if err != 0 {
return err;
}
if nonblocking {
flag |= O_NONBLOCK;
} else {
flag &= ^O_NONBLOCK;
}
flag, err = fcntl(fd, F_SETFL, flag);
return err;
}
// Wait status is 7 bits at bottom, either 0 (exited),
// 0x7F (stopped), or a signal number that caused an exit.
// The 0x80 bit is whether there was a core dump.
// An extra number (exit code, signal causing a stop)
// is in the high bits. At least that's the idea.
// There are various irregularities. For example, the
// "continued" status is 0xFFFF, distinguishing itself
// from stopped via the core dump bit.
const (
mask = 0x7F;
core = 0x80;
exited = 0x00;
stopped = 0x7F;
shift = 8;
)
func (w WaitStatus) Exited() bool {
return w&mask == exited;
}
func (w WaitStatus) Signaled() bool {
return w&mask != stopped && w&mask != exited;
}
func (w WaitStatus) Stopped() bool {
return w&0xFF == stopped;
}
func (w WaitStatus) Continued() bool {
return w == 0xFFFF;
}
func (w WaitStatus) CoreDump() bool {
return w.Signaled() && w&core != 0;
}
func (w WaitStatus) ExitStatus() int {
if !w.Exited() {
return -1;
}
return int(w >> shift) & 0xFF;
}
func (w WaitStatus) Signal() int {
if !w.Signaled() {
return -1;
}
return int(w & mask);
}
func (w WaitStatus) StopSignal() int {
if !w.Stopped() {
return -1;
}
return int(w >> shift) & 0xFF;
}
func (w WaitStatus) TrapCause() int {
if w.StopSignal() != SIGTRAP {
return -1;
}
return int(w >> shift) >> 8;
}
// socket_epoll.go -- GNU/Linux epoll handling.
// 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.
// Support for GNU/Linux epoll.
// Only for implementing net package.
// DO NOT USE DIRECTLY.
package syscall
// We don't take this type directly from the header file because it
// uses a union. FIXME.
type EpollEvent struct {
Events uint32;
Fd int32;
Pad int32;
};
func libc_epoll_create(size int) int __asm__ ("epoll_create");
func libc_epoll_ctl(epfd, op, fd int, event *EpollEvent) int __asm__ ("epoll_ctl");
func libc_epoll_wait(epfd int, events *EpollEvent, maxevents int,
timeout int) int __asm__ ("epoll_wait");
func EpollCreate(size int) (fd int, errno int) {
fd = libc_epoll_create(int(size));
if fd < 0 { errno = GetErrno() }
return;
}
func EpollCtl(epfd, op, fd int, ev *EpollEvent) (errno int) {
r := libc_epoll_ctl(epfd, op, fd, ev);
if r < 0 { errno = GetErrno() }
return;
}
func EpollWait(epfd int, ev []EpollEvent, msec int) (n int, errno int) {
var events *EpollEvent;
var maxevents int;
if len(ev) > 0 {
maxevents = len(ev);
events = &ev[0]
}
n = libc_epoll_wait(epfd, events, maxevents, msec);
if n < 0 { errno = GetErrno() }
return;
}
// stringbyte.go -- string to bytes functions.
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
import "unsafe"
// StringByteSlice returns a NUL-terminated slice of bytes
// containing the text of s.
func StringByteSlice(s string) []byte {
a := make([]byte, len(s)+1);
for i := 0; i < len(s); i++ {
a[i] = s[i];
}
return a;
}
// StringBytePtr returns a pointer to a NUL-terminated array of bytes
// containing the text of s.
func StringBytePtr(s string) *byte {
p := StringByteSlice(s);
return &p[0];
}
// BytePtrToString takes a NUL-terminated array of bytes and convert
// it to a Go string.
func BytePtrToString(p *byte) string {
a := (*[10000]byte)(unsafe.Pointer(p))
i := 0
for a[i] != 0 {
i++
}
return string(a[:i])
}
// syscall_irix.go -- IRIX 6 specific syscall interface.
// 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.
package syscall
import "unsafe"
// FIXME: ptrace(3C) has this, but exec.go expects the next.
//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace")
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
// syscall_linux.go -- GNU/Linux specific syscall interface.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
import "unsafe"
func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) _C_long __asm__ ("ptrace")
func libc_sendfile(int, int, *Offset_t, Size_t) Ssize_t __asm__ ("sendfile")
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
// The peek requests are machine-size oriented, so we wrap it
// to retrieve arbitrary-length data.
var buf [sizeofPtr]byte;
// Leading edge. PEEKTEXT/PEEKDATA don't require aligned
// access (PEEKUSER warns that it might), but if we don't
// align our reads, we might straddle an unmapped page
// boundary and not get the bytes leading up to the page
// boundary.
n := 0;
if addr % sizeofPtr != 0 {
SetErrno(0);
val := libc_ptrace(req, Pid_t(pid), addr - addr%sizeofPtr, nil);
if errno := GetErrno(); errno != 0 {
return 0, errno;
}
*(*_C_long)(unsafe.Pointer(&buf[0])) = val;
n += copy(out, buf[addr%sizeofPtr:]);
out = out[n:];
}
// Remainder.
for len(out) > 0 {
// We use an internal buffer to gaurantee alignment.
// It's not documented if this is necessary, but we're paranoid.
SetErrno(0);
val := libc_ptrace(req, Pid_t(pid), addr+uintptr(n), nil);
if errno = GetErrno(); errno != 0 {
return n, errno;
}
*(*_C_long)(unsafe.Pointer(&buf[0])) = val;
copied := copy(out, buf[0:]);
n += copied;
out = out[copied:];
}
return n, 0;
}
func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
return ptracePeek(_PTRACE_PEEKTEXT, pid, addr, out);
}
func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
return ptracePeek(_PTRACE_PEEKDATA, pid, addr, out);
}
func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
// As for ptracePeek, we need to align our accesses to deal
// with the possibility of straddling an invalid page.
// Leading edge.
n := 0;
if addr % sizeofPtr != 0 {
var buf [sizeofPtr]byte;
if libc_ptrace(peekReq, Pid_t(pid), addr - addr%sizeofPtr, &buf[0]) < 0 {
return 0, GetErrno();
}
n += copy(buf[addr%sizeofPtr:], data);
word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
if libc_ptrace(pokeReq, Pid_t(pid), addr - addr%sizeofPtr, word) < 0 {
return 0, GetErrno();
}
data = data[n:len(data)];
}
// Interior.
for uintptr(len(data)) > sizeofPtr {
word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&data[0])))));
if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
return n, GetErrno();
}
n += int(sizeofPtr);
data = data[sizeofPtr:len(data)];
}
// Trailing edge.
if len(data) > 0 {
var buf [sizeofPtr]byte;
if libc_ptrace(peekReq, Pid_t(pid), addr+uintptr(n), &buf[0]) < 0 {
return n, GetErrno();
}
copy(buf[0:], data);
word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
return n, GetErrno();
}
n += len(data);
}
return n, 0;
}
func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
return ptracePoke(_PTRACE_POKETEXT, _PTRACE_PEEKTEXT, pid, addr, data);
}
func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
return ptracePoke(_PTRACE_POKEDATA, _PTRACE_PEEKDATA, pid, addr, data);
}
func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
if libc_ptrace(_PTRACE_GETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regsout))) < 0 {
return GetErrno();
} else {
return 0;
}
}
func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
if libc_ptrace(_PTRACE_SETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regs))) < 0 {
return GetErrno();
} else {
return 0;
}
}
func PtraceSetOptions(pid int, options int) (errno int) {
if libc_ptrace(_PTRACE_SETOPTIONS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(options)))) < 0 {
return GetErrno();
} else {
return 0;
}
}
func PtraceGetEventMsg(pid int) (msg uint, errno int) {
var data _C_long;
if libc_ptrace(_PTRACE_GETEVENTMSG, Pid_t(pid), 0, (*byte)(unsafe.Pointer(&data))) < 0 {
errno = GetErrno();
}
msg = uint(data);
return;
}
func PtraceCont(pid int, signal int) (errno int) {
if libc_ptrace(_PTRACE_CONT, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(signal)))) < 0 {
return GetErrno();
} else {
return 0;
}
}
func PtraceSingleStep(pid int) (errno int) {
if libc_ptrace(_PTRACE_SINGLESTEP, Pid_t(pid), 0, nil) < 0 {
return GetErrno();
} else {
return 0;
}
}
func PtraceAttach(pid int) (errno int) {
if libc_ptrace(_PTRACE_ATTACH, Pid_t(pid), 0, nil) < 0 {
return GetErrno();
} else {
return 0;
}
}
func PtraceDetach(pid int) (errno int) {
if libc_ptrace(_PTRACE_DETACH, Pid_t(pid), 0, nil) < 0 {
return GetErrno();
} else {
return 0;
}
}
func Tgkill(tgid int, tid int, sig int) (errno int) {
r1, r2, err := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid),
uintptr(sig));
return int(err);
}
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
var o Offset_t
var po *Offset_t
if offset != nil {
o = Offset_t(*offset)
po = &o
}
w := libc_sendfile(outfd, infd, po, Size_t(count))
if offset != nil {
*offset = int64(o)
}
if w < 0 {
return 0, GetErrno()
}
return int(w), 0
}
// syscall_solaris_386.go -- Solaris/x86 specific support
// 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.
package syscall
import "unsafe"
// FIXME: ptrace(3C) has this, but exec.go expects the next.
//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace")
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
func libc_uname(buf *Utsname) (errno int) __asm__("_nuname")
// syscall_solaris_amd64.go -- Solaris/x64 specific support
// 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.
package syscall
import "unsafe"
// FIXME: ptrace(3C) has this, but exec.go expects the next.
//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
// 64-bit ptrace(3C) doesn't exist
func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int {
SetErrno(ENOSYS)
return -1
}
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
// syscall_solaris_sparc.go -- Solaris/SPARC specific support
// 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.
package syscall
import "unsafe"
// FIXME: ptrace(3C) has this, but exec.go expects the next.
//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace")
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
// syscall_solaris_sparc64.go -- Solaris/SPARCV9 specific support
// 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.
package syscall
import "unsafe"
// FIXME: ptrace(3C) has this, but exec.go expects the next.
//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
// 64-bit ptrace(3C) doesn't exist
func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int {
SetErrno(ENOSYS)
return -1
}
var dummy *byte
const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
// syscall_stubs.go -- Stubs of the basic syscall interface.
// Copyright 2010 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 package contains an interface to the low-level operating system
// primitives. The details vary depending on the underlying system.
// Its primary use is inside other packages that provide a more portable
// interface to the system, such as "os", "time" and "net". Use those
// packages rather than this one if you can.
// For details of the functions and data types in this package consult
// the manuals for the appropriate operating system.
// These are stubs.
package syscall
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
var r uintptr;
var i int;
i = -1;
r = uintptr(i);
return r, 0, uintptr(ENOSYS);
}
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
var r uintptr;
var i int;
i = -1;
r = uintptr(i);
return r, 0, uintptr(ENOSYS);
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package syscall
import "unsafe"
var (
Stdin = 0
Stdout = 1
Stderr = 2
)
const ENONE = 0
func GetErrno() int
func SetErrno(int)
func Uname(buf *Utsname) (errno int) {
r := libc_uname(buf)
if r < 0 {
errno = GetErrno()
}
return
}
var mapper = &mmapper{
active: make(map[*byte][]byte),
mmap: mmap,
munmap: munmap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
return mapper.Mmap(fd, offset, length, prot, flags)
}
func Munmap(b []byte) (errno int) {
return mapper.Munmap(b)
}
func libc_munmap(*byte, Size_t) int __asm__ ("munmap")
func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
r0 := libc_mmap((*byte)(unsafe.Pointer(addr)), Size_t(length), prot, flag, fd, Offset_t(pos))
ret = uintptr(unsafe.Pointer(r0))
if ret + 1 == 0 {
errno = GetErrno()
}
return
}
func munmap(addr uintptr, length uintptr) (errno int) {
if libc_munmap((*byte)(unsafe.Pointer(addr)), Size_t(length)) < 0 {
errno = GetErrno()
}
return
}
func libc_getrusage(who int, rusage *Rusage) int __asm__ ("getrusage")
func Getrusage(who int, rusage *Rusage) (errno int) {
if libc_getrusage(who, rusage) < 0 {
errno = GetErrno()
}
return
}
// sysfile_largefile.go -- For systems which use the large file interface.
// 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.
package syscall
func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64")
func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64")
func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek64")
func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate64")
func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate64")
func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap64")
// sysfile_regfile.go -- For systems which do not use the large file interface.
// 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.
package syscall
func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread")
func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite")
func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek")
func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate")
func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate")
func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap")
// sysfile_stat_largefile.go -- For systems which use the large file interface
// for *stat.
// 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.
package syscall
func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat64");
func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat64");
func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat64");
// sysfile_stat_regfile.go -- For systems which do not use the large file
// interface for *stat.
// 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.
package syscall
func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat");
...@@ -86,7 +86,10 @@ GOARCH = @GOARCH@ ...@@ -86,7 +86,10 @@ GOARCH = @GOARCH@
GOC = @GOC@ GOC = @GOC@
GOCFLAGS = @GOCFLAGS@ GOCFLAGS = @GOCFLAGS@
GOOS = @GOOS@ GOOS = @GOOS@
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@ GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
GREP = @GREP@ GREP = @GREP@
INSTALL = @INSTALL@ INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@ INSTALL_DATA = @INSTALL_DATA@
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment