1+ //go:build windows
2+
13package sequential
24
35import (
@@ -6,108 +8,36 @@ import (
68 "strconv"
79 "sync"
810 "time"
9- "unsafe"
10-
11- "golang.org/x/sys/windows"
1211)
1312
1413// Create is a copy of [os.Create], modified to use sequential file access.
1514//
16- // It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
17- // as implemented in golang. Refer to the [Win32 API documentation] for details
18- // on sequential file access.
15+ // It uses the Windows sequential scan file flag. Refer to the [Win32 API
16+ // documentation] for details on sequential file access.
1917//
2018// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
2119func Create (name string ) (* os.File , error ) {
22- return openFileSequential (name , windows .O_RDWR | windows . O_CREAT | windows .O_TRUNC )
20+ return OpenFile (name , os .O_RDWR | os . O_CREATE | os .O_TRUNC , 0o666 )
2321}
2422
2523// Open is a copy of [os.Open], modified to use sequential file access.
2624//
27- // It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
28- // as implemented in golang. Refer to the [Win32 API documentation] for details
29- // on sequential file access.
25+ // It uses the Windows sequential scan file flag. Refer to the [Win32 API
26+ // documentation] for details on sequential file access.
3027//
3128// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
3229func Open (name string ) (* os.File , error ) {
33- return openFileSequential (name , windows .O_RDONLY )
30+ return OpenFile (name , os .O_RDONLY , 0 )
3431}
3532
3633// OpenFile is a copy of [os.OpenFile], modified to use sequential file access.
3734//
38- // It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
39- // as implemented in golang. Refer to the [Win32 API documentation] for details
40- // on sequential file access.
35+ // It uses the Windows sequential scan file flag. Refer to the [Win32 API
36+ // documentation] for details on sequential file access.
4137//
4238// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
43- func OpenFile (name string , flag int , _ os.FileMode ) (* os.File , error ) {
44- return openFileSequential (name , flag )
45- }
46-
47- func openFileSequential (name string , flag int ) (file * os.File , err error ) {
48- if name == "" {
49- return nil , & os.PathError {Op : "open" , Path : name , Err : windows .ERROR_FILE_NOT_FOUND }
50- }
51- r , e := openSequential (name , flag | windows .O_CLOEXEC )
52- if e != nil {
53- return nil , & os.PathError {Op : "open" , Path : name , Err : e }
54- }
55- return os .NewFile (uintptr (r ), name ), nil
56- }
57-
58- func makeInheritSa () * windows.SecurityAttributes {
59- var sa windows.SecurityAttributes
60- sa .Length = uint32 (unsafe .Sizeof (sa ))
61- sa .InheritHandle = 1
62- return & sa
63- }
64-
65- func openSequential (path string , mode int ) (fd windows.Handle , err error ) {
66- if len (path ) == 0 {
67- return windows .InvalidHandle , windows .ERROR_FILE_NOT_FOUND
68- }
69- pathp , err := windows .UTF16PtrFromString (path )
70- if err != nil {
71- return windows .InvalidHandle , err
72- }
73- var access uint32
74- switch mode & (windows .O_RDONLY | windows .O_WRONLY | windows .O_RDWR ) {
75- case windows .O_RDONLY :
76- access = windows .GENERIC_READ
77- case windows .O_WRONLY :
78- access = windows .GENERIC_WRITE
79- case windows .O_RDWR :
80- access = windows .GENERIC_READ | windows .GENERIC_WRITE
81- }
82- if mode & windows .O_CREAT != 0 {
83- access |= windows .GENERIC_WRITE
84- }
85- if mode & windows .O_APPEND != 0 {
86- access &^= windows .GENERIC_WRITE
87- access |= windows .FILE_APPEND_DATA
88- }
89- sharemode := uint32 (windows .FILE_SHARE_READ | windows .FILE_SHARE_WRITE )
90- var sa * windows.SecurityAttributes
91- if mode & windows .O_CLOEXEC == 0 {
92- sa = makeInheritSa ()
93- }
94- var createmode uint32
95- switch {
96- case mode & (windows .O_CREAT | windows .O_EXCL ) == (windows .O_CREAT | windows .O_EXCL ):
97- createmode = windows .CREATE_NEW
98- case mode & (windows .O_CREAT | windows .O_TRUNC ) == (windows .O_CREAT | windows .O_TRUNC ):
99- createmode = windows .CREATE_ALWAYS
100- case mode & windows .O_CREAT == windows .O_CREAT :
101- createmode = windows .OPEN_ALWAYS
102- case mode & windows .O_TRUNC == windows .O_TRUNC :
103- createmode = windows .TRUNCATE_EXISTING
104- default :
105- createmode = windows .OPEN_EXISTING
106- }
107- // Use FILE_FLAG_SEQUENTIAL_SCAN rather than FILE_ATTRIBUTE_NORMAL as implemented in golang.
108- // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
109- h , e := windows .CreateFile (pathp , access , sharemode , sa , createmode , windows .FILE_FLAG_SEQUENTIAL_SCAN , 0 )
110- return h , e
39+ func OpenFile (name string , flag int , perm os.FileMode ) (* os.File , error ) {
40+ return openFileSequential (name , flag , perm )
11141}
11242
11343// Helpers for CreateTemp
@@ -134,9 +64,8 @@ func nextSuffix() string {
13464
13565// CreateTemp is a copy of [os.CreateTemp], modified to use sequential file access.
13666//
137- // It uses [windows.FILE_FLAG_SEQUENTIAL_SCAN] rather than [windows.FILE_ATTRIBUTE_NORMAL]
138- // as implemented in golang. Refer to the [Win32 API documentation] for details
139- // on sequential file access.
67+ // It uses the Windows sequential scan file flag. Refer to the [Win32 API
68+ // documentation] for details on sequential file access.
14069//
14170// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
14271func CreateTemp (dir , prefix string ) (f * os.File , err error ) {
@@ -145,9 +74,9 @@ func CreateTemp(dir, prefix string) (f *os.File, err error) {
14574 }
14675
14776 nconflict := 0
148- for i := 0 ; i < 10000 ; i ++ {
77+ for range 10000 {
14978 name := filepath .Join (dir , prefix + nextSuffix ())
150- f , err = openFileSequential (name , windows .O_RDWR | windows . O_CREAT | windows .O_EXCL )
79+ f , err = OpenFile (name , os .O_RDWR | os . O_CREATE | os .O_EXCL , 0o600 )
15180 if os .IsExist (err ) {
15281 if nconflict ++ ; nconflict > 10 {
15382 randmu .Lock ()
0 commit comments