diff --git a/lib/std/Io/Dir.zig b/lib/std/Io/Dir.zig index 749bea99ba..966ef77bcb 100644 --- a/lib/std/Io/Dir.zig +++ b/lib/std/Io/Dir.zig @@ -101,6 +101,13 @@ pub fn openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) F return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags); } +/// Creates, opens, or overwrites a file with write access. +/// +/// Allocates a resource to be dellocated with `File.close`. +/// +/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). +/// On WASI, `sub_path` should be encoded as valid UTF-8. +/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. pub fn createFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { return io.vtable.dirCreateFile(io.userdata, dir, sub_path, flags); } diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 93d4cc1b42..5fb6b781c1 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -187,7 +187,7 @@ pub fn io(t: *Threaded) Io { else => dirAccessPosix, }, .dirCreateFile = switch (builtin.os.tag) { - .windows => @panic("TODO"), + .windows => dirCreateFileWindows, .wasi => dirCreateFileWasi, else => dirCreateFilePosix, }, @@ -1483,6 +1483,54 @@ fn dirCreateFilePosix( return .{ .handle = fd }; } +fn dirCreateFileWindows( + userdata: ?*anyopaque, + dir: Io.Dir, + sub_path: []const u8, + flags: Io.File.CreateFlags, +) Io.File.OpenError!Io.File { + const w = windows; + const t: *Threaded = @ptrCast(@alignCast(userdata)); + try t.checkCancel(); + + const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path); + const sub_path_w = sub_path_w_array.span(); + + const read_flag = if (flags.read) @as(u32, w.GENERIC_READ) else 0; + const handle = try w.OpenFile(sub_path_w, .{ + .dir = dir.handle, + .access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag, + .creation = if (flags.exclusive) + @as(u32, w.FILE_CREATE) + else if (flags.truncate) + @as(u32, w.FILE_OVERWRITE_IF) + else + @as(u32, w.FILE_OPEN_IF), + }); + errdefer w.CloseHandle(handle); + var io_status_block: w.IO_STATUS_BLOCK = undefined; + const range_off: w.LARGE_INTEGER = 0; + const range_len: w.LARGE_INTEGER = 1; + const exclusive = switch (flags.lock) { + .none => return .{ .handle = handle }, + .shared => false, + .exclusive => true, + }; + try w.LockFile( + handle, + null, + null, + null, + &io_status_block, + &range_off, + &range_len, + null, + @intFromBool(flags.lock_nonblocking), + @intFromBool(exclusive), + ); + return .{ .handle = handle }; +} + fn dirCreateFileWasi( userdata: ?*anyopaque, dir: Io.Dir, diff --git a/lib/std/fs.zig b/lib/std/fs.zig index 01188e29a3..ac4d933d32 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -299,12 +299,6 @@ pub fn createFileAbsolute(absolute_path: []const u8, flags: File.CreateFlags) Fi return cwd().createFile(absolute_path, flags); } -/// Same as `createFileAbsolute` but the path parameter is WTF-16 encoded. -pub fn createFileAbsoluteW(absolute_path_w: [*:0]const u16, flags: File.CreateFlags) File.OpenError!File { - assert(path.isAbsoluteWindowsW(absolute_path_w)); - return cwd().createFileW(mem.span(absolute_path_w), flags); -} - /// Delete a file name and possibly the file it refers to, based on an absolute path. /// Asserts that the path is absolute. See `Dir.deleteFile` for a function that /// operates on both absolute and relative paths. diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig index 2eb85928f6..ecd713c01a 100644 --- a/lib/std/fs/Dir.zig +++ b/lib/std/fs/Dir.zig @@ -900,64 +900,14 @@ pub fn openFileW(self: Dir, sub_path_w: []const u16, flags: File.OpenFlags) File return file; } -/// Creates, opens, or overwrites a file with write access. -/// Call `File.close` on the result when done. -/// Asserts that the path parameter has no null bytes. -/// On Windows, `sub_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/). -/// On WASI, `sub_path` should be encoded as valid UTF-8. -/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding. +/// Deprecated in favor of `Io.Dir.createFile`. pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { - if (native_os == .windows) { - const path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path); - return self.createFileW(path_w.span(), flags); - } var threaded: Io.Threaded = .init_single_threaded; const io = threaded.io(); const new_file = try Io.Dir.createFile(self.adaptToNewApi(), io, sub_path, flags); return .adaptFromNewApi(new_file); } -/// Same as `createFile` but Windows-only and the path parameter is -/// [WTF-16](https://wtf-8.codeberg.page/#potentially-ill-formed-utf-16) encoded. -pub fn createFileW(self: Dir, sub_path_w: []const u16, flags: File.CreateFlags) File.OpenError!File { - const w = windows; - const read_flag = if (flags.read) @as(u32, w.GENERIC_READ) else 0; - const file: File = .{ - .handle = try w.OpenFile(sub_path_w, .{ - .dir = self.fd, - .access_mask = w.SYNCHRONIZE | w.GENERIC_WRITE | read_flag, - .creation = if (flags.exclusive) - @as(u32, w.FILE_CREATE) - else if (flags.truncate) - @as(u32, w.FILE_OVERWRITE_IF) - else - @as(u32, w.FILE_OPEN_IF), - }), - }; - errdefer file.close(); - var io: w.IO_STATUS_BLOCK = undefined; - const range_off: w.LARGE_INTEGER = 0; - const range_len: w.LARGE_INTEGER = 1; - const exclusive = switch (flags.lock) { - .none => return file, - .shared => false, - .exclusive => true, - }; - try w.LockFile( - file.handle, - null, - null, - null, - &io, - &range_off, - &range_len, - null, - @intFromBool(flags.lock_nonblocking), - @intFromBool(exclusive), - ); - return file; -} - /// Deprecated in favor of `Io.Dir.MakeError`. pub const MakeError = Io.Dir.MakeError; diff --git a/lib/std/posix.zig b/lib/std/posix.zig index a186ac7074..4473faf328 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -4684,9 +4684,7 @@ pub const AccessError = error{ /// Windows. See `fs` for the cross-platform file system API. pub fn access(path: []const u8, mode: u32) AccessError!void { if (native_os == .windows) { - const path_w = try windows.sliceToPrefixedFileW(null, path); - _ = try windows.GetFileAttributesW(path_w.span().ptr); - return; + @compileError("use std.Io instead"); } else if (native_os == .wasi and !builtin.link_libc) { @compileError("wasi doesn't support absolute paths"); } @@ -4697,9 +4695,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void { /// Same as `access` except `path` is null-terminated. pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void { if (native_os == .windows) { - const path_w = try windows.cStrToPrefixedFileW(null, path); - _ = try windows.GetFileAttributesW(path_w.span().ptr); - return; + @compileError("use std.Io instead"); } else if (native_os == .wasi and !builtin.link_libc) { return access(mem.sliceTo(path, 0), mode); }