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
This commit is contained in:
Ian Lance Taylor 2011-10-23 19:04:37 +00:00
parent 7b45b87f01
commit de27caacfb
74 changed files with 3559 additions and 2058 deletions

View File

@ -1392,128 +1392,142 @@ go_testing_script_files = \
# Define Syscall and Syscall6.
if LIBGO_IS_RTEMS
syscall_syscall_file = syscalls/syscall_stubs.go
syscall_syscall_file = go/syscall/syscall_stubs.go
else
syscall_syscall_file = syscalls/syscall.go
syscall_syscall_file = go/syscall/syscall_unix.go
endif
# Define ForkExec and Exec.
if LIBGO_IS_RTEMS
syscall_exec_file = go/syscall/exec_stubs.go
else
syscall_exec_file = go/syscall/exec_unix.go
endif
# Define Wait4.
if HAVE_WAIT4
syscall_wait_file = go/syscall/libcall_wait4.go
else
syscall_wait_file = go/syscall/libcall_waitpid.go
endif
# Define Sleep.
if LIBGO_IS_RTEMS
syscall_sleep_file = go/syscall/sleep_rtems.go
else
syscall_sleep_file = go/syscall/sleep_select.go
endif
# Define Errstr.
if LIBGO_IS_LINUX
syscall_errstr_file = go/syscall/errstr_linux.go
else
if LIBGO_IS_RTEMS
syscall_errstr_file = go/syscall/errstr_linux.go
else
if HAVE_STRERROR_R
syscall_errstr_file = go/syscall/errstr.go
else
syscall_errstr_file = go/syscall/errstr_nor.go
endif
endif
endif
# Declare libc functions that vary for largefile systems.
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
syscall_size_file = go/syscall/libcall_posix_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
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_filesize_file = syscalls/sysfile_largefile.go
syscall_stat_file = syscalls/sysfile_stat_largefile.go
syscall_size_file = go/syscall/libcall_posix_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
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_filesize_file = syscalls/sysfile_regfile.go
syscall_stat_file = syscalls/sysfile_stat_regfile.go
syscall_size_file = go/syscall/libcall_posix_regfile.go
endif # !LIBGO_IS_SOLARIS
endif # !LIBGO_IS_LINUX
# Define ForkExec, PtraceForkExec, and Exec.
if LIBGO_IS_RTEMS
syscall_exec_os_file = syscalls/exec_stubs.go
else
syscall_exec_os_file = syscalls/exec.go
endif
# Define Wait4.
if HAVE_WAIT4
syscall_wait_file = syscalls/wait4.go
else
syscall_wait_file = syscalls/waitpid.go
endif
# Define Sleep.
if LIBGO_IS_RTEMS
syscall_sleep_file = syscalls/sleep_rtems.go
else
syscall_sleep_file = syscalls/sleep_select.go
endif
# Define Errstr.
if LIBGO_IS_RTEMS
syscall_errstr_file = syscalls/errstr_rtems.go
else
if HAVE_STRERROR_R
syscall_errstr_file = syscalls/errstr.go
else
syscall_errstr_file = syscalls/errstr_nor.go
endif
endif
# Declare libc_strerror_r which is the Go name for strerror_r.
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
# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r.
syscall_errstr_decl_file = syscalls/errstr_decl_linux.go
else
# On other systems we hope strerror_r is just strerror_r.
syscall_errstr_decl_file = syscalls/errstr_decl.go
endif
endif
# Define socket sizes and types.
if LIBGO_IS_LINUX
syscall_socket_os_file = syscalls/socket_linux.go
syscall_socket_file = go/syscall/socket_linux.go
else
if LIBGO_IS_SOLARIS
syscall_socket_os_file = syscalls/socket_solaris.go
syscall_socket_file = go/syscall/socket_solaris.go
else
if LIBGO_IS_IRIX
syscall_socket_os_file = syscalls/socket_irix.go
syscall_socket_file = go/syscall/socket_irix.go
else
syscall_socket_os_file = syscalls/socket_bsd.go
syscall_socket_file = go/syscall/socket_bsd.go
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.
if LIBGO_IS_SOLARIS
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 =
else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS
syscall_uname_file = syscalls/syscall_uname.go
syscall_uname_file = go/syscall/libcall_uname.go
endif
else # !LIBGO_IS_SOLARIS
syscall_uname_file = syscalls/syscall_uname.go
syscall_uname_file = go/syscall/libcall_uname.go
endif
# Support for netlink sockets and messages.
if LIBGO_IS_LINUX
syscall_netlink_file = syscalls/netlink_linux.go
syscall_netlink_file = go/syscall/netlink_linux.go
else
syscall_netlink_file =
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
s-syscall_arch: Makefile
rm -f syscall_arch.go.tmp
@ -1523,30 +1537,11 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@
go_syscall_files = \
$(syscall_errstr_file) \
$(syscall_errstr_decl_file) \
syscalls/exec_helpers.go \
$(syscall_exec_os_file) \
$(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
sysinfo.go: s-sysinfo; @true
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) $@
if LIBGO_IS_LINUX
# os_lib_inotify_lo = os/inotify.lo
@ -1708,8 +1703,9 @@ libgo_go_objs = \
runtime/pprof.lo \
sync/atomic.lo \
sync/atomic_c.lo \
syscalls/syscall.lo \
syscalls/errno.lo \
syscall/syscall.lo \
syscall/errno.lo \
syscall/wait.lo \
template/parse.lo \
testing/testing.lo \
testing/iotest.lo \
@ -2983,16 +2979,12 @@ testing/script/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: testing/script/check
sysinfo.go: s-sysinfo; @true
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
syscall/syscall.lo: $(go_syscall_files) sync.gox
$(BUILDPACKAGE)
syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo
$(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c
syscall/errno.lo: go/syscall/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.
BUILDGOX = \
@ -3079,7 +3071,7 @@ sync.gox: sync/sync.lo
$(BUILDGOX)
syslog.gox: syslog/syslog.lo
$(BUILDGOX)
syscall.gox: syscalls/syscall.lo
syscall.gox: syscall/syscall.lo
$(BUILDGOX)
tabwriter.gox: tabwriter/tabwriter.lo
$(BUILDGOX)

View File

@ -171,9 +171,10 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
mime/multipart.lo net/dict.lo net/textproto.lo old/template.lo \
$(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
syscalls/errno.lo template/parse.lo testing/testing.lo \
testing/iotest.lo testing/quick.lo testing/script.lo
sync/atomic.lo sync/atomic_c.lo syscall/syscall.lo \
syscall/errno.lo syscall/wait.lo template/parse.lo \
testing/testing.lo testing/iotest.lo testing/quick.lo \
testing/script.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
@ -375,7 +376,10 @@ GOARCH = @GOARCH@
GOC = @GOC@
GOCFLAGS = $(CFLAGS)
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@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@ -1781,97 +1785,85 @@ go_testing_quick_files = \
go_testing_script_files = \
go/testing/script/script.go
@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = syscalls/syscall.go
@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = go/syscall/syscall_unix.go
# Define Syscall and Syscall6.
@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = syscalls/syscall_stubs.go
@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = go/syscall/syscall_stubs.go
@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
# Define ForkExec and Exec.
@LIBGO_IS_RTEMS_TRUE@syscall_exec_file = go/syscall/exec_stubs.go
@HAVE_WAIT4_FALSE@syscall_wait_file = go/syscall/libcall_waitpid.go
# Define Wait4.
@HAVE_WAIT4_TRUE@syscall_wait_file = go/syscall/libcall_wait4.go
@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = go/syscall/sleep_select.go
# Define Sleep.
@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = go/syscall/sleep_rtems.go
@HAVE_STRERROR_R_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr_nor.go
@HAVE_STRERROR_R_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go
# Define Errstr.
@LIBGO_IS_LINUX_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go
# Use lseek on 64-bit Solaris.
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_filesize_file = syscalls/sysfile_regfile.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go
# Use lseek64 on 32-bit Solaris/SPARC.
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
# Use lseek64 on 32-bit Solaris/x86.
@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
# Use lseek by default.
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_filesize_file = syscalls/sysfile_regfile.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go
# Declare libc functions that vary for largefile systems.
# Always use lseek64 on GNU/Linux.
@LIBGO_IS_LINUX_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_stat_file = syscalls/sysfile_stat_regfile.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go
@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_stat_file = syscalls/sysfile_stat_regfile.go
@LIBGO_IS_LINUX_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go
@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = syscalls/exec.go
# Define ForkExec, PtraceForkExec, and Exec.
@LIBGO_IS_RTEMS_TRUE@syscall_exec_os_file = syscalls/exec_stubs.go
@HAVE_WAIT4_FALSE@syscall_wait_file = syscalls/waitpid.go
# Define Wait4.
@HAVE_WAIT4_TRUE@syscall_wait_file = syscalls/wait4.go
@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = syscalls/sleep_select.go
# Define Sleep.
@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = syscalls/sleep_rtems.go
@HAVE_STRERROR_R_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = syscalls/errstr_nor.go
@HAVE_STRERROR_R_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = syscalls/errstr.go
# Define Errstr.
@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = syscalls/errstr_rtems.go
# On other systems we hope strerror_r is just strerror_r.
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_decl_file = syscalls/errstr_decl.go
# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r.
@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_decl_file = syscalls/errstr_decl_linux.go
# Declare libc_strerror_r which is the Go name for strerror_r.
# RTEMS uses newlib in which strerror_r returns char *.
@LIBGO_IS_RTEMS_TRUE@syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = syscalls/socket_bsd.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = syscalls/socket_irix.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_os_file = syscalls/socket_solaris.go
@LIBGO_IS_LINUX_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_bsd.go
@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_irix.go
@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_file = go/syscall/socket_solaris.go
# Define socket sizes and types.
@LIBGO_IS_LINUX_TRUE@syscall_socket_os_file = syscalls/socket_linux.go
@LIBGO_IS_LINUX_FALSE@syscall_socket_epoll_file =
# Support for epoll.
@LIBGO_IS_LINUX_TRUE@syscall_socket_epoll_file = syscalls/socket_epoll.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = syscalls/syscall_uname.go
@LIBGO_IS_LINUX_TRUE@syscall_socket_file = go/syscall/socket_linux.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = go/syscall/libcall_uname.go
# Support for uname.
# 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.
@LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file =
@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = syscalls/syscall_uname.go
@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = go/syscall/libcall_uname.go
@LIBGO_IS_LINUX_FALSE@syscall_netlink_file =
# Support for netlink sockets and messages.
@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = syscalls/netlink_linux.go
go_syscall_files = \
$(syscall_errstr_file) \
$(syscall_errstr_decl_file) \
syscalls/exec_helpers.go \
$(syscall_exec_os_file) \
$(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) \
@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = go/syscall/netlink_linux.go
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) \
syscalls/syscall_unix.go \
syscalls/stringbyte.go \
syscalls/syscall_$(GOOS).go \
$(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \
syscalls/sysfile_posix.go \
$(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 = \
syscalls/errno.c
go/syscall/errno.c \
go/syscall/wait.c
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
@ -2030,8 +2022,9 @@ libgo_go_objs = \
runtime/pprof.lo \
sync/atomic.lo \
sync/atomic_c.lo \
syscalls/syscall.lo \
syscalls/errno.lo \
syscall/syscall.lo \
syscall/errno.lo \
syscall/wait.lo \
template/parse.lo \
testing/testing.lo \
testing/iotest.lo \
@ -4377,6 +4370,14 @@ s-version: Makefile
$(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go
$(STAMP) $@
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
s-syscall_arch: Makefile
rm -f syscall_arch.go.tmp
@ -4386,6 +4387,12 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@
sysinfo.go: s-sysinfo; @true
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) $@
asn1/asn1.lo: $(go_asn1_files) big.gox bytes.gox fmt.gox io.gox os.gox \
reflect.gox strconv.gox strings.gox time.gox
$(BUILDPACKAGE)
@ -5559,16 +5566,12 @@ testing/script/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: testing/script/check
sysinfo.go: s-sysinfo; @true
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
syscall/syscall.lo: $(go_syscall_files) sync.gox
$(BUILDPACKAGE)
syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo
$(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c
syscall/errno.lo: go/syscall/errno.c
$(LTCOMPILE) -c -o $@ $<
syscall/wait.lo: go/syscall/wait.c
$(LTCOMPILE) -c -o $@ $<
asn1.gox: asn1/asn1.lo
$(BUILDGOX)
@ -5650,7 +5653,7 @@ sync.gox: sync/sync.lo
$(BUILDGOX)
syslog.gox: syslog/syslog.lo
$(BUILDGOX)
syscall.gox: syscalls/syscall.lo
syscall.gox: syscall/syscall.lo
$(BUILDGOX)
tabwriter.gox: tabwriter/tabwriter.lo
$(BUILDGOX)

73
libgo/configure vendored
View File

@ -617,7 +617,10 @@ USING_SPLIT_STACK_FALSE
USING_SPLIT_STACK_TRUE
SPLIT_STACK
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
LIBGO_IS_X86_64_FALSE
LIBGO_IS_X86_64_TRUE
@ -10913,7 +10916,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 10916 "configure"
#line 10919 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -11019,7 +11022,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11022 "configure"
#line 11025 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@ -13151,6 +13154,49 @@ CC="$lt_save_CC"
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'
@ -13551,10 +13597,25 @@ fi
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=
if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go
GO_LIBCALL_OS_FILE=
GO_LIBCALL_OS_ARCH_FILE=
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
case "$target" in

View File

@ -45,6 +45,8 @@ AC_SUBST(enable_static)
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
AC_SUBST(CC_FOR_BUILD)
AC_PROG_AWK
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
AC_SUBST(WARN_FLAGS)
@ -249,11 +251,26 @@ AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes)
AC_SUBST(GOARCH)
dnl Some files are only present when needed for specific architectures.
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=
if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go
GO_LIBCALL_OS_FILE=
GO_LIBCALL_OS_ARCH_FILE=
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
AC_SUBST(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE)
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
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.
case "$target" in

View File

@ -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_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) {
ip, err, completed := cgoLookupIP(name)
for _, p := range ip {
@ -99,13 +110,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
} else if gerrno == syscall.EAI_SYSTEM {
str = syscall.Errstr(syscall.GetErrno())
} else {
str = syscall.BytePtrToString(libc_gai_strerror(gerrno))
str = bytePtrToString(libc_gai_strerror(gerrno))
}
return nil, "", &DNSError{Error: str, Name: name}, true
}
defer libc_freeaddrinfo(res)
if res != nil {
cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
if cname == "" {
cname = name
}

View File

@ -12,20 +12,20 @@ import (
)
type pollster struct {
readFds, writeFds, repeatFds *syscall.FdSet_t
readFds, writeFds, repeatFds *syscall.FdSet
maxFd int
readyReadFds, readyWriteFds *syscall.FdSet_t
readyReadFds, readyWriteFds *syscall.FdSet
nReady int
lastFd int
}
func newpollster() (p *pollster, err os.Error) {
p = new(pollster)
p.readFds = new(syscall.FdSet_t)
p.writeFds = new(syscall.FdSet_t)
p.repeatFds = new(syscall.FdSet_t)
p.readyReadFds = new(syscall.FdSet_t)
p.readyWriteFds = new(syscall.FdSet_t)
p.readFds = new(syscall.FdSet)
p.writeFds = new(syscall.FdSet)
p.repeatFds = new(syscall.FdSet)
p.readyReadFds = new(syscall.FdSet)
p.readyWriteFds = new(syscall.FdSet)
p.maxFd = -1
p.nReady = 0
p.lastFd = 0
@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
}
var n, e int
var tmpReadFds, tmpWriteFds syscall.FdSet_t
var tmpReadFds, tmpWriteFds syscall.FdSet
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.
tmpReadFds = *p.readFds
tmpWriteFds = *p.writeFds

View File

@ -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_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() {
implemented = true
}
@ -78,9 +89,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
u := &User{
Uid: int(pwd.Pw_uid),
Gid: int(pwd.Pw_gid),
Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
}
// The pw_gecos field isn't quite standardized. Some docs
// say: "It is expected to be a comma separated list of

169
libgo/go/syscall/bpf_bsd.go Normal file
View File

@ -0,0 +1,169 @@
// 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
}

View File

@ -9,8 +9,8 @@
/* errno is typically a macro. These functions set
and get errno specific to the libc being used. */
int GetErrno() asm ("libgo_syscalls.syscall.GetErrno");
void SetErrno(int) asm ("libgo_syscalls.syscall.SetErrno");
int GetErrno() asm ("libgo_syscall.syscall.GetErrno");
void SetErrno(int) asm ("libgo_syscall.syscall.SetErrno");
int
GetErrno()

View File

@ -6,18 +6,21 @@
package syscall
func Errstr(errno int) string {
for len := Size_t(128); ; len *= 2 {
//sysnb strerror_r(errnum int, buf []byte) (errno int)
//strerror_r(errnum int, buf *byte, buflen Size_t) int
func Errstr(errnum int) string {
for len := 128; ; len *= 2 {
b := make([]byte, len)
r := libc_strerror_r(errno, &b[0], len)
if r >= 0 {
err := strerror_r(errnum, b)
if err == 0 {
i := 0
for b[i] != 0 {
i++
}
return string(b[:i])
}
if GetErrno() != ERANGE {
if err != ERANGE {
return "Errstr failure"
}
}

View File

@ -0,0 +1,23 @@
// errstr_rtems.go -- RTEMS specific error strings.
// 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"
//sysnb strerror_r(errnum int, b []byte) (errstr *byte)
//strerror_r(errnum int, b *byte, len Size_t) *byte
func Errstr(errnum int) string {
a := make([]byte, 128)
p := strerror_r(errnum, a)
b := (*[1000]byte)(unsafe.Pointer(p))
i := 0
for b[i] != 0 {
i++
}
return string(b[:i])
}

View File

@ -11,7 +11,8 @@ import (
"unsafe"
)
func libc_strerror(int) *byte __asm__ ("strerror")
//sysnb strerror(errnum int) *byte
//strerror(errnum int) *byte
var errstr_lock sync.Mutex

View File

@ -1,5 +1,3 @@
// exec_stubs.go -- fork/exec stubs.
// 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.
@ -12,10 +10,6 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int)
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) {
return ENOSYS;
}

View File

@ -1,28 +1,129 @@
// 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.
// +build darwin freebsd linux openbsd
// Fork, exec, wait, etc.
package syscall
import "unsafe"
import (
"sync"
"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")
//sysnb raw_fork() (pid Pid_t, errno int)
//fork() Pid_t
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
//sysnb raw_setsid() (errno int)
//setsid() Pid_t
//sysnb raw_chroot(path *byte) (errno int)
//chroot(path *byte) int
//sysnb raw_chdir(path *byte) (errno int)
//chdir(path *byte) int
//sysnb raw_fcntl(fd int, cmd int, arg int) (val int, errno int)
//fcntl(fd int, cmd int, arg int) int
//sysnb raw_close(fd int) (errno int)
//close(fd int) int
//sysnb raw_ioctl(fd int, cmd int, val int) (rval int, errno int)
//ioctl(fd int, cmd int, val int) int
//sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (errno int)
//execve(argv0 *byte, argv **byte, envv **byte) int
//sysnb raw_read(fd int, p *byte, np int) (n int, errno int)
//read(fd int, buf *byte, count Size_t) Ssize_t
//sysnb raw_write(fd int, buf *byte, count int) int
//write(fd int, buf *byte, count Size_t) Ssize_t
//sysnb raw_exit(status int)
//_exit(status int)
// 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).
var ForkLock sync.RWMutex
// Convert array of string to array
// of NUL-terminated byte pointer.
func StringSlicePtr(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
}
_, err = fcntl(fd, F_SETFL, flag)
return err
}
// 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.
@ -30,81 +131,94 @@ func libc_sysexit(int) __asm__ ("_exit")
// 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.
// The calls to RawSyscall are okay because they are assembly
// functions that do not grow the stack.
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 r1 Pid_t
var err1 int
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()
r1, err1 = raw_fork()
if err1 != 0 {
return 0, int(err1)
}
if child != 0 {
if r1 != 0 {
// parent; return PID
return int(child), 0
return int(r1), 0
}
// Fork succeeded, now in child.
// Enable tracing if requested.
if sys.Ptrace {
if libc_ptrace(_PTRACE_TRACEME, 0, 0, nil) < 0 {
err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
if err1 != 0 {
goto childerror
}
}
// Session ID
if sys.Setsid {
if libc_setsid() == Pid_t(-1) {
err1 = raw_setsid()
if err1 != 0 {
goto childerror
}
}
// Set process group
if sys.Setpgid {
if libc_setpgid(0, 0) < 0 {
err1 = Setpgid(0, 0)
if err1 != 0 {
goto childerror
}
}
// Chroot
if chroot != nil {
if libc_chroot(chroot) < 0 {
err1 = raw_chroot(chroot)
if err1 != 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]))
ngroups := len(cred.Groups)
if ngroups == 0 {
err1 = setgroups(0, nil)
} else {
groups := make([]Gid_t, ngroups)
for i, v := range cred.Groups {
groups[i] = Gid_t(v)
}
err1 = setgroups(ngroups, &groups[0])
}
if libc_setgroups(Size_t(ngroups), groups) < 0 {
if err1 != 0 {
goto childerror
}
if libc_setgid(Gid_t(cred.Gid)) < 0 {
err1 = Setgid(int(cred.Gid))
if err1 != 0 {
goto childerror
}
if libc_setuid(Uid_t(cred.Uid)) < 0 {
err1 = Setuid(int(cred.Uid))
if err1 != 0 {
goto childerror
}
}
// Chdir
if dir != nil {
if libc_chdir(dir) < 0 {
err1 = raw_chdir(dir)
if err1 != 0 {
goto childerror
}
}
@ -113,21 +227,21 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// 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 {
_, err1 = Dup2(pipe, nextfd)
if err1 != 0 {
goto childerror
}
libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
raw_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 {
_, err1 = Dup2(fd[i], nextfd)
if err1 != 0 {
goto childerror
}
libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
fd[i] = nextfd
nextfd++
if nextfd == pipe { // don't stomp on pipe
@ -139,22 +253,22 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// Pass 2: dup fd[i] down onto i.
for i = 0; i < len(fd); i++ {
if fd[i] == -1 {
libc_close(i)
raw_close(i)
continue
}
if fd[i] == int(i) {
// dup2(i, i) won't clear close-on-exec flag on Linux,
// 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 {
_, err1 = raw_fcntl(fd[i], F_SETFD, 0)
if err1 != 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 {
_, err1 = Dup2(fd[i], i)
if err1 != 0 {
goto childerror
}
}
@ -164,33 +278,33 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
// 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)
raw_close(i)
}
// Detach fd 0 from tty
if sys.Noctty {
if libc_ioctl(0, TIOCNOTTY) < 0 {
_, err1 = raw_ioctl(0, TIOCNOTTY, 0)
if err1 != 0 {
goto childerror
}
}
// Make fd 0 the tty
if sys.Setctty {
if libc_ioctl(0, TIOCSCTTY) < 0 {
_, err1 = raw_ioctl(0, TIOCSCTTY, 0)
if err1 != 0 {
goto childerror
}
}
// Time to exec.
libc_execve(argv0, &argv[0], &envv[0])
err1 = raw_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)))
raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
for {
libc_sysexit(253)
raw_exit(253)
}
// Calling panic is not actually safe,
@ -231,8 +345,7 @@ 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 n int
var err1 uintptr
var wstatus WaitStatus
@ -249,8 +362,8 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
// Convert args to C form.
argv0p := StringBytePtr(argv0)
argvp := StringArrayPtr(argv)
envvp := StringArrayPtr(attr.Env)
argvp := StringSlicePtr(argv)
envvp := StringSlicePtr(attr.Env)
if OS == "freebsd" && len(argv[0]) > len(argv0) {
argvp[0] = argv0p
@ -290,15 +403,10 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
// 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()
}
n, err = raw_read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
Close(p[0])
if err != 0 || n != 0 {
if int(n) == unsafe.Sizeof(err1) {
if n == int(unsafe.Sizeof(err1)) {
err = int(err1)
}
if err == 0 {
@ -339,8 +447,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
// 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()
err1 := raw_execve(StringBytePtr(argv0),
&StringSlicePtr(argv)[0],
&StringSlicePtr(envv)[0])
return int(err1)
}

View File

@ -0,0 +1,327 @@
// 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
}

View File

@ -0,0 +1,319 @@
// 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.
// GNU/Linux library calls.
package syscall
import "unsafe"
//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int)
//openat(dirfd int, path *byte, flags int, mode Mode_t) int
//sys futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int)
//futimesat(dirfd int, path *byte, times *[2]Timeval) int
func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
if len(tv) != 2 {
return EINVAL
}
return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
}
func Futimes(fd int, tv []Timeval) (errno int) {
// Believe it or not, this is the best we can do on Linux
// (and is what glibc does).
return Utimes("/proc/self/fd/"+itoa(fd), tv)
}
//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
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.
// The ptrace syscall differs from glibc's ptrace.
// Peeks returns the word in *data, not as the return value.
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 {
errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return 0, errno
}
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.
errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return n, errno
}
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
errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return 0, errno
}
n += copy(buf[addr%sizeofPtr:], data)
word := *((*uintptr)(unsafe.Pointer(&buf[0])))
errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
if errno != 0 {
return 0, errno
}
data = data[n:]
}
// Interior.
for len(data) > int(sizeofPtr) {
word := *((*uintptr)(unsafe.Pointer(&data[0])))
errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
if errno != 0 {
return n, errno
}
n += int(sizeofPtr)
data = data[sizeofPtr:]
}
// Trailing edge.
if len(data) > 0 {
var buf [sizeofPtr]byte
errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
if errno != 0 {
return n, errno
}
copy(buf[0:], data)
word := *((*uintptr)(unsafe.Pointer(&buf[0])))
errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
if errno != 0 {
return n, errno
}
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) {
return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
}
func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
}
func PtraceSetOptions(pid int, options int) (errno int) {
return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
}
func PtraceGetEventMsg(pid int) (msg uint, errno int) {
var data _C_long
errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
msg = uint(data)
return
}
func PtraceCont(pid int, signal int) (errno int) {
return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
}
func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
// FIXME: mksysinfo needs to produce LINUX_REBOOT_MAGIC[12].
// //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int)
// //reboot(magic1 uint, magic2 uint, cmd int, arg *byte) int
// func Reboot(cmd int) (errno int) {
// return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
// }
//sys Acct(path string) (errno int)
//acct(path *byte) int
// FIXME: mksysinfo Timex
// //sys Adjtimex(buf *Timex) (state int, errno int)
// //adjtimex(buf *Timex) int
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (errno int)
//faccessat(dirfd int, pathname *byte, mode int, flags int) int
//sys Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
//fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int)
//fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int)
//fchownat(dirfd int, path *byte, owner Uid_t, group Gid_t, flags int) int
// FIXME: mksysinfo statfs
// //sys Fstatfs(fd int, buf *Statfs_t) (errno int)
// //fstatfs(fd int, buf *Statfs_t) int
//sys Ioperm(from int, num int, on int) (errno int)
//ioperm(from _C_long, num _C_long, on int) int
//sys Iopl(level int) (errno int)
//iopl(level int) int
// FIXME: mksysinfo linux_dirent
// Or just abandon this function.
// //sys Getdents(fd int, buf []byte) (n int, errno int)
// //getdents64(fd int, buf *byte, count uint)
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int)
//inotify_add_watch(fd int, pathname *byte, mask uint32) int
//sysnb InotifyInit() (fd int, errno int)
//inotify_init() int
//sysnb InotifyInit1(flags int) (fd int, errno int)
//inotify_init1(flags int) int
//sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int)
//inotify_rm_watch(fd int, wd uint32) int
//sys Klogctl(typ int, buf []byte) (n int, errno int)
//klogctl(typ int, bufp *byte, len int) int
//sys Mkdirat(dirfd int, path string, mode uint32) (errno int)
//mkdirat(dirfd int, path *byte, mode Mode_t) int
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (errno int)
//mknodat(dirfd int, path *byte, mode Mode_t, dev _dev_t) int
//sys PivotRoot(newroot string, putold string) (errno int)
//pivot_root(newroot *byte, putold *byte) int
//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int)
//renameat(olddirfd int, oldpath *byte, newdirfd int, newpath *byte) int
//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, errno int)
//sendfile64(outfd int, infd int, offset *Offset_t, count Size_t) Ssize_t
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
var soff Offset_t
var psoff *Offset_t
if offset != nil {
psoff = &soff
}
written, errno = sendfile(outfd, infd, psoff, count)
if offset != nil {
*offset = int64(soff)
}
return
}
//sys Setfsgid(gid int) (errno int)
//setfsgid(gid Gid_t) int
//sys Setfsuid(uid int) (errno int)
//setfsuid(uid Uid_t) int
//sysnb Setresgid(rgid int, egid int, sgid int) (errno int)
//setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) int
//sysnb Setresuid(ruid int, eguid int, suid int) (errno int)
//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) int
//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, errno int)
//splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len Size_t, flags uint) Ssize_t
func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int) {
var lroff _loff_t
var plroff *_loff_t
if (roff != nil) {
plroff = &lroff
}
var lwoff _loff_t
var plwoff *_loff_t
if (woff != nil) {
plwoff = &lwoff
}
n, errno = splice(rfd, plroff, wfd, plwoff, len, flags)
if (roff != nil) {
*roff = int64(lroff)
}
if (woff != nil) {
*woff = int64(lwoff)
}
return
}
// FIXME: mksysinfo statfs
// //sys Statfs(path string, buf *Statfs_t) (errno int)
// //statfs(path *byte, buf *Statfs_t) int
//sys SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
//sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
// FIXME: mksysinfo Sysinfo_t
// //sysnb Sysinfo(info *Sysinfo_t) (errno int)
// //sysinfo(info *Sysinfo_t) int
//sys Tee(rfd int, wfd int, len int, flags int) (n int64, errno int)
//tee(rfd int, wfd int, len Size_t, flags uint) Ssize_t
//sysnb Tgkill(tgid int, tid int, sig int) (errno int)
//tgkill(tgid int, tid int, sig int) int
//sys unlinkat(dirfd int, path string, flags int) (errno int)
//unlinkat(dirfd int, path *byte, flags int) int
func Unlinkat(dirfd int, path string) (errno int) {
return unlinkat(dirfd, path, 0)
}
//sys Unmount(target string, flags int) (errno int) = SYS_UMOUNT2
//umount2(target *byte, flags int) int
//sys Unshare(flags int) (errno int)
//unshare(flags int) int
// FIXME: mksysinfo Ustat_t
// //sys Ustat(dev int, ubuf *Ustat_t) (errno int)
// //ustat(dev _dev_t, ubuf *Ustat_t) int

View File

@ -0,0 +1,385 @@
// 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
}

View File

@ -0,0 +1,37 @@
// 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

View File

@ -0,0 +1,38 @@
// 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

View File

@ -1,7 +1,9 @@
// syscall_solaris.go -- Solaris 2 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
// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
//sysnb Uname(buf *Utsname) (errno int)
//_nuname(buf *Utsname) int

View File

@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Declarations for functions which are actually written in C.
package syscall
func libc_uname(buf *Utsname) (errno int) __asm__("uname")
func entersyscall()
func exitsyscall()
func GetErrno() int
func SetErrno(int)

View File

@ -1,7 +1,8 @@
// syscall_rtems.go -- RTEMS 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
//sysnb Uname(buf *Utsname) (errno int)
//uname(buf *Utsname) int

View File

@ -0,0 +1,21 @@
// 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.
// For systems with the wait4 library call.
package syscall
//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) {
var status int
r, err := wait4(Pid_t(pid), &status, options, rusage)
wpid = int(r)
errno = err
if wstatus != nil {
*wstatus = WaitStatus(status)
}
return
}

View File

@ -1,20 +1,19 @@
// waitpid.go -- Wait4 for systems without wait4, but with waitpid.
// Copyright 2011 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
// license that can be found in the LICENSE file.
// For systems with the waitpid library call.
package syscall
func libc_waitpid(Pid_t, *int, int) Pid_t __asm__ ("waitpid")
//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) {
var status int
r := libc_waitpid(Pid_t(pid), &status, options)
r, err := waitpid(Pid_t(pid), &status, options)
wpid = int(r)
if r < 0 {
errno = GetErrno()
}
errno = err
if wstatus != nil {
*wstatus = WaitStatus(status)
}

View File

@ -0,0 +1,78 @@
// 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))
}

View File

@ -0,0 +1,233 @@
# 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
}
}

