1
2
3
4
5 package windows
6
7 import (
8 "syscall"
9 )
10
11
12
13
14
15
16
17
18 const (
19 O_DIRECTORY = 0x100000
20 O_NOFOLLOW_ANY = 0x20000000
21 )
22
23 func Openat(dirfd syscall.Handle, name string, flag int, perm uint32) (_ syscall.Handle, e1 error) {
24 if len(name) == 0 {
25 return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND
26 }
27
28 var access, options uint32
29 switch flag & (syscall.O_RDONLY | syscall.O_WRONLY | syscall.O_RDWR) {
30 case syscall.O_RDONLY:
31
32 access = FILE_GENERIC_READ
33 case syscall.O_WRONLY:
34 access = FILE_GENERIC_WRITE
35 options |= FILE_NON_DIRECTORY_FILE
36 case syscall.O_RDWR:
37 access = FILE_GENERIC_READ | FILE_GENERIC_WRITE
38 options |= FILE_NON_DIRECTORY_FILE
39 }
40 if flag&syscall.O_CREAT != 0 {
41 access |= FILE_GENERIC_WRITE
42 }
43 if flag&syscall.O_APPEND != 0 {
44 access |= FILE_APPEND_DATA
45
46
47 if flag&syscall.O_TRUNC == 0 {
48 access &^= FILE_WRITE_DATA
49 }
50 }
51 if flag&O_DIRECTORY != 0 {
52 options |= FILE_DIRECTORY_FILE
53 access |= FILE_LIST_DIRECTORY
54 }
55 if flag&syscall.O_SYNC != 0 {
56 options |= FILE_WRITE_THROUGH
57 }
58
59 access |= STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | FILE_READ_EA
60
61 objAttrs := &OBJECT_ATTRIBUTES{}
62 if flag&O_NOFOLLOW_ANY != 0 {
63 objAttrs.Attributes |= OBJ_DONT_REPARSE
64 }
65 if flag&syscall.O_CLOEXEC == 0 {
66 objAttrs.Attributes |= OBJ_INHERIT
67 }
68 if err := objAttrs.init(dirfd, name); err != nil {
69 return syscall.InvalidHandle, err
70 }
71
72
73
74
75
76
77 var disposition uint32
78 switch {
79 case flag&(syscall.O_CREAT|syscall.O_EXCL) == (syscall.O_CREAT | syscall.O_EXCL):
80 disposition = FILE_CREATE
81 case flag&syscall.O_CREAT == syscall.O_CREAT:
82 disposition = FILE_OPEN_IF
83 default:
84 disposition = FILE_OPEN
85 }
86
87 fileAttrs := uint32(FILE_ATTRIBUTE_NORMAL)
88 if perm&syscall.S_IWRITE == 0 {
89 fileAttrs = FILE_ATTRIBUTE_READONLY
90 }
91
92 var h syscall.Handle
93 err := NtCreateFile(
94 &h,
95 SYNCHRONIZE|access,
96 objAttrs,
97 &IO_STATUS_BLOCK{},
98 nil,
99 fileAttrs,
100 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
101 disposition,
102 FILE_SYNCHRONOUS_IO_NONALERT|options,
103 0,
104 0,
105 )
106 if err != nil {
107 return h, ntCreateFileError(err, flag)
108 }
109
110 if flag&syscall.O_TRUNC != 0 {
111 err = syscall.Ftruncate(h, 0)
112 if err != nil {
113 syscall.CloseHandle(h)
114 return syscall.InvalidHandle, err
115 }
116 }
117
118 return h, nil
119 }
120
121
122 func ntCreateFileError(err error, flag int) error {
123 s, ok := err.(NTStatus)
124 if !ok {
125
126 return err
127 }
128 switch s {
129 case STATUS_REPARSE_POINT_ENCOUNTERED:
130 return syscall.ELOOP
131 case STATUS_NOT_A_DIRECTORY:
132
133
134
135
136
137
138
139
140 if flag&O_DIRECTORY != 0 {
141 return syscall.ENOTDIR
142 }
143 case STATUS_FILE_IS_A_DIRECTORY:
144 return syscall.EISDIR
145 }
146 return s.Errno()
147 }
148
149 func Mkdirat(dirfd syscall.Handle, name string, mode uint32) error {
150 objAttrs := &OBJECT_ATTRIBUTES{}
151 if err := objAttrs.init(dirfd, name); err != nil {
152 return err
153 }
154 var h syscall.Handle
155 err := NtCreateFile(
156 &h,
157 FILE_GENERIC_READ,
158 objAttrs,
159 &IO_STATUS_BLOCK{},
160 nil,
161 syscall.FILE_ATTRIBUTE_NORMAL,
162 syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
163 FILE_CREATE,
164 FILE_DIRECTORY_FILE,
165 0,
166 0,
167 )
168 if err != nil {
169 return ntCreateFileError(err, 0)
170 }
171 syscall.CloseHandle(h)
172 return nil
173 }
174
View as plain text