if flag&syscall.O_TRUNC != 0 {
err = syscall.Ftruncate(h, 0)
+ if err == ERROR_INVALID_PARAMETER {
+ // ERROR_INVALID_PARAMETER means truncation is not supported on this file handle.
+ // Unix's O_TRUNC specification says to ignore O_TRUNC on named pipes and terminal devices.
+ // We do the same here.
+ if t, err1 := syscall.GetFileType(h); err1 == nil && (t == syscall.FILE_TYPE_PIPE || t == syscall.FILE_TYPE_CHAR) {
+ err = nil
+ }
+ }
if err != nil {
syscall.CloseHandle(h)
return syscall.InvalidHandle, err
}
f.Close()
}
+
+func TestOpenFileTruncateNamedPipe(t *testing.T) {
+ t.Parallel()
+ name := pipeName()
+ pipe := newBytePipe(t, name, false)
+ defer pipe.Close()
+
+ f, err := os.OpenFile(name, os.O_TRUNC|os.O_RDWR|os.O_CREATE, 0666)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+}
})
}
}
+
+func TestRootOpenFileTruncateNamedPipe(t *testing.T) {
+ t.Parallel()
+ name := pipeName()
+ pipe := newBytePipe(t, name, false)
+ defer pipe.Close()
+
+ root, err := os.OpenRoot(filepath.Dir(name))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer root.Close()
+
+ f, err := root.OpenFile(filepath.Base(name), os.O_TRUNC|os.O_RDWR|os.O_CREATE, 0666)
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.Close()
+}
if flag&O_TRUNC == O_TRUNC &&
(createmode == OPEN_EXISTING || (createmode == OPEN_ALWAYS && err == ERROR_ALREADY_EXISTS)) {
err = Ftruncate(h, 0)
+ if err == _ERROR_INVALID_PARAMETER {
+ // ERROR_INVALID_PARAMETER means truncation is not supported on this file handle.
+ // Unix's O_TRUNC specification says to ignore O_TRUNC on named pipes and terminal devices.
+ // We do the same here.
+ if t, err1 := GetFileType(h); err1 == nil && (t == FILE_TYPE_PIPE || t == FILE_TYPE_CHAR) {
+ err = nil
+ }
+ }
if err != nil {
CloseHandle(h)
return InvalidHandle, err
WSAECONNRESET Errno = 10054
)
+const (
+ _ERROR_INVALID_PARAMETER Errno = 87
+)
+
const (
// Invented values to support what package os expects.
O_RDONLY = 0x00000