View File

@ -195,10 +195,12 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
)
switch msg.Header.Type {
case RTM_NEWLINK:
case RTM_NEWLINK, RTM_DELLINK:
buf = msg.Data[SizeofIfInfomsg:]
case RTM_NEWADDR:
case RTM_NEWADDR, RTM_DELADDR:
buf = msg.Data[SizeofIfAddrmsg:]
case RTM_NEWROUTE, RTM_DELROUTE:
buf = msg.Data[SizeofRtMsg:]
default:
return nil, EINVAL
}

View File

@ -0,0 +1,197 @@
// 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
}

View File

@ -0,0 +1,77 @@
// 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
}

View File

@ -0,0 +1,77 @@
// 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
}

View File

@ -0,0 +1,35 @@
// 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
}

View File

@ -6,14 +6,8 @@
package syscall
func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
func Sleep(nsec int64) (errno int) {
errno = 0
ts := NsecToTimespec(nsec)
r := libc_nanosleep(&ts, nil)
if r < 0 {
errno = GetErrno()
}
errno = Nanosleep(&ts, nil)
return
}

View File

@ -8,6 +8,6 @@ package syscall
func Sleep(nsec int64) (errno int) {
tv := NsecToTimeval(nsec);
n, err := Select(0, nil, nil, nil, &tv);
_, err := Select(0, nil, nil, nil, &tv);
return err;
}

