summaryrefslogtreecommitdiff
path: root/src/pkg/syscall/fd_nacl.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/syscall/fd_nacl.go')
-rw-r--r--src/pkg/syscall/fd_nacl.go326
1 files changed, 0 insertions, 326 deletions
diff --git a/src/pkg/syscall/fd_nacl.go b/src/pkg/syscall/fd_nacl.go
deleted file mode 100644
index 74324142a..000000000
--- a/src/pkg/syscall/fd_nacl.go
+++ /dev/null
@@ -1,326 +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.
-
-// File descriptor support for Native Client.
-// We want to provide access to a broader range of (simulated) files than
-// Native Client allows, so we maintain our own file descriptor table exposed
-// to higher-level packages.
-
-package syscall
-
-import (
- "sync"
-)
-
-// files is the table indexed by a file descriptor.
-var files struct {
- sync.RWMutex
- tab []*file
-}
-
-// A file is an open file, something with a file descriptor.
-// A particular *file may appear in files multiple times, due to use of Dup or Dup2.
-type file struct {
- fdref int // uses in files.tab
- impl fileImpl // underlying implementation
-}
-
-// A fileImpl is the implementation of something that can be a file.
-type fileImpl interface {
- // Standard operations.
- // These can be called concurrently from multiple goroutines.
- stat(*Stat_t) error
- read([]byte) (int, error)
- write([]byte) (int, error)
- seek(int64, int) (int64, error)
- pread([]byte, int64) (int, error)
- pwrite([]byte, int64) (int, error)
-
- // Close is called when the last reference to a *file is removed
- // from the file descriptor table. It may be called concurrently
- // with active operations such as blocked read or write calls.
- close() error
-}
-
-// newFD adds impl to the file descriptor table,
-// returning the new file descriptor.
-// Like Unix, it uses the lowest available descriptor.
-func newFD(impl fileImpl) int {
- files.Lock()
- defer files.Unlock()
- f := &file{impl: impl, fdref: 1}
- for fd, oldf := range files.tab {
- if oldf == nil {
- files.tab[fd] = f
- return fd
- }
- }
- fd := len(files.tab)
- files.tab = append(files.tab, f)
- return fd
-}
-
-// Install Native Client stdin, stdout, stderr.
-func init() {
- newFD(&naclFile{naclFD: 0})
- newFD(&naclFile{naclFD: 1})
- newFD(&naclFile{naclFD: 2})
-}
-
-// fdToFile retrieves the *file corresponding to a file descriptor.
-func fdToFile(fd int) (*file, error) {
- files.Lock()
- defer files.Unlock()
- if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil {
- return nil, EBADF
- }
- return files.tab[fd], nil
-}
-
-func Close(fd int) error {
- files.Lock()
- if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil {
- files.Unlock()
- return EBADF
- }
- f := files.tab[fd]
- files.tab[fd] = nil
- f.fdref--
- fdref := f.fdref
- files.Unlock()
- if fdref > 0 {
- return nil
- }
- return f.impl.close()
-}
-
-func CloseOnExec(fd int) {
- // nothing to do - no exec
-}
-
-func Dup(fd int) (int, error) {
- files.Lock()
- defer files.Unlock()
- if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil {
- return -1, EBADF
- }
- f := files.tab[fd]
- f.fdref++
- for newfd, oldf := range files.tab {
- if oldf == nil {
- files.tab[newfd] = f
- return newfd, nil
- }
- }
- newfd := len(files.tab)
- files.tab = append(files.tab, f)
- return newfd, nil
-}
-
-func Dup2(fd, newfd int) error {
- files.Lock()
- defer files.Unlock()
- if fd < 0 || fd >= len(files.tab) || files.tab[fd] == nil || newfd < 0 || newfd >= len(files.tab)+100 {
- files.Unlock()
- return EBADF
- }
- f := files.tab[fd]
- f.fdref++
- for cap(files.tab) <= newfd {
- files.tab = append(files.tab[:cap(files.tab)], nil)
- }
- oldf := files.tab[newfd]
- var oldfdref int
- if oldf != nil {
- oldf.fdref--
- oldfdref = oldf.fdref
- }
- files.tab[newfd] = f
- files.Unlock()
- if oldf != nil {
- if oldfdref == 0 {
- oldf.impl.close()
- }
- }
- return nil
-}
-
-func Fstat(fd int, st *Stat_t) error {
- f, err := fdToFile(fd)
- if err != nil {
- return err
- }
- return f.impl.stat(st)
-}
-
-func Read(fd int, b []byte) (int, error) {
- f, err := fdToFile(fd)
- if err != nil {
- return 0, err
- }
- return f.impl.read(b)
-}
-
-var zerobuf [0]byte
-
-func Write(fd int, b []byte) (int, error) {
- if b == nil {
- // avoid nil in syscalls; nacl doesn't like that.
- b = zerobuf[:]
- }
- f, err := fdToFile(fd)
- if err != nil {
- return 0, err
- }
- return f.impl.write(b)
-}
-
-func Pread(fd int, b []byte, offset int64) (int, error) {
- f, err := fdToFile(fd)
- if err != nil {
- return 0, err
- }
- return f.impl.pread(b, offset)
-}
-
-func Pwrite(fd int, b []byte, offset int64) (int, error) {
- f, err := fdToFile(fd)
- if err != nil {
- return 0, err
- }
- return f.impl.pwrite(b, offset)
-}
-
-func Seek(fd int, offset int64, whence int) (int64, error) {
- f, err := fdToFile(fd)
- if err != nil {
- return 0, err
- }
- return f.impl.seek(offset, whence)
-}
-
-// defaulFileImpl implements fileImpl.
-// It can be embedded to complete a partial fileImpl implementation.
-type defaultFileImpl struct{}
-
-func (*defaultFileImpl) close() error { return nil }
-func (*defaultFileImpl) stat(*Stat_t) error { return ENOSYS }
-func (*defaultFileImpl) read([]byte) (int, error) { return 0, ENOSYS }
-func (*defaultFileImpl) write([]byte) (int, error) { return 0, ENOSYS }
-func (*defaultFileImpl) seek(int64, int) (int64, error) { return 0, ENOSYS }
-func (*defaultFileImpl) pread([]byte, int64) (int, error) { return 0, ENOSYS }
-func (*defaultFileImpl) pwrite([]byte, int64) (int, error) { return 0, ENOSYS }
-
-// naclFile is the fileImpl implementation for a Native Client file descriptor.
-type naclFile struct {
- defaultFileImpl
- naclFD int
-}
-
-func (f *naclFile) stat(st *Stat_t) error {
- return naclFstat(f.naclFD, st)
-}
-
-func (f *naclFile) read(b []byte) (int, error) {
- n, err := naclRead(f.naclFD, b)
- if err != nil {
- n = 0
- }
- return n, err
-}
-
-// implemented in package runtime, to add time header on playground
-func naclWrite(fd int, b []byte) int
-
-func (f *naclFile) write(b []byte) (int, error) {
- n := naclWrite(f.naclFD, b)
- if n < 0 {
- return 0, Errno(-n)
- }
- return n, nil
-}
-
-func (f *naclFile) seek(off int64, whence int) (int64, error) {
- old := off
- err := naclSeek(f.naclFD, &off, whence)
- if err != nil {
- return old, err
- }
- return off, nil
-}
-
-func (f *naclFile) prw(b []byte, offset int64, rw func([]byte) (int, error)) (int, error) {
- // NaCl has no pread; simulate with seek and hope for no races.
- old, err := f.seek(0, 1)
- if err != nil {
- return 0, err
- }
- if _, err := f.seek(offset, 0); err != nil {
- return 0, err
- }
- n, err := rw(b)
- f.seek(old, 0)
- return n, err
-}
-
-func (f *naclFile) pread(b []byte, offset int64) (int, error) {
- return f.prw(b, offset, f.read)
-}
-
-func (f *naclFile) pwrite(b []byte, offset int64) (int, error) {
- return f.prw(b, offset, f.write)
-}
-
-func (f *naclFile) close() error {
- err := naclClose(f.naclFD)
- f.naclFD = -1
- return err
-}
-
-// A pipeFile is an in-memory implementation of a pipe.
-// The byteq implementation is in net_nacl.go.
-type pipeFile struct {
- defaultFileImpl
- rd *byteq
- wr *byteq
-}
-
-func (f *pipeFile) close() error {
- if f.rd != nil {
- f.rd.close()
- }
- if f.wr != nil {
- f.wr.close()
- }
- return nil
-}
-
-func (f *pipeFile) read(b []byte) (int, error) {
- if f.rd == nil {
- return 0, EINVAL
- }
- n, err := f.rd.read(b, 0)
- if err == EAGAIN {
- err = nil
- }
- return n, err
-}
-
-func (f *pipeFile) write(b []byte) (int, error) {
- if f.wr == nil {
- return 0, EINVAL
- }
- n, err := f.wr.write(b, 0)
- if err == EAGAIN {
- err = EPIPE
- }
- return n, err
-}
-
-func Pipe(fd []int) error {
- q := newByteq()
- fd[0] = newFD(&pipeFile{rd: q})
- fd[1] = newFD(&pipeFile{wr: q})
- return nil
-}