authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-30 17:00:50+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-07-31 16:31:23+02:00
loga89d5cfc3eaaf97b914abc5d355099ec8357925d
tree7c4ff9d033abd54aec89601906f8c6b0358fc0f9
parent0d31877444bf6c21307dfd3c412f9673dfd8acab

Remove CreateDirectoryW and CreateFileW calls

Replace them with `std.os.windows.OpenFile` instead. To allow creation/opening of directories, `std.os.windows.OpenFileOptions` now features a `.expect_dir: bool` member which is meant to emualate POSIX's `O_DIRECTORY` flag.

5 files changed, 90 insertions(+), 169 deletions(-)

lib/std/child_process.zig+8-13
...@@ -480,25 +480,20 @@ pub const ChildProcess = struct {...@@ -480,25 +480,20 @@ pub const ChildProcess = struct {
480480
481 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);481 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
482482
483 // TODO use CreateFileW here since we are using a string literal for the path
484 const nul_handle = if (any_ignore)483 const nul_handle = if (any_ignore)
485 windows.CreateFile(484 windows.OpenFile(&[_]u16{ 'N', 'U', 'L' }, .{
486 "NUL",485 .dir = std.fs.cwd().fd,
487 windows.GENERIC_READ,486 .access_mask = windows.GENERIC_READ,
488 windows.FILE_SHARE_READ,487 .share_access = windows.FILE_SHARE_READ,
489 null,488 .creation = windows.OPEN_EXISTING,
490 windows.OPEN_EXISTING,489 .io_mode = .blocking,
491 windows.FILE_ATTRIBUTE_NORMAL,490 }) catch |err| switch (err) {
492 null,
493 ) catch |err| switch (err) {
494 error.SharingViolation => unreachable, // not possible for "NUL"
495 error.PathAlreadyExists => unreachable, // not possible for "NUL"491 error.PathAlreadyExists => unreachable, // not possible for "NUL"
496 error.PipeBusy => unreachable, // not possible for "NUL"492 error.PipeBusy => unreachable, // not possible for "NUL"
497 error.InvalidUtf8 => unreachable, // not possible for "NUL"
498 error.BadPathName => unreachable, // not possible for "NUL"
499 error.FileNotFound => unreachable, // not possible for "NUL"493 error.FileNotFound => unreachable, // not possible for "NUL"
500 error.AccessDenied => unreachable, // not possible for "NUL"494 error.AccessDenied => unreachable, // not possible for "NUL"
501 error.NameTooLong => unreachable, // not possible for "NUL"495 error.NameTooLong => unreachable, // not possible for "NUL"
496 error.WouldBlock => unreachable, // not possible for "NUL"
502 else => |e| return e,497 else => |e| return e,
503 }498 }
504 else499 else
lib/std/fs.zig+2-4
...@@ -225,8 +225,7 @@ pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void {...@@ -225,8 +225,7 @@ pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void {
225/// Same as `makeDirAbsolute` except the parameter is a null-terminated WTF-16 encoded string.225/// Same as `makeDirAbsolute` except the parameter is a null-terminated WTF-16 encoded string.
226pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {226pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {
227 assert(path.isAbsoluteWindowsW(absolute_path_w));227 assert(path.isAbsoluteWindowsW(absolute_path_w));
228 const handle = try os.windows.CreateDirectoryW(null, absolute_path_w, null);228 return os.mkdirW(absolute_path_w, default_new_dir_mode);
229 os.windows.CloseHandle(handle);
230}229}
231230
232pub const deleteDir = @compileError("deprecated; use dir.deleteDir or deleteDirAbsolute");231pub const deleteDir = @compileError("deprecated; use dir.deleteDir or deleteDirAbsolute");
...@@ -881,8 +880,7 @@ pub const Dir = struct {...@@ -881,8 +880,7 @@ pub const Dir = struct {
881 }880 }
882881
883 pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) !void {882 pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) !void {
884 const handle = try os.windows.CreateDirectoryW(self.fd, sub_path, null);883 try os.mkdiratW(self.fd, sub_path, default_new_dir_mode);
885 os.windows.CloseHandle(handle);
886 }884 }
887885
888 /// Calls makeDir recursively to make an entire path. Returns success if the path886 /// Calls makeDir recursively to make an entire path. Returns success if the path
lib/std/fs/watch.zig+7-9
...@@ -374,15 +374,13 @@ pub fn Watch(comptime V: type) type {...@@ -374,15 +374,13 @@ pub fn Watch(comptime V: type) type {
374 defer if (!basename_utf16le_null_consumed) self.allocator.free(basename_utf16le_null);374 defer if (!basename_utf16le_null_consumed) self.allocator.free(basename_utf16le_null);
375 const basename_utf16le_no_null = basename_utf16le_null[0 .. basename_utf16le_null.len - 1];375 const basename_utf16le_no_null = basename_utf16le_null[0 .. basename_utf16le_null.len - 1];
376376
377 const dir_handle = try windows.CreateFileW(377 const dir_handle = try windows.OpenFile(dirname_utf16le, .{
378 dirname_utf16le.ptr,378 .dir = std.fs.cwd().fd,
379 windows.FILE_LIST_DIRECTORY,379 .access_mask = windows.FILE_LIST_DIRECTORY,
380 windows.FILE_SHARE_READ | windows.FILE_SHARE_DELETE | windows.FILE_SHARE_WRITE,380 .creation = windows.FILE_OPEN,
381 null,381 .io_mode = .blocking,
382 windows.OPEN_EXISTING,382 .expect_dir = true,
383 windows.FILE_FLAG_BACKUP_SEMANTICS | windows.FILE_FLAG_OVERLAPPED,383 });
384 null,
385 );
386 var dir_handle_consumed = false;384 var dir_handle_consumed = false;
387 defer if (!dir_handle_consumed) windows.CloseHandle(dir_handle);385 defer if (!dir_handle_consumed) windows.CloseHandle(dir_handle);
388386
lib/std/os.zig+65-19
...@@ -2146,7 +2146,18 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr...@@ -2146,7 +2146,18 @@ pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr
2146}2146}
21472147
2148pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirError!void {2148pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirError!void {
2149 const sub_dir_handle = try windows.CreateDirectoryW(dir_fd, sub_path_w, null);2149 const sub_dir_handle = windows.OpenFile(std.mem.spanZ(sub_path_w), .{
2150 .dir = dir_fd,
2151 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
2152 .creation = windows.FILE_CREATE,
2153 .io_mode = .blocking,
2154 .expect_dir = true,
2155 }) catch |err| switch (err) {
2156 error.IsDir => unreachable,
2157 error.PipeBusy => unreachable,
2158 error.WouldBlock => unreachable,
2159 else => |e| return e,
2160 };
2150 windows.CloseHandle(sub_dir_handle);2161 windows.CloseHandle(sub_dir_handle);
2151}2162}
21522163
...@@ -2175,9 +2186,8 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {...@@ -2175,9 +2186,8 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
2175 if (builtin.os.tag == .wasi) {2186 if (builtin.os.tag == .wasi) {
2176 @compileError("mkdir is not supported in WASI; use mkdirat instead");2187 @compileError("mkdir is not supported in WASI; use mkdirat instead");
2177 } else if (builtin.os.tag == .windows) {2188 } else if (builtin.os.tag == .windows) {
2178 const sub_dir_handle = try windows.CreateDirectory(null, dir_path, null);2189 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
2179 windows.CloseHandle(sub_dir_handle);2190 return mkdirW(dir_path_w.span().ptr, mode);
2180 return;
2181 } else {2191 } else {
2182 const dir_path_c = try toPosixPath(dir_path);2192 const dir_path_c = try toPosixPath(dir_path);
2183 return mkdirZ(&dir_path_c, mode);2193 return mkdirZ(&dir_path_c, mode);
...@@ -2188,9 +2198,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {...@@ -2188,9 +2198,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
2188pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {2198pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
2189 if (builtin.os.tag == .windows) {2199 if (builtin.os.tag == .windows) {
2190 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);2200 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
2191 const sub_dir_handle = try windows.CreateDirectoryW(null, dir_path_w.span().ptr, null);2201 return mkdirW(dir_path_w.span().ptr, mode);
2192 windows.CloseHandle(sub_dir_handle);
2193 return;
2194 }2202 }
2195 switch (errno(system.mkdir(dir_path, mode))) {2203 switch (errno(system.mkdir(dir_path, mode))) {
2196 0 => return,2204 0 => return,
...@@ -2211,6 +2219,23 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {...@@ -2211,6 +2219,23 @@ pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
2211 }2219 }
2212}2220}
22132221
2222/// Windows-only. Same as `mkdir` but the parameters is null-terminated, WTF16 encoded.
2223pub fn mkdirW(dir_path_w: [*:0]const u16, mode: u32) MakeDirError!void {
2224 const sub_dir_handle = windows.OpenFile(std.mem.spanZ(dir_path_w), .{
2225 .dir = std.fs.cwd().fd,
2226 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
2227 .creation = windows.FILE_CREATE,
2228 .io_mode = .blocking,
2229 .expect_dir = true,
2230 }) catch |err| switch (err) {
2231 error.IsDir => unreachable,
2232 error.PipeBusy => unreachable,
2233 error.WouldBlock => unreachable,
2234 else => |e| return e,
2235 };
2236 windows.CloseHandle(sub_dir_handle);
2237}
2238
2214pub const DeleteDirError = error{2239pub const DeleteDirError = error{
2215 AccessDenied,2240 AccessDenied,
2216 FileBusy,2241 FileBusy,
...@@ -4013,19 +4038,40 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP...@@ -4013,19 +4038,40 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP
4013/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.4038/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.
4014/// TODO use ntdll for better semantics4039/// TODO use ntdll for better semantics
4015pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {4040pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
4016 const h_file = try windows.CreateFileW(4041 const w = windows;
4017 pathname,4042
4018 windows.GENERIC_READ,4043 const dir = std.fs.cwd().fd;
4019 windows.FILE_SHARE_READ,4044 const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
4020 null,4045 const share_access = w.FILE_SHARE_READ;
4021 windows.OPEN_EXISTING,4046 const creation = w.FILE_OPEN;
4022 windows.FILE_FLAG_BACKUP_SEMANTICS,4047 const h_file = blk: {
4023 null,4048 const res = w.OpenFile(std.mem.spanZ(pathname), .{
4024 );4049 .dir = dir,
4025 defer windows.CloseHandle(h_file);4050 .access_mask = access_mask,
4051 .share_access = share_access,
4052 .creation = creation,
4053 .io_mode = .blocking,
4054 }) catch |err| switch (err) {
4055 error.IsDir => break :blk w.OpenFile(std.mem.spanZ(pathname), .{
4056 .dir = dir,
4057 .access_mask = access_mask,
4058 .share_access = share_access,
4059 .creation = creation,
4060 .io_mode = .blocking,
4061 .expect_dir = true,
4062 }) catch |er| switch (er) {
4063 error.WouldBlock => unreachable,
4064 else => |e2| return e2,
4065 },
4066 error.WouldBlock => unreachable,
4067 else => |e| return e,
4068 };
4069 break :blk res;
4070 };
4071 defer w.CloseHandle(h_file);
40264072
4027 var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;4073 var wide_buf: [w.PATH_MAX_WIDE]u16 = undefined;
4028 const wide_slice = try windows.GetFinalPathNameByHandleW(h_file, &wide_buf, wide_buf.len, windows.VOLUME_NAME_DOS);4074 const wide_slice = try w.GetFinalPathNameByHandleW(h_file, &wide_buf, wide_buf.len, w.VOLUME_NAME_DOS);
40294075
4030 // Windows returns \\?\ prepended to the path.4076 // Windows returns \\?\ prepended to the path.
4031 // We strip it to make this function consistent across platforms.4077 // We strip it to make this function consistent across platforms.
lib/std/os/windows.zig+8-124
...@@ -49,52 +49,10 @@ pub const CreateFileError = error{...@@ -49,52 +49,10 @@ pub const CreateFileError = error{
49 Unexpected,49 Unexpected,
50};50};
5151
52pub fn CreateFile(
53 file_path: []const u8,
54 desired_access: DWORD,
55 share_mode: DWORD,
56 lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES,
57 creation_disposition: DWORD,
58 flags_and_attrs: DWORD,
59 hTemplateFile: ?HANDLE,
60) CreateFileError!HANDLE {
61 const file_path_w = try sliceToPrefixedFileW(file_path);
62 return CreateFileW(file_path_w.span().ptr, desired_access, share_mode, lpSecurityAttributes, creation_disposition, flags_and_attrs, hTemplateFile);
63}
64
65pub fn CreateFileW(
66 file_path_w: [*:0]const u16,
67 desired_access: DWORD,
68 share_mode: DWORD,
69 lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES,
70 creation_disposition: DWORD,
71 flags_and_attrs: DWORD,
72 hTemplateFile: ?HANDLE,
73) CreateFileError!HANDLE {
74 const result = kernel32.CreateFileW(file_path_w, desired_access, share_mode, lpSecurityAttributes, creation_disposition, flags_and_attrs, hTemplateFile);
75
76 if (result == INVALID_HANDLE_VALUE) {
77 switch (kernel32.GetLastError()) {
78 .SHARING_VIOLATION => return error.SharingViolation,
79 .ALREADY_EXISTS => return error.PathAlreadyExists,
80 .FILE_EXISTS => return error.PathAlreadyExists,
81 .FILE_NOT_FOUND => return error.FileNotFound,
82 .PATH_NOT_FOUND => return error.FileNotFound,
83 .ACCESS_DENIED => return error.AccessDenied,
84 .PIPE_BUSY => return error.PipeBusy,
85 .FILENAME_EXCED_RANGE => return error.NameTooLong,
86 else => |err| return unexpectedError(err),
87 }
88 }
89
90 return result;
91}
92
93pub const OpenError = error{52pub const OpenError = error{
94 IsDir,53 IsDir,
95 FileNotFound,54 FileNotFound,
96 NoDevice,55 NoDevice,
97 SharingViolation,
98 AccessDenied,56 AccessDenied,
99 PipeBusy,57 PipeBusy,
100 PathAlreadyExists,58 PathAlreadyExists,
...@@ -111,15 +69,16 @@ pub const OpenFileOptions = struct {...@@ -111,15 +69,16 @@ pub const OpenFileOptions = struct {
111 share_access_nonblocking: bool = false,69 share_access_nonblocking: bool = false,
112 creation: ULONG,70 creation: ULONG,
113 io_mode: std.io.ModeOverride,71 io_mode: std.io.ModeOverride,
72 expect_dir: bool = false,
114};73};
11574
116/// TODO when share_access_nonblocking is false, this implementation uses75/// TODO when share_access_nonblocking is false, this implementation uses
117/// untinterruptible sleep() to block. This is not the final iteration of the API.76/// untinterruptible sleep() to block. This is not the final iteration of the API.
118pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE {77pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE {
119 if (mem.eql(u16, sub_path_w, &[_]u16{'.'})) {78 if (mem.eql(u16, sub_path_w, &[_]u16{'.'}) and !options.expect_dir) {
120 return error.IsDir;79 return error.IsDir;
121 }80 }
122 if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' })) {81 if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' }) and !options.expect_dir) {
123 return error.IsDir;82 return error.IsDir;
124 }83 }
12584
...@@ -145,8 +104,9 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -145,8 +104,9 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
145104
146 var delay: usize = 1;105 var delay: usize = 1;
147 while (true) {106 while (true) {
148 var flags: ULONG = undefined;
149 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;107 const blocking_flag: ULONG = if (options.io_mode == .blocking) FILE_SYNCHRONOUS_IO_NONALERT else 0;
108 const file_or_dir_flag: ULONG = if (options.expect_dir) FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT else FILE_NON_DIRECTORY_FILE;
109 const flags: ULONG = file_or_dir_flag | blocking_flag;
150 const rc = ntdll.NtCreateFile(110 const rc = ntdll.NtCreateFile(
151 &result,111 &result,
152 options.access_mask,112 options.access_mask,
...@@ -156,7 +116,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -156,7 +116,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
156 FILE_ATTRIBUTE_NORMAL,116 FILE_ATTRIBUTE_NORMAL,
157 options.share_access,117 options.share_access,
158 options.creation,118 options.creation,
159 FILE_NON_DIRECTORY_FILE | blocking_flag,119 flags,
160 null,120 null,
161 0,121 0,
162 );122 );
...@@ -183,7 +143,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN...@@ -183,7 +143,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
183 .PIPE_BUSY => return error.PipeBusy,143 .PIPE_BUSY => return error.PipeBusy,
184 .OBJECT_PATH_SYNTAX_BAD => unreachable,144 .OBJECT_PATH_SYNTAX_BAD => unreachable,
185 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,145 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
186 .FILE_IS_A_DIRECTORY => return error.IsDir,146 .FILE_IS_A_DIRECTORY => if (options.expect_dir) unreachable else return error.IsDir,
187 else => return unexpectedStatus(rc),147 else => return unexpectedStatus(rc),
188 }148 }
189 }149 }
...@@ -733,7 +693,6 @@ pub fn CreateSymbolicLinkW(...@@ -733,7 +693,6 @@ pub fn CreateSymbolicLinkW(
733 error.WouldBlock => unreachable,693 error.WouldBlock => unreachable,
734 error.IsDir => return error.PathAlreadyExists,694 error.IsDir => return error.PathAlreadyExists,
735 error.PipeBusy => unreachable,695 error.PipeBusy => unreachable,
736 error.SharingViolation => return error.AccessDenied,
737 else => |e| return e,696 else => |e| return e,
738 };697 };
739 }698 }
...@@ -915,80 +874,6 @@ pub fn MoveFileExW(old_path: [*:0]const u16, new_path: [*:0]const u16, flags: DW...@@ -915,80 +874,6 @@ pub fn MoveFileExW(old_path: [*:0]const u16, new_path: [*:0]const u16, flags: DW
915 }874 }
916}875}
917876
918pub const CreateDirectoryError = error{
919 NameTooLong,
920 PathAlreadyExists,
921 FileNotFound,
922 NoDevice,
923 AccessDenied,
924 InvalidUtf8,
925 BadPathName,
926 Unexpected,
927};
928
929/// Returns an open directory handle which the caller is responsible for closing with `CloseHandle`.
930pub fn CreateDirectory(dir: ?HANDLE, pathname: []const u8, sa: ?*SECURITY_ATTRIBUTES) CreateDirectoryError!HANDLE {
931 const pathname_w = try sliceToPrefixedFileW(pathname);
932 return CreateDirectoryW(dir, pathname_w.span().ptr, sa);
933}
934
935/// Same as `CreateDirectory` except takes a WTF-16 encoded path.
936pub fn CreateDirectoryW(
937 dir: ?HANDLE,
938 sub_path_w: [*:0]const u16,
939 sa: ?*SECURITY_ATTRIBUTES,
940) CreateDirectoryError!HANDLE {
941 const path_len_bytes = math.cast(u16, mem.lenZ(sub_path_w) * 2) catch |err| switch (err) {
942 error.Overflow => return error.NameTooLong,
943 };
944 var nt_name = UNICODE_STRING{
945 .Length = path_len_bytes,
946 .MaximumLength = path_len_bytes,
947 .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)),
948 };
949
950 if (sub_path_w[0] == '.' and sub_path_w[1] == 0) {
951 // Windows does not recognize this, but it does work with empty string.
952 nt_name.Length = 0;
953 }
954
955 var attr = OBJECT_ATTRIBUTES{
956 .Length = @sizeOf(OBJECT_ATTRIBUTES),
957 .RootDirectory = if (std.fs.path.isAbsoluteWindowsW(sub_path_w)) null else dir,
958 .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here.
959 .ObjectName = &nt_name,
960 .SecurityDescriptor = if (sa) |ptr| ptr.lpSecurityDescriptor else null,
961 .SecurityQualityOfService = null,
962 };
963 var io: IO_STATUS_BLOCK = undefined;
964 var result_handle: HANDLE = undefined;
965 const rc = ntdll.NtCreateFile(
966 &result_handle,
967 GENERIC_READ | SYNCHRONIZE,
968 &attr,
969 &io,
970 null,
971 FILE_ATTRIBUTE_NORMAL,
972 FILE_SHARE_READ,
973 FILE_CREATE,
974 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
975 null,
976 0,
977 );
978 switch (rc) {
979 .SUCCESS => return result_handle,
980 .OBJECT_NAME_INVALID => unreachable,
981 .OBJECT_NAME_NOT_FOUND => return error.FileNotFound,
982 .OBJECT_PATH_NOT_FOUND => return error.FileNotFound,
983 .NO_MEDIA_IN_DEVICE => return error.NoDevice,
984 .INVALID_PARAMETER => unreachable,
985 .ACCESS_DENIED => return error.AccessDenied,
986 .OBJECT_PATH_SYNTAX_BAD => unreachable,
987 .OBJECT_NAME_COLLISION => return error.PathAlreadyExists,
988 else => return unexpectedStatus(rc),
989 }
990}
991
992pub const RemoveDirectoryError = error{877pub const RemoveDirectoryError = error{
993 FileNotFound,878 FileNotFound,
994 DirNotEmpty,879 DirNotEmpty,
...@@ -1493,8 +1378,7 @@ pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace {...@@ -1493,8 +1378,7 @@ pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace {
1493}1378}
14941379
1495/// Converts the path `s` to WTF16, null-terminated. If the path is absolute,1380/// Converts the path `s` to WTF16, null-terminated. If the path is absolute,
1496/// it will get NT-style prefix `\??\` prepended automatically. For prepending1381/// it will get NT-style prefix `\??\` prepended automatically.
1497/// Win32-style prefix, see `sliceToWin32PrefixedFileW` instead.
1498pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {1382pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {
1499 // TODO https://github.com/ziglang/zig/issues/27651383 // TODO https://github.com/ziglang/zig/issues/2765
1500 var path_space: PathSpace = undefined;1384 var path_space: PathSpace = undefined;