View File

@ -0,0 +1,38 @@
// 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
}

View File

@ -0,0 +1,115 @@
// 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
}

423
libgo/go/syscall/socket.go Normal file
View File

@ -0,0 +1,423 @@
// socket.go -- Socket 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.
// Low-level socket interface.
// Only for implementing net package.
// DO NOT USE DIRECTLY.
package syscall
import "unsafe"
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool
type Sockaddr interface {
sockaddr() (ptr *RawSockaddrAny, len Socklen_t, errno int) // lowercase; only we can define Sockaddrs
}
type RawSockaddrAny struct {
Addr RawSockaddr
Pad [12]int8
}
const SizeofSockaddrAny = 0x1c
type SockaddrInet4 struct {
Port int
Addr [4]byte
raw RawSockaddrInet4
}
func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL
}
sa.raw.Family = AF_INET
n := sa.raw.setLen()
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port>>8)
p[1] = byte(sa.Port)
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0
}
type SockaddrInet6 struct {
Port int
ZoneId uint32
Addr [16]byte
raw RawSockaddrInet6
}
func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL
}
sa.raw.Family = AF_INET6
n := sa.raw.setLen()
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
p[0] = byte(sa.Port>>8)
p[1] = byte(sa.Port)
sa.raw.Scope_id = sa.ZoneId
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i]
}
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0
}
type SockaddrUnix struct {
Name string
raw RawSockaddrUnix
}
func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
name := sa.Name
n := len(name)
if n >= len(sa.raw.Path) || n == 0 {
return nil, 0, EINVAL
}
sa.raw.Family = AF_UNIX
sa.raw.setLen(n)
for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i])
}
if sa.raw.Path[0] == '@' {
sa.raw.Path[0] = 0
}
// length is family (uint16), name, NUL.
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 2 + Socklen_t(n) + 1, 0
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
switch rsa.Addr.Family {
case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
sa := new(SockaddrUnix)
n, err := pp.getLen()
if err != 0 {
return nil, err
}
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
sa.Name = string(bytes[0:n]);
return sa, 0;
case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
sa := new(SockaddrInet4);
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
sa.Port = int(p[0])<<8 + int(p[1]);
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i];
}
return sa, 0;
case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
sa := new(SockaddrInet6);
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
sa.Port = int(p[0])<<8 + int(p[1]);
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i];
}
return sa, 0;
}
return anyToSockaddrOS(rsa)
}
//sys accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, errno int)
//accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
var rsa RawSockaddrAny
var len Socklen_t = SizeofSockaddrAny
nfd, errno = accept(fd, &rsa, &len)
if errno != 0 {
return
}
sa, errno = anyToSockaddr(&rsa)
if errno != 0 {
Close(nfd)
nfd = 0
}
return
}
//sysnb getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (errno int)
//getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) int
func Getsockname(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny
var len Socklen_t = SizeofSockaddrAny
if errno = getsockname(fd, &rsa, &len); errno != 0 {
return
}
return anyToSockaddr(&rsa)
}
//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (errno int)
//getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int
func Getpeername(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny
var len Socklen_t = SizeofSockaddrAny
if getpeername(fd, &rsa, &len); errno != 0 {
return
}
return anyToSockaddr(&rsa)
}
//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (errno int)
//bind(fd int, sa *RawSockaddrAny, len Socklen_t) int
func Bind(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr()
if err != 0 {
return err
}
return bind(fd, ptr, n)
}
//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (errno int)
//connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) int
func Connect(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr()
if err != 0 {
return err
}
return connect(fd, ptr, n)
}
//sysnb socket(domain int, typ int, proto int) (fd int, errno int)
//socket(domain int, typ int, protocol int) int
func Socket(domain, typ, proto int) (fd, errno int) {
if domain == AF_INET6 && SocketDisableIPv6 {
return -1, EAFNOSUPPORT
}
fd, errno = socket(domain, typ, proto)
return
}
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (errno int)
//socketpair(domain int, typ int, protocol int, fd *[2]int) int
func Socketpair(domain, typ, proto int) (fd [2]int, errno int) {
errno = socketpair(domain, typ, proto, &fd)
return
}
//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (errno int)
//getsockopt(s int, level int, name int, val *byte, vallen *Socklen_t) int
func GetsockoptInt(fd, level, opt int) (value, errno int) {
var n int32
vallen := Socklen_t(4)
errno = getsockopt(fd, level, opt, (uintptr)(unsafe.Pointer(&n)), &vallen)
return int(n), errno
}
func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, errno int) {
vallen := Socklen_t(4)
errno = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), &vallen)
return value, errno
}
func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, int) {
var value IPMreq
vallen := Socklen_t(SizeofIPMreq)
errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
return &value, errno
}
/* FIXME: mksysinfo needs to support IPMreqn.
func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, int) {
var value IPMreqn
vallen := Socklen_t(SizeofIPMreqn)
errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
return &value, errno
}
*/
/* FIXME: mksysinfo needs to support IPv6Mreq.
func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, int) {
var value IPv6Mreq
vallen := Socklen_t(SizeofIPv6Mreq)
errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
return &value, errno
}
*/
//sys setsockopt(s int, level int, name int, val *byte, vallen Socklen_t) (errno int)
//setsockopt(s int, level int, optname int, val *byte, vallen Socklen_t) int
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
var n = int32(value)
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&n)), 4)
}
func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&value[0])), 4)
}
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv)))
}
type Linger struct {
Onoff int32;
Linger int32;
}
func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l)));
}
func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
}
/* FIXME: mksysinfo needs to support IMPreqn.
func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
}
*/
/* FIXME: mksysinfo needs to support IPv6Mreq.
func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
}
*/
func SetsockoptString(fd, level, opt int, s string) (errno int) {
return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
}
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, errno int)
//recvfrom(fd int, buf *byte, len Size_t, flags int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
var rsa RawSockaddrAny
var len Socklen_t = SizeofSockaddrAny
if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
return
}
from, errno = anyToSockaddr(&rsa)
return
}
//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (errno int)
//sendto(s int, buf *byte, len Size_t, flags int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
ptr, n, err := to.sockaddr()
if err != 0 {
return err
}
return sendto(fd, p, flags, ptr, n)
}
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
//recvmsg(s int, msg *Msghdr, flags int) Ssize_t
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
var msg Msghdr
var rsa RawSockaddrAny
msg.Name = (*byte)(unsafe.Pointer(&rsa))
msg.Namelen = uint32(SizeofSockaddrAny)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
iov.SetLen(len(p))
}
var dummy byte
if len(oob) > 0 {
// receive at least one normal byte
if len(p) == 0 {
iov.Base = &dummy
iov.SetLen(1)
}
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
return
}
oobn = int(msg.Controllen)
recvflags = int(msg.Flags)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != AF_UNSPEC {
from, errno = anyToSockaddr(&rsa)
}
return
}
//sys sendmsg(s int, msg *Msghdr, flags int) (errno int)
//sendmsg(s int, msg *Msghdr, flags int) Ssize_t
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
var ptr *RawSockaddrAny
var salen Socklen_t
if to != nil {
var err int
ptr, salen, err = to.sockaddr()
if err != 0 {
return err
}
}
var msg Msghdr
msg.Name = (*byte)(unsafe.Pointer(ptr))
msg.Namelen = uint32(salen)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
iov.SetLen(len(p))
}
var dummy byte
if len(oob) > 0 {
// send at least one normal byte
if len(p) == 0 {
iov.Base = &dummy
iov.SetLen(1)
}
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
if errno = sendmsg(fd, &msg, flags); errno != 0 {
return
}
return
}
//sys Listen(fd int, n int) (errno int)
//listen(fd int, n int) int
//sys Shutdown(fd int, how int) (errno int)
//shutdown(fd int, how int) int
func (iov *Iovec) SetLen(length int) {
iov.Len = Iovec_len_t(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = Msghdr_controllen_t(length)
}

View File

@ -57,10 +57,10 @@ func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
}
type RawSockaddrInet4 struct {
Family uint16;
Port uint16;
Addr [4]byte /* in_addr */;
Zero [8]uint8;
Family uint16
Port uint16
Addr [4]byte /* in_addr */
Zero [8]uint8
}
func (sa *RawSockaddrInet4) setLen() Socklen_t {
@ -68,11 +68,11 @@ func (sa *RawSockaddrInet4) setLen() Socklen_t {
}
type RawSockaddrInet6 struct {
Family uint16;
Port uint16;
Flowinfo uint32;
Addr [16]byte /* in6_addr */;
Scope_id uint32;
Family uint16
Port uint16
Flowinfo uint32
Addr [16]byte /* in6_addr */
Scope_id uint32
}
func (sa *RawSockaddrInet6) setLen() Socklen_t {
@ -80,8 +80,8 @@ func (sa *RawSockaddrInet6) setLen() Socklen_t {
}
type RawSockaddrUnix struct {
Family uint16;
Path [108]int8;
Family uint16
Path [108]int8
}
func (sa *RawSockaddrUnix) setLen(int) {
@ -94,7 +94,7 @@ func (sa *RawSockaddrUnix) getLen() (int, int) {
// (This is the standard convention.)
// Not friendly to overwrite in place,
// but the callers below don't care.
sa.Path[0] = '@';
sa.Path[0] = '@'
}
// Assume path ends at NUL.
@ -102,9 +102,9 @@ func (sa *RawSockaddrUnix) getLen() (int, int) {
// abstract Unix domain sockets--they are supposed
// to be uninterpreted fixed-size binary blobs--but
// everyone uses this convention.
n := 0;
n := 0
for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
n++;
n++
}
return n, 0
@ -128,8 +128,8 @@ type RawSockaddrNetlink struct {
}
type RawSockaddr struct {
Family uint16;
Data [14]int8;
Family uint16
Data [14]int8
}
// BindToDevice binds the socket associated with fd to device.
@ -161,5 +161,23 @@ func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
}
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

20
libgo/go/syscall/str.go Normal file
View File

@ -0,0 +1,20 @@
// 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:])
}

View File

@ -0,0 +1,35 @@
// 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))

View File

@ -0,0 +1,27 @@
// 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)
}

