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:
parent
7b45b87f01
commit
de27caacfb
@ -1392,128 +1392,142 @@ go_testing_script_files = \
|
|||||||
|
|
||||||
# Define Syscall and Syscall6.
|
# Define Syscall and Syscall6.
|
||||||
if LIBGO_IS_RTEMS
|
if LIBGO_IS_RTEMS
|
||||||
syscall_syscall_file = syscalls/syscall_stubs.go
|
syscall_syscall_file = go/syscall/syscall_stubs.go
|
||||||
else
|
else
|
||||||
syscall_syscall_file = syscalls/syscall.go
|
syscall_syscall_file = go/syscall/syscall_unix.go
|
||||||
|
endif
|
||||||
|
|
||||||
|
# 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
|
endif
|
||||||
|
|
||||||
# Declare libc functions that vary for largefile systems.
|
# Declare libc functions that vary for largefile systems.
|
||||||
if LIBGO_IS_LINUX
|
if LIBGO_IS_LINUX
|
||||||
# Always use lseek64 on GNU/Linux.
|
# Always use lseek64 on GNU/Linux.
|
||||||
syscall_filesize_file = syscalls/sysfile_largefile.go
|
syscall_size_file = go/syscall/libcall_posix_largefile.go
|
||||||
syscall_stat_file = syscalls/sysfile_stat_largefile.go
|
|
||||||
else # !LIBGO_IS_LINUX
|
else # !LIBGO_IS_LINUX
|
||||||
if LIBGO_IS_SOLARIS
|
if LIBGO_IS_SOLARIS
|
||||||
if LIBGO_IS_386
|
if LIBGO_IS_386
|
||||||
# Use lseek64 on 32-bit Solaris/x86.
|
# Use lseek64 on 32-bit Solaris/x86.
|
||||||
syscall_filesize_file = syscalls/sysfile_largefile.go
|
syscall_size_file = go/syscall/libcall_posix_largefile.go
|
||||||
syscall_stat_file = syscalls/sysfile_stat_largefile.go
|
|
||||||
else # !LIBGO_IS_386
|
else # !LIBGO_IS_386
|
||||||
if LIBGO_IS_SPARC
|
if LIBGO_IS_SPARC
|
||||||
# Use lseek64 on 32-bit Solaris/SPARC.
|
# Use lseek64 on 32-bit Solaris/SPARC.
|
||||||
syscall_filesize_file = syscalls/sysfile_largefile.go
|
syscall_size_file = go/syscall/libcall_posix_largefile.go
|
||||||
syscall_stat_file = syscalls/sysfile_stat_largefile.go
|
|
||||||
else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
|
else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
|
||||||
# Use lseek on 64-bit Solaris.
|
# Use lseek on 64-bit Solaris.
|
||||||
syscall_filesize_file = syscalls/sysfile_regfile.go
|
syscall_size_file = go/syscall/libcall_posix_regfile.go
|
||||||
syscall_stat_file = syscalls/sysfile_stat_regfile.go
|
|
||||||
endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
|
endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
|
||||||
endif # !LIBGO_IS_SOLARIS
|
endif # !LIBGO_IS_SOLARIS
|
||||||
else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
|
else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
|
||||||
# Use lseek by default.
|
# Use lseek by default.
|
||||||
syscall_filesize_file = syscalls/sysfile_regfile.go
|
syscall_size_file = go/syscall/libcall_posix_regfile.go
|
||||||
syscall_stat_file = syscalls/sysfile_stat_regfile.go
|
|
||||||
endif # !LIBGO_IS_SOLARIS
|
endif # !LIBGO_IS_SOLARIS
|
||||||
endif # !LIBGO_IS_LINUX
|
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.
|
# Define socket sizes and types.
|
||||||
if LIBGO_IS_LINUX
|
if LIBGO_IS_LINUX
|
||||||
syscall_socket_os_file = syscalls/socket_linux.go
|
syscall_socket_file = go/syscall/socket_linux.go
|
||||||
else
|
else
|
||||||
if LIBGO_IS_SOLARIS
|
if LIBGO_IS_SOLARIS
|
||||||
syscall_socket_os_file = syscalls/socket_solaris.go
|
syscall_socket_file = go/syscall/socket_solaris.go
|
||||||
else
|
else
|
||||||
if LIBGO_IS_IRIX
|
if LIBGO_IS_IRIX
|
||||||
syscall_socket_os_file = syscalls/socket_irix.go
|
syscall_socket_file = go/syscall/socket_irix.go
|
||||||
else
|
else
|
||||||
syscall_socket_os_file = syscalls/socket_bsd.go
|
syscall_socket_file = go/syscall/socket_bsd.go
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Support for epoll.
|
|
||||||
if LIBGO_IS_LINUX
|
|
||||||
syscall_socket_epoll_file = syscalls/socket_epoll.go
|
|
||||||
else
|
|
||||||
syscall_socket_epoll_file =
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Support for uname.
|
# Support for uname.
|
||||||
if LIBGO_IS_SOLARIS
|
if LIBGO_IS_SOLARIS
|
||||||
if LIBGO_IS_386
|
if LIBGO_IS_386
|
||||||
# 32-bit Solaris 2/x86 needs _nuname, handled in syscall_solaris_386.go.
|
# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go.
|
||||||
syscall_uname_file =
|
syscall_uname_file =
|
||||||
else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS
|
else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS
|
||||||
syscall_uname_file = syscalls/syscall_uname.go
|
syscall_uname_file = go/syscall/libcall_uname.go
|
||||||
endif
|
endif
|
||||||
else # !LIBGO_IS_SOLARIS
|
else # !LIBGO_IS_SOLARIS
|
||||||
syscall_uname_file = syscalls/syscall_uname.go
|
syscall_uname_file = go/syscall/libcall_uname.go
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Support for netlink sockets and messages.
|
# Support for netlink sockets and messages.
|
||||||
if LIBGO_IS_LINUX
|
if LIBGO_IS_LINUX
|
||||||
syscall_netlink_file = syscalls/netlink_linux.go
|
syscall_netlink_file = go/syscall/netlink_linux.go
|
||||||
else
|
else
|
||||||
syscall_netlink_file =
|
syscall_netlink_file =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
go_base_syscall_files = \
|
||||||
|
go/syscall/libcall_support.go \
|
||||||
|
go/syscall/libcall_posix.go \
|
||||||
|
go/syscall/socket.go \
|
||||||
|
go/syscall/str.go \
|
||||||
|
go/syscall/syscall.go \
|
||||||
|
$(syscall_syscall_file) \
|
||||||
|
$(syscall_exec_file) \
|
||||||
|
$(syscall_wait_file) \
|
||||||
|
$(syscall_sleep_file) \
|
||||||
|
$(syscall_errstr_file) \
|
||||||
|
$(syscall_size_file) \
|
||||||
|
$(syscall_socket_file) \
|
||||||
|
$(syscall_uname_file) \
|
||||||
|
$(syscall_netlink_file) \
|
||||||
|
$(GO_LIBCALL_OS_FILE) \
|
||||||
|
$(GO_LIBCALL_OS_ARCH_FILE) \
|
||||||
|
$(GO_SYSCALL_OS_FILE) \
|
||||||
|
$(GO_SYSCALL_OS_ARCH_FILE)
|
||||||
|
|
||||||
|
go_syscall_files = \
|
||||||
|
$(go_base_syscall_files) \
|
||||||
|
libcalls.go \
|
||||||
|
sysinfo.go \
|
||||||
|
syscall_arch.go
|
||||||
|
go_syscall_c_files = \
|
||||||
|
go/syscall/errno.c \
|
||||||
|
go/syscall/wait.c
|
||||||
|
|
||||||
|
libcalls.go: s-libcalls; @true
|
||||||
|
s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files)
|
||||||
|
rm -f libcalls.go.tmp
|
||||||
|
files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \
|
||||||
|
$(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp
|
||||||
|
$(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go
|
||||||
|
$(STAMP) $@
|
||||||
|
|
||||||
syscall_arch.go: s-syscall_arch; @true
|
syscall_arch.go: s-syscall_arch; @true
|
||||||
s-syscall_arch: Makefile
|
s-syscall_arch: Makefile
|
||||||
rm -f syscall_arch.go.tmp
|
rm -f syscall_arch.go.tmp
|
||||||
@ -1523,30 +1537,11 @@ s-syscall_arch: Makefile
|
|||||||
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
|
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
|
||||||
$(STAMP) $@
|
$(STAMP) $@
|
||||||
|
|
||||||
go_syscall_files = \
|
sysinfo.go: s-sysinfo; @true
|
||||||
$(syscall_errstr_file) \
|
s-sysinfo: $(srcdir)/mksysinfo.sh config.h
|
||||||
$(syscall_errstr_decl_file) \
|
CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
|
||||||
syscalls/exec_helpers.go \
|
$(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
|
||||||
$(syscall_exec_os_file) \
|
$(STAMP) $@
|
||||||
$(syscall_wait_file) \
|
|
||||||
$(syscall_filesize_file) \
|
|
||||||
$(syscall_netlink_file) \
|
|
||||||
$(syscall_stat_file) \
|
|
||||||
$(syscall_sleep_file) \
|
|
||||||
syscalls/socket.go \
|
|
||||||
$(syscall_socket_os_file) \
|
|
||||||
$(syscall_socket_epoll_file) \
|
|
||||||
$(syscall_syscall_file) \
|
|
||||||
$(syscall_uname_file) \
|
|
||||||
syscalls/syscall_unix.go \
|
|
||||||
syscalls/stringbyte.go \
|
|
||||||
syscalls/syscall_$(GOOS).go \
|
|
||||||
$(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \
|
|
||||||
syscalls/sysfile_posix.go \
|
|
||||||
sysinfo.go \
|
|
||||||
syscall_arch.go
|
|
||||||
go_syscall_c_files = \
|
|
||||||
syscalls/errno.c
|
|
||||||
|
|
||||||
if LIBGO_IS_LINUX
|
if LIBGO_IS_LINUX
|
||||||
# os_lib_inotify_lo = os/inotify.lo
|
# os_lib_inotify_lo = os/inotify.lo
|
||||||
@ -1708,8 +1703,9 @@ libgo_go_objs = \
|
|||||||
runtime/pprof.lo \
|
runtime/pprof.lo \
|
||||||
sync/atomic.lo \
|
sync/atomic.lo \
|
||||||
sync/atomic_c.lo \
|
sync/atomic_c.lo \
|
||||||
syscalls/syscall.lo \
|
syscall/syscall.lo \
|
||||||
syscalls/errno.lo \
|
syscall/errno.lo \
|
||||||
|
syscall/wait.lo \
|
||||||
template/parse.lo \
|
template/parse.lo \
|
||||||
testing/testing.lo \
|
testing/testing.lo \
|
||||||
testing/iotest.lo \
|
testing/iotest.lo \
|
||||||
@ -2983,16 +2979,12 @@ testing/script/check: $(CHECK_DEPS)
|
|||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: testing/script/check
|
.PHONY: testing/script/check
|
||||||
|
|
||||||
sysinfo.go: s-sysinfo; @true
|
syscall/syscall.lo: $(go_syscall_files) sync.gox
|
||||||
s-sysinfo: $(srcdir)/mksysinfo.sh config.h
|
|
||||||
CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
|
|
||||||
$(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
|
|
||||||
$(STAMP) $@
|
|
||||||
|
|
||||||
syscalls/syscall.lo: $(go_syscall_files) sync.gox
|
|
||||||
$(BUILDPACKAGE)
|
$(BUILDPACKAGE)
|
||||||
syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo
|
syscall/errno.lo: go/syscall/errno.c
|
||||||
$(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c
|
$(LTCOMPILE) -c -o $@ $<
|
||||||
|
syscall/wait.lo: go/syscall/wait.c
|
||||||
|
$(LTCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
# How to build a .gox file from a .lo file.
|
# How to build a .gox file from a .lo file.
|
||||||
BUILDGOX = \
|
BUILDGOX = \
|
||||||
@ -3079,7 +3071,7 @@ sync.gox: sync/sync.lo
|
|||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
syslog.gox: syslog/syslog.lo
|
syslog.gox: syslog/syslog.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
syscall.gox: syscalls/syscall.lo
|
syscall.gox: syscall/syscall.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
tabwriter.gox: tabwriter/tabwriter.lo
|
tabwriter.gox: tabwriter/tabwriter.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
@ -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 \
|
mime/multipart.lo net/dict.lo net/textproto.lo old/template.lo \
|
||||||
$(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
|
$(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
|
||||||
rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
|
rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
|
||||||
sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
|
sync/atomic.lo sync/atomic_c.lo syscall/syscall.lo \
|
||||||
syscalls/errno.lo template/parse.lo testing/testing.lo \
|
syscall/errno.lo syscall/wait.lo template/parse.lo \
|
||||||
testing/iotest.lo testing/quick.lo testing/script.lo
|
testing/testing.lo testing/iotest.lo testing/quick.lo \
|
||||||
|
testing/script.lo
|
||||||
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||||
$(am__DEPENDENCIES_1)
|
$(am__DEPENDENCIES_1)
|
||||||
@ -375,7 +376,10 @@ GOARCH = @GOARCH@
|
|||||||
GOC = @GOC@
|
GOC = @GOC@
|
||||||
GOCFLAGS = $(CFLAGS)
|
GOCFLAGS = $(CFLAGS)
|
||||||
GOOS = @GOOS@
|
GOOS = @GOOS@
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@
|
GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
|
||||||
|
GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
|
||||||
|
GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
|
||||||
|
GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
|
||||||
GREP = @GREP@
|
GREP = @GREP@
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
@ -1781,97 +1785,85 @@ go_testing_quick_files = \
|
|||||||
go_testing_script_files = \
|
go_testing_script_files = \
|
||||||
go/testing/script/script.go
|
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.
|
# 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.
|
# 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.
|
# 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.
|
# 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.
|
# 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.
|
# Declare libc functions that vary for largefile systems.
|
||||||
# Always use lseek64 on GNU/Linux.
|
# Always use lseek64 on GNU/Linux.
|
||||||
@LIBGO_IS_LINUX_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
|
@LIBGO_IS_LINUX_TRUE@syscall_size_file = go/syscall/libcall_posix_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_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_bsd.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_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_irix.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_TRUE@syscall_socket_file = go/syscall/socket_solaris.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
|
|
||||||
|
|
||||||
# Define socket sizes and types.
|
# Define socket sizes and types.
|
||||||
@LIBGO_IS_LINUX_TRUE@syscall_socket_os_file = syscalls/socket_linux.go
|
@LIBGO_IS_LINUX_TRUE@syscall_socket_file = go/syscall/socket_linux.go
|
||||||
@LIBGO_IS_LINUX_FALSE@syscall_socket_epoll_file =
|
@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = go/syscall/libcall_uname.go
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Support for uname.
|
# 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_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 =
|
@LIBGO_IS_LINUX_FALSE@syscall_netlink_file =
|
||||||
|
|
||||||
# Support for netlink sockets and messages.
|
# Support for netlink sockets and messages.
|
||||||
@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = syscalls/netlink_linux.go
|
@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = go/syscall/netlink_linux.go
|
||||||
go_syscall_files = \
|
go_base_syscall_files = \
|
||||||
$(syscall_errstr_file) \
|
go/syscall/libcall_support.go \
|
||||||
$(syscall_errstr_decl_file) \
|
go/syscall/libcall_posix.go \
|
||||||
syscalls/exec_helpers.go \
|
go/syscall/socket.go \
|
||||||
$(syscall_exec_os_file) \
|
go/syscall/str.go \
|
||||||
$(syscall_wait_file) \
|
go/syscall/syscall.go \
|
||||||
$(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_syscall_file) \
|
||||||
|
$(syscall_exec_file) \
|
||||||
|
$(syscall_wait_file) \
|
||||||
|
$(syscall_sleep_file) \
|
||||||
|
$(syscall_errstr_file) \
|
||||||
|
$(syscall_size_file) \
|
||||||
|
$(syscall_socket_file) \
|
||||||
$(syscall_uname_file) \
|
$(syscall_uname_file) \
|
||||||
syscalls/syscall_unix.go \
|
$(syscall_netlink_file) \
|
||||||
syscalls/stringbyte.go \
|
$(GO_LIBCALL_OS_FILE) \
|
||||||
syscalls/syscall_$(GOOS).go \
|
$(GO_LIBCALL_OS_ARCH_FILE) \
|
||||||
$(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \
|
$(GO_SYSCALL_OS_FILE) \
|
||||||
syscalls/sysfile_posix.go \
|
$(GO_SYSCALL_OS_ARCH_FILE)
|
||||||
|
|
||||||
|
go_syscall_files = \
|
||||||
|
$(go_base_syscall_files) \
|
||||||
|
libcalls.go \
|
||||||
sysinfo.go \
|
sysinfo.go \
|
||||||
syscall_arch.go
|
syscall_arch.go
|
||||||
|
|
||||||
go_syscall_c_files = \
|
go_syscall_c_files = \
|
||||||
syscalls/errno.c
|
go/syscall/errno.c \
|
||||||
|
go/syscall/wait.c
|
||||||
|
|
||||||
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
|
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
|
||||||
|
|
||||||
@ -2030,8 +2022,9 @@ libgo_go_objs = \
|
|||||||
runtime/pprof.lo \
|
runtime/pprof.lo \
|
||||||
sync/atomic.lo \
|
sync/atomic.lo \
|
||||||
sync/atomic_c.lo \
|
sync/atomic_c.lo \
|
||||||
syscalls/syscall.lo \
|
syscall/syscall.lo \
|
||||||
syscalls/errno.lo \
|
syscall/errno.lo \
|
||||||
|
syscall/wait.lo \
|
||||||
template/parse.lo \
|
template/parse.lo \
|
||||||
testing/testing.lo \
|
testing/testing.lo \
|
||||||
testing/iotest.lo \
|
testing/iotest.lo \
|
||||||
@ -4377,6 +4370,14 @@ s-version: Makefile
|
|||||||
$(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go
|
$(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go
|
||||||
$(STAMP) $@
|
$(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
|
syscall_arch.go: s-syscall_arch; @true
|
||||||
s-syscall_arch: Makefile
|
s-syscall_arch: Makefile
|
||||||
rm -f syscall_arch.go.tmp
|
rm -f syscall_arch.go.tmp
|
||||||
@ -4386,6 +4387,12 @@ s-syscall_arch: Makefile
|
|||||||
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
|
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
|
||||||
$(STAMP) $@
|
$(STAMP) $@
|
||||||
|
|
||||||
|
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 \
|
asn1/asn1.lo: $(go_asn1_files) big.gox bytes.gox fmt.gox io.gox os.gox \
|
||||||
reflect.gox strconv.gox strings.gox time.gox
|
reflect.gox strconv.gox strings.gox time.gox
|
||||||
$(BUILDPACKAGE)
|
$(BUILDPACKAGE)
|
||||||
@ -5559,16 +5566,12 @@ testing/script/check: $(CHECK_DEPS)
|
|||||||
@$(CHECK)
|
@$(CHECK)
|
||||||
.PHONY: testing/script/check
|
.PHONY: testing/script/check
|
||||||
|
|
||||||
sysinfo.go: s-sysinfo; @true
|
syscall/syscall.lo: $(go_syscall_files) sync.gox
|
||||||
s-sysinfo: $(srcdir)/mksysinfo.sh config.h
|
|
||||||
CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
|
|
||||||
$(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
|
|
||||||
$(STAMP) $@
|
|
||||||
|
|
||||||
syscalls/syscall.lo: $(go_syscall_files) sync.gox
|
|
||||||
$(BUILDPACKAGE)
|
$(BUILDPACKAGE)
|
||||||
syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo
|
syscall/errno.lo: go/syscall/errno.c
|
||||||
$(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c
|
$(LTCOMPILE) -c -o $@ $<
|
||||||
|
syscall/wait.lo: go/syscall/wait.c
|
||||||
|
$(LTCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
asn1.gox: asn1/asn1.lo
|
asn1.gox: asn1/asn1.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
@ -5650,7 +5653,7 @@ sync.gox: sync/sync.lo
|
|||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
syslog.gox: syslog/syslog.lo
|
syslog.gox: syslog/syslog.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
syscall.gox: syscalls/syscall.lo
|
syscall.gox: syscall/syscall.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
tabwriter.gox: tabwriter/tabwriter.lo
|
tabwriter.gox: tabwriter/tabwriter.lo
|
||||||
$(BUILDGOX)
|
$(BUILDGOX)
|
||||||
|
73
libgo/configure
vendored
73
libgo/configure
vendored
@ -617,7 +617,10 @@ USING_SPLIT_STACK_FALSE
|
|||||||
USING_SPLIT_STACK_TRUE
|
USING_SPLIT_STACK_TRUE
|
||||||
SPLIT_STACK
|
SPLIT_STACK
|
||||||
OSCFLAGS
|
OSCFLAGS
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE
|
GO_SYSCALL_OS_ARCH_FILE
|
||||||
|
GO_SYSCALL_OS_FILE
|
||||||
|
GO_LIBCALL_OS_ARCH_FILE
|
||||||
|
GO_LIBCALL_OS_FILE
|
||||||
GOARCH
|
GOARCH
|
||||||
LIBGO_IS_X86_64_FALSE
|
LIBGO_IS_X86_64_FALSE
|
||||||
LIBGO_IS_X86_64_TRUE
|
LIBGO_IS_X86_64_TRUE
|
||||||
@ -10913,7 +10916,7 @@ else
|
|||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<_LT_EOF
|
cat > conftest.$ac_ext <<_LT_EOF
|
||||||
#line 10916 "configure"
|
#line 10919 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
@ -11019,7 +11022,7 @@ else
|
|||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<_LT_EOF
|
cat > conftest.$ac_ext <<_LT_EOF
|
||||||
#line 11022 "configure"
|
#line 11025 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
@ -13151,6 +13154,49 @@ CC="$lt_save_CC"
|
|||||||
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
|
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
|
||||||
|
|
||||||
|
|
||||||
|
for ac_prog in gawk mawk nawk awk
|
||||||
|
do
|
||||||
|
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||||
|
set dummy $ac_prog; ac_word=$2
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||||
|
$as_echo_n "checking for $ac_word... " >&6; }
|
||||||
|
if test "${ac_cv_prog_AWK+set}" = set; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
if test -n "$AWK"; then
|
||||||
|
ac_cv_prog_AWK="$AWK" # Let the user override the test.
|
||||||
|
else
|
||||||
|
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||||
|
for as_dir in $PATH
|
||||||
|
do
|
||||||
|
IFS=$as_save_IFS
|
||||||
|
test -z "$as_dir" && as_dir=.
|
||||||
|
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||||
|
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||||
|
ac_cv_prog_AWK="$ac_prog"
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
IFS=$as_save_IFS
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AWK=$ac_cv_prog_AWK
|
||||||
|
if test -n "$AWK"; then
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
|
||||||
|
$as_echo "$AWK" >&6; }
|
||||||
|
else
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||||
|
$as_echo "no" >&6; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
test -n "$AWK" && break
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
|
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
|
||||||
|
|
||||||
|
|
||||||
@ -13551,10 +13597,25 @@ fi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=
|
GO_LIBCALL_OS_FILE=
|
||||||
if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then
|
GO_LIBCALL_OS_ARCH_FILE=
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go
|
GO_SYSCALL_OS_FILE=
|
||||||
|
GO_SYSCALL_OS_ARCH_FILE=
|
||||||
|
if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then
|
||||||
|
GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go
|
||||||
fi
|
fi
|
||||||
|
if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then
|
||||||
|
GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go
|
||||||
|
fi
|
||||||
|
if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then
|
||||||
|
GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go
|
||||||
|
fi
|
||||||
|
if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then
|
||||||
|
GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "$target" in
|
case "$target" in
|
||||||
|
@ -45,6 +45,8 @@ AC_SUBST(enable_static)
|
|||||||
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
|
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
|
||||||
AC_SUBST(CC_FOR_BUILD)
|
AC_SUBST(CC_FOR_BUILD)
|
||||||
|
|
||||||
|
AC_PROG_AWK
|
||||||
|
|
||||||
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
|
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
|
||||||
AC_SUBST(WARN_FLAGS)
|
AC_SUBST(WARN_FLAGS)
|
||||||
|
|
||||||
@ -249,11 +251,26 @@ AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes)
|
|||||||
AC_SUBST(GOARCH)
|
AC_SUBST(GOARCH)
|
||||||
|
|
||||||
dnl Some files are only present when needed for specific architectures.
|
dnl Some files are only present when needed for specific architectures.
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=
|
GO_LIBCALL_OS_FILE=
|
||||||
if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then
|
GO_LIBCALL_OS_ARCH_FILE=
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go
|
GO_SYSCALL_OS_FILE=
|
||||||
|
GO_SYSCALL_OS_ARCH_FILE=
|
||||||
|
if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then
|
||||||
|
GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go
|
||||||
fi
|
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.
|
dnl Some targets need special flags to build sysinfo.go.
|
||||||
case "$target" in
|
case "$target" in
|
||||||
|
@ -24,6 +24,17 @@ func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **
|
|||||||
func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo")
|
func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo")
|
||||||
func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror")
|
func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror")
|
||||||
|
|
||||||
|
// bytePtrToString takes a NUL-terminated array of bytes and convert
|
||||||
|
// it to a Go string.
|
||||||
|
func bytePtrToString(p *byte) string {
|
||||||
|
a := (*[10000]byte)(unsafe.Pointer(p))
|
||||||
|
i := 0
|
||||||
|
for a[i] != 0 {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return string(a[:i])
|
||||||
|
}
|
||||||
|
|
||||||
func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
|
func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
|
||||||
ip, err, completed := cgoLookupIP(name)
|
ip, err, completed := cgoLookupIP(name)
|
||||||
for _, p := range ip {
|
for _, p := range ip {
|
||||||
@ -99,13 +110,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
|
|||||||
} else if gerrno == syscall.EAI_SYSTEM {
|
} else if gerrno == syscall.EAI_SYSTEM {
|
||||||
str = syscall.Errstr(syscall.GetErrno())
|
str = syscall.Errstr(syscall.GetErrno())
|
||||||
} else {
|
} else {
|
||||||
str = syscall.BytePtrToString(libc_gai_strerror(gerrno))
|
str = bytePtrToString(libc_gai_strerror(gerrno))
|
||||||
}
|
}
|
||||||
return nil, "", &DNSError{Error: str, Name: name}, true
|
return nil, "", &DNSError{Error: str, Name: name}, true
|
||||||
}
|
}
|
||||||
defer libc_freeaddrinfo(res)
|
defer libc_freeaddrinfo(res)
|
||||||
if res != nil {
|
if res != nil {
|
||||||
cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
|
cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
|
||||||
if cname == "" {
|
if cname == "" {
|
||||||
cname = name
|
cname = name
|
||||||
}
|
}
|
||||||
|
@ -12,20 +12,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type pollster struct {
|
type pollster struct {
|
||||||
readFds, writeFds, repeatFds *syscall.FdSet_t
|
readFds, writeFds, repeatFds *syscall.FdSet
|
||||||
maxFd int
|
maxFd int
|
||||||
readyReadFds, readyWriteFds *syscall.FdSet_t
|
readyReadFds, readyWriteFds *syscall.FdSet
|
||||||
nReady int
|
nReady int
|
||||||
lastFd int
|
lastFd int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newpollster() (p *pollster, err os.Error) {
|
func newpollster() (p *pollster, err os.Error) {
|
||||||
p = new(pollster)
|
p = new(pollster)
|
||||||
p.readFds = new(syscall.FdSet_t)
|
p.readFds = new(syscall.FdSet)
|
||||||
p.writeFds = new(syscall.FdSet_t)
|
p.writeFds = new(syscall.FdSet)
|
||||||
p.repeatFds = new(syscall.FdSet_t)
|
p.repeatFds = new(syscall.FdSet)
|
||||||
p.readyReadFds = new(syscall.FdSet_t)
|
p.readyReadFds = new(syscall.FdSet)
|
||||||
p.readyWriteFds = new(syscall.FdSet_t)
|
p.readyWriteFds = new(syscall.FdSet)
|
||||||
p.maxFd = -1
|
p.maxFd = -1
|
||||||
p.nReady = 0
|
p.nReady = 0
|
||||||
p.lastFd = 0
|
p.lastFd = 0
|
||||||
@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
|
|||||||
}
|
}
|
||||||
|
|
||||||
var n, e int
|
var n, e int
|
||||||
var tmpReadFds, tmpWriteFds syscall.FdSet_t
|
var tmpReadFds, tmpWriteFds syscall.FdSet
|
||||||
for {
|
for {
|
||||||
// Temporary syscall.FdSet_ts into which the values are copied
|
// Temporary syscall.FdSet's into which the values are copied
|
||||||
// because select mutates the values.
|
// because select mutates the values.
|
||||||
tmpReadFds = *p.readFds
|
tmpReadFds = *p.readFds
|
||||||
tmpWriteFds = *p.writeFds
|
tmpWriteFds = *p.writeFds
|
||||||
|
@ -27,6 +27,17 @@ static int mygetpwuid_r(int uid, struct passwd *pwd,
|
|||||||
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r")
|
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r")
|
||||||
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r")
|
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r")
|
||||||
|
|
||||||
|
// bytePtrToString takes a NUL-terminated array of bytes and convert
|
||||||
|
// it to a Go string.
|
||||||
|
func bytePtrToString(p *byte) string {
|
||||||
|
a := (*[10000]byte)(unsafe.Pointer(p))
|
||||||
|
i := 0
|
||||||
|
for a[i] != 0 {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return string(a[:i])
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
implemented = true
|
implemented = true
|
||||||
}
|
}
|
||||||
@ -78,9 +89,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
|
|||||||
u := &User{
|
u := &User{
|
||||||
Uid: int(pwd.Pw_uid),
|
Uid: int(pwd.Pw_uid),
|
||||||
Gid: int(pwd.Pw_gid),
|
Gid: int(pwd.Pw_gid),
|
||||||
Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
|
Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
|
||||||
Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
|
Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
|
||||||
HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
|
HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
|
||||||
}
|
}
|
||||||
// The pw_gecos field isn't quite standardized. Some docs
|
// The pw_gecos field isn't quite standardized. Some docs
|
||||||
// say: "It is expected to be a comma separated list of
|
// say: "It is expected to be a comma separated list of
|
||||||
|
169
libgo/go/syscall/bpf_bsd.go
Normal file
169
libgo/go/syscall/bpf_bsd.go
Normal 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
|
||||||
|
}
|
@ -9,8 +9,8 @@
|
|||||||
/* errno is typically a macro. These functions set
|
/* errno is typically a macro. These functions set
|
||||||
and get errno specific to the libc being used. */
|
and get errno specific to the libc being used. */
|
||||||
|
|
||||||
int GetErrno() asm ("libgo_syscalls.syscall.GetErrno");
|
int GetErrno() asm ("libgo_syscall.syscall.GetErrno");
|
||||||
void SetErrno(int) asm ("libgo_syscalls.syscall.SetErrno");
|
void SetErrno(int) asm ("libgo_syscall.syscall.SetErrno");
|
||||||
|
|
||||||
int
|
int
|
||||||
GetErrno()
|
GetErrno()
|
@ -6,18 +6,21 @@
|
|||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
func Errstr(errno int) string {
|
//sysnb strerror_r(errnum int, buf []byte) (errno int)
|
||||||
for len := Size_t(128); ; len *= 2 {
|
//strerror_r(errnum int, buf *byte, buflen Size_t) int
|
||||||
|
|
||||||
|
func Errstr(errnum int) string {
|
||||||
|
for len := 128; ; len *= 2 {
|
||||||
b := make([]byte, len)
|
b := make([]byte, len)
|
||||||
r := libc_strerror_r(errno, &b[0], len)
|
err := strerror_r(errnum, b)
|
||||||
if r >= 0 {
|
if err == 0 {
|
||||||
i := 0
|
i := 0
|
||||||
for b[i] != 0 {
|
for b[i] != 0 {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return string(b[:i])
|
return string(b[:i])
|
||||||
}
|
}
|
||||||
if GetErrno() != ERANGE {
|
if err != ERANGE {
|
||||||
return "Errstr failure"
|
return "Errstr failure"
|
||||||
}
|
}
|
||||||
}
|
}
|
23
libgo/go/syscall/errstr_linux.go
Normal file
23
libgo/go/syscall/errstr_linux.go
Normal 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])
|
||||||
|
}
|
@ -11,7 +11,8 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
func libc_strerror(int) *byte __asm__ ("strerror")
|
//sysnb strerror(errnum int) *byte
|
||||||
|
//strerror(errnum int) *byte
|
||||||
|
|
||||||
var errstr_lock sync.Mutex
|
var errstr_lock sync.Mutex
|
||||||
|
|
@ -1,5 +1,3 @@
|
|||||||
// exec_stubs.go -- fork/exec stubs.
|
|
||||||
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
@ -12,10 +10,6 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int)
|
|||||||
return -1, ENOSYS;
|
return -1, ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
|
|
||||||
return -1, ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
func Exec(argv0 string, argv []string, envv []string) (err int) {
|
func Exec(argv0 string, argv []string, envv []string) (err int) {
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
}
|
}
|
@ -1,28 +1,129 @@
|
|||||||
// exec.go -- fork/exec syscall support.
|
|
||||||
|
|
||||||
// Copyright 2009 The Go Authors. All rights reserved.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build darwin freebsd linux openbsd
|
||||||
|
|
||||||
// Fork, exec, wait, etc.
|
// Fork, exec, wait, etc.
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
import "unsafe"
|
import (
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl")
|
//sysnb raw_fork() (pid Pid_t, errno int)
|
||||||
func libc_fork() Pid_t __asm__ ("fork")
|
//fork() Pid_t
|
||||||
func libc_setsid() Pid_t __asm__ ("setsid")
|
|
||||||
func libc_setpgid(Pid_t, Pid_t) int __asm__ ("setpgid")
|
//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
|
||||||
func libc_chroot(path *byte) int __asm__ ("chroot")
|
//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
|
||||||
func libc_setuid(Uid_t) int __asm__ ("setuid")
|
|
||||||
func libc_setgid(Gid_t) int __asm__ ("setgid")
|
//sysnb raw_setsid() (errno int)
|
||||||
func libc_setgroups(Size_t, *Gid_t) int __asm__ ("setgroups")
|
//setsid() Pid_t
|
||||||
func libc_chdir(name *byte) int __asm__ ("chdir")
|
|
||||||
func libc_dup2(int, int) int __asm__ ("dup2")
|
//sysnb raw_chroot(path *byte) (errno int)
|
||||||
func libc_ioctl(int, int) int __asm__ ("ioctl")
|
//chroot(path *byte) int
|
||||||
func libc_execve(*byte, **byte, **byte) int __asm__ ("execve")
|
|
||||||
func libc_sysexit(int) __asm__ ("_exit")
|
//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.
|
// 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.
|
// 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
|
// In the child, this function must not acquire any locks, because
|
||||||
// they might have been locked at the time of the fork. This means
|
// they might have been locked at the time of the fork. This means
|
||||||
// no rescheduling, no malloc calls, and no new stack segments.
|
// 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) {
|
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
|
// Declare all variables at top in case any
|
||||||
// declarations require heap allocation (e.g., err1).
|
// declarations require heap allocation (e.g., err1).
|
||||||
var r1, r2, err1 uintptr
|
var r1 Pid_t
|
||||||
|
var err1 int
|
||||||
var nextfd int
|
var nextfd int
|
||||||
var i int
|
var i int
|
||||||
|
|
||||||
// guard against side effects of shuffling fds below.
|
// guard against side effects of shuffling fds below.
|
||||||
fd := append([]int(nil), attr.Files...)
|
fd := append([]int(nil), attr.Files...)
|
||||||
|
|
||||||
darwin := OS == "darwin"
|
|
||||||
|
|
||||||
// About to call fork.
|
// About to call fork.
|
||||||
// No more allocation or calls of non-assembly functions.
|
// No more allocation or calls of non-assembly functions.
|
||||||
child := libc_fork()
|
r1, err1 = raw_fork()
|
||||||
if child == -1 {
|
if err1 != 0 {
|
||||||
return 0, GetErrno()
|
return 0, int(err1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if child != 0 {
|
if r1 != 0 {
|
||||||
// parent; return PID
|
// parent; return PID
|
||||||
return int(child), 0
|
return int(r1), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fork succeeded, now in child.
|
// Fork succeeded, now in child.
|
||||||
|
|
||||||
// Enable tracing if requested.
|
// Enable tracing if requested.
|
||||||
if sys.Ptrace {
|
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
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session ID
|
// Session ID
|
||||||
if sys.Setsid {
|
if sys.Setsid {
|
||||||
if libc_setsid() == Pid_t(-1) {
|
err1 = raw_setsid()
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set process group
|
// Set process group
|
||||||
if sys.Setpgid {
|
if sys.Setpgid {
|
||||||
if libc_setpgid(0, 0) < 0 {
|
err1 = Setpgid(0, 0)
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chroot
|
// Chroot
|
||||||
if chroot != nil {
|
if chroot != nil {
|
||||||
if libc_chroot(chroot) < 0 {
|
err1 = raw_chroot(chroot)
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// User and groups
|
// User and groups
|
||||||
if cred := sys.Credential; cred != nil {
|
if cred := sys.Credential; cred != nil {
|
||||||
ngroups := uintptr(len(cred.Groups))
|
ngroups := len(cred.Groups)
|
||||||
var groups *Gid_t
|
if ngroups == 0 {
|
||||||
if ngroups > 0 {
|
err1 = setgroups(0, nil)
|
||||||
groups = (*Gid_t)(unsafe.Pointer(&cred.Groups[0]))
|
} 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
|
goto childerror
|
||||||
}
|
}
|
||||||
if libc_setgid(Gid_t(cred.Gid)) < 0 {
|
err1 = Setgid(int(cred.Gid))
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
if libc_setuid(Uid_t(cred.Uid)) < 0 {
|
err1 = Setuid(int(cred.Uid))
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chdir
|
// Chdir
|
||||||
if dir != nil {
|
if dir != nil {
|
||||||
if libc_chdir(dir) < 0 {
|
err1 = raw_chdir(dir)
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
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.
|
// so that pass 2 won't stomp on an fd it needs later.
|
||||||
nextfd = int(len(fd))
|
nextfd = int(len(fd))
|
||||||
if pipe < nextfd {
|
if pipe < nextfd {
|
||||||
r := libc_dup2(pipe, nextfd)
|
_, err1 = Dup2(pipe, nextfd)
|
||||||
if r == -1 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
|
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
|
||||||
pipe = nextfd
|
pipe = nextfd
|
||||||
nextfd++
|
nextfd++
|
||||||
}
|
}
|
||||||
for i = 0; i < len(fd); i++ {
|
for i = 0; i < len(fd); i++ {
|
||||||
if fd[i] >= 0 && fd[i] < int(i) {
|
if fd[i] >= 0 && fd[i] < int(i) {
|
||||||
r := libc_dup2(fd[i], nextfd)
|
_, err1 = Dup2(fd[i], nextfd)
|
||||||
if r == -1 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
|
raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
|
||||||
fd[i] = nextfd
|
fd[i] = nextfd
|
||||||
nextfd++
|
nextfd++
|
||||||
if nextfd == pipe { // don't stomp on pipe
|
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.
|
// Pass 2: dup fd[i] down onto i.
|
||||||
for i = 0; i < len(fd); i++ {
|
for i = 0; i < len(fd); i++ {
|
||||||
if fd[i] == -1 {
|
if fd[i] == -1 {
|
||||||
libc_close(i)
|
raw_close(i)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if fd[i] == int(i) {
|
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.
|
// probably not elsewhere either.
|
||||||
r := libc_fcntl(fd[i], F_SETFD, 0)
|
_, err1 = raw_fcntl(fd[i], F_SETFD, 0)
|
||||||
if r != 0 {
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// The new fd is created NOT close-on-exec,
|
// The new fd is created NOT close-on-exec,
|
||||||
// which is exactly what we want.
|
// which is exactly what we want.
|
||||||
r := libc_dup2(fd[i], i)
|
_, err1 = Dup2(fd[i], i)
|
||||||
if r == -1 {
|
if err1 != 0 {
|
||||||
goto childerror
|
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
|
// Programs that know they inherit fds >= 3 will need
|
||||||
// to set them close-on-exec.
|
// to set them close-on-exec.
|
||||||
for i = len(fd); i < 3; i++ {
|
for i = len(fd); i < 3; i++ {
|
||||||
libc_close(i)
|
raw_close(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detach fd 0 from tty
|
// Detach fd 0 from tty
|
||||||
if sys.Noctty {
|
if sys.Noctty {
|
||||||
if libc_ioctl(0, TIOCNOTTY) < 0 {
|
_, err1 = raw_ioctl(0, TIOCNOTTY, 0)
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make fd 0 the tty
|
// Make fd 0 the tty
|
||||||
if sys.Setctty {
|
if sys.Setctty {
|
||||||
if libc_ioctl(0, TIOCSCTTY) < 0 {
|
_, err1 = raw_ioctl(0, TIOCSCTTY, 0)
|
||||||
|
if err1 != 0 {
|
||||||
goto childerror
|
goto childerror
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time to exec.
|
// Time to exec.
|
||||||
libc_execve(argv0, &argv[0], &envv[0])
|
err1 = raw_execve(argv0, &argv[0], &envv[0])
|
||||||
|
|
||||||
childerror:
|
childerror:
|
||||||
// send error code on pipe
|
// send error code on pipe
|
||||||
var e uintptr = uintptr(GetErrno())
|
raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
|
||||||
libc_write(pipe, (*byte)(unsafe.Pointer(&e)),
|
|
||||||
Size_t(unsafe.Sizeof(err1)))
|
|
||||||
for {
|
for {
|
||||||
libc_sysexit(253)
|
raw_exit(253)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calling panic is not actually safe,
|
// 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) {
|
func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
||||||
var p [2]int
|
var p [2]int
|
||||||
var n Ssize_t
|
var n int
|
||||||
var r1 int
|
|
||||||
var err1 uintptr
|
var err1 uintptr
|
||||||
var wstatus WaitStatus
|
var wstatus WaitStatus
|
||||||
|
|
||||||
@ -249,8 +362,8 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
|
|||||||
|
|
||||||
// Convert args to C form.
|
// Convert args to C form.
|
||||||
argv0p := StringBytePtr(argv0)
|
argv0p := StringBytePtr(argv0)
|
||||||
argvp := StringArrayPtr(argv)
|
argvp := StringSlicePtr(argv)
|
||||||
envvp := StringArrayPtr(attr.Env)
|
envvp := StringSlicePtr(attr.Env)
|
||||||
|
|
||||||
if OS == "freebsd" && len(argv[0]) > len(argv0) {
|
if OS == "freebsd" && len(argv[0]) > len(argv0) {
|
||||||
argvp[0] = argv0p
|
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.
|
// Read child error status from pipe.
|
||||||
Close(p[1])
|
Close(p[1])
|
||||||
n = libc_read(p[0], (*byte)(unsafe.Pointer(&err1)),
|
n, err = raw_read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
|
||||||
Size_t(unsafe.Sizeof(err1)))
|
|
||||||
err = 0
|
|
||||||
if n < 0 {
|
|
||||||
err = GetErrno()
|
|
||||||
}
|
|
||||||
Close(p[0])
|
Close(p[0])
|
||||||
if err != 0 || n != 0 {
|
if err != 0 || n != 0 {
|
||||||
if int(n) == unsafe.Sizeof(err1) {
|
if n == int(unsafe.Sizeof(err1)) {
|
||||||
err = int(err1)
|
err = int(err1)
|
||||||
}
|
}
|
||||||
if err == 0 {
|
if err == 0 {
|
||||||
@ -339,8 +447,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
|
|||||||
|
|
||||||
// Ordinary exec.
|
// Ordinary exec.
|
||||||
func Exec(argv0 string, argv []string, envv []string) (err int) {
|
func Exec(argv0 string, argv []string, envv []string) (err int) {
|
||||||
argv_arg := StringArrayPtr(argv)
|
err1 := raw_execve(StringBytePtr(argv0),
|
||||||
envv_arg := StringArrayPtr(envv)
|
&StringSlicePtr(argv)[0],
|
||||||
libc_execve(StringBytePtr(argv0), &argv_arg[0], &envv_arg[0])
|
&StringSlicePtr(envv)[0])
|
||||||
return GetErrno()
|
return int(err1)
|
||||||
}
|
}
|
327
libgo/go/syscall/exec_windows.go
Normal file
327
libgo/go/syscall/exec_windows.go
Normal 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
|
||||||
|
}
|
319
libgo/go/syscall/libcall_linux.go
Normal file
319
libgo/go/syscall/libcall_linux.go
Normal 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
|
385
libgo/go/syscall/libcall_posix.go
Normal file
385
libgo/go/syscall/libcall_posix.go
Normal 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
|
||||||
|
}
|
37
libgo/go/syscall/libcall_posix_largefile.go
Normal file
37
libgo/go/syscall/libcall_posix_largefile.go
Normal 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
|
38
libgo/go/syscall/libcall_posix_regfile.go
Normal file
38
libgo/go/syscall/libcall_posix_regfile.go
Normal 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
|
@ -1,7 +1,9 @@
|
|||||||
// syscall_solaris.go -- Solaris 2 specific syscall interface.
|
|
||||||
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
|
||||||
|
//sysnb Uname(buf *Utsname) (errno int)
|
||||||
|
//_nuname(buf *Utsname) int
|
@ -2,6 +2,11 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Declarations for functions which are actually written in C.
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
func libc_uname(buf *Utsname) (errno int) __asm__("uname")
|
func entersyscall()
|
||||||
|
func exitsyscall()
|
||||||
|
func GetErrno() int
|
||||||
|
func SetErrno(int)
|
@ -1,7 +1,8 @@
|
|||||||
// syscall_rtems.go -- RTEMS specific syscall interface.
|
|
||||||
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
//sysnb Uname(buf *Utsname) (errno int)
|
||||||
|
//uname(buf *Utsname) int
|
21
libgo/go/syscall/libcall_wait4.go
Normal file
21
libgo/go/syscall/libcall_wait4.go
Normal 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
|
||||||
|
}
|
@ -1,20 +1,19 @@
|
|||||||
// waitpid.go -- Wait4 for systems without wait4, but with waitpid.
|
// Copyright 2009 The Go Authors. All rights reserved.
|
||||||
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// For systems with the waitpid library call.
|
||||||
|
|
||||||
package syscall
|
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) {
|
func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
|
||||||
var status int
|
var status int
|
||||||
r := libc_waitpid(Pid_t(pid), &status, options)
|
r, err := waitpid(Pid_t(pid), &status, options)
|
||||||
wpid = int(r)
|
wpid = int(r)
|
||||||
if r < 0 {
|
errno = err
|
||||||
errno = GetErrno()
|
|
||||||
}
|
|
||||||
if wstatus != nil {
|
if wstatus != nil {
|
||||||
*wstatus = WaitStatus(status)
|
*wstatus = WaitStatus(status)
|
||||||
}
|
}
|
78
libgo/go/syscall/lsf_linux.go
Normal file
78
libgo/go/syscall/lsf_linux.go
Normal 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))
|
||||||
|
}
|
233
libgo/go/syscall/mksyscall.awk
Normal file
233
libgo/go/syscall/mksyscall.awk
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -195,10 +195,12 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
switch msg.Header.Type {
|
switch msg.Header.Type {
|
||||||
case RTM_NEWLINK:
|
case RTM_NEWLINK, RTM_DELLINK:
|
||||||
buf = msg.Data[SizeofIfInfomsg:]
|
buf = msg.Data[SizeofIfInfomsg:]
|
||||||
case RTM_NEWADDR:
|
case RTM_NEWADDR, RTM_DELADDR:
|
||||||
buf = msg.Data[SizeofIfAddrmsg:]
|
buf = msg.Data[SizeofIfAddrmsg:]
|
||||||
|
case RTM_NEWROUTE, RTM_DELROUTE:
|
||||||
|
buf = msg.Data[SizeofRtMsg:]
|
||||||
default:
|
default:
|
||||||
return nil, EINVAL
|
return nil, EINVAL
|
||||||
}
|
}
|
197
libgo/go/syscall/route_bsd.go
Normal file
197
libgo/go/syscall/route_bsd.go
Normal 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
|
||||||
|
}
|
77
libgo/go/syscall/route_darwin.go
Normal file
77
libgo/go/syscall/route_darwin.go
Normal 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
|
||||||
|
}
|
77
libgo/go/syscall/route_freebsd.go
Normal file
77
libgo/go/syscall/route_freebsd.go
Normal 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
|
||||||
|
}
|
35
libgo/go/syscall/route_openbsd.go
Normal file
35
libgo/go/syscall/route_openbsd.go
Normal 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
|
||||||
|
}
|
@ -6,14 +6,8 @@
|
|||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
|
|
||||||
|
|
||||||
func Sleep(nsec int64) (errno int) {
|
func Sleep(nsec int64) (errno int) {
|
||||||
errno = 0
|
|
||||||
ts := NsecToTimespec(nsec)
|
ts := NsecToTimespec(nsec)
|
||||||
r := libc_nanosleep(&ts, nil)
|
errno = Nanosleep(&ts, nil)
|
||||||
if r < 0 {
|
|
||||||
errno = GetErrno()
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
@ -8,6 +8,6 @@ package syscall
|
|||||||
|
|
||||||
func Sleep(nsec int64) (errno int) {
|
func Sleep(nsec int64) (errno int) {
|
||||||
tv := NsecToTimeval(nsec);
|
tv := NsecToTimeval(nsec);
|
||||||
n, err := Select(0, nil, nil, nil, &tv);
|
_, err := Select(0, nil, nil, nil, &tv);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
38
libgo/go/syscall/sockcmsg_linux.go
Normal file
38
libgo/go/syscall/sockcmsg_linux.go
Normal 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
|
||||||
|
}
|
115
libgo/go/syscall/sockcmsg_unix.go
Normal file
115
libgo/go/syscall/sockcmsg_unix.go
Normal 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
423
libgo/go/syscall/socket.go
Normal 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)
|
||||||
|
}
|
@ -57,10 +57,10 @@ func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawSockaddrInet4 struct {
|
type RawSockaddrInet4 struct {
|
||||||
Family uint16;
|
Family uint16
|
||||||
Port uint16;
|
Port uint16
|
||||||
Addr [4]byte /* in_addr */;
|
Addr [4]byte /* in_addr */
|
||||||
Zero [8]uint8;
|
Zero [8]uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *RawSockaddrInet4) setLen() Socklen_t {
|
func (sa *RawSockaddrInet4) setLen() Socklen_t {
|
||||||
@ -68,11 +68,11 @@ func (sa *RawSockaddrInet4) setLen() Socklen_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawSockaddrInet6 struct {
|
type RawSockaddrInet6 struct {
|
||||||
Family uint16;
|
Family uint16
|
||||||
Port uint16;
|
Port uint16
|
||||||
Flowinfo uint32;
|
Flowinfo uint32
|
||||||
Addr [16]byte /* in6_addr */;
|
Addr [16]byte /* in6_addr */
|
||||||
Scope_id uint32;
|
Scope_id uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *RawSockaddrInet6) setLen() Socklen_t {
|
func (sa *RawSockaddrInet6) setLen() Socklen_t {
|
||||||
@ -80,8 +80,8 @@ func (sa *RawSockaddrInet6) setLen() Socklen_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawSockaddrUnix struct {
|
type RawSockaddrUnix struct {
|
||||||
Family uint16;
|
Family uint16
|
||||||
Path [108]int8;
|
Path [108]int8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sa *RawSockaddrUnix) setLen(int) {
|
func (sa *RawSockaddrUnix) setLen(int) {
|
||||||
@ -94,7 +94,7 @@ func (sa *RawSockaddrUnix) getLen() (int, int) {
|
|||||||
// (This is the standard convention.)
|
// (This is the standard convention.)
|
||||||
// Not friendly to overwrite in place,
|
// Not friendly to overwrite in place,
|
||||||
// but the callers below don't care.
|
// but the callers below don't care.
|
||||||
sa.Path[0] = '@';
|
sa.Path[0] = '@'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume path ends at NUL.
|
// Assume path ends at NUL.
|
||||||
@ -102,9 +102,9 @@ func (sa *RawSockaddrUnix) getLen() (int, int) {
|
|||||||
// abstract Unix domain sockets--they are supposed
|
// abstract Unix domain sockets--they are supposed
|
||||||
// to be uninterpreted fixed-size binary blobs--but
|
// to be uninterpreted fixed-size binary blobs--but
|
||||||
// everyone uses this convention.
|
// everyone uses this convention.
|
||||||
n := 0;
|
n := 0
|
||||||
for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
|
for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
|
||||||
n++;
|
n++
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, 0
|
return n, 0
|
||||||
@ -128,8 +128,8 @@ type RawSockaddrNetlink struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RawSockaddr struct {
|
type RawSockaddr struct {
|
||||||
Family uint16;
|
Family uint16
|
||||||
Data [14]int8;
|
Data [14]int8
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindToDevice binds the socket associated with fd to device.
|
// BindToDevice binds the socket associated with fd to device.
|
||||||
@ -161,5 +161,23 @@ func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
|
|||||||
}
|
}
|
||||||
return sa, 0
|
return sa, 0
|
||||||
}
|
}
|
||||||
return nil, EAFNOSUPPORT;
|
return nil, EAFNOSUPPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't take this type directly from the header file because it
|
||||||
|
// uses a union. FIXME.
|
||||||
|
|
||||||
|
type EpollEvent struct {
|
||||||
|
Events uint32
|
||||||
|
Fd int32
|
||||||
|
Pad int32
|
||||||
|
}
|
||||||
|
|
||||||
|
//sysnb EpollCreate(size int) (fd int, errno int)
|
||||||
|
//epoll_create(size int) int
|
||||||
|
|
||||||
|
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int)
|
||||||
|
//epoll_ctl(epfd int, op int, fd int, event *EpollEvent) int
|
||||||
|
|
||||||
|
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int)
|
||||||
|
//epoll_wait(epfd int, events *EpollEvent, maxevents int, timeout int) int
|
20
libgo/go/syscall/str.go
Normal file
20
libgo/go/syscall/str.go
Normal 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:])
|
||||||
|
}
|
35
libgo/go/syscall/syscall.go
Normal file
35
libgo/go/syscall/syscall.go
Normal 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))
|
27
libgo/go/syscall/syscall_stubs.go
Normal file
27
libgo/go/syscall/syscall_stubs.go
Normal 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)
|
||||||
|
}
|
159
libgo/go/syscall/syscall_unix.go
Normal file
159
libgo/go/syscall/syscall_unix.go
Normal 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
107
libgo/go/syscall/wait.c
Normal 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
|
||||||
|
}
|
@ -197,16 +197,13 @@ if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then
|
|||||||
echo "const EPOLLRDHUP = 0x2000" >> ${OUT}
|
echo "const EPOLLRDHUP = 0x2000" >> ${OUT}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ptrace constants. We don't expose all the PTRACE flags, just the
|
# Ptrace constants.
|
||||||
# PTRACE_O_xxx and PTRACE_EVENT_xxx ones.
|
grep '^const _PTRACE' gen-sysinfo.go |
|
||||||
grep '^const _PTRACE_O' gen-sysinfo.go |
|
sed -e 's/^\(const \)_\(PTRACE[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
|
||||||
sed -e 's/^\(const \)_\(PTRACE_O[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
|
# We need some ptrace options that are not defined in older versions
|
||||||
grep '^const _PTRACE_EVENT' gen-sysinfo.go |
|
# of glibc.
|
||||||
sed -e 's/^\(const \)_\(PTRACE_EVENT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
|
if ! grep '^const PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
|
||||||
# We need PTRACE_SETOPTIONS and PTRACE_GETEVENTMSG, but they are not
|
echo "const PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
|
||||||
# defined in older versions of glibc.
|
|
||||||
if ! grep '^const _PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
|
|
||||||
echo "const _PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
|
|
||||||
fi
|
fi
|
||||||
if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then
|
if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then
|
||||||
echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT}
|
echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT}
|
||||||
@ -254,7 +251,7 @@ if ! grep '^const PTRACE_EVENT_EXIT' ${OUT} > /dev/null 2>&1; then
|
|||||||
echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT}
|
echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT}
|
||||||
fi
|
fi
|
||||||
if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then
|
if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then
|
||||||
echo "const _PTRACE_TRACEME = 0" >> ${OUT}
|
echo "const PTRACE_TRACEME = 0" >> ${OUT}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The registers returned by PTRACE_GETREGS. This is probably
|
# The registers returned by PTRACE_GETREGS. This is probably
|
||||||
@ -474,6 +471,11 @@ grep '^type _ip_mreq ' gen-sysinfo.go | \
|
|||||||
-e 's/_in_addr/[4]byte/g' \
|
-e 's/_in_addr/[4]byte/g' \
|
||||||
>> ${OUT}
|
>> ${OUT}
|
||||||
|
|
||||||
|
# The size of the ip_mreq struct.
|
||||||
|
if grep 'type IPMreq ' ${OUT} > /dev/null 2>&1; then
|
||||||
|
echo 'var SizeofIPMreq = int(unsafe.Sizeof(IPMreq{}))' >> ${OUT}
|
||||||
|
fi
|
||||||
|
|
||||||
# Try to guess the type to use for fd_set.
|
# Try to guess the type to use for fd_set.
|
||||||
fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
|
fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
|
||||||
fds_bits_type="_C_long"
|
fds_bits_type="_C_long"
|
||||||
@ -531,6 +533,25 @@ if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# The rtmsg struct.
|
||||||
|
grep '^type _rtmsg ' gen-sysinfo.go | \
|
||||||
|
sed -e 's/_rtmsg/RtMsg/' \
|
||||||
|
-e 's/rtm_family/Family/' \
|
||||||
|
-e 's/rtm_dst_len/Dst_len/' \
|
||||||
|
-e 's/rtm_src_len/Src_len/' \
|
||||||
|
-e 's/rtm_tos/Tos/' \
|
||||||
|
-e 's/rtm_table/Table/' \
|
||||||
|
-e 's/rtm_protocol/Procotol/' \
|
||||||
|
-e 's/rtm_scope/Scope/' \
|
||||||
|
-e 's/rtm_type/Type/' \
|
||||||
|
-e 's/rtm_flags/Flags/' \
|
||||||
|
>> ${OUT}
|
||||||
|
|
||||||
|
# The size of the rtmsg struct.
|
||||||
|
if grep 'type RtMsg ' ${OUT} > /dev/null 2>&1; then
|
||||||
|
echo 'var SizeofRtMsg = int(unsafe.Sizeof(RtMsg{}))' >> ${OUT}
|
||||||
|
fi
|
||||||
|
|
||||||
# The rtgenmsg struct.
|
# The rtgenmsg struct.
|
||||||
grep '^type _rtgenmsg ' gen-sysinfo.go | \
|
grep '^type _rtgenmsg ' gen-sysinfo.go | \
|
||||||
sed -e 's/_rtgenmsg/RtGenmsg/' \
|
sed -e 's/_rtgenmsg/RtGenmsg/' \
|
||||||
|
@ -71,3 +71,21 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
|
|||||||
if(hz != 0)
|
if(hz != 0)
|
||||||
runtime_resetcpuprofiler(hz);
|
runtime_resetcpuprofiler(hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The entersyscall and exitsyscall functions aren't used for anything
|
||||||
|
yet. Eventually they will be used to switch to a new OS thread
|
||||||
|
when making a potentially-blocking library call. */
|
||||||
|
|
||||||
|
void runtime_entersyscall() __asm__("libgo_syscall.syscall.entersyscall");
|
||||||
|
|
||||||
|
void
|
||||||
|
runtime_entersyscall()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void runtime_exitsyscall() __asm__("libgo_syscall.syscall.exitsyscall");
|
||||||
|
|
||||||
|
void
|
||||||
|
runtime_exitsyscall()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
@ -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")
|
|
@ -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")
|
|
@ -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")
|
|
@ -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])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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])
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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))
|
|
@ -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
|
|
||||||
}
|
|
@ -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")
|
|
@ -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))
|
|
@ -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))
|
|
@ -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))
|
|
@ -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);
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
@ -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")
|
|
@ -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
|
|
||||||
}
|
|
@ -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")
|
|
@ -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");
|
|
@ -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");
|
|
@ -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
|
|
||||||
}
|
|
@ -86,7 +86,10 @@ GOARCH = @GOARCH@
|
|||||||
GOC = @GOC@
|
GOC = @GOC@
|
||||||
GOCFLAGS = @GOCFLAGS@
|
GOCFLAGS = @GOCFLAGS@
|
||||||
GOOS = @GOOS@
|
GOOS = @GOOS@
|
||||||
GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@
|
GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
|
||||||
|
GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
|
||||||
|
GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
|
||||||
|
GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
|
||||||
GREP = @GREP@
|
GREP = @GREP@
|
||||||
INSTALL = @INSTALL@
|
INSTALL = @INSTALL@
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
Loading…
x
Reference in New Issue
Block a user