diff options
Diffstat (limited to 'src/pkg/os/file_windows.go')
-rw-r--r-- | src/pkg/os/file_windows.go | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/src/pkg/os/file_windows.go b/src/pkg/os/file_windows.go index 80886f6f5..70dd6e241 100644 --- a/src/pkg/os/file_windows.go +++ b/src/pkg/os/file_windows.go @@ -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 +} |