View File

@ -0,0 +1,159 @@
// 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.
// +build darwin freebsd linux openbsd
package syscall
import (
"sync"
"unsafe"
)
var (
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
// the arguments, so that we don't pass a 64-bit value when the function
// expects a 32-bit one.
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
entersyscall()
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()
exitsyscall()
return r, 0, uintptr(errno)
}
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
entersyscall()
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()
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.
// Gccgo only has one implementation but we do this to correspond to gc.
type mmapper struct {
sync.Mutex
active map[*byte][]byte // active mappings; key is last byte in mapping
mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
munmap func(addr uintptr, length uintptr) int
}
func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
if length <= 0 {
return nil, EINVAL
}
// Map the requested memory.
addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
if errno != 0 {
return nil, errno
}
// Slice memory layout
var sl = struct {
addr uintptr
len int
cap int
}{addr, length, length}
// Use unsafe to turn sl into a []byte.
b := *(*[]byte)(unsafe.Pointer(&sl))
// Register mapping in m and return it.
p := &b[cap(b)-1]
m.Lock()
defer m.Unlock()
m.active[p] = b
return b, 0
}
func (m *mmapper) Munmap(data []byte) (errno int) {
if len(data) == 0 || len(data) != cap(data) {
return EINVAL
}
// Find the base of the mapping.
p := &data[cap(data)-1]
m.Lock()
defer m.Unlock()
b := m.active[p]
if b == nil || &b[0] != &data[0] {
return EINVAL
}
// Unmap the memory and update m.
if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
return errno
}
m.active[p] = nil, false
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)
}

