diff --git a/libgo/Makefile.am b/libgo/Makefile.am index ff58d262c36..ce0fe837c4f 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -1392,128 +1392,142 @@ go_testing_script_files = \ # Define Syscall and Syscall6. if LIBGO_IS_RTEMS -syscall_syscall_file = syscalls/syscall_stubs.go +syscall_syscall_file = go/syscall/syscall_stubs.go else -syscall_syscall_file = syscalls/syscall.go +syscall_syscall_file = go/syscall/syscall_unix.go +endif + +# Define ForkExec and Exec. +if LIBGO_IS_RTEMS +syscall_exec_file = go/syscall/exec_stubs.go +else +syscall_exec_file = go/syscall/exec_unix.go +endif + +# Define Wait4. +if HAVE_WAIT4 +syscall_wait_file = go/syscall/libcall_wait4.go +else +syscall_wait_file = go/syscall/libcall_waitpid.go +endif + +# Define Sleep. +if LIBGO_IS_RTEMS +syscall_sleep_file = go/syscall/sleep_rtems.go +else +syscall_sleep_file = go/syscall/sleep_select.go +endif + +# Define Errstr. +if LIBGO_IS_LINUX +syscall_errstr_file = go/syscall/errstr_linux.go +else +if LIBGO_IS_RTEMS +syscall_errstr_file = go/syscall/errstr_linux.go +else +if HAVE_STRERROR_R +syscall_errstr_file = go/syscall/errstr.go +else +syscall_errstr_file = go/syscall/errstr_nor.go +endif +endif endif # Declare libc functions that vary for largefile systems. if LIBGO_IS_LINUX # Always use lseek64 on GNU/Linux. -syscall_filesize_file = syscalls/sysfile_largefile.go -syscall_stat_file = syscalls/sysfile_stat_largefile.go +syscall_size_file = go/syscall/libcall_posix_largefile.go else # !LIBGO_IS_LINUX if LIBGO_IS_SOLARIS if LIBGO_IS_386 # Use lseek64 on 32-bit Solaris/x86. -syscall_filesize_file = syscalls/sysfile_largefile.go -syscall_stat_file = syscalls/sysfile_stat_largefile.go +syscall_size_file = go/syscall/libcall_posix_largefile.go else # !LIBGO_IS_386 if LIBGO_IS_SPARC # Use lseek64 on 32-bit Solaris/SPARC. -syscall_filesize_file = syscalls/sysfile_largefile.go -syscall_stat_file = syscalls/sysfile_stat_largefile.go +syscall_size_file = go/syscall/libcall_posix_largefile.go else # !LIBGO_IS_386 && !LIBGO_IS_SPARC # Use lseek on 64-bit Solaris. -syscall_filesize_file = syscalls/sysfile_regfile.go -syscall_stat_file = syscalls/sysfile_stat_regfile.go +syscall_size_file = go/syscall/libcall_posix_regfile.go endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC endif # !LIBGO_IS_SOLARIS else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS # Use lseek by default. -syscall_filesize_file = syscalls/sysfile_regfile.go -syscall_stat_file = syscalls/sysfile_stat_regfile.go +syscall_size_file = go/syscall/libcall_posix_regfile.go endif # !LIBGO_IS_SOLARIS endif # !LIBGO_IS_LINUX - -# Define ForkExec, PtraceForkExec, and Exec. -if LIBGO_IS_RTEMS -syscall_exec_os_file = syscalls/exec_stubs.go -else -syscall_exec_os_file = syscalls/exec.go -endif - -# Define Wait4. -if HAVE_WAIT4 -syscall_wait_file = syscalls/wait4.go -else -syscall_wait_file = syscalls/waitpid.go -endif - -# Define Sleep. -if LIBGO_IS_RTEMS -syscall_sleep_file = syscalls/sleep_rtems.go -else -syscall_sleep_file = syscalls/sleep_select.go -endif - -# Define Errstr. -if LIBGO_IS_RTEMS -syscall_errstr_file = syscalls/errstr_rtems.go -else -if HAVE_STRERROR_R -syscall_errstr_file = syscalls/errstr.go -else -syscall_errstr_file = syscalls/errstr_nor.go -endif -endif - -# Declare libc_strerror_r which is the Go name for strerror_r. -if LIBGO_IS_RTEMS -# RTEMS uses newlib in which strerror_r returns char *. -syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go -else -if LIBGO_IS_LINUX -# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r. -syscall_errstr_decl_file = syscalls/errstr_decl_linux.go -else -# On other systems we hope strerror_r is just strerror_r. -syscall_errstr_decl_file = syscalls/errstr_decl.go -endif -endif - # Define socket sizes and types. if LIBGO_IS_LINUX -syscall_socket_os_file = syscalls/socket_linux.go +syscall_socket_file = go/syscall/socket_linux.go else if LIBGO_IS_SOLARIS -syscall_socket_os_file = syscalls/socket_solaris.go +syscall_socket_file = go/syscall/socket_solaris.go else if LIBGO_IS_IRIX -syscall_socket_os_file = syscalls/socket_irix.go +syscall_socket_file = go/syscall/socket_irix.go else -syscall_socket_os_file = syscalls/socket_bsd.go +syscall_socket_file = go/syscall/socket_bsd.go endif endif endif -# Support for epoll. -if LIBGO_IS_LINUX -syscall_socket_epoll_file = syscalls/socket_epoll.go -else -syscall_socket_epoll_file = -endif - # Support for uname. if LIBGO_IS_SOLARIS if LIBGO_IS_386 -# 32-bit Solaris 2/x86 needs _nuname, handled in syscall_solaris_386.go. +# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go. syscall_uname_file = else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS -syscall_uname_file = syscalls/syscall_uname.go +syscall_uname_file = go/syscall/libcall_uname.go endif else # !LIBGO_IS_SOLARIS -syscall_uname_file = syscalls/syscall_uname.go +syscall_uname_file = go/syscall/libcall_uname.go endif # Support for netlink sockets and messages. if LIBGO_IS_LINUX -syscall_netlink_file = syscalls/netlink_linux.go +syscall_netlink_file = go/syscall/netlink_linux.go else syscall_netlink_file = endif +go_base_syscall_files = \ + go/syscall/libcall_support.go \ + go/syscall/libcall_posix.go \ + go/syscall/socket.go \ + go/syscall/str.go \ + go/syscall/syscall.go \ + $(syscall_syscall_file) \ + $(syscall_exec_file) \ + $(syscall_wait_file) \ + $(syscall_sleep_file) \ + $(syscall_errstr_file) \ + $(syscall_size_file) \ + $(syscall_socket_file) \ + $(syscall_uname_file) \ + $(syscall_netlink_file) \ + $(GO_LIBCALL_OS_FILE) \ + $(GO_LIBCALL_OS_ARCH_FILE) \ + $(GO_SYSCALL_OS_FILE) \ + $(GO_SYSCALL_OS_ARCH_FILE) + +go_syscall_files = \ + $(go_base_syscall_files) \ + libcalls.go \ + sysinfo.go \ + syscall_arch.go +go_syscall_c_files = \ + go/syscall/errno.c \ + go/syscall/wait.c + +libcalls.go: s-libcalls; @true +s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files) + rm -f libcalls.go.tmp + files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ + $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp + $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go + $(STAMP) $@ + syscall_arch.go: s-syscall_arch; @true s-syscall_arch: Makefile rm -f syscall_arch.go.tmp @@ -1523,30 +1537,11 @@ s-syscall_arch: Makefile $(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go $(STAMP) $@ -go_syscall_files = \ - $(syscall_errstr_file) \ - $(syscall_errstr_decl_file) \ - syscalls/exec_helpers.go \ - $(syscall_exec_os_file) \ - $(syscall_wait_file) \ - $(syscall_filesize_file) \ - $(syscall_netlink_file) \ - $(syscall_stat_file) \ - $(syscall_sleep_file) \ - syscalls/socket.go \ - $(syscall_socket_os_file) \ - $(syscall_socket_epoll_file) \ - $(syscall_syscall_file) \ - $(syscall_uname_file) \ - syscalls/syscall_unix.go \ - syscalls/stringbyte.go \ - syscalls/syscall_$(GOOS).go \ - $(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \ - syscalls/sysfile_posix.go \ - sysinfo.go \ - syscall_arch.go -go_syscall_c_files = \ - syscalls/errno.c +sysinfo.go: s-sysinfo; @true +s-sysinfo: $(srcdir)/mksysinfo.sh config.h + CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh + $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go + $(STAMP) $@ if LIBGO_IS_LINUX # os_lib_inotify_lo = os/inotify.lo @@ -1708,8 +1703,9 @@ libgo_go_objs = \ runtime/pprof.lo \ sync/atomic.lo \ sync/atomic_c.lo \ - syscalls/syscall.lo \ - syscalls/errno.lo \ + syscall/syscall.lo \ + syscall/errno.lo \ + syscall/wait.lo \ template/parse.lo \ testing/testing.lo \ testing/iotest.lo \ @@ -2983,16 +2979,12 @@ testing/script/check: $(CHECK_DEPS) @$(CHECK) .PHONY: testing/script/check -sysinfo.go: s-sysinfo; @true -s-sysinfo: $(srcdir)/mksysinfo.sh config.h - CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh - $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go - $(STAMP) $@ - -syscalls/syscall.lo: $(go_syscall_files) sync.gox +syscall/syscall.lo: $(go_syscall_files) sync.gox $(BUILDPACKAGE) -syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo - $(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c +syscall/errno.lo: go/syscall/errno.c + $(LTCOMPILE) -c -o $@ $< +syscall/wait.lo: go/syscall/wait.c + $(LTCOMPILE) -c -o $@ $< # How to build a .gox file from a .lo file. BUILDGOX = \ @@ -3079,7 +3071,7 @@ sync.gox: sync/sync.lo $(BUILDGOX) syslog.gox: syslog/syslog.lo $(BUILDGOX) -syscall.gox: syscalls/syscall.lo +syscall.gox: syscall/syscall.lo $(BUILDGOX) tabwriter.gox: tabwriter/tabwriter.lo $(BUILDGOX) diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 1a8741d42b6..e18d242c56f 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -171,9 +171,10 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \ mime/multipart.lo net/dict.lo net/textproto.lo old/template.lo \ $(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \ rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \ - sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \ - syscalls/errno.lo template/parse.lo testing/testing.lo \ - testing/iotest.lo testing/quick.lo testing/script.lo + sync/atomic.lo sync/atomic_c.lo syscall/syscall.lo \ + syscall/errno.lo syscall/wait.lo template/parse.lo \ + testing/testing.lo testing/iotest.lo testing/quick.lo \ + testing/script.lo libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) @@ -375,7 +376,10 @@ GOARCH = @GOARCH@ GOC = @GOC@ GOCFLAGS = $(CFLAGS) GOOS = @GOOS@ -GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@ +GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@ +GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@ +GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@ +GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -1781,97 +1785,85 @@ go_testing_quick_files = \ go_testing_script_files = \ go/testing/script/script.go -@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = syscalls/syscall.go +@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = go/syscall/syscall_unix.go # Define Syscall and Syscall6. -@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = syscalls/syscall_stubs.go +@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = go/syscall/syscall_stubs.go +@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go + +# Define ForkExec and Exec. +@LIBGO_IS_RTEMS_TRUE@syscall_exec_file = go/syscall/exec_stubs.go +@HAVE_WAIT4_FALSE@syscall_wait_file = go/syscall/libcall_waitpid.go + +# Define Wait4. +@HAVE_WAIT4_TRUE@syscall_wait_file = go/syscall/libcall_wait4.go +@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = go/syscall/sleep_select.go + +# Define Sleep. +@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = go/syscall/sleep_rtems.go +@HAVE_STRERROR_R_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr_nor.go +@HAVE_STRERROR_R_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr.go +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go + +# Define Errstr. +@LIBGO_IS_LINUX_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go # Use lseek on 64-bit Solaris. -@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_filesize_file = syscalls/sysfile_regfile.go +@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go # Use lseek64 on 32-bit Solaris/SPARC. -@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go +@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go # Use lseek64 on 32-bit Solaris/x86. -@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go +@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go # Use lseek by default. -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_filesize_file = syscalls/sysfile_regfile.go +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go # Declare libc functions that vary for largefile systems. # Always use lseek64 on GNU/Linux. -@LIBGO_IS_LINUX_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go -@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_stat_file = syscalls/sysfile_stat_regfile.go -@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go -@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_stat_file = syscalls/sysfile_stat_regfile.go -@LIBGO_IS_LINUX_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go -@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = syscalls/exec.go - -# Define ForkExec, PtraceForkExec, and Exec. -@LIBGO_IS_RTEMS_TRUE@syscall_exec_os_file = syscalls/exec_stubs.go -@HAVE_WAIT4_FALSE@syscall_wait_file = syscalls/waitpid.go - -# Define Wait4. -@HAVE_WAIT4_TRUE@syscall_wait_file = syscalls/wait4.go -@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = syscalls/sleep_select.go - -# Define Sleep. -@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = syscalls/sleep_rtems.go -@HAVE_STRERROR_R_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = syscalls/errstr_nor.go -@HAVE_STRERROR_R_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = syscalls/errstr.go - -# Define Errstr. -@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = syscalls/errstr_rtems.go -# On other systems we hope strerror_r is just strerror_r. -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_decl_file = syscalls/errstr_decl.go -# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r. -@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_decl_file = syscalls/errstr_decl_linux.go - -# Declare libc_strerror_r which is the Go name for strerror_r. -# RTEMS uses newlib in which strerror_r returns char *. -@LIBGO_IS_RTEMS_TRUE@syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go -@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = syscalls/socket_bsd.go -@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = syscalls/socket_irix.go -@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_os_file = syscalls/socket_solaris.go +@LIBGO_IS_LINUX_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go +@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_bsd.go +@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_irix.go +@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_file = go/syscall/socket_solaris.go # Define socket sizes and types. -@LIBGO_IS_LINUX_TRUE@syscall_socket_os_file = syscalls/socket_linux.go -@LIBGO_IS_LINUX_FALSE@syscall_socket_epoll_file = - -# Support for epoll. -@LIBGO_IS_LINUX_TRUE@syscall_socket_epoll_file = syscalls/socket_epoll.go -@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = syscalls/syscall_uname.go +@LIBGO_IS_LINUX_TRUE@syscall_socket_file = go/syscall/socket_linux.go +@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = go/syscall/libcall_uname.go # Support for uname. -# 32-bit Solaris 2/x86 needs _nuname, handled in syscall_solaris_386.go. +# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go. @LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = -@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = syscalls/syscall_uname.go +@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = go/syscall/libcall_uname.go @LIBGO_IS_LINUX_FALSE@syscall_netlink_file = # Support for netlink sockets and messages. -@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = syscalls/netlink_linux.go -go_syscall_files = \ - $(syscall_errstr_file) \ - $(syscall_errstr_decl_file) \ - syscalls/exec_helpers.go \ - $(syscall_exec_os_file) \ - $(syscall_wait_file) \ - $(syscall_filesize_file) \ - $(syscall_netlink_file) \ - $(syscall_stat_file) \ - $(syscall_sleep_file) \ - syscalls/socket.go \ - $(syscall_socket_os_file) \ - $(syscall_socket_epoll_file) \ +@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = go/syscall/netlink_linux.go +go_base_syscall_files = \ + go/syscall/libcall_support.go \ + go/syscall/libcall_posix.go \ + go/syscall/socket.go \ + go/syscall/str.go \ + go/syscall/syscall.go \ $(syscall_syscall_file) \ + $(syscall_exec_file) \ + $(syscall_wait_file) \ + $(syscall_sleep_file) \ + $(syscall_errstr_file) \ + $(syscall_size_file) \ + $(syscall_socket_file) \ $(syscall_uname_file) \ - syscalls/syscall_unix.go \ - syscalls/stringbyte.go \ - syscalls/syscall_$(GOOS).go \ - $(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \ - syscalls/sysfile_posix.go \ + $(syscall_netlink_file) \ + $(GO_LIBCALL_OS_FILE) \ + $(GO_LIBCALL_OS_ARCH_FILE) \ + $(GO_SYSCALL_OS_FILE) \ + $(GO_SYSCALL_OS_ARCH_FILE) + +go_syscall_files = \ + $(go_base_syscall_files) \ + libcalls.go \ sysinfo.go \ syscall_arch.go go_syscall_c_files = \ - syscalls/errno.c + go/syscall/errno.c \ + go/syscall/wait.c @LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo = @@ -2030,8 +2022,9 @@ libgo_go_objs = \ runtime/pprof.lo \ sync/atomic.lo \ sync/atomic_c.lo \ - syscalls/syscall.lo \ - syscalls/errno.lo \ + syscall/syscall.lo \ + syscall/errno.lo \ + syscall/wait.lo \ template/parse.lo \ testing/testing.lo \ testing/iotest.lo \ @@ -4377,6 +4370,14 @@ s-version: Makefile $(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go $(STAMP) $@ +libcalls.go: s-libcalls; @true +s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files) + rm -f libcalls.go.tmp + files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \ + $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp + $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go + $(STAMP) $@ + syscall_arch.go: s-syscall_arch; @true s-syscall_arch: Makefile rm -f syscall_arch.go.tmp @@ -4386,6 +4387,12 @@ s-syscall_arch: Makefile $(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go $(STAMP) $@ +sysinfo.go: s-sysinfo; @true +s-sysinfo: $(srcdir)/mksysinfo.sh config.h + CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh + $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go + $(STAMP) $@ + asn1/asn1.lo: $(go_asn1_files) big.gox bytes.gox fmt.gox io.gox os.gox \ reflect.gox strconv.gox strings.gox time.gox $(BUILDPACKAGE) @@ -5559,16 +5566,12 @@ testing/script/check: $(CHECK_DEPS) @$(CHECK) .PHONY: testing/script/check -sysinfo.go: s-sysinfo; @true -s-sysinfo: $(srcdir)/mksysinfo.sh config.h - CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh - $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go - $(STAMP) $@ - -syscalls/syscall.lo: $(go_syscall_files) sync.gox +syscall/syscall.lo: $(go_syscall_files) sync.gox $(BUILDPACKAGE) -syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo - $(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c +syscall/errno.lo: go/syscall/errno.c + $(LTCOMPILE) -c -o $@ $< +syscall/wait.lo: go/syscall/wait.c + $(LTCOMPILE) -c -o $@ $< asn1.gox: asn1/asn1.lo $(BUILDGOX) @@ -5650,7 +5653,7 @@ sync.gox: sync/sync.lo $(BUILDGOX) syslog.gox: syslog/syslog.lo $(BUILDGOX) -syscall.gox: syscalls/syscall.lo +syscall.gox: syscall/syscall.lo $(BUILDGOX) tabwriter.gox: tabwriter/tabwriter.lo $(BUILDGOX) diff --git a/libgo/configure b/libgo/configure index e6b5d15ba59..b9e6a31f842 100755 --- a/libgo/configure +++ b/libgo/configure @@ -617,7 +617,10 @@ USING_SPLIT_STACK_FALSE USING_SPLIT_STACK_TRUE SPLIT_STACK OSCFLAGS -GO_SYSCALLS_SYSCALL_OS_ARCH_FILE +GO_SYSCALL_OS_ARCH_FILE +GO_SYSCALL_OS_FILE +GO_LIBCALL_OS_ARCH_FILE +GO_LIBCALL_OS_FILE GOARCH LIBGO_IS_X86_64_FALSE LIBGO_IS_X86_64_TRUE @@ -10913,7 +10916,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10916 "configure" +#line 10919 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11019,7 +11022,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11022 "configure" +#line 11025 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13151,6 +13154,49 @@ CC="$lt_save_CC" CC_FOR_BUILD=${CC_FOR_BUILD:-gcc} +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual' @@ -13551,10 +13597,25 @@ fi -GO_SYSCALLS_SYSCALL_OS_ARCH_FILE= -if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then - GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go +GO_LIBCALL_OS_FILE= +GO_LIBCALL_OS_ARCH_FILE= +GO_SYSCALL_OS_FILE= +GO_SYSCALL_OS_ARCH_FILE= +if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then + GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go fi +if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then + GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go +fi +if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then + GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go +fi +if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then + GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go +fi + + + case "$target" in diff --git a/libgo/configure.ac b/libgo/configure.ac index 6702c26c2f8..206e189bb94 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -45,6 +45,8 @@ AC_SUBST(enable_static) CC_FOR_BUILD=${CC_FOR_BUILD:-gcc} AC_SUBST(CC_FOR_BUILD) +AC_PROG_AWK + WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual' AC_SUBST(WARN_FLAGS) @@ -249,11 +251,26 @@ AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes) AC_SUBST(GOARCH) dnl Some files are only present when needed for specific architectures. -GO_SYSCALLS_SYSCALL_OS_ARCH_FILE= -if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then - GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go +GO_LIBCALL_OS_FILE= +GO_LIBCALL_OS_ARCH_FILE= +GO_SYSCALL_OS_FILE= +GO_SYSCALL_OS_ARCH_FILE= +if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then + GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go fi -AC_SUBST(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) +if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then + GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go +fi +if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then + GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go +fi +if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then + GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go +fi +AC_SUBST(GO_LIBCALL_OS_FILE) +AC_SUBST(GO_LIBCALL_OS_ARCH_FILE) +AC_SUBST(GO_SYSCALL_OS_FILE) +AC_SUBST(GO_SYSCALL_OS_ARCH_FILE) dnl Some targets need special flags to build sysinfo.go. case "$target" in diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go index b8090181293..d088eabc2b5 100644 --- a/libgo/go/net/cgo_unix.go +++ b/libgo/go/net/cgo_unix.go @@ -24,6 +24,17 @@ func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res ** func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo") func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror") +// bytePtrToString takes a NUL-terminated array of bytes and convert +// it to a Go string. +func bytePtrToString(p *byte) string { + a := (*[10000]byte)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) { ip, err, completed := cgoLookupIP(name) for _, p := range ip { @@ -99,13 +110,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp } else if gerrno == syscall.EAI_SYSTEM { str = syscall.Errstr(syscall.GetErrno()) } else { - str = syscall.BytePtrToString(libc_gai_strerror(gerrno)) + str = bytePtrToString(libc_gai_strerror(gerrno)) } return nil, "", &DNSError{Error: str, Name: name}, true } defer libc_freeaddrinfo(res) if res != nil { - cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname))) + cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname))) if cname == "" { cname = name } diff --git a/libgo/go/net/fd_select.go b/libgo/go/net/fd_select.go index e9c68ab2ccc..21fd8010fa6 100644 --- a/libgo/go/net/fd_select.go +++ b/libgo/go/net/fd_select.go @@ -12,20 +12,20 @@ import ( ) type pollster struct { - readFds, writeFds, repeatFds *syscall.FdSet_t + readFds, writeFds, repeatFds *syscall.FdSet maxFd int - readyReadFds, readyWriteFds *syscall.FdSet_t + readyReadFds, readyWriteFds *syscall.FdSet nReady int lastFd int } func newpollster() (p *pollster, err os.Error) { p = new(pollster) - p.readFds = new(syscall.FdSet_t) - p.writeFds = new(syscall.FdSet_t) - p.repeatFds = new(syscall.FdSet_t) - p.readyReadFds = new(syscall.FdSet_t) - p.readyWriteFds = new(syscall.FdSet_t) + p.readFds = new(syscall.FdSet) + p.writeFds = new(syscall.FdSet) + p.repeatFds = new(syscall.FdSet) + p.readyReadFds = new(syscall.FdSet) + p.readyWriteFds = new(syscall.FdSet) p.maxFd = -1 p.nReady = 0 p.lastFd = 0 @@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E } var n, e int - var tmpReadFds, tmpWriteFds syscall.FdSet_t + var tmpReadFds, tmpWriteFds syscall.FdSet for { - // Temporary syscall.FdSet_ts into which the values are copied + // Temporary syscall.FdSet's into which the values are copied // because select mutates the values. tmpReadFds = *p.readFds tmpWriteFds = *p.writeFds diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go index 0f04012c02f..18a9687c264 100644 --- a/libgo/go/os/user/lookup_unix.go +++ b/libgo/go/os/user/lookup_unix.go @@ -27,6 +27,17 @@ static int mygetpwuid_r(int uid, struct passwd *pwd, func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r") func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r") +// bytePtrToString takes a NUL-terminated array of bytes and convert +// it to a Go string. +func bytePtrToString(p *byte) string { + a := (*[10000]byte)(unsafe.Pointer(p)) + i := 0 + for a[i] != 0 { + i++ + } + return string(a[:i]) +} + func init() { implemented = true } @@ -78,9 +89,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) { u := &User{ Uid: int(pwd.Pw_uid), Gid: int(pwd.Pw_gid), - Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))), - Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))), - HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))), + Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))), + Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))), + HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))), } // The pw_gecos field isn't quite standardized. Some docs // say: "It is expected to be a comma separated list of diff --git a/libgo/go/syscall/bpf_bsd.go b/libgo/go/syscall/bpf_bsd.go new file mode 100644 index 00000000000..06a2953e7fe --- /dev/null +++ b/libgo/go/syscall/bpf_bsd.go @@ -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 +} diff --git a/libgo/syscalls/errno.c b/libgo/go/syscall/errno.c similarity index 78% rename from libgo/syscalls/errno.c rename to libgo/go/syscall/errno.c index 34771a0d831..854b5aaec28 100644 --- a/libgo/syscalls/errno.c +++ b/libgo/go/syscall/errno.c @@ -9,8 +9,8 @@ /* errno is typically a macro. These functions set and get errno specific to the libc being used. */ -int GetErrno() asm ("libgo_syscalls.syscall.GetErrno"); -void SetErrno(int) asm ("libgo_syscalls.syscall.SetErrno"); +int GetErrno() asm ("libgo_syscall.syscall.GetErrno"); +void SetErrno(int) asm ("libgo_syscall.syscall.SetErrno"); int GetErrno() diff --git a/libgo/syscalls/errstr.go b/libgo/go/syscall/errstr.go similarity index 58% rename from libgo/syscalls/errstr.go rename to libgo/go/syscall/errstr.go index a95abc686f3..d9f3fe82eb4 100644 --- a/libgo/syscalls/errstr.go +++ b/libgo/go/syscall/errstr.go @@ -6,18 +6,21 @@ package syscall -func Errstr(errno int) string { - for len := Size_t(128); ; len *= 2 { +//sysnb strerror_r(errnum int, buf []byte) (errno int) +//strerror_r(errnum int, buf *byte, buflen Size_t) int + +func Errstr(errnum int) string { + for len := 128; ; len *= 2 { b := make([]byte, len) - r := libc_strerror_r(errno, &b[0], len) - if r >= 0 { + err := strerror_r(errnum, b) + if err == 0 { i := 0 for b[i] != 0 { i++ } return string(b[:i]) } - if GetErrno() != ERANGE { + if err != ERANGE { return "Errstr failure" } } diff --git a/libgo/go/syscall/errstr_linux.go b/libgo/go/syscall/errstr_linux.go new file mode 100644 index 00000000000..00fca80fc14 --- /dev/null +++ b/libgo/go/syscall/errstr_linux.go @@ -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]) +} diff --git a/libgo/syscalls/errstr_nor.go b/libgo/go/syscall/errstr_nor.go similarity index 88% rename from libgo/syscalls/errstr_nor.go rename to libgo/go/syscall/errstr_nor.go index 358b3ee9cf6..b331d0eb965 100644 --- a/libgo/syscalls/errstr_nor.go +++ b/libgo/go/syscall/errstr_nor.go @@ -11,7 +11,8 @@ import ( "unsafe" ) -func libc_strerror(int) *byte __asm__ ("strerror") +//sysnb strerror(errnum int) *byte +//strerror(errnum int) *byte var errstr_lock sync.Mutex diff --git a/libgo/syscalls/exec_stubs.go b/libgo/go/syscall/exec_stubs.go similarity index 76% rename from libgo/syscalls/exec_stubs.go rename to libgo/go/syscall/exec_stubs.go index 7b4346cc4c5..ce5dabe1e3b 100644 --- a/libgo/syscalls/exec_stubs.go +++ b/libgo/go/syscall/exec_stubs.go @@ -1,5 +1,3 @@ -// exec_stubs.go -- fork/exec stubs. - // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -12,10 +10,6 @@ func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) return -1, ENOSYS; } -func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) { - return -1, ENOSYS; -} - func Exec(argv0 string, argv []string, envv []string) (err int) { return ENOSYS; } diff --git a/libgo/syscalls/exec.go b/libgo/go/syscall/exec_unix.go similarity index 50% rename from libgo/syscalls/exec.go rename to libgo/go/syscall/exec_unix.go index 8ad45f9aea5..765f4d12fd5 100644 --- a/libgo/syscalls/exec.go +++ b/libgo/go/syscall/exec_unix.go @@ -1,28 +1,129 @@ -// exec.go -- fork/exec syscall support. - // Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build darwin freebsd linux openbsd + // Fork, exec, wait, etc. package syscall -import "unsafe" +import ( + "sync" + "unsafe" +) -func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl") -func libc_fork() Pid_t __asm__ ("fork") -func libc_setsid() Pid_t __asm__ ("setsid") -func libc_setpgid(Pid_t, Pid_t) int __asm__ ("setpgid") -func libc_chroot(path *byte) int __asm__ ("chroot") -func libc_setuid(Uid_t) int __asm__ ("setuid") -func libc_setgid(Gid_t) int __asm__ ("setgid") -func libc_setgroups(Size_t, *Gid_t) int __asm__ ("setgroups") -func libc_chdir(name *byte) int __asm__ ("chdir") -func libc_dup2(int, int) int __asm__ ("dup2") -func libc_ioctl(int, int) int __asm__ ("ioctl") -func libc_execve(*byte, **byte, **byte) int __asm__ ("execve") -func libc_sysexit(int) __asm__ ("_exit") +//sysnb raw_fork() (pid Pid_t, errno int) +//fork() Pid_t + +//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int) +//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long + +//sysnb raw_setsid() (errno int) +//setsid() Pid_t + +//sysnb raw_chroot(path *byte) (errno int) +//chroot(path *byte) int + +//sysnb raw_chdir(path *byte) (errno int) +//chdir(path *byte) int + +//sysnb raw_fcntl(fd int, cmd int, arg int) (val int, errno int) +//fcntl(fd int, cmd int, arg int) int + +//sysnb raw_close(fd int) (errno int) +//close(fd int) int + +//sysnb raw_ioctl(fd int, cmd int, val int) (rval int, errno int) +//ioctl(fd int, cmd int, val int) int + +//sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (errno int) +//execve(argv0 *byte, argv **byte, envv **byte) int + +//sysnb raw_read(fd int, p *byte, np int) (n int, errno int) +//read(fd int, buf *byte, count Size_t) Ssize_t + +//sysnb raw_write(fd int, buf *byte, count int) int +//write(fd int, buf *byte, count Size_t) Ssize_t + +//sysnb raw_exit(status int) +//_exit(status int) + +// Lock synchronizing creation of new file descriptors with fork. +// +// We want the child in a fork/exec sequence to inherit only the +// file descriptors we intend. To do that, we mark all file +// descriptors close-on-exec and then, in the child, explicitly +// unmark the ones we want the exec'ed program to keep. +// Unix doesn't make this easy: there is, in general, no way to +// allocate a new file descriptor close-on-exec. Instead you +// have to allocate the descriptor and then mark it close-on-exec. +// If a fork happens between those two events, the child's exec +// will inherit an unwanted file descriptor. +// +// This lock solves that race: the create new fd/mark close-on-exec +// operation is done holding ForkLock for reading, and the fork itself +// is done holding ForkLock for writing. At least, that's the idea. +// There are some complications. +// +// Some system calls that create new file descriptors can block +// for arbitrarily long times: open on a hung NFS server or named +// pipe, accept on a socket, and so on. We can't reasonably grab +// the lock across those operations. +// +// It is worse to inherit some file descriptors than others. +// If a non-malicious child accidentally inherits an open ordinary file, +// that's not a big deal. On the other hand, if a long-lived child +// accidentally inherits the write end of a pipe, then the reader +// of that pipe will not see EOF until that child exits, potentially +// causing the parent program to hang. This is a common problem +// in threaded C programs that use popen. +// +// Luckily, the file descriptors that are most important not to +// inherit are not the ones that can take an arbitrarily long time +// to create: pipe returns instantly, and the net package uses +// non-blocking I/O to accept on a listening socket. +// The rules for which file descriptor-creating operations use the +// ForkLock are as follows: +// +// 1) Pipe. Does not block. Use the ForkLock. +// 2) Socket. Does not block. Use the ForkLock. +// 3) Accept. If using non-blocking mode, use the ForkLock. +// Otherwise, live with the race. +// 4) Open. Can block. Use O_CLOEXEC if available (Linux). +// Otherwise, live with the race. +// 5) Dup. Does not block. Use the ForkLock. +// On Linux, could use fcntl F_DUPFD_CLOEXEC +// instead of the ForkLock, but only for dup(fd, -1). + +var ForkLock sync.RWMutex + +// Convert array of string to array +// of NUL-terminated byte pointer. +func StringSlicePtr(ss []string) []*byte { + bb := make([]*byte, len(ss)+1) + for i := 0; i < len(ss); i++ { + bb[i] = StringBytePtr(ss[i]) + } + bb[len(ss)] = nil + return bb +} + +func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) } + +func SetNonblock(fd int, nonblocking bool) (errno int) { + flag, err := fcntl(fd, F_GETFL, 0) + if err != 0 { + return err + } + if nonblocking { + flag |= O_NONBLOCK + } else { + flag &= ^O_NONBLOCK + } + _, err = fcntl(fd, F_SETFL, flag) + return err +} // Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child. // If a dup or exec fails, write the errno int to pipe. @@ -30,81 +131,94 @@ func libc_sysexit(int) __asm__ ("_exit") // In the child, this function must not acquire any locks, because // they might have been locked at the time of the fork. This means // no rescheduling, no malloc calls, and no new stack segments. +// The calls to RawSyscall are okay because they are assembly +// functions that do not grow the stack. func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) { // Declare all variables at top in case any // declarations require heap allocation (e.g., err1). - var r1, r2, err1 uintptr + var r1 Pid_t + var err1 int var nextfd int var i int // guard against side effects of shuffling fds below. fd := append([]int(nil), attr.Files...) - darwin := OS == "darwin" - // About to call fork. // No more allocation or calls of non-assembly functions. - child := libc_fork() - if child == -1 { - return 0, GetErrno() + r1, err1 = raw_fork() + if err1 != 0 { + return 0, int(err1) } - if child != 0 { + if r1 != 0 { // parent; return PID - return int(child), 0 + return int(r1), 0 } // Fork succeeded, now in child. // Enable tracing if requested. if sys.Ptrace { - if libc_ptrace(_PTRACE_TRACEME, 0, 0, nil) < 0 { + err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil) + if err1 != 0 { goto childerror } } // Session ID if sys.Setsid { - if libc_setsid() == Pid_t(-1) { + err1 = raw_setsid() + if err1 != 0 { goto childerror } } // Set process group if sys.Setpgid { - if libc_setpgid(0, 0) < 0 { + err1 = Setpgid(0, 0) + if err1 != 0 { goto childerror } } // Chroot if chroot != nil { - if libc_chroot(chroot) < 0 { + err1 = raw_chroot(chroot) + if err1 != 0 { goto childerror } } // User and groups if cred := sys.Credential; cred != nil { - ngroups := uintptr(len(cred.Groups)) - var groups *Gid_t - if ngroups > 0 { - groups = (*Gid_t)(unsafe.Pointer(&cred.Groups[0])) + ngroups := len(cred.Groups) + if ngroups == 0 { + err1 = setgroups(0, nil) + } else { + groups := make([]Gid_t, ngroups) + for i, v := range cred.Groups { + groups[i] = Gid_t(v) + } + err1 = setgroups(ngroups, &groups[0]) } - if libc_setgroups(Size_t(ngroups), groups) < 0 { + if err1 != 0 { goto childerror } - if libc_setgid(Gid_t(cred.Gid)) < 0 { + err1 = Setgid(int(cred.Gid)) + if err1 != 0 { goto childerror } - if libc_setuid(Uid_t(cred.Uid)) < 0 { + err1 = Setuid(int(cred.Uid)) + if err1 != 0 { goto childerror } } // Chdir if dir != nil { - if libc_chdir(dir) < 0 { + err1 = raw_chdir(dir) + if err1 != 0 { goto childerror } } @@ -113,21 +227,21 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // so that pass 2 won't stomp on an fd it needs later. nextfd = int(len(fd)) if pipe < nextfd { - r := libc_dup2(pipe, nextfd) - if r == -1 { + _, err1 = Dup2(pipe, nextfd) + if err1 != 0 { goto childerror } - libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC) + raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) pipe = nextfd nextfd++ } for i = 0; i < len(fd); i++ { if fd[i] >= 0 && fd[i] < int(i) { - r := libc_dup2(fd[i], nextfd) - if r == -1 { + _, err1 = Dup2(fd[i], nextfd) + if err1 != 0 { goto childerror } - libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC) + raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC) fd[i] = nextfd nextfd++ if nextfd == pipe { // don't stomp on pipe @@ -139,22 +253,22 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Pass 2: dup fd[i] down onto i. for i = 0; i < len(fd); i++ { if fd[i] == -1 { - libc_close(i) + raw_close(i) continue } if fd[i] == int(i) { - // dup2(i, i) won't clear close-on-exec flag on Linux, + // Dup2(i, i) won't clear close-on-exec flag on Linux, // probably not elsewhere either. - r := libc_fcntl(fd[i], F_SETFD, 0) - if r != 0 { + _, err1 = raw_fcntl(fd[i], F_SETFD, 0) + if err1 != 0 { goto childerror } continue } // The new fd is created NOT close-on-exec, // which is exactly what we want. - r := libc_dup2(fd[i], i) - if r == -1 { + _, err1 = Dup2(fd[i], i) + if err1 != 0 { goto childerror } } @@ -164,33 +278,33 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr // Programs that know they inherit fds >= 3 will need // to set them close-on-exec. for i = len(fd); i < 3; i++ { - libc_close(i) + raw_close(i) } // Detach fd 0 from tty if sys.Noctty { - if libc_ioctl(0, TIOCNOTTY) < 0 { + _, err1 = raw_ioctl(0, TIOCNOTTY, 0) + if err1 != 0 { goto childerror } } // Make fd 0 the tty if sys.Setctty { - if libc_ioctl(0, TIOCSCTTY) < 0 { + _, err1 = raw_ioctl(0, TIOCSCTTY, 0) + if err1 != 0 { goto childerror } } // Time to exec. - libc_execve(argv0, &argv[0], &envv[0]) + err1 = raw_execve(argv0, &argv[0], &envv[0]) childerror: // send error code on pipe - var e uintptr = uintptr(GetErrno()) - libc_write(pipe, (*byte)(unsafe.Pointer(&e)), - Size_t(unsafe.Sizeof(err1))) + raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) for { - libc_sysexit(253) + raw_exit(253) } // Calling panic is not actually safe, @@ -231,8 +345,7 @@ var zeroSysProcAttr SysProcAttr func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) { var p [2]int - var n Ssize_t - var r1 int + var n int var err1 uintptr var wstatus WaitStatus @@ -249,8 +362,8 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) { // Convert args to C form. argv0p := StringBytePtr(argv0) - argvp := StringArrayPtr(argv) - envvp := StringArrayPtr(attr.Env) + argvp := StringSlicePtr(argv) + envvp := StringSlicePtr(attr.Env) if OS == "freebsd" && len(argv[0]) > len(argv0) { argvp[0] = argv0p @@ -290,15 +403,10 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) { // Read child error status from pipe. Close(p[1]) - n = libc_read(p[0], (*byte)(unsafe.Pointer(&err1)), - Size_t(unsafe.Sizeof(err1))) - err = 0 - if n < 0 { - err = GetErrno() - } + n, err = raw_read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1))) Close(p[0]) if err != 0 || n != 0 { - if int(n) == unsafe.Sizeof(err1) { + if n == int(unsafe.Sizeof(err1)) { err = int(err1) } if err == 0 { @@ -339,8 +447,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, // Ordinary exec. func Exec(argv0 string, argv []string, envv []string) (err int) { - argv_arg := StringArrayPtr(argv) - envv_arg := StringArrayPtr(envv) - libc_execve(StringBytePtr(argv0), &argv_arg[0], &envv_arg[0]) - return GetErrno() + err1 := raw_execve(StringBytePtr(argv0), + &StringSlicePtr(argv)[0], + &StringSlicePtr(envv)[0]) + return int(err1) } diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go new file mode 100644 index 00000000000..e8b540ad160 --- /dev/null +++ b/libgo/go/syscall/exec_windows.go @@ -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 +} diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go new file mode 100644 index 00000000000..d3e1d3a90c5 --- /dev/null +++ b/libgo/go/syscall/libcall_linux.go @@ -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 diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go new file mode 100644 index 00000000000..ea7dfc89af7 --- /dev/null +++ b/libgo/go/syscall/libcall_posix.go @@ -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 . + +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 +} diff --git a/libgo/go/syscall/libcall_posix_largefile.go b/libgo/go/syscall/libcall_posix_largefile.go new file mode 100644 index 00000000000..acfafecc581 --- /dev/null +++ b/libgo/go/syscall/libcall_posix_largefile.go @@ -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 diff --git a/libgo/go/syscall/libcall_posix_regfile.go b/libgo/go/syscall/libcall_posix_regfile.go new file mode 100644 index 00000000000..b71da0ceb48 --- /dev/null +++ b/libgo/go/syscall/libcall_posix_regfile.go @@ -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 diff --git a/libgo/syscalls/syscall_solaris.go b/libgo/go/syscall/libcall_solaris_386.go similarity index 54% rename from libgo/syscalls/syscall_solaris.go rename to libgo/go/syscall/libcall_solaris_386.go index ec229339d94..a008a221db2 100644 --- a/libgo/syscalls/syscall_solaris.go +++ b/libgo/go/syscall/libcall_solaris_386.go @@ -1,7 +1,9 @@ -// syscall_solaris.go -- Solaris 2 specific syscall interface. - // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syscall + +// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. . +//sysnb Uname(buf *Utsname) (errno int) +//_nuname(buf *Utsname) int diff --git a/libgo/syscalls/syscall_uname.go b/libgo/go/syscall/libcall_support.go similarity index 55% rename from libgo/syscalls/syscall_uname.go rename to libgo/go/syscall/libcall_support.go index 955866c89f1..daed8073caf 100644 --- a/libgo/syscalls/syscall_uname.go +++ b/libgo/go/syscall/libcall_support.go @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// Declarations for functions which are actually written in C. + package syscall -func libc_uname(buf *Utsname) (errno int) __asm__("uname") +func entersyscall() +func exitsyscall() +func GetErrno() int +func SetErrno(int) diff --git a/libgo/syscalls/syscall_rtems.go b/libgo/go/syscall/libcall_uname.go similarity index 72% rename from libgo/syscalls/syscall_rtems.go rename to libgo/go/syscall/libcall_uname.go index 7f0c1195443..e4c32b12d6a 100644 --- a/libgo/syscalls/syscall_rtems.go +++ b/libgo/go/syscall/libcall_uname.go @@ -1,7 +1,8 @@ -// syscall_rtems.go -- RTEMS specific syscall interface. - // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package syscall + +//sysnb Uname(buf *Utsname) (errno int) +//uname(buf *Utsname) int diff --git a/libgo/go/syscall/libcall_wait4.go b/libgo/go/syscall/libcall_wait4.go new file mode 100644 index 00000000000..7a63bc71e97 --- /dev/null +++ b/libgo/go/syscall/libcall_wait4.go @@ -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 +} diff --git a/libgo/syscalls/waitpid.go b/libgo/go/syscall/libcall_waitpid.go similarity index 51% rename from libgo/syscalls/waitpid.go rename to libgo/go/syscall/libcall_waitpid.go index 1cb4d5dda95..014446307e3 100644 --- a/libgo/syscalls/waitpid.go +++ b/libgo/go/syscall/libcall_waitpid.go @@ -1,20 +1,19 @@ -// waitpid.go -- Wait4 for systems without wait4, but with waitpid. - -// Copyright 2011 The Go Authors. All rights reserved. +// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// For systems with the waitpid library call. + package syscall -func libc_waitpid(Pid_t, *int, int) Pid_t __asm__ ("waitpid") +//sys waitpid(pid Pid_t, status *int, options int) (wpid Pid_t, errno int) +//waitpid(pid Pid_t, status *int, options int) Pid_t func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) { var status int - r := libc_waitpid(Pid_t(pid), &status, options) + r, err := waitpid(Pid_t(pid), &status, options) wpid = int(r) - if r < 0 { - errno = GetErrno() - } + errno = err if wstatus != nil { *wstatus = WaitStatus(status) } diff --git a/libgo/go/syscall/lsf_linux.go b/libgo/go/syscall/lsf_linux.go new file mode 100644 index 00000000000..f2bd2b757f9 --- /dev/null +++ b/libgo/go/syscall/lsf_linux.go @@ -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)) +} diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk new file mode 100644 index 00000000000..d19a8ba73fc --- /dev/null +++ b/libgo/go/syscall/mksyscall.awk @@ -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 + } +} diff --git a/libgo/syscalls/netlink_linux.go b/libgo/go/syscall/netlink_linux.go similarity index 97% rename from libgo/syscalls/netlink_linux.go rename to libgo/go/syscall/netlink_linux.go index 6f621cee69c..4ee78d62f25 100644 --- a/libgo/syscalls/netlink_linux.go +++ b/libgo/go/syscall/netlink_linux.go @@ -195,10 +195,12 @@ func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) { ) switch msg.Header.Type { - case RTM_NEWLINK: + case RTM_NEWLINK, RTM_DELLINK: buf = msg.Data[SizeofIfInfomsg:] - case RTM_NEWADDR: + case RTM_NEWADDR, RTM_DELADDR: buf = msg.Data[SizeofIfAddrmsg:] + case RTM_NEWROUTE, RTM_DELROUTE: + buf = msg.Data[SizeofRtMsg:] default: return nil, EINVAL } diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go new file mode 100644 index 00000000000..f6b124b64e4 --- /dev/null +++ b/libgo/go/syscall/route_bsd.go @@ -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< 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<= 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 +} diff --git a/libgo/go/syscall/route_darwin.go b/libgo/go/syscall/route_darwin.go new file mode 100644 index 00000000000..9d3a701daba --- /dev/null +++ b/libgo/go/syscall/route_darwin.go @@ -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<= 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 +} diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go new file mode 100644 index 00000000000..9da8a686e3e --- /dev/null +++ b/libgo/go/syscall/socket.go @@ -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) +} diff --git a/libgo/syscalls/socket_bsd.go b/libgo/go/syscall/socket_bsd.go similarity index 100% rename from libgo/syscalls/socket_bsd.go rename to libgo/go/syscall/socket_bsd.go diff --git a/libgo/syscalls/socket_irix.go b/libgo/go/syscall/socket_irix.go similarity index 100% rename from libgo/syscalls/socket_irix.go rename to libgo/go/syscall/socket_irix.go diff --git a/libgo/syscalls/socket_linux.go b/libgo/go/syscall/socket_linux.go similarity index 80% rename from libgo/syscalls/socket_linux.go rename to libgo/go/syscall/socket_linux.go index 57ea7c3ff1b..20a37f7390b 100644 --- a/libgo/syscalls/socket_linux.go +++ b/libgo/go/syscall/socket_linux.go @@ -57,10 +57,10 @@ func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) { } type RawSockaddrInet4 struct { - Family uint16; - Port uint16; - Addr [4]byte /* in_addr */; - Zero [8]uint8; + Family uint16 + Port uint16 + Addr [4]byte /* in_addr */ + Zero [8]uint8 } func (sa *RawSockaddrInet4) setLen() Socklen_t { @@ -68,11 +68,11 @@ func (sa *RawSockaddrInet4) setLen() Socklen_t { } type RawSockaddrInet6 struct { - Family uint16; - Port uint16; - Flowinfo uint32; - Addr [16]byte /* in6_addr */; - Scope_id uint32; + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 } func (sa *RawSockaddrInet6) setLen() Socklen_t { @@ -80,8 +80,8 @@ func (sa *RawSockaddrInet6) setLen() Socklen_t { } type RawSockaddrUnix struct { - Family uint16; - Path [108]int8; + Family uint16 + Path [108]int8 } func (sa *RawSockaddrUnix) setLen(int) { @@ -94,7 +94,7 @@ func (sa *RawSockaddrUnix) getLen() (int, int) { // (This is the standard convention.) // Not friendly to overwrite in place, // but the callers below don't care. - sa.Path[0] = '@'; + sa.Path[0] = '@' } // Assume path ends at NUL. @@ -102,9 +102,9 @@ func (sa *RawSockaddrUnix) getLen() (int, int) { // abstract Unix domain sockets--they are supposed // to be uninterpreted fixed-size binary blobs--but // everyone uses this convention. - n := 0; + n := 0 for n < len(sa.Path) - 3 && sa.Path[n] != 0 { - n++; + n++ } return n, 0 @@ -128,8 +128,8 @@ type RawSockaddrNetlink struct { } type RawSockaddr struct { - Family uint16; - Data [14]int8; + Family uint16 + Data [14]int8 } // BindToDevice binds the socket associated with fd to device. @@ -161,5 +161,23 @@ func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) { } return sa, 0 } - return nil, EAFNOSUPPORT; + return nil, EAFNOSUPPORT } + +// We don't take this type directly from the header file because it +// uses a union. FIXME. + +type EpollEvent struct { + Events uint32 + Fd int32 + Pad int32 +} + +//sysnb EpollCreate(size int) (fd int, errno int) +//epoll_create(size int) int + +//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int) +//epoll_ctl(epfd int, op int, fd int, event *EpollEvent) int + +//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int) +//epoll_wait(epfd int, events *EpollEvent, maxevents int, timeout int) int diff --git a/libgo/syscalls/socket_solaris.go b/libgo/go/syscall/socket_solaris.go similarity index 100% rename from libgo/syscalls/socket_solaris.go rename to libgo/go/syscall/socket_solaris.go diff --git a/libgo/go/syscall/str.go b/libgo/go/syscall/str.go new file mode 100644 index 00000000000..0fce842e8c1 --- /dev/null +++ b/libgo/go/syscall/str.go @@ -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:]) +} diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go new file mode 100644 index 00000000000..a802ba0bbf2 --- /dev/null +++ b/libgo/go/syscall/syscall.go @@ -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)) diff --git a/libgo/syscalls/syscall_linux_386.go b/libgo/go/syscall/syscall_linux_386.go similarity index 100% rename from libgo/syscalls/syscall_linux_386.go rename to libgo/go/syscall/syscall_linux_386.go diff --git a/libgo/syscalls/syscall_linux_alpha.go b/libgo/go/syscall/syscall_linux_alpha.go similarity index 100% rename from libgo/syscalls/syscall_linux_alpha.go rename to libgo/go/syscall/syscall_linux_alpha.go diff --git a/libgo/syscalls/syscall_linux_amd64.go b/libgo/go/syscall/syscall_linux_amd64.go similarity index 100% rename from libgo/syscalls/syscall_linux_amd64.go rename to libgo/go/syscall/syscall_linux_amd64.go diff --git a/libgo/go/syscall/syscall_stubs.go b/libgo/go/syscall/syscall_stubs.go new file mode 100644 index 00000000000..76c05cb546a --- /dev/null +++ b/libgo/go/syscall/syscall_stubs.go @@ -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) +} diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go new file mode 100644 index 00000000000..c734b2cf06a --- /dev/null +++ b/libgo/go/syscall/syscall_unix.go @@ -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) +} diff --git a/libgo/go/syscall/wait.c b/libgo/go/syscall/wait.c new file mode 100644 index 00000000000..cee84c9cb52 --- /dev/null +++ b/libgo/go/syscall/wait.c @@ -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 +#include + +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 +} diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh index f959d640fdc..6bc10ee0c8a 100755 --- a/libgo/mksysinfo.sh +++ b/libgo/mksysinfo.sh @@ -197,16 +197,13 @@ if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then echo "const EPOLLRDHUP = 0x2000" >> ${OUT} fi -# Ptrace constants. We don't expose all the PTRACE flags, just the -# PTRACE_O_xxx and PTRACE_EVENT_xxx ones. -grep '^const _PTRACE_O' gen-sysinfo.go | - sed -e 's/^\(const \)_\(PTRACE_O[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} -grep '^const _PTRACE_EVENT' gen-sysinfo.go | - sed -e 's/^\(const \)_\(PTRACE_EVENT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} -# We need PTRACE_SETOPTIONS and PTRACE_GETEVENTMSG, but they are not -# defined in older versions of glibc. -if ! grep '^const _PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then - echo "const _PTRACE_SETOPTIONS = 0x4200" >> ${OUT} +# Ptrace constants. +grep '^const _PTRACE' gen-sysinfo.go | + sed -e 's/^\(const \)_\(PTRACE[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT} +# We need some ptrace options that are not defined in older versions +# of glibc. +if ! grep '^const PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then + echo "const PTRACE_SETOPTIONS = 0x4200" >> ${OUT} fi if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT} @@ -254,7 +251,7 @@ if ! grep '^const PTRACE_EVENT_EXIT' ${OUT} > /dev/null 2>&1; then echo "const PTRACE_EVENT_EXIT = 6" >> ${OUT} fi if ! grep '^const _PTRACE_TRACEME' ${OUT} > /dev/null 2>&1; then - echo "const _PTRACE_TRACEME = 0" >> ${OUT} + echo "const PTRACE_TRACEME = 0" >> ${OUT} fi # The registers returned by PTRACE_GETREGS. This is probably @@ -474,6 +471,11 @@ grep '^type _ip_mreq ' gen-sysinfo.go | \ -e 's/_in_addr/[4]byte/g' \ >> ${OUT} +# The size of the ip_mreq struct. +if grep 'type IPMreq ' ${OUT} > /dev/null 2>&1; then + echo 'var SizeofIPMreq = int(unsafe.Sizeof(IPMreq{}))' >> ${OUT} +fi + # Try to guess the type to use for fd_set. fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true` fds_bits_type="_C_long" @@ -531,6 +533,25 @@ if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then fi fi +# The rtmsg struct. +grep '^type _rtmsg ' gen-sysinfo.go | \ + sed -e 's/_rtmsg/RtMsg/' \ + -e 's/rtm_family/Family/' \ + -e 's/rtm_dst_len/Dst_len/' \ + -e 's/rtm_src_len/Src_len/' \ + -e 's/rtm_tos/Tos/' \ + -e 's/rtm_table/Table/' \ + -e 's/rtm_protocol/Procotol/' \ + -e 's/rtm_scope/Scope/' \ + -e 's/rtm_type/Type/' \ + -e 's/rtm_flags/Flags/' \ + >> ${OUT} + +# The size of the rtmsg struct. +if grep 'type RtMsg ' ${OUT} > /dev/null 2>&1; then + echo 'var SizeofRtMsg = int(unsafe.Sizeof(RtMsg{}))' >> ${OUT} +fi + # The rtgenmsg struct. grep '^type _rtgenmsg ' gen-sysinfo.go | \ sed -e 's/_rtgenmsg/RtGenmsg/' \ diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index bbdf894f49d..521bcd648cc 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -71,3 +71,21 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz) if(hz != 0) runtime_resetcpuprofiler(hz); } + +/* The entersyscall and exitsyscall functions aren't used for anything + yet. Eventually they will be used to switch to a new OS thread + when making a potentially-blocking library call. */ + +void runtime_entersyscall() __asm__("libgo_syscall.syscall.entersyscall"); + +void +runtime_entersyscall() +{ +} + +void runtime_exitsyscall() __asm__("libgo_syscall.syscall.exitsyscall"); + +void +runtime_exitsyscall() +{ +} diff --git a/libgo/syscalls/errstr_decl.go b/libgo/syscalls/errstr_decl.go deleted file mode 100644 index b6bff0fb00b..00000000000 --- a/libgo/syscalls/errstr_decl.go +++ /dev/null @@ -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") diff --git a/libgo/syscalls/errstr_decl_linux.go b/libgo/syscalls/errstr_decl_linux.go deleted file mode 100644 index 4c1cb82a073..00000000000 --- a/libgo/syscalls/errstr_decl_linux.go +++ /dev/null @@ -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") diff --git a/libgo/syscalls/errstr_decl_rtems.go b/libgo/syscalls/errstr_decl_rtems.go deleted file mode 100644 index b83eedc8e1c..00000000000 --- a/libgo/syscalls/errstr_decl_rtems.go +++ /dev/null @@ -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") diff --git a/libgo/syscalls/errstr_rtems.go b/libgo/syscalls/errstr_rtems.go deleted file mode 100644 index f6b453bdc73..00000000000 --- a/libgo/syscalls/errstr_rtems.go +++ /dev/null @@ -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]) - } - } -} diff --git a/libgo/syscalls/exec_helpers.go b/libgo/syscalls/exec_helpers.go deleted file mode 100644 index c8a68a058b3..00000000000 --- a/libgo/syscalls/exec_helpers.go +++ /dev/null @@ -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; -} diff --git a/libgo/syscalls/socket.go b/libgo/syscalls/socket.go deleted file mode 100644 index be7a89b7ff2..00000000000 --- a/libgo/syscalls/socket.go +++ /dev/null @@ -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; -} diff --git a/libgo/syscalls/socket_epoll.go b/libgo/syscalls/socket_epoll.go deleted file mode 100644 index 0013f33498f..00000000000 --- a/libgo/syscalls/socket_epoll.go +++ /dev/null @@ -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; -} diff --git a/libgo/syscalls/stringbyte.go b/libgo/syscalls/stringbyte.go deleted file mode 100644 index 17619536f2e..00000000000 --- a/libgo/syscalls/stringbyte.go +++ /dev/null @@ -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]) -} diff --git a/libgo/syscalls/syscall.go b/libgo/syscalls/syscall.go deleted file mode 100644 index 8c7a7ba5fee..00000000000 --- a/libgo/syscalls/syscall.go +++ /dev/null @@ -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 -} diff --git a/libgo/syscalls/syscall_irix.go b/libgo/syscalls/syscall_irix.go deleted file mode 100644 index e66cef045db..00000000000 --- a/libgo/syscalls/syscall_irix.go +++ /dev/null @@ -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)) diff --git a/libgo/syscalls/syscall_linux.go b/libgo/syscalls/syscall_linux.go deleted file mode 100644 index 29c8b62403e..00000000000 --- a/libgo/syscalls/syscall_linux.go +++ /dev/null @@ -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 -} diff --git a/libgo/syscalls/syscall_solaris_386.go b/libgo/syscalls/syscall_solaris_386.go deleted file mode 100644 index 7ff8f5b0740..00000000000 --- a/libgo/syscalls/syscall_solaris_386.go +++ /dev/null @@ -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. . -func libc_uname(buf *Utsname) (errno int) __asm__("_nuname") diff --git a/libgo/syscalls/syscall_solaris_amd64.go b/libgo/syscalls/syscall_solaris_amd64.go deleted file mode 100644 index 15d22561507..00000000000 --- a/libgo/syscalls/syscall_solaris_amd64.go +++ /dev/null @@ -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)) diff --git a/libgo/syscalls/syscall_solaris_sparc.go b/libgo/syscalls/syscall_solaris_sparc.go deleted file mode 100644 index 0be60b92967..00000000000 --- a/libgo/syscalls/syscall_solaris_sparc.go +++ /dev/null @@ -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)) diff --git a/libgo/syscalls/syscall_solaris_sparc64.go b/libgo/syscalls/syscall_solaris_sparc64.go deleted file mode 100644 index 81e2010cd13..00000000000 --- a/libgo/syscalls/syscall_solaris_sparc64.go +++ /dev/null @@ -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)) diff --git a/libgo/syscalls/syscall_stubs.go b/libgo/syscalls/syscall_stubs.go deleted file mode 100644 index d864902eaf7..00000000000 --- a/libgo/syscalls/syscall_stubs.go +++ /dev/null @@ -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); -} diff --git a/libgo/syscalls/syscall_unix.go b/libgo/syscalls/syscall_unix.go deleted file mode 100644 index e633ea19146..00000000000 --- a/libgo/syscalls/syscall_unix.go +++ /dev/null @@ -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 -} diff --git a/libgo/syscalls/sysfile_largefile.go b/libgo/syscalls/sysfile_largefile.go deleted file mode 100644 index c0c4e555e63..00000000000 --- a/libgo/syscalls/sysfile_largefile.go +++ /dev/null @@ -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") diff --git a/libgo/syscalls/sysfile_posix.go b/libgo/syscalls/sysfile_posix.go deleted file mode 100644 index a16ba4aba60..00000000000 --- a/libgo/syscalls/sysfile_posix.go +++ /dev/null @@ -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 -} diff --git a/libgo/syscalls/sysfile_regfile.go b/libgo/syscalls/sysfile_regfile.go deleted file mode 100644 index fcbf254dc0e..00000000000 --- a/libgo/syscalls/sysfile_regfile.go +++ /dev/null @@ -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") diff --git a/libgo/syscalls/sysfile_stat_largefile.go b/libgo/syscalls/sysfile_stat_largefile.go deleted file mode 100644 index 1b785f70a64..00000000000 --- a/libgo/syscalls/sysfile_stat_largefile.go +++ /dev/null @@ -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"); diff --git a/libgo/syscalls/sysfile_stat_regfile.go b/libgo/syscalls/sysfile_stat_regfile.go deleted file mode 100644 index b3d48641375..00000000000 --- a/libgo/syscalls/sysfile_stat_regfile.go +++ /dev/null @@ -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"); diff --git a/libgo/syscalls/wait4.go b/libgo/syscalls/wait4.go deleted file mode 100644 index bb00c792bc0..00000000000 --- a/libgo/syscalls/wait4.go +++ /dev/null @@ -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 -} diff --git a/libgo/testsuite/Makefile.in b/libgo/testsuite/Makefile.in index 0acbbb3da4f..3d3bc984a07 100644 --- a/libgo/testsuite/Makefile.in +++ b/libgo/testsuite/Makefile.in @@ -86,7 +86,10 @@ GOARCH = @GOARCH@ GOC = @GOC@ GOCFLAGS = @GOCFLAGS@ GOOS = @GOOS@ -GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@ +GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@ +GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@ +GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@ +GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@