aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/syscall
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/syscall')
-rw-r--r--libgo/go/syscall/creds_test.go109
-rw-r--r--libgo/go/syscall/env_windows.go6
-rw-r--r--libgo/go/syscall/exec_unix.go30
-rw-r--r--libgo/go/syscall/exec_windows.go16
-rw-r--r--libgo/go/syscall/libcall_posix.go10
-rw-r--r--libgo/go/syscall/mksyscall.awk22
-rw-r--r--libgo/go/syscall/passfd_test.go151
-rw-r--r--libgo/go/syscall/race0.go19
-rw-r--r--libgo/go/syscall/security_windows.go10
-rw-r--r--libgo/go/syscall/syscall.go16
-rw-r--r--libgo/go/syscall/syscall_unix.go17
11 files changed, 363 insertions, 43 deletions
diff --git a/libgo/go/syscall/creds_test.go b/libgo/go/syscall/creds_test.go
new file mode 100644
index 0000000..6eaa97e
--- /dev/null
+++ b/libgo/go/syscall/creds_test.go
@@ -0,0 +1,109 @@
+// Copyright 2012 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 linux
+
+package syscall_test
+
+import (
+ "bytes"
+ "net"
+ "os"
+ "syscall"
+ "testing"
+)
+
+// TestSCMCredentials tests the sending and receiving of credentials
+// (PID, UID, GID) in an ancillary message between two UNIX
+// sockets. The SO_PASSCRED socket option is enabled on the sending
+// socket for this to work.
+func TestSCMCredentials(t *testing.T) {
+ fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ t.Fatalf("Socketpair: %v", err)
+ }
+ defer syscall.Close(fds[0])
+ defer syscall.Close(fds[1])
+
+ err = syscall.SetsockoptInt(fds[0], syscall.SOL_SOCKET, syscall.SO_PASSCRED, 1)
+ if err != nil {
+ t.Fatalf("SetsockoptInt: %v", err)
+ }
+
+ srv, err := net.FileConn(os.NewFile(uintptr(fds[0]), ""))
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer srv.Close()
+
+ cli, err := net.FileConn(os.NewFile(uintptr(fds[1]), ""))
+ if err != nil {
+ t.Errorf("FileConn: %v", err)
+ return
+ }
+ defer cli.Close()
+
+ var ucred syscall.Ucred
+ if os.Getuid() != 0 {
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = 0
+ ucred.Gid = 0
+ oob := syscall.UnixCredentials(&ucred)
+ _, _, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if err.(*net.OpError).Err != syscall.EPERM {
+ t.Fatalf("WriteMsgUnix failed with %v, want EPERM", err)
+ }
+ }
+
+ ucred.Pid = int32(os.Getpid())
+ ucred.Uid = uint32(os.Getuid())
+ ucred.Gid = uint32(os.Getgid())
+ oob := syscall.UnixCredentials(&ucred)
+
+ // this is going to send a dummy byte
+ n, oobn, err := cli.(*net.UnixConn).WriteMsgUnix(nil, oob, nil)
+ if err != nil {
+ t.Fatalf("WriteMsgUnix: %v", err)
+ }
+ if n != 0 {
+ t.Fatalf("WriteMsgUnix n = %d, want 0", n)
+ }
+ if oobn != len(oob) {
+ t.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn, len(oob))
+ }
+
+ oob2 := make([]byte, 10*len(oob))
+ n, oobn2, flags, _, err := srv.(*net.UnixConn).ReadMsgUnix(nil, oob2)
+ if err != nil {
+ t.Fatalf("ReadMsgUnix: %v", err)
+ }
+ if flags != 0 {
+ t.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags)
+ }
+ if n != 1 {
+ t.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n)
+ }
+ if oobn2 != oobn {
+ // without SO_PASSCRED set on the socket, ReadMsgUnix will
+ // return zero oob bytes
+ t.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2, oobn)
+ }
+ oob2 = oob2[:oobn2]
+ if !bytes.Equal(oob, oob2) {
+ t.Fatal("ReadMsgUnix oob bytes don't match")
+ }
+
+ scm, err := syscall.ParseSocketControlMessage(oob2)
+ if err != nil {
+ t.Fatalf("ParseSocketControlMessage: %v", err)
+ }
+ newUcred, err := syscall.ParseUnixCredentials(&scm[0])
+ if err != nil {
+ t.Fatalf("ParseUnixCredentials: %v", err)
+ }
+ if *newUcred != ucred {
+ t.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred, ucred)
+ }
+}
diff --git a/libgo/go/syscall/env_windows.go b/libgo/go/syscall/env_windows.go
index 3107ae5..39bd502 100644
--- a/libgo/go/syscall/env_windows.go
+++ b/libgo/go/syscall/env_windows.go
@@ -12,7 +12,7 @@ import (
)
func Getenv(key string) (value string, found bool) {
- keyp, err := utf16PtrFromString(key)
+ keyp, err := UTF16PtrFromString(key)
if err != nil {
return "", false
}
@@ -38,12 +38,12 @@ func Setenv(key, value string) error {
var v *uint16
var err error
if len(value) > 0 {
- v, err = utf16PtrFromString(value)
+ v, err = UTF16PtrFromString(value)
if err != nil {
return err
}
}
- keyp, err := utf16PtrFromString(key)
+ keyp, err := UTF16PtrFromString(key)
if err != nil {
return err
}
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
index b34ee1b..813627b 100644
--- a/libgo/go/syscall/exec_unix.go
+++ b/libgo/go/syscall/exec_unix.go
@@ -50,10 +50,6 @@ import (
//sysnb raw_dup2(oldfd int, newfd int) (err Errno)
//dup2(oldfd int, newfd int) int
-// Note: not raw, returns error rather than Errno.
-//sys read(fd int, p *byte, np int) (n int, err error)
-//read(fd int, buf *byte, count Size_t) Ssize_t
-
// Lock synchronizing creation of new file descriptors with fork.
//
// We want the child in a fork/exec sequence to inherit only the
@@ -103,7 +99,7 @@ import (
var ForkLock sync.RWMutex
-// Convert array of string to array of NUL-terminated byte pointer.
+// StringSlicePtr is deprecated. Use SlicePtrFromStrings instead.
// If any string contains a NUL byte this function panics instead
// of returning an error.
func StringSlicePtr(ss []string) []*byte {
@@ -115,14 +111,14 @@ func StringSlicePtr(ss []string) []*byte {
return bb
}
-// slicePtrFromStrings converts a slice of strings to a slice of
+// SlicePtrFromStrings converts a slice of strings to a slice of
// pointers to NUL-terminated byte slices. If any string contains
// a NUL byte, it returns (nil, EINVAL).
-func slicePtrFromStrings(ss []string) ([]*byte, error) {
+func SlicePtrFromStrings(ss []string) ([]*byte, error) {
var err error
bb := make([]*byte, len(ss)+1)
for i := 0; i < len(ss); i++ {
- bb[i], err = bytePtrFromString(ss[i])
+ bb[i], err = BytePtrFromString(ss[i])
if err != nil {
return nil, err
}
@@ -185,15 +181,15 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
p[1] = -1
// Convert args to C form.
- argv0p, err := bytePtrFromString(argv0)
+ argv0p, err := BytePtrFromString(argv0)
if err != nil {
return 0, err
}
- argvp, err := slicePtrFromStrings(argv)
+ argvp, err := SlicePtrFromStrings(argv)
if err != nil {
return 0, err
}
- envvp, err := slicePtrFromStrings(attr.Env)
+ envvp, err := SlicePtrFromStrings(attr.Env)
if err != nil {
return 0, err
}
@@ -204,14 +200,14 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
var chroot *byte
if sys.Chroot != "" {
- chroot, err = bytePtrFromString(sys.Chroot)
+ chroot, err = BytePtrFromString(sys.Chroot)
if err != nil {
return 0, err
}
}
var dir *byte
if attr.Dir != "" {
- dir, err = bytePtrFromString(attr.Dir)
+ dir, err = BytePtrFromString(attr.Dir)
if err != nil {
return 0, err
}
@@ -242,7 +238,7 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
// Read child error status from pipe.
Close(p[1])
- n, err = read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ n, err = readlen(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
Close(p[0])
if err != nil || n != 0 {
if n == int(unsafe.Sizeof(err1)) {
@@ -286,15 +282,15 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
// Ordinary exec.
func Exec(argv0 string, argv []string, envv []string) (err error) {
- argv0p, err := bytePtrFromString(argv0)
+ argv0p, err := BytePtrFromString(argv0)
if err != nil {
return err
}
- argvp, err := slicePtrFromStrings(argv)
+ argvp, err := SlicePtrFromStrings(argv)
if err != nil {
return err
}
- envvp, err := slicePtrFromStrings(envv)
+ envvp, err := SlicePtrFromStrings(envv)
if err != nil {
return err
}
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
index 68779c4..82abc07 100644
--- a/libgo/go/syscall/exec_windows.go
+++ b/libgo/go/syscall/exec_windows.go
@@ -132,7 +132,7 @@ func SetNonblock(fd Handle, nonblocking bool) (err error) {
// getFullPath retrieves the full path of the specified file.
// Just a wrapper for Windows GetFullPathName api.
func getFullPath(name string) (path string, err error) {
- p, err := utf16PtrFromString(name)
+ p, err := UTF16PtrFromString(name)
if err != nil {
return "", err
}
@@ -228,8 +228,9 @@ type ProcAttr struct {
}
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
+ HideWindow bool
+ CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+ CreationFlags uint32
}
var zeroProcAttr ProcAttr
@@ -264,7 +265,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
return 0, 0, err
}
}
- argv0p, err := utf16PtrFromString(argv0)
+ argv0p, err := UTF16PtrFromString(argv0)
if err != nil {
return 0, 0, err
}
@@ -281,7 +282,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
var argvp *uint16
if len(cmdline) != 0 {
- argvp, err = utf16PtrFromString(cmdline)
+ argvp, err = UTF16PtrFromString(cmdline)
if err != nil {
return 0, 0, err
}
@@ -289,7 +290,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
var dirp *uint16
if len(attr.Dir) != 0 {
- dirp, err = utf16PtrFromString(attr.Dir)
+ dirp, err = UTF16PtrFromString(attr.Dir)
if err != nil {
return 0, 0, err
}
@@ -325,7 +326,8 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle
pi := new(ProcessInformation)
- err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
+ flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT
+ err = CreateProcess(argv0p, argvp, nil, nil, true, flags, createEnvBlock(attr.Env), dirp, si, pi)
if err != nil {
return 0, 0, err
}
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
index 4f25b82..9623103 100644
--- a/libgo/go/syscall/libcall_posix.go
+++ b/libgo/go/syscall/libcall_posix.go
@@ -277,7 +277,10 @@ func Gettimeofday(tv *Timeval) (err error) {
//sys Pause() (err error)
//pause() int
-//sys Read(fd int, p []byte) (n int, err error)
+//sys read(fd int, p []byte) (n int, err error)
+//read(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys readlen(fd int, p *byte, np int) (n int, err error)
//read(fd int, buf *byte, count Size_t) Ssize_t
//sys Readlink(path string, buf []byte) (n int, err error)
@@ -344,7 +347,10 @@ func Settimeofday(tv *Timeval) (err error) {
//sys Utime(path string, buf *Utimbuf) (err error)
//utime(path *byte, buf *Utimbuf) int
-//sys Write(fd int, p []byte) (n int, err error)
+//sys write(fd int, p []byte) (n int, err error)
+//write(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys writelen(fd int, p *byte, np int) (n int, err error)
//write(fd int, buf *byte, count Size_t) Ssize_t
//sys munmap(addr uintptr, length uintptr) (err error)
diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk
index b817960..74f0e28 100644
--- a/libgo/go/syscall/mksyscall.awk
+++ b/libgo/go/syscall/mksyscall.awk
@@ -104,6 +104,19 @@ BEGIN {
loc = gofnname "/" cfnname ":"
+ haserr = 0
+ if (gofnresults != "") {
+ fields = split(gofnresults, goresults, ", *")
+ for (goresult = 1; goresults[goresult] != ""; goresult++) {
+ if (split(goresults[goresult], goparam) == 2) {
+ if (goparam[1] == "err") {
+ haserr = 1
+ break
+ }
+ }
+ }
+ }
+
split(gofnparams, goargs, ", *")
split(cfnparams, cargs, ", *")
args = ""
@@ -147,7 +160,14 @@ BEGIN {
status = 1
next
}
- printf("\t_p%d := StringBytePtr(%s)\n", goarg, goname)
+ printf("\tvar _p%d *byte\n", goarg)
+ if (haserr) {
+ printf("\t_p%d, err = BytePtrFromString(%s)\n", goarg, goname)
+ printf("\tif err != nil {\n\t\treturn\n\t}\n")
+ } else {
+ print loc, "uses string arguments but has no error return" | "cat 1>&2"
+ printf("\t_p%d, _ = BytePtrFromString(%s)\n", goarg, goname)
+ }
args = sprintf("%s_p%d", args, goarg)
} else if (gotype ~ /^\[\](.*)/) {
if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
diff --git a/libgo/go/syscall/passfd_test.go b/libgo/go/syscall/passfd_test.go
new file mode 100644
index 0000000..20ef39e
--- /dev/null
+++ b/libgo/go/syscall/passfd_test.go
@@ -0,0 +1,151 @@
+// Copyright 2012 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 linux darwin
+
+package syscall_test
+
+import (
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "os/exec"
+ "syscall"
+ "testing"
+ "time"
+)
+
+// TestPassFD tests passing a file descriptor over a Unix socket.
+//
+// This test involved both a parent and child process. The parent
+// process is invoked as a normal test, with "go test", which then
+// runs the child process by running the current test binary with args
+// "-test.run=^TestPassFD$" and an environment variable used to signal
+// that the test should become the child process instead.
+func TestPassFD(t *testing.T) {
+ if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+ passFDChild()
+ return
+ }
+
+ tempDir, err := ioutil.TempDir("", "TestPassFD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tempDir)
+
+ fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
+ if err != nil {
+ t.Fatalf("Socketpair: %v", err)
+ }
+ defer syscall.Close(fds[0])
+ defer syscall.Close(fds[1])
+ writeFile := os.NewFile(uintptr(fds[0]), "child-writes")
+ readFile := os.NewFile(uintptr(fds[1]), "parent-reads")
+ defer writeFile.Close()
+ defer readFile.Close()
+
+ cmd := exec.Command(os.Args[0], "-test.run=^TestPassFD$", "--", tempDir)
+ cmd.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
+ cmd.ExtraFiles = []*os.File{writeFile}
+
+ out, err := cmd.CombinedOutput()
+ if len(out) > 0 || err != nil {
+ t.Fatalf("child process: %q, %v", out, err)
+ }
+
+ c, err := net.FileConn(readFile)
+ if err != nil {
+ t.Fatalf("FileConn: %v", err)
+ }
+ defer c.Close()
+
+ uc, ok := c.(*net.UnixConn)
+ if !ok {
+ t.Fatalf("unexpected FileConn type; expected UnixConn, got %T", c)
+ }
+
+ buf := make([]byte, 32) // expect 1 byte
+ oob := make([]byte, 32) // expect 24 bytes
+ closeUnix := time.AfterFunc(5*time.Second, func() {
+ t.Logf("timeout reading from unix socket")
+ uc.Close()
+ })
+ _, oobn, _, _, err := uc.ReadMsgUnix(buf, oob)
+ closeUnix.Stop()
+
+ scms, err := syscall.ParseSocketControlMessage(oob[:oobn])
+ if err != nil {
+ t.Fatalf("ParseSocketControlMessage: %v", err)
+ }
+ if len(scms) != 1 {
+ t.Fatalf("expected 1 SocketControlMessage; got scms = %#v", scms)
+ }
+ scm := scms[0]
+ gotFds, err := syscall.ParseUnixRights(&scm)
+ if err != nil {
+ t.Fatalf("syscall.ParseUnixRights: %v", err)
+ }
+ if len(gotFds) != 1 {
+ t.Fatalf("wanted 1 fd; got %#v", gotFds)
+ }
+
+ f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
+ defer f.Close()
+
+ got, err := ioutil.ReadAll(f)
+ want := "Hello from child process!\n"
+ if string(got) != want {
+ t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
+ }
+}
+
+// passFDChild is the child process used by TestPassFD.
+func passFDChild() {
+ defer os.Exit(0)
+
+ // Look for our fd. It should be fd 3, but we work around an fd leak
+ // bug here (http://golang.org/issue/2603) to let it be elsewhere.
+ var uc *net.UnixConn
+ for fd := uintptr(3); fd <= 10; fd++ {
+ f := os.NewFile(fd, "unix-conn")
+ var ok bool
+ netc, _ := net.FileConn(f)
+ uc, ok = netc.(*net.UnixConn)
+ if ok {
+ break
+ }
+ }
+ if uc == nil {
+ fmt.Println("failed to find unix fd")
+ return
+ }
+
+ // Make a file f to send to our parent process on uc.
+ // We make it in tempDir, which our parent will clean up.
+ flag.Parse()
+ tempDir := flag.Arg(0)
+ f, err := ioutil.TempFile(tempDir, "")
+ if err != nil {
+ fmt.Printf("TempFile: %v", err)
+ return
+ }
+
+ f.Write([]byte("Hello from child process!\n"))
+ f.Seek(0, 0)
+
+ rights := syscall.UnixRights(int(f.Fd()))
+ dummyByte := []byte("x")
+ n, oobn, err := uc.WriteMsgUnix(dummyByte, rights, nil)
+ if err != nil {
+ fmt.Printf("WriteMsgUnix: %v", err)
+ return
+ }
+ if n != 1 || oobn != len(rights) {
+ fmt.Printf("WriteMsgUnix = %d, %d; want 1, %d", n, oobn, len(rights))
+ return
+ }
+}
diff --git a/libgo/go/syscall/race0.go b/libgo/go/syscall/race0.go
new file mode 100644
index 0000000..e94fb47
--- /dev/null
+++ b/libgo/go/syscall/race0.go
@@ -0,0 +1,19 @@
+// Copyright 2012 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 !race
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
diff --git a/libgo/go/syscall/security_windows.go b/libgo/go/syscall/security_windows.go
index 4353af4..71aef2f 100644
--- a/libgo/go/syscall/security_windows.go
+++ b/libgo/go/syscall/security_windows.go
@@ -37,7 +37,7 @@ const (
// TranslateAccountName converts a directory service
// object name from one format to another.
func TranslateAccountName(username string, from, to uint32, initSize int) (string, error) {
- u, e := utf16PtrFromString(username)
+ u, e := UTF16PtrFromString(username)
if e != nil {
return "", e
}
@@ -97,7 +97,7 @@ type SID struct{}
// sid into a valid, functional sid.
func StringToSid(s string) (*SID, error) {
var sid *SID
- p, e := utf16PtrFromString(s)
+ p, e := UTF16PtrFromString(s)
if e != nil {
return nil, e
}
@@ -116,13 +116,13 @@ func LookupSID(system, account string) (sid *SID, domain string, accType uint32,
if len(account) == 0 {
return nil, "", 0, EINVAL
}
- acc, e := utf16PtrFromString(account)
+ acc, e := UTF16PtrFromString(account)
if e != nil {
return nil, "", 0, e
}
var sys *uint16
if len(system) > 0 {
- sys, e = utf16PtrFromString(system)
+ sys, e = UTF16PtrFromString(system)
if e != nil {
return nil, "", 0, e
}
@@ -183,7 +183,7 @@ func (sid *SID) Copy() (*SID, error) {
func (sid *SID) LookupAccount(system string) (account, domain string, accType uint32, err error) {
var sys *uint16
if len(system) > 0 {
- sys, err = utf16PtrFromString(system)
+ sys, err = UTF16PtrFromString(system)
if err != nil {
return "", "", 0, err
}
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
index 3090a5e..56296c8 100644
--- a/libgo/go/syscall/syscall.go
+++ b/libgo/go/syscall/syscall.go
@@ -16,21 +16,21 @@ package syscall
import "unsafe"
-// StringByteSlice returns a NUL-terminated slice of bytes containing the text of s.
+// StringByteSlice is deprecated. Use ByteSliceFromString instead.
// If s contains a NUL byte this function panics instead of
// returning an error.
func StringByteSlice(s string) []byte {
- a, err := byteSliceFromString(s)
+ a, err := ByteSliceFromString(s)
if err != nil {
panic("syscall: string with NUL passed to StringByteSlice")
}
return a
}
-// byteSliceFromString returns a NUL-terminated slice of bytes
+// ByteSliceFromString returns a NUL-terminated slice of bytes
// containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
-func byteSliceFromString(s string) ([]byte, error) {
+func ByteSliceFromString(s string) ([]byte, error) {
for i := 0; i < len(s); i++ {
if s[i] == 0 {
return nil, EINVAL
@@ -41,16 +41,16 @@ func byteSliceFromString(s string) ([]byte, error) {
return a, nil
}
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes containing the text of s.
+// StringBytePtr is deprecated. Use BytePtrFromString instead.
// If s contains a NUL byte this function panics instead of
// returning an error.
func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
-// bytePtrFromString returns a pointer to a NUL-terminated array of
+// BytePtrFromString returns a pointer to a NUL-terminated array of
// bytes containing the text of s. If s contains a NUL byte at any
// location, it returns (nil, EINVAL).
-func bytePtrFromString(s string) (*byte, error) {
- a, err := byteSliceFromString(s)
+func BytePtrFromString(s string) (*byte, error) {
+ a, err := ByteSliceFromString(s)
if err != nil {
return nil, err
}
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
index d4bff9e..fb62681 100644
--- a/libgo/go/syscall/syscall_unix.go
+++ b/libgo/go/syscall/syscall_unix.go
@@ -179,3 +179,20 @@ func Signame(s Signal) string
func (s Signal) String() string {
return Signame(s)
}
+
+func Read(fd int, p []byte) (n int, err error) {
+ n, err = read(fd, p)
+ if raceenabled && err == nil {
+ raceAcquire(unsafe.Pointer(&ioSync))
+ }
+ return
+}
+
+func Write(fd int, p []byte) (n int, err error) {
+ if raceenabled {
+ raceReleaseMerge(unsafe.Pointer(&ioSync))
+ }
+ return write(fd, p)
+}
+
+var ioSync int64