Commit 63b8b948 authored by Wei Guangjing's avatar Wei Guangjing Committed by Russ Cox

windows: define and use syscall.Handle

Fixes #1487.

R=rsc, alex.brainman, go.peter.90, mikioh.mikioh, mattn.jp
CC=golang-dev
https://golang.org/cl/4600042
parent 21efa147
// 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 file
import (
"os"
"syscall"
)
type File struct {
fd syscall.Handle // file descriptor number
name string // file name at Open time
}
func newFile(fd syscall.Handle, name string) *File {
if fd < 0 {
return nil
}
return &File{fd, name}
}
var (
Stdin = newFile(syscall.Stdin, "/dev/stdin")
Stdout = newFile(syscall.Stdout, "/dev/stdout")
Stderr = newFile(syscall.Stderr, "/dev/stderr")
)
func OpenFile(name string, mode int, perm uint32) (file *File, err os.Error) {
r, e := syscall.Open(name, mode, perm)
if e != 0 {
err = os.Errno(e)
}
return newFile(r, name), err
}
const (
O_RDONLY = syscall.O_RDONLY
O_RDWR = syscall.O_RDWR
O_CREATE = syscall.O_CREAT
O_TRUNC = syscall.O_TRUNC
)
func Open(name string) (file *File, err os.Error) {
return OpenFile(name, O_RDONLY, 0)
}
func Create(name string) (file *File, err os.Error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
func (file *File) Close() os.Error {
if file == nil {
return os.EINVAL
}
e := syscall.Close(file.fd)
file.fd = syscall.InvalidHandle // so it can't be closed again
if e != 0 {
return os.Errno(e)
}
return nil
}
func (file *File) Read(b []byte) (ret int, err os.Error) {
if file == nil {
return -1, os.EINVAL
}
r, e := syscall.Read(file.fd, b)
if e != 0 {
err = os.Errno(e)
}
return int(r), err
}
func (file *File) Write(b []byte) (ret int, err os.Error) {
if file == nil {
return -1, os.EINVAL
}
r, e := syscall.Write(file.fd, b)
if e != 0 {
err = os.Errno(e)
}
return int(r), err
}
func (file *File) String() string {
return file.name
}
......@@ -14,8 +14,13 @@ fi
rm -f *.$O
if [ "$GOOS" = "windows" ];then
$GC -o file.8 file_windows.go
else
$GC file.go
fi
for i in \
file.go \
helloworld.go \
helloworld3.go \
echo.go \
......
......@@ -19,7 +19,7 @@ func init() { Reader = &rngReader{} }
// A rngReader satisfies reads by reading from the Windows CryptGenRandom API.
type rngReader struct {
prov uint32
prov syscall.Handle
mu sync.Mutex
}
......
......@@ -29,8 +29,8 @@ func init() {
}
}
func closesocket(s int) (errno int) {
return syscall.Closesocket(int32(s))
func closesocket(s syscall.Handle) (errno int) {
return syscall.Closesocket(s)
}
// Interface for all io operations.
......@@ -88,7 +88,7 @@ func (o *bufOp) Init(fd *netFD, buf []byte) {
// iocp and send them to the correspondent waiting client
// goroutine via channel supplied in the request.
type resultSrv struct {
iocp int32
iocp syscall.Handle
}
func (s *resultSrv) Run() {
......@@ -132,7 +132,7 @@ func (s *ioSrv) ProcessRemoteIO() {
case o := <-s.submchan:
o.Op().errnoc <- o.Submit()
case o := <-s.canchan:
o.Op().errnoc <- syscall.CancelIo(uint32(o.Op().fd.sysfd))
o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().fd.sysfd))
}
}
}
......@@ -189,7 +189,7 @@ var onceStartServer sync.Once
func startServer() {
resultsrv = new(resultSrv)
var errno int
resultsrv.iocp, errno = syscall.CreateIoCompletionPort(-1, 0, 0, 1)
resultsrv.iocp, errno = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
if errno != 0 {
panic("CreateIoCompletionPort failed " + syscall.Errstr(errno))
}
......@@ -209,7 +209,7 @@ type netFD struct {
closing bool
// immutable until Close
sysfd int
sysfd syscall.Handle
family int
proto int
net string
......@@ -225,7 +225,7 @@ type netFD struct {
wio sync.Mutex
}
func allocFD(fd, family, proto int, net string) (f *netFD) {
func allocFD(fd syscall.Handle, family, proto int, net string) (f *netFD) {
f = &netFD{
sysfd: fd,
family: family,
......@@ -236,13 +236,13 @@ func allocFD(fd, family, proto int, net string) (f *netFD) {
return f
}
func newFD(fd, family, proto int, net string) (f *netFD, err os.Error) {
func newFD(fd syscall.Handle, family, proto int, net string) (f *netFD, err os.Error) {
if initErr != nil {
return nil, initErr
}
onceStartServer.Do(startServer)
// Associate our socket with resultsrv.iocp.
if _, e := syscall.CreateIoCompletionPort(int32(fd), resultsrv.iocp, 0, 0); e != 0 {
if _, e := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); e != 0 {
return nil, os.Errno(e)
}
return allocFD(fd, family, proto, net), nil
......@@ -280,7 +280,7 @@ func (fd *netFD) decref() {
// use the resultsrv for Close too. Sigh.
syscall.SetNonblock(fd.sysfd, false)
closesocket(fd.sysfd)
fd.sysfd = -1
fd.sysfd = syscall.InvalidHandle
// no need for a finalizer anymore
runtime.SetFinalizer(fd, nil)
}
......@@ -288,7 +288,7 @@ func (fd *netFD) decref() {
}
func (fd *netFD) Close() os.Error {
if fd == nil || fd.sysfd == -1 {
if fd == nil || fd.sysfd == syscall.InvalidHandle {
return os.EINVAL
}
......@@ -307,7 +307,7 @@ type readOp struct {
func (o *readOp) Submit() (errno int) {
var d, f uint32
return syscall.WSARecv(uint32(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
}
func (o *readOp) Name() string {
......@@ -322,7 +322,7 @@ func (fd *netFD) Read(buf []byte) (n int, err os.Error) {
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
if fd.sysfd == -1 {
if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL
}
var o readOp
......@@ -344,7 +344,7 @@ type readFromOp struct {
func (o *readFromOp) Submit() (errno int) {
var d, f uint32
l := int32(unsafe.Sizeof(o.rsa))
return syscall.WSARecvFrom(uint32(o.fd.sysfd), &o.buf, 1, &d, &f, &o.rsa, &l, &o.o, nil)
return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &l, &o.o, nil)
}
func (o *readFromOp) Name() string {
......@@ -362,7 +362,7 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err os.Error)
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
if fd.sysfd == -1 {
if fd.sysfd == syscall.InvalidHandle {
return 0, nil, os.EINVAL
}
var o readFromOp
......@@ -380,7 +380,7 @@ type writeOp struct {
func (o *writeOp) Submit() (errno int) {
var d uint32
return syscall.WSASend(uint32(o.fd.sysfd), &o.buf, 1, &d, 0, &o.o, nil)
return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil)
}
func (o *writeOp) Name() string {
......@@ -395,7 +395,7 @@ func (fd *netFD) Write(buf []byte) (n int, err os.Error) {
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
if fd.sysfd == -1 {
if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL
}
var o writeOp
......@@ -412,7 +412,7 @@ type writeToOp struct {
func (o *writeToOp) Submit() (errno int) {
var d uint32
return syscall.WSASendto(uint32(o.fd.sysfd), &o.buf, 1, &d, 0, o.sa, &o.o, nil)
return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil)
}
func (o *writeToOp) Name() string {
......@@ -430,7 +430,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err os.Error)
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
if fd.sysfd == -1 {
if fd.sysfd == syscall.InvalidHandle {
return 0, os.EINVAL
}
var o writeToOp
......@@ -443,14 +443,14 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err os.Error)
type acceptOp struct {
anOp
newsock int
newsock syscall.Handle
attrs [2]syscall.RawSockaddrAny // space for local and remote address only
}
func (o *acceptOp) Submit() (errno int) {
var d uint32
l := uint32(unsafe.Sizeof(o.attrs[0]))
return syscall.AcceptEx(uint32(o.fd.sysfd), uint32(o.newsock),
return syscall.AcceptEx(o.fd.sysfd, o.newsock,
(*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &d, &o.o)
}
......@@ -459,7 +459,7 @@ func (o *acceptOp) Name() string {
}
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) {
if fd == nil || fd.sysfd == -1 {
if fd == nil || fd.sysfd == syscall.InvalidHandle {
return nil, os.EINVAL
}
fd.incref()
......@@ -478,7 +478,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
// Associate our new socket with IOCP.
onceStartServer.Do(startServer)
if _, e = syscall.CreateIoCompletionPort(int32(s), resultsrv.iocp, 0, 0); e != 0 {
if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 {
return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)}
}
......@@ -493,7 +493,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
}
// Inherit properties of the listening socket.
e = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, fd.sysfd)
e = syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, int(fd.sysfd))
if e != 0 {
closesocket(s)
return nil, err
......
......@@ -42,12 +42,12 @@ func getInterfaceList() ([]syscall.InterfaceInfo, os.Error) {
if e != 0 {
return nil, os.NewSyscallError("Socket", e)
}
defer syscall.Closesocket(int32(s))
defer syscall.Closesocket(s)
ii := [20]syscall.InterfaceInfo{}
ret := uint32(0)
size := uint32(unsafe.Sizeof(ii))
e = syscall.WSAIoctl(int32(s), syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
e = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&ii[0])), size, &ret, nil, 0)
if e != 0 {
return nil, os.NewSyscallError("WSAIoctl", e)
}
......
......@@ -26,28 +26,26 @@ import (
// boolean value is true, kernel supports IPv6 IPv4-mapping.
func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
var probes = []struct {
s int
la TCPAddr
ok bool
}{
// IPv6 communication capability
{-1, TCPAddr{IP: ParseIP("::1")}, false},
{TCPAddr{IP: ParseIP("::1")}, false},
// IPv6 IPv4-mapped address communication capability
{-1, TCPAddr{IP: IPv4(127, 0, 0, 1)}, false},
{TCPAddr{IP: IPv4(127, 0, 0, 1)}, false},
}
var errno int
for i := range probes {
probes[i].s, errno = syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
s, errno := syscall.Socket(syscall.AF_INET6, syscall.SOCK_STREAM, syscall.IPPROTO_TCP)
if errno != 0 {
continue
}
defer closesocket(probes[i].s)
defer closesocket(s)
sa, err := probes[i].la.toAddr().sockaddr(syscall.AF_INET6)
if err != nil {
continue
}
errno = syscall.Bind(probes[i].s, sa)
errno = syscall.Bind(s, sa)
if errno != 0 {
continue
}
......
......@@ -12,12 +12,12 @@ import (
type sendfileOp struct {
anOp
src int32 // source
src syscall.Handle // source
n uint32
}
func (o *sendfileOp) Submit() (errno int) {
return syscall.TransmitFile(int32(o.fd.sysfd), o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
return syscall.TransmitFile(o.fd.sysfd, o.src, o.n, 0, &o.o, nil, syscall.TF_WRITE_BEHIND)
}
func (o *sendfileOp) Name() string {
......@@ -56,7 +56,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool)
var o sendfileOp
o.Init(c)
o.n = uint32(n)
o.src = int32(f.Fd())
o.src = f.Fd()
done, err := iosrv.ExecIO(&o, 0)
if err != nil {
return 0, err, false
......
......@@ -50,8 +50,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
if ra != nil {
if err = fd.connect(ra); err != nil {
fd.sysfd = -1
closesocket(s)
fd.Close()
return nil, err
}
}
......@@ -65,25 +64,25 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
return fd, nil
}
func setsockoptInt(fd, level, opt int, value int) os.Error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd, level, opt, value))
func setsockoptInt(fd *netFD, level, opt int, value int) os.Error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, level, opt, value))
}
func setsockoptNsec(fd, level, opt int, nsec int64) os.Error {
func setsockoptNsec(fd *netFD, level, opt int, nsec int64) os.Error {
var tv = syscall.NsecToTimeval(nsec)
return os.NewSyscallError("setsockopt", syscall.SetsockoptTimeval(fd, level, opt, &tv))
return os.NewSyscallError("setsockopt", syscall.SetsockoptTimeval(fd.sysfd, level, opt, &tv))
}
func setReadBuffer(fd *netFD, bytes int) os.Error {
fd.incref()
defer fd.decref()
return setsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
}
func setWriteBuffer(fd *netFD, bytes int) os.Error {
fd.incref()
defer fd.decref()
return setsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
}
func setReadTimeout(fd *netFD, nsec int64) os.Error {
......@@ -106,7 +105,7 @@ func setTimeout(fd *netFD, nsec int64) os.Error {
func setReuseAddr(fd *netFD, reuse bool) os.Error {
fd.incref()
defer fd.decref()
return setsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, boolint(reuse))
}
func bindToDevice(fd *netFD, dev string) os.Error {
......@@ -117,19 +116,19 @@ func bindToDevice(fd *netFD, dev string) os.Error {
func setDontRoute(fd *netFD, dontroute bool) os.Error {
fd.incref()
defer fd.decref()
return setsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_DONTROUTE, boolint(dontroute))
}
func setKeepAlive(fd *netFD, keepalive bool) os.Error {
fd.incref()
defer fd.decref()
return setsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
return setsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
}
func setNoDelay(fd *netFD, noDelay bool) os.Error {
fd.incref()
defer fd.decref()
return setsockoptInt(fd.sysfd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
return setsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_NODELAY, boolint(noDelay))
}
func setLinger(fd *netFD, sec int) os.Error {
......
......@@ -10,7 +10,7 @@ import (
"syscall"
)
func setKernelSpecificSockopt(s, f int) {
func setKernelSpecificSockopt(s syscall.Handle, f int) {
// Allow reuse of recently-used addresses and ports.
syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
......
......@@ -119,7 +119,7 @@ func init() {
if e != 0 {
return
}
defer syscall.LocalFree(uint32(uintptr(unsafe.Pointer(argv))))
defer syscall.LocalFree(syscall.Handle(uintptr(unsafe.Pointer(argv))))
Args = make([]string, argc)
for i, v := range (*argv)[:argc] {
Args[i] = string(syscall.UTF16ToString((*v)[:]))
......
......@@ -35,16 +35,9 @@ func StartProcess(name string, argv []string, attr *ProcAttr) (p *Process, err E
if sysattr.Env == nil {
sysattr.Env = Environ()
}
// Create array of integer (system) fds.
intfd := make([]int, len(attr.Files))
for i, f := range attr.Files {
if f == nil {
intfd[i] = -1
} else {
intfd[i] = f.Fd()
for _, f := range attr.Files {
sysattr.Files = append(sysattr.Files, f.Fd())
}
}
sysattr.Files = intfd
pid, h, e := syscall.StartProcess(name, argv, sysattr)
if iserror(e) {
......
......@@ -10,7 +10,7 @@ import (
)
func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
s, e := syscall.WaitForSingleObject(int32(p.handle), syscall.INFINITE)
s, e := syscall.WaitForSingleObject(syscall.Handle(p.handle), syscall.INFINITE)
switch s {
case syscall.WAIT_OBJECT_0:
break
......@@ -20,7 +20,7 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
return nil, NewError("os: unexpected result from WaitForSingleObject")
}
var ec uint32
e = syscall.GetExitCodeProcess(int32(p.handle), &ec)
e = syscall.GetExitCodeProcess(syscall.Handle(p.handle), &ec)
if e != 0 {
return nil, NewSyscallError("GetExitCodeProcess", e)
}
......@@ -31,7 +31,7 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
func (p *Process) Signal(sig Signal) Error {
switch sig.(UnixSignal) {
case SIGKILL:
e := syscall.TerminateProcess(int32(p.handle), 1)
e := syscall.TerminateProcess(syscall.Handle(p.handle), 1)
return NewSyscallError("TerminateProcess", e)
}
return Errno(syscall.EWINDOWS)
......@@ -41,7 +41,7 @@ func (p *Process) Release() Error {
if p.handle == -1 {
return EINVAL
}
e := syscall.CloseHandle(int32(p.handle))
e := syscall.CloseHandle(syscall.Handle(p.handle))
if e != 0 {
return NewSyscallError("CloseHandle", e)
}
......
......@@ -9,36 +9,12 @@
package os
import (
"runtime"
"sync"
"syscall"
)
// File represents an open file descriptor.
type File struct {
fd int
name string
dirinfo *dirInfo // nil unless directory being read
nepipe int // number of consecutive EPIPE in Write
l sync.Mutex // used to implement windows pread/pwrite
}
// Fd returns the integer Unix file descriptor referencing the open file.
func (file *File) Fd() int { return file.fd }
// Name returns the name of the file as presented to Open.
func (file *File) Name() string { return file.name }
// NewFile returns a new File with the given file descriptor and name.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := &File{fd: fd, name: name}
runtime.SetFinalizer(f, (*File).Close)
return f
}
// Stdin, Stdout, and Stderr are open Files pointing to the standard input,
// standard output, and standard error file descriptors.
var (
......
......@@ -21,26 +21,6 @@ func epipecheck(file *File, e int) {
}
}
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an Error, if any.
func Pipe() (r *File, w *File, err Error) {
var p [2]int
// See ../syscall/exec.go for description of lock.
syscall.ForkLock.RLock()
e := syscall.Pipe(p[0:])
if iserror(e) {
syscall.ForkLock.RUnlock()
return nil, nil, NewSyscallError("pipe", e)
}
syscall.CloseOnExec(p[0])
syscall.CloseOnExec(p[1])
syscall.ForkLock.RUnlock()
return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
}
// Stat returns a FileInfo structure describing the named file and an error, if any.
// If name names a valid symbolic link, the returned FileInfo describes
// the file pointed at by the link and has fi.FollowedSymlink set to true.
......
......@@ -6,9 +6,37 @@ package os
import (
"runtime"
"sync"
"syscall"
)
// File represents an open file descriptor.
type File struct {
fd int
name string
dirinfo *dirInfo // nil unless directory being read
nepipe int // number of consecutive EPIPE in Write
l sync.Mutex // used to implement windows pread/pwrite
}
// Fd returns the integer Unix file descriptor referencing the open file.
func (file *File) Fd() int {
if file == nil {
return -1
}
return file.fd
}
// NewFile returns a new File with the given file descriptor and name.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := &File{fd: fd, name: name}
runtime.SetFinalizer(f, (*File).Close)
return f
}
// Auxiliary information if the File describes a directory
type dirInfo struct {
buf []byte // buffer for directory I/O
......@@ -161,3 +189,22 @@ func basename(name string) string {
return name
}
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an Error, if any.
func Pipe() (r *File, w *File, err Error) {
var p [2]int
// See ../syscall/exec.go for description of lock.
syscall.ForkLock.RLock()
e := syscall.Pipe(p[0:])
if iserror(e) {
syscall.ForkLock.RUnlock()
return nil, nil, NewSyscallError("pipe", e)
}
syscall.CloseOnExec(p[0])
syscall.CloseOnExec(p[1])
syscall.ForkLock.RUnlock()
return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
}
......@@ -6,9 +6,37 @@ package os
import (
"runtime"
"sync"
"syscall"
)
// File represents an open file descriptor.
type File struct {
fd syscall.Handle
name string
dirinfo *dirInfo // nil unless directory being read
nepipe int // number of consecutive EPIPE in Write
l sync.Mutex // used to implement windows pread/pwrite
}
// Fd returns the Windows handle referencing the open file.
func (file *File) Fd() syscall.Handle {
if file == nil {
return syscall.InvalidHandle
}
return file.fd
}
// NewFile returns a new File with the given file descriptor and name.
func NewFile(fd syscall.Handle, name string) *File {
if fd < 0 {
return nil
}
f := &File{fd: fd, name: name}
runtime.SetFinalizer(f, (*File).Close)
return f
}
// Auxiliary information if the File describes a directory
type dirInfo struct {
stat syscall.Stat_t
......@@ -40,7 +68,7 @@ func openDir(name string) (file *File, err Error) {
if e != 0 {
return nil, &PathError{"open", name, Errno(e)}
}
f := NewFile(int(r), name)
f := NewFile(r, name)
d.usefirststat = true
f.dirinfo = d
return f, nil
......@@ -85,15 +113,15 @@ func (file *File) Close() Error {
}
var e int
if file.isdir() {
e = syscall.FindClose(int32(file.fd))
e = syscall.FindClose(syscall.Handle(file.fd))
} else {
e = syscall.CloseHandle(int32(file.fd))
e = syscall.CloseHandle(syscall.Handle(file.fd))
}
var err Error
if e != 0 {
err = &PathError{"close", file.name, Errno(e)}
}
file.fd = -1 // so it can't be closed again
file.fd = syscall.InvalidHandle // so it can't be closed again
// no need for a finalizer anymore
runtime.SetFinalizer(file, nil)
......@@ -102,7 +130,7 @@ func (file *File) Close() Error {
func (file *File) statFile(name string) (fi *FileInfo, err Error) {
var stat syscall.ByHandleFileInformation
e := syscall.GetFileInformationByHandle(int32(file.fd), &stat)
e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &stat)
if e != 0 {
return nil, &PathError{"stat", file.name, Errno(e)}
}
......@@ -156,7 +184,7 @@ func (file *File) Readdir(n int) (fi []FileInfo, err Error) {
if di.usefirststat {
di.usefirststat = false
} else {
e := syscall.FindNextFile(int32(file.fd), &di.stat.Windata)
e := syscall.FindNextFile(syscall.Handle(file.fd), &di.stat.Windata)
if e != 0 {
if e == syscall.ERROR_NO_MORE_FILES {
break
......@@ -207,7 +235,7 @@ func (f *File) pread(b []byte, off int64) (n int, err int) {
Offset: uint32(off),
}
var done uint32
e = syscall.ReadFile(int32(f.fd), b, &done, &o)
e = syscall.ReadFile(syscall.Handle(f.fd), b, &done, &o)
if e != 0 {
return 0, e
}
......@@ -237,7 +265,7 @@ func (f *File) pwrite(b []byte, off int64) (n int, err int) {
Offset: uint32(off),
}
var done uint32
e = syscall.WriteFile(int32(f.fd), b, &done, &o)
e = syscall.WriteFile(syscall.Handle(f.fd), b, &done, &o)
if e != 0 {
return 0, e
}
......@@ -268,3 +296,22 @@ func Truncate(name string, size int64) Error {
}
return nil
}
// Pipe returns a connected pair of Files; reads from r return bytes written to w.
// It returns the files and an Error, if any.
func Pipe() (r *File, w *File, err Error) {
var p [2]syscall.Handle
// See ../syscall/exec.go for description of lock.
syscall.ForkLock.RLock()
e := syscall.Pipe(p[0:])
if iserror(e) {
syscall.ForkLock.RUnlock()
return nil, nil, NewSyscallError("pipe", e)
}
syscall.CloseOnExec(p[0])
syscall.CloseOnExec(p[1])
syscall.ForkLock.RUnlock()
return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil
}
......@@ -121,11 +121,11 @@ func createEnvBlock(envv []string) *uint16 {
return &utf16.Encode([]int(string(b)))[0]
}
func CloseOnExec(fd int) {
SetHandleInformation(int32(fd), HANDLE_FLAG_INHERIT, 0)
func CloseOnExec(fd Handle) {
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}
func SetNonblock(fd int, nonblocking bool) (errno int) {
func SetNonblock(fd Handle, nonblocking bool) (errno int) {
return 0
}
......@@ -220,7 +220,7 @@ func joinExeDirAndFName(dir, p string) (name string, err int) {
type ProcAttr struct {
Dir string
Env []string
Files []int
Files []Handle
Sys *SysProcAttr
}
......@@ -290,14 +290,14 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
defer ForkLock.Unlock()
p, _ := GetCurrentProcess()
fd := make([]int32, len(attr.Files))
fd := make([]Handle, len(attr.Files))
for i := range attr.Files {
if attr.Files[i] > 0 {
err := DuplicateHandle(p, int32(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
if err != 0 {
return 0, 0, err
}
defer CloseHandle(int32(fd[i]))
defer CloseHandle(Handle(fd[i]))
}
}
si := new(StartupInfo)
......@@ -317,7 +317,7 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int,
if err != 0 {
return 0, 0, err
}
defer CloseHandle(pi.Thread)
defer CloseHandle(Handle(pi.Thread))
return int(pi.ProcessId), int(pi.Process), 0
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -216,7 +216,7 @@ type Overlapped struct {
InternalHigh uint32
Offset uint32
OffsetHigh uint32
HEvent int32
HEvent Handle
}
type Filetime struct {
......@@ -306,14 +306,14 @@ type StartupInfo struct {
ShowWindow uint16
_ uint16
_ *byte
StdInput int32
StdOutput int32
StdErr int32
StdInput Handle
StdOutput Handle
StdErr Handle
}
type ProcessInformation struct {
Process int32
Thread int32
Process Handle
Thread Handle
ProcessId uint32
ThreadId uint32
}
......
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