]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: remove nacl srpc helper
authorDave Cheney <dave@cheney.net>
Thu, 27 Aug 2015 06:15:00 +0000 (16:15 +1000)
committerDave Cheney <dave@cheney.net>
Fri, 28 Aug 2015 04:44:44 +0000 (04:44 +0000)
Fixes #11961

Minux removed the use of SRPC in 003dccfa, but the SRPC name service
code was left in the tree. SRPC was removed in pepper_42 making the
code, which ran on startup, fail, even though it was not used.

Removing srpc_nacl.go for a total diff of -822 lines has got to count
as one of the easiest nacl fixes we've had to date.

Change-Id: Ic4e348146bfe47450bbb9cabb91699ba153e6bf0
Reviewed-on: https://go-review.googlesource.com/13958
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Minux Ma <minux@golang.org>
Run-TryBot: Minux Ma <minux@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/syscall/srpc_nacl.go [deleted file]

diff --git a/src/syscall/srpc_nacl.go b/src/syscall/srpc_nacl.go
deleted file mode 100644 (file)
index dd07373..0000000
+++ /dev/null
@@ -1,822 +0,0 @@
-// Copyright 2013 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.
-
-// Native Client SRPC message passing.
-// This code is needed to invoke SecureRandom, the NaCl equivalent of /dev/random.
-
-package syscall
-
-import (
-       "errors"
-       "sync"
-       "unsafe"
-)
-
-// An srpcClient represents the client side of an SRPC connection.
-type srpcClient struct {
-       fd      int // to server
-       r       msgReceiver
-       s       msgSender
-       service map[string]srpcService // services by name
-
-       outMu sync.Mutex // protects writing to connection
-
-       mu      sync.Mutex // protects following fields
-       muxer   bool       // is someone reading and muxing responses
-       pending map[uint32]*srpc
-       idGen   uint32 // generator for request IDs
-}
-
-// An srpcService is a single method that the server offers.
-type srpcService struct {
-       num uint32 // method number
-       fmt string // argument format; see "parsing of RPC messages" below
-}
-
-// An srpc represents a single srpc issued by a client.
-type srpc struct {
-       Ret  []interface{}
-       Done chan *srpc
-       Err  error
-       c    *srpcClient
-       id   uint32
-}
-
-// newClient allocates a new SRPC client using the file descriptor fd.
-func newClient(fd int) (*srpcClient, error) {
-       c := new(srpcClient)
-       c.fd = fd
-       c.r.fd = fd
-       c.s.fd = fd
-       c.service = make(map[string]srpcService)
-       c.pending = make(map[uint32]*srpc)
-
-       // service discovery request
-       m := &msg{
-               isRequest: 1,
-               template:  []interface{}{[]byte(nil)},
-               size:      []int{4000}, // max size to accept for returned byte slice
-       }
-       if err := m.pack(); err != nil {
-               return nil, errors.New("Native Client SRPC service_discovery: preparing request: " + err.Error())
-       }
-       c.s.send(m)
-       m, err := c.r.recv()
-       if err != nil {
-               return nil, err
-       }
-       m.unpack()
-       if m.status != uint32(srpcOK) {
-               return nil, errors.New("Native Client SRPC service_discovery: " + srpcErrno(m.status).Error())
-       }
-       list := m.value[0].([]byte)
-       var n uint32
-       for len(list) > 0 {
-               var line []byte
-               i := byteIndex(list, '\n')
-               if i < 0 {
-                       line, list = list, nil
-               } else {
-                       line, list = list[:i], list[i+1:]
-               }
-               i = byteIndex(line, ':')
-               if i >= 0 {
-                       c.service[string(line)] = srpcService{n, string(line[i+1:])}
-               }
-               n++
-       }
-
-       return c, nil
-}
-
-func byteIndex(b []byte, c byte) int {
-       for i, bi := range b {
-               if bi == c {
-                       return i
-               }
-       }
-       return -1
-}
-
-var yourTurn srpc
-
-func (c *srpcClient) wait(r *srpc) {
-       var rx *srpc
-       for rx = range r.Done {
-               if rx != &yourTurn {
-                       break
-               }
-               c.input()
-       }
-       return
-}
-
-func (c *srpcClient) input() {
-       // read message
-       m, err := c.r.recv()
-       if err != nil {
-               println("Native Client SRPC receive error:", err.Error())
-               return
-       }
-       if m.unpack(); m.status != uint32(srpcOK) {
-               println("Native Client SRPC receive error: invalid message: ", srpcErrno(m.status).Error())
-               return
-       }
-
-       // deliver to intended recipient
-       c.mu.Lock()
-       rpc, ok := c.pending[m.id]
-       if ok {
-               delete(c.pending, m.id)
-       }
-
-       // wake a new muxer if there are more RPCs to read
-       c.muxer = false
-       for _, rpc := range c.pending {
-               c.muxer = true
-               rpc.Done <- &yourTurn
-               break
-       }
-       c.mu.Unlock()
-       if !ok {
-               println("Native Client: unexpected response for ID", m.id)
-               return
-       }
-       rpc.Ret = m.value
-       rpc.Done <- rpc
-}
-
-// Wait blocks until the RPC has finished.
-func (r *srpc) Wait() {
-       r.c.wait(r)
-}
-
-// Start issues an RPC request for method name with the given arguments.
-// The RPC r must not be in use for another pending request.
-// To wait for the RPC to finish, receive from r.Done and then
-// inspect r.Ret and r.Errno.
-func (r *srpc) Start(name string, arg []interface{}) {
-       r.Err = nil
-       r.c.mu.Lock()
-       srv, ok := r.c.service[name]
-       if !ok {
-               r.c.mu.Unlock()
-               r.Err = srpcErrBadRPCNumber
-               r.Done <- r
-               return
-       }
-       r.c.pending[r.id] = r
-       if !r.c.muxer {
-               r.c.muxer = true
-               r.Done <- &yourTurn
-       }
-       r.c.mu.Unlock()
-
-       var m msg
-       m.id = r.id
-       m.isRequest = 1
-       m.rpc = srv.num
-       m.value = arg
-
-       // Fill in the return values and sizes to generate
-       // the right type chars.  We'll take most any size.
-
-       // Skip over input arguments.
-       // We could check them against arg, but the server
-       // will do that anyway.
-       i := 0
-       for srv.fmt[i] != ':' {
-               i++
-       }
-       format := srv.fmt[i+1:]
-
-       // Now the return prototypes.
-       m.template = make([]interface{}, len(format))
-       m.size = make([]int, len(format))
-       for i := 0; i < len(format); i++ {
-               switch format[i] {
-               default:
-                       println("Native Client SRPC: unexpected service type " + string(format[i]))
-                       r.Err = srpcErrBadRPCNumber
-                       r.Done <- r
-                       return
-               case 'b':
-                       m.template[i] = false
-               case 'C':
-                       m.template[i] = []byte(nil)
-                       m.size[i] = 1 << 30
-               case 'd':
-                       m.template[i] = float64(0)
-               case 'D':
-                       m.template[i] = []float64(nil)
-                       m.size[i] = 1 << 30
-               case 'h':
-                       m.template[i] = int(-1)
-               case 'i':
-                       m.template[i] = int32(0)
-               case 'I':
-                       m.template[i] = []int32(nil)
-                       m.size[i] = 1 << 30
-               case 's':
-                       m.template[i] = ""
-                       m.size[i] = 1 << 30
-               }
-       }
-
-       if err := m.pack(); err != nil {
-               r.Err = errors.New("Native Client RPC Start " + name + ": preparing request: " + err.Error())
-               r.Done <- r
-               return
-       }
-
-       r.c.outMu.Lock()
-       r.c.s.send(&m)
-       r.c.outMu.Unlock()
-}
-
-// Call is a convenience wrapper that starts the RPC request,
-// waits for it to finish, and then returns the results.
-// Its implementation is:
-//
-//     r.Start(name, arg)
-//     r.Wait()
-//     return r.Ret, r.Errno
-//
-func (c *srpcClient) Call(name string, arg ...interface{}) (ret []interface{}, err error) {
-       r := c.NewRPC(nil)
-       r.Start(name, arg)
-       r.Wait()
-       return r.Ret, r.Err
-}
-
-// NewRPC creates a new RPC on the client connection.
-func (c *srpcClient) NewRPC(done chan *srpc) *srpc {
-       if done == nil {
-               done = make(chan *srpc, 1)
-       }
-       c.mu.Lock()
-       id := c.idGen
-       c.idGen++
-       c.mu.Unlock()
-       return &srpc{Done: done, c: c, id: id}
-}
-
-// The current protocol number.
-// Kind of useless, since there have been backwards-incompatible changes
-// to the wire protocol that did not update the protocol number.
-// At this point it's really just a sanity check.
-const protocol = 0xc0da0002
-
-// An srpcErrno is an SRPC status code.
-type srpcErrno uint32
-
-const (
-       srpcOK srpcErrno = 256 + iota
-       srpcErrBreak
-       srpcErrMessageTruncated
-       srpcErrNoMemory
-       srpcErrProtocolMismatch
-       srpcErrBadRPCNumber
-       srpcErrBadArgType
-       srpcErrTooFewArgs
-       srpcErrTooManyArgs
-       srpcErrInArgTypeMismatch
-       srpcErrOutArgTypeMismatch
-       srpcErrInternalError
-       srpcErrAppError
-)
-
-var srpcErrstr = [...]string{
-       srpcOK - srpcOK:                    "ok",
-       srpcErrBreak - srpcOK:              "break",
-       srpcErrMessageTruncated - srpcOK:   "message truncated",
-       srpcErrNoMemory - srpcOK:           "out of memory",
-       srpcErrProtocolMismatch - srpcOK:   "protocol mismatch",
-       srpcErrBadRPCNumber - srpcOK:       "invalid RPC method number",
-       srpcErrBadArgType - srpcOK:         "unexpected argument type",
-       srpcErrTooFewArgs - srpcOK:         "too few arguments",
-       srpcErrTooManyArgs - srpcOK:        "too many arguments",
-       srpcErrInArgTypeMismatch - srpcOK:  "input argument type mismatch",
-       srpcErrOutArgTypeMismatch - srpcOK: "output argument type mismatch",
-       srpcErrInternalError - srpcOK:      "internal error",
-       srpcErrAppError - srpcOK:           "application error",
-}
-
-func (e srpcErrno) Error() string {
-       if e < srpcOK || int(e-srpcOK) >= len(srpcErrstr) {
-               return "srpcErrno(" + itoa(int(e)) + ")"
-       }
-       return srpcErrstr[e-srpcOK]
-}
-
-// A msgHdr is the data argument to the imc_recvmsg
-// and imc_sendmsg system calls.
-type msgHdr struct {
-       iov   *iov
-       niov  int32
-       desc  *int32
-       ndesc int32
-       flags uint32
-}
-
-// A single region for I/O.
-type iov struct {
-       base *byte
-       len  int32
-}
-
-const maxMsgSize = 1<<16 - 4*4
-
-// A msgReceiver receives messages from a file descriptor.
-type msgReceiver struct {
-       fd   int
-       data [maxMsgSize]byte
-       desc [8]int32
-       hdr  msgHdr
-       iov  iov
-}
-
-func (r *msgReceiver) recv() (*msg, error) {
-       // Init pointers to buffers where syscall recvmsg can write.
-       r.iov.base = &r.data[0]
-       r.iov.len = int32(len(r.data))
-       r.hdr.iov = &r.iov
-       r.hdr.niov = 1
-       r.hdr.desc = &r.desc[0]
-       r.hdr.ndesc = int32(len(r.desc))
-       n, _, e := Syscall(sys_imc_recvmsg, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0)
-       if e != 0 {
-               println("Native Client imc_recvmsg: ", e.Error())
-               return nil, e
-       }
-
-       // Make a copy of the data so that the next recvmsg doesn't
-       // smash it.  The system call did not update r.iov.len.  Instead it
-       // returned the total byte count as n.
-       m := new(msg)
-       m.data = make([]byte, n)
-       copy(m.data, r.data[0:])
-
-       // Make a copy of the desc too.
-       // The system call *did* update r.hdr.ndesc.
-       if r.hdr.ndesc > 0 {
-               m.desc = make([]int32, r.hdr.ndesc)
-               copy(m.desc, r.desc[:])
-       }
-
-       return m, nil
-}
-
-// A msgSender sends messages on a file descriptor.
-type msgSender struct {
-       fd  int
-       hdr msgHdr
-       iov iov
-}
-
-func (s *msgSender) send(m *msg) error {
-       if len(m.data) > 0 {
-               s.iov.base = &m.data[0]
-       }
-       s.iov.len = int32(len(m.data))
-       s.hdr.iov = &s.iov
-       s.hdr.niov = 1
-       s.hdr.desc = nil
-       s.hdr.ndesc = 0
-       _, _, e := Syscall(sys_imc_sendmsg, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0)
-       if e != 0 {
-               println("Native Client imc_sendmsg: ", e.Error())
-               return e
-       }
-       return nil
-}
-
-// A msg is the Go representation of an SRPC message.
-type msg struct {
-       data []byte  // message data
-       desc []int32 // message file descriptors
-
-       // parsed version of message
-       id        uint32
-       isRequest uint32
-       rpc       uint32
-       status    uint32
-       value     []interface{}
-       template  []interface{}
-       size      []int
-       format    string
-       broken    bool
-}
-
-// reading from a msg
-
-func (m *msg) uint32() uint32 {
-       if m.broken {
-               return 0
-       }
-       if len(m.data) < 4 {
-               m.broken = true
-               return 0
-       }
-       b := m.data[:4]
-       x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-       m.data = m.data[4:]
-       return x
-}
-
-func (m *msg) uint64() uint64 {
-       x := uint64(m.uint32()) | uint64(m.uint32())<<32
-       if m.broken {
-               return 0
-       }
-       return x
-}
-
-func (m *msg) bytes(n int) []byte {
-       if m.broken {
-               return nil
-       }
-       if len(m.data) < n {
-               m.broken = true
-               return nil
-       }
-       x := m.data[0:n]
-       m.data = m.data[n:]
-       return x
-}
-
-// writing to a msg
-
-func (m *msg) wuint32(x uint32) {
-       m.data = append(m.data, byte(x), byte(x>>8), byte(x>>16), byte(x>>24))
-}
-
-func (m *msg) wuint64(x uint64) {
-       lo := uint32(x)
-       hi := uint32(x >> 32)
-       m.data = append(m.data, byte(lo), byte(lo>>8), byte(lo>>16), byte(lo>>24), byte(hi), byte(hi>>8), byte(hi>>16), byte(hi>>24))
-}
-
-func (m *msg) wbytes(p []byte) {
-       m.data = append(m.data, p...)
-}
-
-func (m *msg) wstring(s string) {
-       m.data = append(m.data, s...)
-}
-
-// Parsing of RPC messages.
-//
-// Each message begins with
-//     total_size uint32
-//     total_descs uint32
-//     fragment_size uint32
-//     fragment_descs uint32
-//
-// If fragment_size < total_size or fragment_descs < total_descs, the actual
-// message is broken up in multiple messages; follow-up messages omit
-// the "total" fields and begin with the "fragment" fields.
-// We do not support putting fragmented messages back together.
-// To do this we would need to change the message receiver.
-//
-// After that size information, the message header follows:
-//     protocol uint32
-//     requestID uint32
-//     isRequest uint32
-//     rpcNumber uint32
-//     status uint32
-//     numValue uint32
-//     numTemplate uint32
-//
-// After the header come numTemplate fixed-size arguments,
-// numValue fixed-size arguments, and then the variable-sized
-// part of the values. The templates describe the expected results
-// and have no associated variable sized data in the request.
-//
-// Each fixed-size argument has the form:
-//     tag uint32 // really a char, like 'b' or 'C'
-//     pad uint32 // unused
-//     val1 uint32
-//     val2 uint32
-//
-// The tags are:
-//     'b':    bool; val1 == 0 or 1
-//     'C':    []byte; val1 == len, data in variable-sized section
-//     'd':    float64; (val1, val2) is data
-//     'D':    []float64; val1 == len, data in variable-sized section
-//     'h':    int; val1 == file descriptor
-//     'i':    int32; descriptor in next entry in m.desc
-//     'I':    []int; val1 == len, data in variable-sized section
-//     's':    string; val1 == len, data in variable-sized section
-//
-
-func (m *msg) pack() error {
-       m.data = m.data[:0]
-       m.desc = m.desc[:0]
-
-       // sizes, to fill in later
-       m.wuint32(0)
-       m.wuint32(0)
-       m.wuint32(0)
-       m.wuint32(0)
-
-       // message header
-       m.wuint32(protocol)
-       m.wuint32(m.id)
-       m.wuint32(m.isRequest)
-       m.wuint32(m.rpc)
-       m.wuint32(m.status)
-       m.wuint32(uint32(len(m.value)))
-       m.wuint32(uint32(len(m.template)))
-
-       // fixed-size templates
-       for i, x := range m.template {
-               var tag, val1, val2 uint32
-               switch x.(type) {
-               default:
-                       return errors.New("unexpected template type")
-               case bool:
-                       tag = 'b'
-               case []byte:
-                       tag = 'C'
-                       val1 = uint32(m.size[i])
-               case float64:
-                       tag = 'd'
-               case []float64:
-                       tag = 'D'
-                       val1 = uint32(m.size[i])
-               case int:
-                       tag = 'h'
-               case int32:
-                       tag = 'i'
-               case []int32:
-                       tag = 'I'
-                       val1 = uint32(m.size[i])
-               case string:
-                       tag = 's'
-                       val1 = uint32(m.size[i])
-               }
-               m.wuint32(tag)
-               m.wuint32(0)
-               m.wuint32(val1)
-               m.wuint32(val2)
-       }
-
-       // fixed-size values
-       for _, x := range m.value {
-               var tag, val1, val2 uint32
-               switch x := x.(type) {
-               default:
-                       return errors.New("unexpected value type")
-               case bool:
-                       tag = 'b'
-                       if x {
-                               val1 = 1
-                       }
-               case []byte:
-                       tag = 'C'
-                       val1 = uint32(len(x))
-               case float64:
-                       tag = 'd'
-                       v := float64bits(x)
-                       val1 = uint32(v)
-                       val2 = uint32(v >> 32)
-               case []float64:
-                       tag = 'D'
-                       val1 = uint32(len(x))
-               case int32:
-                       tag = 'i'
-                       m.desc = append(m.desc, x)
-               case []int32:
-                       tag = 'I'
-                       val1 = uint32(len(x))
-               case string:
-                       tag = 's'
-                       val1 = uint32(len(x) + 1)
-               }
-               m.wuint32(tag)
-               m.wuint32(0)
-               m.wuint32(val1)
-               m.wuint32(val2)
-       }
-
-       // variable-length data for values
-       for _, x := range m.value {
-               switch x := x.(type) {
-               case []byte:
-                       m.wbytes(x)
-               case []float64:
-                       for _, f := range x {
-                               m.wuint64(float64bits(f))
-                       }
-               case []int32:
-                       for _, j := range x {
-                               m.wuint32(uint32(j))
-                       }
-               case string:
-                       m.wstring(x)
-                       m.wstring("\x00")
-               }
-       }
-
-       // fill in sizes
-       data := m.data
-       m.data = m.data[:0]
-       m.wuint32(uint32(len(data)))
-       m.wuint32(uint32(len(m.desc)))
-       m.wuint32(uint32(len(data)))
-       m.wuint32(uint32(len(m.desc)))
-       m.data = data
-
-       return nil
-}
-
-func (m *msg) unpack() error {
-       totalSize := m.uint32()
-       totalDesc := m.uint32()
-       fragSize := m.uint32()
-       fragDesc := m.uint32()
-       if totalSize != fragSize || totalDesc != fragDesc {
-               return errors.New("Native Client: fragmented RPC messages not supported")
-       }
-       if m.uint32() != protocol {
-               return errors.New("Native Client: RPC protocol mismatch")
-       }
-
-       // message header
-       m.id = m.uint32()
-       m.isRequest = m.uint32()
-       m.rpc = m.uint32()
-       m.status = m.uint32()
-       m.value = make([]interface{}, m.uint32())
-       m.template = make([]interface{}, m.uint32())
-       m.size = make([]int, len(m.template))
-       if m.broken {
-               return errors.New("Native Client: malformed message")
-       }
-
-       // fixed-size templates
-       for i := range m.template {
-               tag := m.uint32()
-               m.uint32() // padding
-               val1 := m.uint32()
-               m.uint32() // val2
-               switch tag {
-               default:
-                       return errors.New("Native Client: unexpected template type " + string(rune(tag)))
-               case 'b':
-                       m.template[i] = false
-               case 'C':
-                       m.template[i] = []byte(nil)
-                       m.size[i] = int(val1)
-               case 'd':
-                       m.template[i] = float64(0)
-               case 'D':
-                       m.template[i] = []float64(nil)
-                       m.size[i] = int(val1)
-               case 'i':
-                       m.template[i] = int32(0)
-               case 'I':
-                       m.template[i] = []int32(nil)
-                       m.size[i] = int(val1)
-               case 'h':
-                       m.template[i] = int(0)
-               case 's':
-                       m.template[i] = ""
-                       m.size[i] = int(val1)
-               }
-       }
-
-       // fixed-size values
-       var (
-               strsize []uint32
-               d       int
-       )
-       for i := range m.value {
-               tag := m.uint32()
-               m.uint32() // padding
-               val1 := m.uint32()
-               val2 := m.uint32()
-               switch tag {
-               default:
-                       return errors.New("Native Client: unexpected value type " + string(rune(tag)))
-               case 'b':
-                       m.value[i] = val1 > 0
-               case 'C':
-                       m.value[i] = []byte(nil)
-                       strsize = append(strsize, val1)
-               case 'd':
-                       m.value[i] = float64frombits(uint64(val1) | uint64(val2)<<32)
-               case 'D':
-                       m.value[i] = make([]float64, val1)
-               case 'i':
-                       m.value[i] = int32(val1)
-               case 'I':
-                       m.value[i] = make([]int32, val1)
-               case 'h':
-                       m.value[i] = int(m.desc[d])
-                       d++
-               case 's':
-                       m.value[i] = ""
-                       strsize = append(strsize, val1)
-               }
-       }
-
-       // variable-sized parts of values
-       for i, x := range m.value {
-               switch x := x.(type) {
-               case []byte:
-                       m.value[i] = m.bytes(int(strsize[0]))
-                       strsize = strsize[1:]
-               case []float64:
-                       for i := range x {
-                               x[i] = float64frombits(m.uint64())
-                       }
-               case []int32:
-                       for i := range x {
-                               x[i] = int32(m.uint32())
-                       }
-               case string:
-                       m.value[i] = string(m.bytes(int(strsize[0])))
-                       strsize = strsize[1:]
-               }
-       }
-
-       if len(m.data) > 0 {
-               return errors.New("Native Client: junk at end of message")
-       }
-       return nil
-}
-
-func float64bits(x float64) uint64 {
-       return *(*uint64)(unsafe.Pointer(&x))
-}
-
-func float64frombits(x uint64) float64 {
-       return *(*float64)(unsafe.Pointer(&x))
-}
-
-// At startup, connect to the name service.
-var nsClient = nsConnect()
-
-func nsConnect() *srpcClient {
-       var ns int32 = -1
-       _, _, errno := Syscall(sys_nameservice, uintptr(unsafe.Pointer(&ns)), 0, 0)
-       if errno != 0 {
-               println("Native Client nameservice:", errno.Error())
-               return nil
-       }
-
-       sock, _, errno := Syscall(sys_imc_connect, uintptr(ns), 0, 0)
-       if errno != 0 {
-               println("Native Client nameservice connect:", errno.Error())
-               return nil
-       }
-
-       c, err := newClient(int(sock))
-       if err != nil {
-               println("Native Client nameservice init:", err.Error())
-               return nil
-       }
-
-       return c
-}
-
-const (
-       nsSuccess               = 0
-       nsNameNotFound          = 1
-       nsDuplicateName         = 2
-       nsInsufficientResources = 3
-       nsPermissionDenied      = 4
-       nsInvalidArgument       = 5
-)
-
-func openNamedService(name string, mode int32) (fd int, err error) {
-       if nsClient == nil {
-               return 0, errors.New("no name service")
-       }
-       ret, err := nsClient.Call("lookup:si:ih", name, int32(mode))
-       if err != nil {
-               return 0, err
-       }
-       status := ret[0].(int32)
-       fd = ret[1].(int)
-       switch status {
-       case nsSuccess:
-               // ok
-       case nsNameNotFound:
-               return -1, ENOENT
-       case nsDuplicateName:
-               return -1, EEXIST
-       case nsInsufficientResources:
-               return -1, EWOULDBLOCK
-       case nsPermissionDenied:
-               return -1, EPERM
-       case nsInvalidArgument:
-               return -1, EINVAL
-       default:
-               return -1, EINVAL
-       }
-       return fd, nil
-}