]> Cypherpunks repositories - gostls13.git/commitdiff
os: fix Stdin.Stat() on windows
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Fri, 18 Mar 2016 04:00:26 +0000 (13:00 +0900)
committerAlex Brainman <alex.brainman@gmail.com>
Thu, 24 Mar 2016 09:22:33 +0000 (09:22 +0000)
If name is /dev/{stdin,stdout,stderr}, return fileInfo.

Fixes #14853.

Change-Id: Ibf7d1ae7b9f3dc43f6ed7c905ea2c5102e1971cc
Reviewed-on: https://go-review.googlesource.com/20845
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
src/os/os_test.go
src/os/stat_windows.go
src/os/types_windows.go

index a878e40fd2b1d9ac42e94ccbe7ac7e43b3168a1b..606496b00a990933f5ca17019f95cdee4037c983 100644 (file)
@@ -1583,6 +1583,41 @@ func TestStatDirModeExec(t *testing.T) {
        }
 }
 
+func TestStatStdin(t *testing.T) {
+       if runtime.GOOS == "plan9" {
+               t.Skipf("skipping test on plan9")
+       }
+
+       testenv.MustHaveExec(t)
+
+       if Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+               st, err := Stdin.Stat()
+               if err != nil {
+                       t.Fatalf("Stat failed: %v", err)
+               }
+               fmt.Println(st.Mode() & ModeNamedPipe)
+               Exit(0)
+       }
+
+       var cmd *osexec.Cmd
+       if runtime.GOOS == "windows" {
+               cmd = osexec.Command("cmd", "/c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
+       } else {
+               cmd = osexec.Command("/bin/sh", "-c", "echo output | "+Args[0]+" -test.run=TestStatStdin")
+       }
+       cmd.Env = append(Environ(), "GO_WANT_HELPER_PROCESS=1")
+
+       output, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("Failed to spawn child process: %v %q", err, string(output))
+       }
+
+       // result will be like "prw-rw-rw"
+       if len(output) < 1 || output[0] != 'p' {
+               t.Fatalf("Child process reports stdin is not pipe '%v'", string(output))
+       }
+}
+
 func TestReadAtEOF(t *testing.T) {
        f := newFile("TestReadAtEOF", t)
        defer Remove(f.Name())
index d65c58200f6967c2bb54c0e0a96497912ecab676..b8f97ad60a8e16097fa3f1152567bd720b61e625 100644 (file)
@@ -25,10 +25,19 @@ func (file *File) Stat() (FileInfo, error) {
        if file.name == DevNull {
                return &devNullStat, nil
        }
+
+       ft, err := syscall.GetFileType(file.fd)
+       if err != nil {
+               return nil, &PathError{"GetFileType", file.name, err}
+       }
+       if ft == syscall.FILE_TYPE_PIPE {
+               return &fileStat{name: basename(file.name), pipe: true}, nil
+       }
+
        var d syscall.ByHandleFileInformation
-       e := syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d)
-       if e != nil {
-               return nil, &PathError{"GetFileInformationByHandle", file.name, e}
+       err = syscall.GetFileInformationByHandle(syscall.Handle(file.fd), &d)
+       if err != nil {
+               return nil, &PathError{"GetFileInformationByHandle", file.name, err}
        }
        return &fileStat{
                name: basename(file.name),
@@ -43,6 +52,7 @@ func (file *File) Stat() (FileInfo, error) {
                vol:   d.VolumeSerialNumber,
                idxhi: d.FileIndexHigh,
                idxlo: d.FileIndexLow,
+               pipe:  false,
        }, nil
 }
 
index 7b2e54698c389212b99084c02e482c90bb6d5ede..900d444b0e012c0a6da81751bad50203eb98e778 100644 (file)
@@ -14,6 +14,7 @@ import (
 type fileStat struct {
        name string
        sys  syscall.Win32FileAttributeData
+       pipe bool
 
        // used to implement SameFile
        sync.Mutex
@@ -42,6 +43,9 @@ func (fs *fileStat) Mode() (m FileMode) {
        if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
                m |= ModeSymlink
        }
+       if fs.pipe {
+               m |= ModeNamedPipe
+       }
        return m
 }