Commit af7c9a42 authored by Shawn Walker-Salas's avatar Shawn Walker-Salas Committed by Aram Hăvărneanu

syscall: implement getwd on Solaris

In support of the changes required for #8609, it was suggested that
syscall.getwd() be updated to work on Solaris first since the runtime
uses it and today it's unimplemented.

Fixes #12507

Change-Id: Ifb58ac9db8540936d5685c2c58bdc465dbc836cb
Reviewed-on: https://go-review.googlesource.com/14420Reviewed-by: 's avatarAram Hăvărneanu <aram@mgk.ro>
parent cf3134a0
...@@ -13,6 +13,11 @@ export LC_CTYPE=C ...@@ -13,6 +13,11 @@ export LC_CTYPE=C
CC=${CC:-gcc} CC=${CC:-gcc}
if [[ "$GOOS" -eq "solaris" ]]; then
# Assumes GNU versions of utilities in PATH.
export PATH=/usr/gnu/bin:$PATH
fi
uname=$(uname) uname=$(uname)
includes_Darwin=' includes_Darwin='
...@@ -195,6 +200,7 @@ includes_OpenBSD=' ...@@ -195,6 +200,7 @@ includes_OpenBSD='
' '
includes_SunOS=' includes_SunOS='
#include <limits.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
......
...@@ -38,6 +38,11 @@ if($ARGV[0] =~ /^-/) { ...@@ -38,6 +38,11 @@ if($ARGV[0] =~ /^-/) {
exit 1; exit 1;
} }
if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
print STDERR "GOARCH or GOOS not defined in environment\n";
exit 1;
}
sub parseparamlist($) { sub parseparamlist($) {
my ($list) = @_; my ($list) = @_;
$list =~ s/^\s*//; $list =~ s/^\s*//;
...@@ -60,9 +65,9 @@ sub parseparam($) { ...@@ -60,9 +65,9 @@ sub parseparam($) {
my $package = ""; my $package = "";
my $text = ""; my $text = "";
my $vars = "";
my $dynimports = ""; my $dynimports = "";
my $linknames = ""; my $linknames = "";
my @vars = ();
while(<>) { while(<>) {
chomp; chomp;
s/\s+/ /g; s/\s+/ /g;
...@@ -100,20 +105,19 @@ while(<>) { ...@@ -100,20 +105,19 @@ while(<>) {
} }
# System call pointer variable name. # System call pointer variable name.
my $sysvarname = "libc_$sysname"; my $sysvarname = "libc_${sysname}";
my $strconvfunc = "BytePtrFromString"; my $strconvfunc = "BytePtrFromString";
my $strconvtype = "*byte"; my $strconvtype = "*byte";
# Library proc address variable.
$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase. $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
if($vars eq "") {
$vars .= "\t$sysvarname"; # Runtime import of function to allow cross-platform builds.
} else { $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname.so\"\n";
$vars .= ",\n\t$sysvarname"; # Link symbol to proc address variable.
} $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n";
$dynimports .= "//go:cgo_import_dynamic $sysvarname $sysname \"$modname.so\"\n"; # Library proc address variable.
$linknames .= "//go:linkname $sysvarname $sysvarname\n"; push @vars, $sysvarname;
# Go function header. # Go function header.
$out = join(', ', @out); $out = join(', ', @out);
...@@ -264,6 +268,8 @@ print <<EOF; ...@@ -264,6 +268,8 @@ print <<EOF;
// $cmdline // $cmdline
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// +build $ENV{'GOARCH'},$ENV{'GOOS'}
package $package package $package
import "unsafe" import "unsafe"
...@@ -271,17 +277,20 @@ EOF ...@@ -271,17 +277,20 @@ EOF
print "import \"syscall\"\n" if $package ne "syscall"; print "import \"syscall\"\n" if $package ne "syscall";
print <<EOF; my $vardecls = "\t" . join(",\n\t", @vars);
$vardecls .= " libcFunc";
chomp($_=<<EOF);
$dynimports $dynimports
$linknames $linknames
type libcFunc uintptr type libcFunc uintptr
var ( var (
$vars libcFunc $vardecls
) )
$text $text
EOF EOF
print $_;
exit 0; exit 0;
...@@ -142,12 +142,23 @@ func Getsockname(fd int) (sa Sockaddr, err error) { ...@@ -142,12 +142,23 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
return anyToSockaddr(&rsa) return anyToSockaddr(&rsa)
} }
// The const provides a compile-time constant so clients const ImplementsGetwd = true
// can adjust to whether there is a working Getwd and avoid
// even linking this function into the binary. See ../os/getwd.go.
const ImplementsGetwd = false
func Getwd() (string, error) { return "", ENOTSUP } //sys Getcwd(buf []byte) (n int, err error)
func Getwd() (wd string, err error) {
var buf [PathMax]byte
// Getcwd will return an error if it failed for any reason.
_, err = Getcwd(buf[0:])
if err != nil {
return "", err
}
n := clen(buf[:])
if n < 1 {
return "", EINVAL
}
return string(buf[:n]), nil
}
/* /*
* Wrapped * Wrapped
......
...@@ -15,8 +15,14 @@ package syscall ...@@ -15,8 +15,14 @@ package syscall
/* /*
#define KERNEL #define KERNEL
// These defines ensure that builds done on newer versions of Solaris are
// backwards-compatible with older versions of Solaris and
// OpenSolaris-based derivatives.
#define __USE_SUNOS_SOCKETS__ // msghdr
#define __USE_LEGACY_PROTOTYPES__ // iovec
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h>
#include <signal.h> #include <signal.h>
#include <termios.h> #include <termios.h>
#include <stdio.h> #include <stdio.h>
...@@ -69,6 +75,7 @@ const ( ...@@ -69,6 +75,7 @@ const (
sizeofInt = C.sizeof_int sizeofInt = C.sizeof_int
sizeofLong = C.sizeof_long sizeofLong = C.sizeof_long
sizeofLongLong = C.sizeof_longlong sizeofLongLong = C.sizeof_longlong
PathMax = C.PATH_MAX
) )
// Basic types // Basic types
......
...@@ -7,6 +7,7 @@ package syscall ...@@ -7,6 +7,7 @@ package syscall
import "unsafe" import "unsafe"
//go:cgo_import_dynamic libc_Getcwd getcwd "libc.so"
//go:cgo_import_dynamic libc_getgroups getgroups "libc.so" //go:cgo_import_dynamic libc_getgroups getgroups "libc.so"
//go:cgo_import_dynamic libc_setgroups setgroups "libc.so" //go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
//go:cgo_import_dynamic libc_fcntl fcntl "libc.so" //go:cgo_import_dynamic libc_fcntl fcntl "libc.so"
...@@ -89,6 +90,7 @@ import "unsafe" ...@@ -89,6 +90,7 @@ import "unsafe"
//go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so"
//go:cgo_import_dynamic libc_recvmsg recvmsg "libsocket.so" //go:cgo_import_dynamic libc_recvmsg recvmsg "libsocket.so"
//go:linkname libc_Getcwd libc_Getcwd
//go:linkname libc_getgroups libc_getgroups //go:linkname libc_getgroups libc_getgroups
//go:linkname libc_setgroups libc_setgroups //go:linkname libc_setgroups libc_setgroups
//go:linkname libc_fcntl libc_fcntl //go:linkname libc_fcntl libc_fcntl
...@@ -174,6 +176,7 @@ import "unsafe" ...@@ -174,6 +176,7 @@ import "unsafe"
type libcFunc uintptr type libcFunc uintptr
var ( var (
libc_Getcwd,
libc_getgroups, libc_getgroups,
libc_setgroups, libc_setgroups,
libc_fcntl, libc_fcntl,
...@@ -257,6 +260,19 @@ var ( ...@@ -257,6 +260,19 @@ var (
libc_recvmsg libcFunc libc_recvmsg libcFunc
) )
func Getcwd(buf []byte) (n int, err error) {
var _p0 *byte
if len(buf) > 0 {
_p0 = &buf[0]
}
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_Getcwd)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0, 0, 0, 0)
n = int(r0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
func getgroups(ngid int, gid *_Gid_t) (n int, err error) { func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_getgroups)), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0) r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_getgroups)), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0)
n = int(r0) n = int(r0)
......
...@@ -11,6 +11,7 @@ const ( ...@@ -11,6 +11,7 @@ const (
sizeofInt = 0x4 sizeofInt = 0x4
sizeofLong = 0x8 sizeofLong = 0x8
sizeofLongLong = 0x8 sizeofLongLong = 0x8
PathMax = 0x400
) )
type ( type (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment