@@ -1571,15 +1571,10 @@ func TestReadWriteFileOverlapped(t *testing.T) {
1571
1571
t .Parallel ()
1572
1572
1573
1573
name := filepath .Join (t .TempDir (), "test.txt" )
1574
- wname , err := syscall .UTF16PtrFromString (name )
1575
- if err != nil {
1576
- t .Fatal (err )
1577
- }
1578
- h , err := syscall .CreateFile (wname , syscall .GENERIC_ALL , 0 , nil , syscall .CREATE_NEW , syscall .FILE_ATTRIBUTE_NORMAL | syscall .FILE_FLAG_OVERLAPPED , 0 )
1574
+ f , err := os .OpenFile (name , os .O_RDWR | os .O_CREATE | windows .O_FILE_FLAG_OVERLAPPED , 0666 )
1579
1575
if err != nil {
1580
1576
t .Fatal (err )
1581
1577
}
1582
- f := os .NewFile (uintptr (h ), name )
1583
1578
defer f .Close ()
1584
1579
1585
1580
data := []byte ("test" )
@@ -1655,22 +1650,14 @@ func TestStdinOverlappedPipe(t *testing.T) {
1655
1650
}
1656
1651
1657
1652
func newFileOverlapped (t testing.TB , name string , overlapped bool ) * os.File {
1658
- namep , err := syscall .UTF16PtrFromString (name )
1659
- if err != nil {
1660
- t .Fatal (err )
1661
- }
1662
- flags := syscall .FILE_ATTRIBUTE_NORMAL
1653
+ flags := os .O_RDWR | os .O_CREATE
1663
1654
if overlapped {
1664
- flags |= syscall . FILE_FLAG_OVERLAPPED
1655
+ flags |= windows . O_FILE_FLAG_OVERLAPPED
1665
1656
}
1666
- h , err := syscall .CreateFile (namep ,
1667
- syscall .GENERIC_READ | syscall .GENERIC_WRITE ,
1668
- syscall .FILE_SHARE_WRITE | syscall .FILE_SHARE_READ ,
1669
- nil , syscall .OPEN_ALWAYS , uint32 (flags ), 0 )
1657
+ f , err := os .OpenFile (name , flags , 0666 )
1670
1658
if err != nil {
1671
1659
t .Fatal (err )
1672
1660
}
1673
- f := os .NewFile (uintptr (h ), name )
1674
1661
t .Cleanup (func () {
1675
1662
if err := f .Close (); err != nil && ! errors .Is (err , os .ErrClosed ) {
1676
1663
t .Fatal (err )
@@ -1706,7 +1693,7 @@ func newPipe(t testing.TB, name string, message, overlapped bool) *os.File {
1706
1693
// Create the read handle.
1707
1694
flags := windows .PIPE_ACCESS_DUPLEX
1708
1695
if overlapped {
1709
- flags |= syscall . FILE_FLAG_OVERLAPPED
1696
+ flags |= windows . O_FILE_FLAG_OVERLAPPED
1710
1697
}
1711
1698
typ := windows .PIPE_TYPE_BYTE | windows .PIPE_READMODE_BYTE
1712
1699
if message {
@@ -1888,21 +1875,13 @@ func TestFileOverlappedReadAtVolume(t *testing.T) {
1888
1875
// See https://go.dev/issues/74951.
1889
1876
t .Parallel ()
1890
1877
name := `\\.\` + filepath .VolumeName (t .TempDir ())
1891
- namep , err := syscall .UTF16PtrFromString (name )
1892
- if err != nil {
1893
- t .Fatal (err )
1894
- }
1895
- h , err := syscall .CreateFile (namep ,
1896
- syscall .GENERIC_READ | syscall .GENERIC_WRITE ,
1897
- syscall .FILE_SHARE_WRITE | syscall .FILE_SHARE_READ ,
1898
- nil , syscall .OPEN_ALWAYS , syscall .FILE_FLAG_OVERLAPPED , 0 )
1878
+ f , err := os .OpenFile (name , os .O_RDWR | os .O_CREATE | windows .O_FILE_FLAG_OVERLAPPED , 0666 )
1899
1879
if err != nil {
1900
1880
if errors .Is (err , syscall .ERROR_ACCESS_DENIED ) {
1901
1881
t .Skip ("skipping test: access denied" )
1902
1882
}
1903
1883
t .Fatal (err )
1904
1884
}
1905
- f := os .NewFile (uintptr (h ), name )
1906
1885
defer f .Close ()
1907
1886
1908
1887
var buf [0 ]byte
@@ -2209,3 +2188,71 @@ func TestSplitPath(t *testing.T) {
2209
2188
}
2210
2189
}
2211
2190
}
2191
+
2192
+ func TestOpenFileFlags (t * testing.T ) {
2193
+ t .Parallel ()
2194
+
2195
+ // The only way to retrieve some of the flags passed in CreateFile
2196
+ // is using NtQueryInformationFile, which returns the file flags
2197
+ // NT equivalent. Note that FILE_SYNCHRONOUS_IO_NONALERT is always
2198
+ // set when FILE_FLAG_OVERLAPPED is not passed.
2199
+ // The flags that can't be retrieved using NtQueryInformationFile won't
2200
+ // be tested in here, but we at least know that the logic to handle them is correct.
2201
+ tests := []struct {
2202
+ flag uint32
2203
+ wantMode uint32
2204
+ }{
2205
+ {0 , windows .FILE_SYNCHRONOUS_IO_NONALERT },
2206
+ {windows .O_FILE_FLAG_OVERLAPPED , 0 },
2207
+ {windows .O_FILE_FLAG_NO_BUFFERING , windows .FILE_NO_INTERMEDIATE_BUFFERING | windows .FILE_SYNCHRONOUS_IO_NONALERT },
2208
+ {windows .O_FILE_FLAG_NO_BUFFERING | windows .O_FILE_FLAG_OVERLAPPED , windows .FILE_NO_INTERMEDIATE_BUFFERING },
2209
+ {windows .O_FILE_FLAG_SEQUENTIAL_SCAN , windows .FILE_SEQUENTIAL_ONLY | windows .FILE_SYNCHRONOUS_IO_NONALERT },
2210
+ {windows .O_FILE_FLAG_WRITE_THROUGH , windows .FILE_WRITE_THROUGH | windows .FILE_SYNCHRONOUS_IO_NONALERT },
2211
+ }
2212
+ for i , tt := range tests {
2213
+ t .Run (strconv .Itoa (i ), func (t * testing.T ) {
2214
+ t .Parallel ()
2215
+ f , err := os .OpenFile (filepath .Join (t .TempDir (), "test.txt" ), syscall .O_RDWR | syscall .O_CREAT | int (tt .flag ), 0666 )
2216
+ if err != nil {
2217
+ t .Fatal (err )
2218
+ }
2219
+ defer f .Close ()
2220
+ var info windows.FILE_MODE_INFORMATION
2221
+ if err := windows .NtQueryInformationFile (syscall .Handle (f .Fd ()), & windows.IO_STATUS_BLOCK {},
2222
+ unsafe .Pointer (& info ), uint32 (unsafe .Sizeof (info )), windows .FileModeInformation ); err != nil {
2223
+ t .Fatal (err )
2224
+ }
2225
+ if info .Mode != tt .wantMode {
2226
+ t .Errorf ("file mode = 0x%x; want 0x%x" , info .Mode , tt .wantMode )
2227
+ }
2228
+ })
2229
+ }
2230
+ }
2231
+
2232
+ func TestOpenFileDeleteOnClose (t * testing.T ) {
2233
+ t .Parallel ()
2234
+ name := filepath .Join (t .TempDir (), "test.txt" )
2235
+ f , err := os .OpenFile (name , syscall .O_RDWR | syscall .O_CREAT | windows .O_FILE_FLAG_DELETE_ON_CLOSE , 0666 )
2236
+ if err != nil {
2237
+ t .Fatal (err )
2238
+ }
2239
+ if err := f .Close (); err != nil {
2240
+ t .Fatal (err )
2241
+ }
2242
+ // The file should be deleted after closing.
2243
+ if _ , err := os .Stat (name ); ! errors .Is (err , os .ErrNotExist ) {
2244
+ t .Errorf ("expected file to be deleted, got %v" , err )
2245
+ }
2246
+ }
2247
+
2248
+ func TestOpenFileFlagInvalid (t * testing.T ) {
2249
+ t .Parallel ()
2250
+ // invalidFileFlag is the only value in the file flag range that is not supported,
2251
+ // as it is not defined in the Windows API.
2252
+ const invalidFileFlag = 0x00400000
2253
+ f , err := os .OpenFile (filepath .Join (t .TempDir (), "test.txt" ), syscall .O_RDWR | syscall .O_CREAT | invalidFileFlag , 0666 )
2254
+ if ! errors .Is (err , os .ErrInvalid ) {
2255
+ t .Fatalf ("expected os.ErrInvalid, got %v" , err )
2256
+ }
2257
+ f .Close ()
2258
+ }
0 commit comments