107
libgo/go/syscall/wait.c Normal file
View File

@ -0,0 +1,107 @@
/* 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
}

View File

@ -197,16 +197,13 @@ if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then
echo "const EPOLLRDHUP = 0x2000" >> ${OUT}
fi
# Ptrace constants. We don't expose all the PTRACE flags, just the
# PTRACE_O_xxx and PTRACE_EVENT_xxx ones.
grep '^const _PTRACE_O' gen-sysinfo.go |
sed -e 's/^\(const \)_\(PTRACE_O[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
grep '^const _PTRACE_EVENT' gen-sysinfo.go |
sed -e 's/^\(const \)_\(PTRACE_EVENT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
# We need PTRACE_SETOPTIONS and PTRACE_GETEVENTMSG, but they are not
# defined in older versions of glibc.
if ! grep '^const _PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
echo "const _PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
# Ptrace constants.
grep '^const _PTRACE' gen-sysinfo.go |
sed -e 's/^\(const \)_\(PTRACE[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
# We need some ptrace options that are not defined in older versions
# of glibc.
if ! grep '^const PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
echo "const PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
fi
if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then
echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT}
@ -254,7 +251,7 @@ if ! grep '^const PTRACE_EVENT_EXIT' ${OUT} > /dev/null 2>&1; then
echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT}
fi
if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then
echo "const _PTRACE_TRACEME = 0" >> ${OUT}
echo "const PTRACE_TRACEME = 0" >> ${OUT}
fi
# The registers returned by PTRACE_GETREGS. This is probably
@ -474,6 +471,11 @@ grep '^type _ip_mreq ' gen-sysinfo.go | \
-e 's/_in_addr/[4]byte/g' \
>> ${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.
fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
fds_bits_type="_C_long"
@ -531,6 +533,25 @@ if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then
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.
grep '^type _rtgenmsg ' gen-sysinfo.go | \
sed -e 's/_rtgenmsg/RtGenmsg/' \

View File

@ -71,3 +71,21 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
if(hz != 0)
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()
{
}

View File

@ -1,9 +0,0 @@
// 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")

View File

@ -1,9 +0,0 @@
// 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")

View File

@ -1,10 +0,0 @@
// 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")

View File

@ -1,26 +0,0 @@
// errstr_rtems.go -- RTEMS specific error strings.
// 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 Errstr(errno int) string {
for len := Size_t(128); ; len *= 2 {
b := make([]byte, len+1)
// The newlib strerror_r always returns the string in buffer.
libc_strerror_r(errno, &b[0], len)
b[len] = 0
i := 0
for b[i] != 0 {
i++
}
if Size_t(i) < len {
return string(b[0:i])
}
}
}

View File

@ -1,154 +0,0 @@
// 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;
}

View File

@ -1,392 +0,0 @@
// socket.go -- Socket 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.
// Low-level socket interface.
// Only for implementing net package.
// DO NOT USE DIRECTLY.
package syscall
import "unsafe"
type RawSockaddrAny struct {
Addr RawSockaddr;
Pad [12]int8;
}
const SizeofSockaddrAny = 0x1c;
// For testing: clients can set this flag to force
// creation of IPv6 sockets to return EAFNOSUPPORT.
var SocketDisableIPv6 bool
type Sockaddr interface {
sockaddr() (ptr *RawSockaddrAny, len Socklen_t, errno int); // lowercase; only we can define Sockaddrs
}
type SockaddrInet4 struct {
Port int;
Addr [4]byte;
raw RawSockaddrInet4;
}
type SockaddrInet6 struct {
Port int;
Addr [16]byte;
raw RawSockaddrInet6;
}
type SockaddrUnix struct {
Name string;
raw RawSockaddrUnix;
}
type Linger struct {
Onoff int32;
Linger int32;
}
func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL;
}
sa.raw.Family = AF_INET;
n := sa.raw.setLen()
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
p[0] = byte(sa.Port>>8);
p[1] = byte(sa.Port);
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i];
}
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0;
}
func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
if sa.Port < 0 || sa.Port > 0xFFFF {
return nil, 0, EINVAL;
}
sa.raw.Family = AF_INET6;
n := sa.raw.setLen()
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
p[0] = byte(sa.Port>>8);
p[1] = byte(sa.Port);
for i := 0; i < len(sa.Addr); i++ {
sa.raw.Addr[i] = sa.Addr[i];
}
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0;
}
func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
name := sa.Name;
n := len(name);
if n >= len(sa.raw.Path) || n == 0 {
return nil, 0, EINVAL;
}
sa.raw.Family = AF_UNIX;
sa.raw.setLen(n)
for i := 0; i < n; i++ {
sa.raw.Path[i] = int8(name[i]);
}
if sa.raw.Path[0] == '@' {
sa.raw.Path[0] = 0;
}
// length is family (uint16), name, NUL.
return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 2 + Socklen_t(n) + 1, 0;
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
switch rsa.Addr.Family {
case AF_UNIX:
pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
sa := new(SockaddrUnix)
n, err := pp.getLen()
if err != 0 {
return nil, err
}
bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
sa.Name = string(bytes[0:n]);
return sa, 0;
case AF_INET:
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
sa := new(SockaddrInet4);
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
sa.Port = int(p[0])<<8 + int(p[1]);
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i];
}
return sa, 0;
case AF_INET6:
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
sa := new(SockaddrInet6);
p := (*[2]byte)(unsafe.Pointer(&pp.Port));
sa.Port = int(p[0])<<8 + int(p[1]);
for i := 0; i < len(sa.Addr); i++ {
sa.Addr[i] = pp.Addr[i];
}
return sa, 0;
}
return anyToSockaddrOS(rsa)
}
func libc_accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("accept");
func libc_bind(fd int, sa *RawSockaddrAny, len Socklen_t) int __asm__ ("bind");
func libc_connect(fd int, sa *RawSockaddrAny, len Socklen_t) int __asm__ ("connect");
func libc_socket(domain, typ, protocol int) int __asm__ ("socket");
func libc_setsockopt(fd, level, optname int, optval *byte, optlen Socklen_t) int __asm__ ("setsockopt");
func libc_listen(fd, backlog int) int __asm__ ("listen");
func libc_getsockopt(fd, level, optname int, optval *byte, optlen *Socklen_t) int __asm__ ("getsockopt");
func libc_getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("getsockname");
func libc_getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("getpeername");
func libc_recv(fd int, buf *byte, len Size_t, flags int) Ssize_t __asm__ ("recv");
func libc_recvfrom(fd int, buf *byte, len Size_t, flags int,
from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t __asm__("recvfrom");
func libc_recvmsg(fd int, msg *Msghdr, flags int) Ssize_t __asm__("recvmsg")
func libc_send(fd int, buf *byte, len Size_t, flags int) Ssize_t __asm__("send");
func libc_sendto(fd int, buf *byte, len Size_t, flags int,
to *RawSockaddrAny, tolen Socklen_t) Ssize_t __asm__("sendto");
func libc_sendmsg(fd int, msg *Msghdr, flags int) Ssize_t __asm__("sendmsg")
func libc_shutdown(fd int, how int) int __asm__ ("shutdown");
func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
var rsa RawSockaddrAny;
var len Socklen_t = SizeofSockaddrAny;
nfd = libc_accept(fd, &rsa, &len);
if nfd < 0 {
errno = GetErrno();
return;
}
sa, errno = anyToSockaddr(&rsa);
if errno != 0 {
Close(nfd);
nfd = 0;
}
return;
}
func Bind(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr();
if err != 0 {
return err;
}
if libc_bind(fd, ptr, n) < 0 {
errno = GetErrno();
}
return;
}
func Connect(fd int, sa Sockaddr) (errno int) {
ptr, n, err := sa.sockaddr();
if err != 0 {
return err;
}
if libc_connect(fd, ptr, n) < 0 {
errno = GetErrno();
}
return;
}
func Socket(domain, typ, proto int) (fd, errno int) {
if domain == AF_INET6 && SocketDisableIPv6 {
return -1, EAFNOSUPPORT
}
fd = libc_socket(int(domain), int(typ), int(proto));
if fd < 0 {
errno = GetErrno();
}
return;
}
func Listen(fd int, n int) (errno int) {
r := libc_listen(int(fd), int(n));
if r < 0 { errno = GetErrno() }
return;
}
func GetsockoptInt(fd, level, opt int) (value, errno int) {
var n int32
vallen := Socklen_t(4)
errno = libc_getsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&n)), &vallen)
return int(n), errno
}
func setsockopt(fd, level, opt int, valueptr uintptr, length Socklen_t) (errno int) {
r := libc_setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(valueptr)),
length);
if r < 0 { errno = GetErrno() }
return;
}
func SetsockoptInt(fd, level, opt int, value int) (errno int) {
var n = int32(value);
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
}
func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv)));
}
func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l)));
}
func SetsockoptString(fd, level, opt int, s string) (errno int) {
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
}
func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
}
func Getsockname(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny;
var len Socklen_t = SizeofSockaddrAny;
if libc_getsockname(fd, &rsa, &len) != 0 {
errno = GetErrno();
return;
}
return anyToSockaddr(&rsa);
}
func Getpeername(fd int) (sa Sockaddr, errno int) {
var rsa RawSockaddrAny;
var len Socklen_t = SizeofSockaddrAny;
if libc_getpeername(fd, &rsa, &len) != 0 {
errno = GetErrno();
return;
}
return anyToSockaddr(&rsa);
}
func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
var rsa RawSockaddrAny;
var slen Socklen_t = SizeofSockaddrAny;
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }
r := libc_recvfrom(fd, _p0, Size_t(len(p)), flags, &rsa, &slen);
n = int(r);
if r == -1 {
errno = GetErrno();
} else {
from, errno = anyToSockaddr(&rsa);
}
return;
}
func (iov *Iovec) SetLen(length int) {
iov.Len = Iovec_len_t(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = Msghdr_controllen_t(length)
}
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
var msg Msghdr
var rsa RawSockaddrAny
msg.Name = (*byte)(unsafe.Pointer(&rsa))
msg.Namelen = uint32(SizeofSockaddrAny)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
iov.SetLen(len(p))
}
var dummy byte
if len(oob) > 0 {
// receive at least one normal byte
if len(p) == 0 {
iov.Base = &dummy
iov.SetLen(1)
}
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
return
}
oobn = int(msg.Controllen)
recvflags = int(msg.Flags)
// source address is only specified if the socket is unconnected
if rsa.Addr.Family != 0 {
from, errno = anyToSockaddr(&rsa)
}
return
}
func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
r := libc_recvmsg(s, msg, flags)
if r < 0 {
errno = GetErrno()
} else {
n = int(r)
}
return
}
func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
ptr, n, err := to.sockaddr();
if err != 0 {
return err;
}
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }
r := libc_sendto(fd, _p0, Size_t(len(p)), flags, ptr, n);
if r == -1 { errno = GetErrno(); }
return;
}
func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
var ptr *RawSockaddrAny
var nsock Socklen_t
if to != nil {
var err int
ptr, nsock, err = to.sockaddr()
if err != 0 {
return err
}
}
var msg Msghdr
msg.Name = (*byte)(unsafe.Pointer(ptr))
msg.Namelen = uint32(nsock)
var iov Iovec
if len(p) > 0 {
iov.Base = (*byte)(unsafe.Pointer(&p[0]))
iov.SetLen(len(p))
}
var dummy byte
if len(oob) > 0 {
// send at least one normal byte
if len(p) == 0 {
iov.Base = &dummy
iov.SetLen(1)
}
msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
msg.SetControllen(len(oob))
}
msg.Iov = &iov
msg.Iovlen = 1
if errno = sendmsg(fd, &msg, flags); errno != 0 {
return
}
return
}
func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
if libc_sendmsg(s, msg, flags) < 0 {
errno = GetErrno()
}
return
}
func Shutdown(fd int, how int) (errno int) {
r := libc_shutdown(fd, how);
if r < 0 { errno = GetErrno() }
return;
}

View File

@ -1,50 +0,0 @@
// 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;
}

View File

@ -1,37 +0,0 @@
// 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])
}

View File

@ -1,111 +0,0 @@
// syscall.go -- Basic 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.
// 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.
package syscall
import (
"sync"
"unsafe"
)
func libc_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
func libc_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
// the arguments, so that we don't pass a 64-bit value when the function
// expects a 32-bit one.
func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
var r uintptr;
if unsafe.Sizeof(r) == 4 {
r1 := libc_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0);
r = uintptr(r1);
} else {
r1 := libc_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0);
r = uintptr(r1);
}
return r, 0, uintptr(GetErrno());
}
func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
var r uintptr;
if unsafe.Sizeof(r) == 4 {
r1 := libc_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
int32(a4), int32(a5), int32(a6));
r = uintptr(r1);
} else {
r1 := libc_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
int64(a4), int64(a5), int64(a6));
r = uintptr(r1);
}
return r, 0, uintptr(GetErrno());
}
// Mmap manager, for use by operating system-specific implementations.
type mmapper struct {
sync.Mutex
active map[*byte][]byte // active mappings; key is last byte in mapping
mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
munmap func(addr uintptr, length uintptr) int
}
func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
if length <= 0 {
return nil, EINVAL
}
// Map the requested memory.
addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
if errno != 0 {
return nil, errno
}
// Slice memory layout
var sl = struct {
addr uintptr
len int
cap int
}{addr, length, length}
// Use unsafe to turn sl into a []byte.
b := *(*[]byte)(unsafe.Pointer(&sl))
// Register mapping in m and return it.
p := &b[cap(b)-1]
m.Lock()
defer m.Unlock()
m.active[p] = b
return b, 0
}
func (m *mmapper) Munmap(data []byte) (errno int) {
if len(data) == 0 || len(data) != cap(data) {
return EINVAL
}
// Find the base of the mapping.
p := &data[cap(data)-1]
m.Lock()
defer m.Unlock()
b := m.active[p]
if b == nil || &b[0] != &data[0] {
return EINVAL
}
// Unmap the memory and update m.
if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
return errno
}
m.active[p] = nil, false
return 0
}

View File

@ -1,17 +0,0 @@
// 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))

View File

@ -1,206 +0,0 @@
// 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
}

View File

@ -1,20 +0,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")

View File

@ -1,21 +0,0 @@
// 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))

View File

@ -1,17 +0,0 @@
// 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))

View File

@ -1,21 +0,0 @@
// 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))

View File

@ -1,33 +0,0 @@
// 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);
}

View File

@ -1,67 +0,0 @@
// 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
}

View File

@ -1,14 +0,0 @@
// 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")

View File

@ -1,429 +0,0 @@
// sysfile_posix.go -- POSIX File handling.
// 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.
// Support for basic Unix file operations. This file simply
// translates from Go data types to Unix data types, and handles
// errno. FIXME: This could probably be done mechanically.
package syscall
import "unsafe"
func libc_open(name *byte, mode int, perm Mode_t) int __asm__ ("open");
func libc_close(fd int) int __asm__ ("close");
func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
func libc_fsync(fd int) int __asm__ ("fsync")
func libc_pipe(filedes *int) int __asm__("pipe");
func libc_unlink(name *byte) int __asm__ ("unlink");
func libc_rmdir(name *byte) int __asm__ ("rmdir");
func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl");
func libc_mkdir(name *byte, perm Mode_t) int __asm__ ("mkdir");
func libc_dup(int) int __asm__ ("dup")
func libc_gettimeofday(tv *Timeval, tz *byte) int __asm__ ("gettimeofday");
func libc_select(int, *byte, *byte, *byte, *Timeval) int __asm__ ("select");
func libc_chdir(name *byte) int __asm__ ("chdir");
func libc_fchdir(int) int __asm__ ("fchdir");
func libc_getcwd(*byte, Size_t) *byte __asm__ ("getcwd");
func libc_link(oldpath *byte, newpath *byte) int __asm__ ("link");
func libc_symlink(oldpath *byte, newpath *byte) int __asm__ ("symlink");
func libc_readlink(*byte, *byte, Size_t) Ssize_t __asm__ ("readlink");
func libc_rename(oldpath *byte, newpath *byte) int __asm__ ("rename");
func libc_chmod(path *byte, mode Mode_t) int __asm__ ("chmod");
func libc_fchmod(fd int, mode Mode_t) int __asm__ ("fchmod");
func libc_chown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("chown");
func libc_fchown(fd int, owner Uid_t, group Gid_t) int __asm__ ("fchown");
func libc_lchown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("lchown");
func libc_utimes(filename *byte, times *[2]Timeval) int __asm__ ("utimes");
func libc_getuid() Uid_t __asm__ ("getuid");
func libc_geteuid() Uid_t __asm__ ("geteuid");
func libc_getgid() Gid_t __asm__ ("getgid");
func libc_getegid() Gid_t __asm__ ("getegid");
func libc_getgroups(size int, list *Gid_t) int __asm__ ("getgroups");
func libc_getpagesize() int __asm__ ("getpagesize");
func libc_exit(status int) __asm__ ("exit")
func libc_getpid() Pid_t __asm__ ("getpid")
func libc_getppid() Pid_t __asm__ ("getppid")
func libc_kill(Pid_t, int) int __asm__ ("kill")
func Open(name string, mode int, perm uint32) (fd int, errno int) {
fd = libc_open(StringBytePtr(name), mode, Mode_t(perm));
if fd < 0 { errno = GetErrno() }
return;
}
func Creat(name string, perm uint32) (fd int, errno int) {
fd = libc_open(StringBytePtr(name), O_CREAT | O_WRONLY | O_TRUNC, Mode_t(perm));
if fd < 0 { errno = GetErrno() }
return;
}
func Close(fd int) (errno int) {
r := libc_close(fd);
if r < 0 { errno = GetErrno() }
return;
}
func Read(fd int, p []byte) (n int, errno int) {
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }
r := libc_read(fd, _p0, Size_t(len(p)));
if r == -1 { errno = GetErrno() }
n = int(r);
return;
}
func Write(fd int, p []byte) (n int, errno int) {
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }
r := libc_write(fd, _p0, Size_t(len(p)));
if r == -1 { errno = GetErrno() }
n = int(r);
return;
}
func Fsync(fd int) (errno int) {
if libc_fsync(fd) < 0 {
errno = GetErrno()
}
return
}
func Pread(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }
r := libc_pread(fd, _p0, Size_t(len(p)), Offset_t(offset));
if r == -1 { errno = GetErrno() }
n = int(r);
return;
}
func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
var _p0 *byte;
if len(p) > 0 { _p0 = &p[0]; }
r := libc_pwrite(fd, _p0, Size_t(len(p)), Offset_t(offset));
if r == -1 { errno = GetErrno() }
n = int(r);
return;
}
func Seek(fd int, offset int64, whence int) (off int64, errno int) {
r := libc_lseek(fd, Offset_t(offset), whence);
if r == -1 { errno = GetErrno() }
off = int64(r);
return;
}
func Pipe(p []int) (errno int) {
if len(p) != 2 {
return EINVAL;
}
var pp [2]int;
r := libc_pipe(&pp[0]);
if r < 0 {
errno = GetErrno();
}
p[0] = pp[0];
p[1] = pp[1];
return;
}
func Stat(name string, buf *Stat_t) (errno int) {
r := libc_stat(StringBytePtr(name), buf);
if r < 0 { errno = GetErrno() }
return;
}
func Lstat(name string, buf *Stat_t) (errno int) {
r := libc_lstat(StringBytePtr(name), buf);
if r < 0 { errno = GetErrno() }
return;
}
func Fstat(fd int, buf *Stat_t) (errno int) {
r := libc_fstat(fd, buf);
if r < 0 { errno = GetErrno() }
return;
}
func Unlink(name string) (errno int) {
r := libc_unlink(StringBytePtr(name));
if r < 0 { errno = GetErrno() }
return;
}
func Rmdir(name string) (errno int) {
r := libc_rmdir(StringBytePtr(name));
if r < 0 { errno = GetErrno() }
return;
}
func Mkdir(path string, mode uint32) (errno int) {
r := libc_mkdir(StringBytePtr(path), Mode_t(mode));
if r < 0 { errno = GetErrno() }
return;
}
func Dup(oldfd int) (fd int, errno int) {
fd = libc_dup(oldfd)
if fd < 0 {
errno = GetErrno()
}
return
}
func Gettimeofday(tv *Timeval) (errno int) {
r := libc_gettimeofday(tv, nil);
if r < 0 { errno = GetErrno() }
return;
}
const nfdbits = unsafe.Sizeof(fds_bits_type) * 8
type FdSet_t struct {
Fds_bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type
}
func FDSet(fd int, set *FdSet_t) {
set.Fds_bits[fd / nfdbits] |= (1 << (uint)(fd % nfdbits))
}
func FDClr(fd int, set *FdSet_t) {
set.Fds_bits[fd / nfdbits] &^= (1 << (uint)(fd % nfdbits))
}
func FDIsSet(fd int, set *FdSet_t) bool {
if set.Fds_bits[fd / nfdbits] & (1 << (uint)(fd % nfdbits)) != 0 {
return true
} else {
return false
}
}
func FDZero(set *FdSet_t) {
for i := range set.Fds_bits {
set.Fds_bits[i] = 0
}
}
func Select(nfds int, r *FdSet_t, w *FdSet_t, e *FdSet_t, timeout *Timeval) (n int, errno int) {
n = libc_select(nfds, (*byte)(unsafe.Pointer(r)),
(*byte)(unsafe.Pointer(w)),
(*byte)(unsafe.Pointer(e)), timeout);
if n < 0 { errno = GetErrno() }
return;
}
func Chdir(path string) (errno int) {
r := libc_chdir(StringBytePtr(path));
if r < 0 { errno = GetErrno() }
return;
}
func Fchdir(fd int) (errno int) {
r := libc_fchdir(int(fd));
if r < 0 { errno = GetErrno() }
return;
}
const ImplementsGetwd = true
func Getwd() (ret string, errno int) {
for len := Size_t(4096); ; len *= 2 {
b := make([]byte, len);
p := libc_getcwd(&b[0], len);
if p != nil {
i := 0;
for b[i] != 0 {
i++;
}
return string(b[0:i]), 0;
}
e := GetErrno();
if e != ERANGE {
return "", e;
}
}
}
func Link(oldpath, newpath string) (errno int) {
r := libc_link(StringBytePtr(oldpath), StringBytePtr(newpath));
if r < 0 { errno = GetErrno() }
return;
}
func Symlink(oldpath, newpath string) (errno int) {
r := libc_symlink(StringBytePtr(oldpath), StringBytePtr(newpath));
if r < 0 { errno = GetErrno() }
return;
}
func Readlink(path string, buf []byte) (n int, errno int) {
var _p0 *byte;
if len(buf) > 0 { _p0 = &buf[0]; }
r := libc_readlink(StringBytePtr(path), _p0, Size_t(len(buf)));
if r < 0 { errno = GetErrno() }
n = int(r);
return;
}
func Rename(oldpath, newpath string) (errno int) {
r := libc_rename(StringBytePtr(oldpath), StringBytePtr(newpath));
if r < 0 { errno = GetErrno() }
return
}
func Chmod(path string, mode uint32) (errno int) {
r := libc_chmod(StringBytePtr(path), Mode_t(mode));
if r < 0 { errno = GetErrno() }
return;
}
func Fchmod(fd int, mode uint32) (errno int) {
r := libc_fchmod(fd, Mode_t(mode));
if r < 0 { errno = GetErrno() }
return;
}
func Chown(path string, uid int, gid int) (errno int) {
r := libc_chown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
if r < 0 { errno = GetErrno() }
return;
}
func Lchown(path string, uid int, gid int) (errno int) {
r := libc_lchown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
if r < 0 { errno = GetErrno() }
return;
}
func Fchown(fd int, uid int, gid int) (errno int) {
r := libc_fchown(fd, Uid_t(uid), Gid_t(gid));
if r < 0 { errno = GetErrno() }
return;
}
func Truncate(path string, length int64) (errno int) {
r := libc_truncate(StringBytePtr(path), Offset_t(length));
if r < 0 { errno = GetErrno() }
return;
}
func Ftruncate(fd int, length int64) (errno int) {
r := libc_ftruncate(fd, Offset_t(length));
if r < 0 { errno = GetErrno() }
return;
}
func Utimes(path string, tv []Timeval) (errno int) {
if len(tv) != 2 {
return EINVAL;
}
r := libc_utimes(StringBytePtr(path),
(*[2]Timeval)(unsafe.Pointer(&tv[0])));
if r < 0 {
errno = GetErrno();
}
return;
}
// Getuid returns the numeric user id of the caller.
func Getuid() int {
return int(libc_getuid());
}
// Geteuid returns the numeric effective user id of the caller.
func Geteuid() int {
return int(libc_geteuid());
}
// Getgid returns the numeric group id of the caller.
func Getgid() int {
return int(libc_getgid());
}
// Getegid returns the numeric effective group id of the caller.
func Getegid() int {
return int(libc_getegid());
}
// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
func Getgroups() (gids []int, errno int) {
n := libc_getgroups(0, nil);
if n < 0 {
return nil, GetErrno();
}
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 = libc_getgroups(n, &a[0]);
if n < 0 {
return nil, GetErrno();
}
gids = make([]int, n);
for i, v := range a[0:n] {
gids[i] = int(v);
}
return;
}
func Getpagesize() int {
return libc_getpagesize();
}
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;
}
func Exit(code int) {
libc_exit(code);
}
func fcntl(fd, cmd, arg int) (val int, errno int) {
val = libc_fcntl(int(fd), int(cmd), int(arg));
if val == -1 { errno = GetErrno() }
return;
}
func Getpid() (pid int) {
return int(libc_getpid());
}
func Getppid() (ppid int) {
return int(libc_getppid());
}
func Kill(pid int, sig int) (errno int) {
r := libc_kill(Pid_t(pid), sig)
if r < 0 {
errno = GetErrno()
}
return
}

View File

@ -1,14 +0,0 @@
// 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")

View File

@ -1,12 +0,0 @@
// 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");

View File

@ -1,12 +0,0 @@
// 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");

View File

@ -1,22 +0,0 @@
// wait4.go -- Wait4 for systems with wait4.
// 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_wait4(Pid_t, *int, int, *Rusage) Pid_t __asm__ ("wait4")
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
var status int
r := libc_wait4(Pid_t(pid), &status, options, rusage)
wpid = int(r)
if r < 0 {
errno = GetErrno()
}
if wstatus != nil {
*wstatus = WaitStatus(status)
}
return
}

View File

@ -86,7 +86,10 @@ GOARCH = @GOARCH@
GOC = @GOC@
GOCFLAGS = @GOCFLAGS@
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@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@