1
2
3
4
5 package windows_test
6
7 import (
8 "internal/syscall/windows"
9 "os"
10 "path/filepath"
11 "syscall"
12 "testing"
13 "unsafe"
14 )
15
16 func TestOpen(t *testing.T) {
17 t.Parallel()
18
19 dir := t.TempDir()
20 file := filepath.Join(dir, "a")
21 f, err := os.Create(file)
22 if err != nil {
23 t.Fatal(err)
24 }
25 f.Close()
26
27 tests := []struct {
28 path string
29 flag int
30 err error
31 }{
32 {dir, syscall.O_RDONLY, nil},
33 {dir, syscall.O_CREAT, nil},
34 {dir, syscall.O_RDONLY | syscall.O_CREAT, nil},
35 {file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE, nil},
36 {file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE | os.O_TRUNC, nil},
37 {dir, syscall.O_RDONLY | syscall.O_TRUNC, syscall.ERROR_ACCESS_DENIED},
38 {dir, syscall.O_WRONLY | syscall.O_RDWR, nil},
39 {dir, syscall.O_WRONLY, syscall.EISDIR},
40 {dir, syscall.O_RDWR, syscall.EISDIR},
41 }
42 for i, tt := range tests {
43 dir := filepath.Dir(tt.path)
44 dirfd, err := syscall.Open(dir, syscall.O_RDONLY, 0)
45 if err != nil {
46 t.Error(err)
47 continue
48 }
49 base := filepath.Base(tt.path)
50 h, err := windows.Openat(dirfd, base, uint64(tt.flag), 0o660)
51 syscall.CloseHandle(dirfd)
52 if err == nil {
53 syscall.CloseHandle(h)
54 }
55 if err != tt.err {
56 t.Errorf("%d: Open got %q, want %q", i, err, tt.err)
57 }
58 }
59 }
60
61 func TestDeleteAt(t *testing.T) {
62 testCases := []struct {
63 name string
64 modifier func(t *testing.T, path string)
65 }{
66 {"DeleteAt removes normal file", func(t *testing.T, name string) {}},
67 {"DeleteAt removes file with no read permission", makeFileNotReadable},
68 {"DeleteAt removes readonly file", makeFileReadonly},
69 }
70
71 for _, tc := range testCases {
72 t.Run(tc.name, func(t *testing.T) {
73 t.Parallel()
74
75 dir := t.TempDir()
76 file := filepath.Join(dir, "a")
77 f, err := os.Create(file)
78 if err != nil {
79 t.Fatal(err)
80 }
81 f.Close()
82
83
84
85 tc.modifier(t, file)
86
87
88 dirfd, err := syscall.Open(dir, syscall.O_RDONLY, 0)
89 if err != nil {
90 t.Fatal(err)
91 }
92 base := filepath.Base(file)
93 err = windows.Deleteat(dirfd, base, 0)
94 syscall.CloseHandle(dirfd)
95 if err != nil {
96 t.Fatalf("Deleteat failed: %v", err)
97 }
98
99
100 if _, err := os.Stat(file); !os.IsNotExist(err) {
101 t.Fatalf("file still exists after DeleteAt")
102 }
103 })
104 }
105 }
106
107 func makeFileReadonly(t *testing.T, name string) {
108 if err := os.Chmod(name, 0); err != nil {
109 t.Fatal(err)
110 }
111 }
112
113 func makeFileNotReadable(t *testing.T, name string) {
114 creatorOwnerSID, err := syscall.StringToSid("S-1-3-0")
115 if err != nil {
116 t.Fatal(err)
117 }
118 creatorGroupSID, err := syscall.StringToSid("S-1-3-1")
119 if err != nil {
120 t.Fatal(err)
121 }
122 everyoneSID, err := syscall.StringToSid("S-1-1-0")
123 if err != nil {
124 t.Fatal(err)
125 }
126
127 entryForSid := func(sid *syscall.SID) windows.EXPLICIT_ACCESS {
128 return windows.EXPLICIT_ACCESS{
129 AccessPermissions: 0,
130 AccessMode: windows.GRANT_ACCESS,
131 Inheritance: windows.SUB_CONTAINERS_AND_OBJECTS_INHERIT,
132 Trustee: windows.TRUSTEE{
133 TrusteeForm: windows.TRUSTEE_IS_SID,
134 Name: (uintptr)(unsafe.Pointer(sid)),
135 },
136 }
137 }
138
139 entries := []windows.EXPLICIT_ACCESS{
140 entryForSid(creatorOwnerSID),
141 entryForSid(creatorGroupSID),
142 entryForSid(everyoneSID),
143 }
144
145 var oldAcl, newAcl *windows.ACL
146 if err := windows.SetEntriesInAcl(
147 uint32(len(entries)),
148 &entries[0],
149 oldAcl,
150 &newAcl,
151 ); err != nil {
152 t.Fatal(err)
153 }
154
155 defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newAcl)))
156 if err := windows.SetNamedSecurityInfo(
157 name,
158 windows.SE_FILE_OBJECT,
159 windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
160 nil,
161 nil,
162 newAcl,
163 nil,
164 ); err != nil {
165 t.Fatal(err)
166 }
167 }
168
View as plain text