mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
std.Io.Threaded: implement dirOpenFile for Windows
This commit is contained in:
parent
b561d5f3fe
commit
1c67607397
@ -97,6 +97,15 @@ pub fn close(dir: Dir, io: Io) void {
|
||||
return io.vtable.dirClose(io.userdata, dir);
|
||||
}
|
||||
|
||||
/// Opens a file for reading or writing, without attempting to create a new file.
|
||||
///
|
||||
/// To create a new file, see `createFile`.
|
||||
///
|
||||
/// Allocates a resource to be released 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 openFile(dir: Dir, io: Io, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
|
||||
return io.vtable.dirOpenFile(io.userdata, dir, sub_path, flags);
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ pub fn io(t: *Threaded) Io {
|
||||
else => dirCreateFilePosix,
|
||||
},
|
||||
.dirOpenFile = switch (builtin.os.tag) {
|
||||
.windows => @panic("TODO"),
|
||||
.windows => dirOpenFileWindows,
|
||||
.wasi => dirOpenFileWasi,
|
||||
else => dirOpenFilePosix,
|
||||
},
|
||||
@ -1731,6 +1731,50 @@ fn dirOpenFilePosix(
|
||||
return .{ .handle = fd };
|
||||
}
|
||||
|
||||
fn dirOpenFileWindows(
|
||||
userdata: ?*anyopaque,
|
||||
dir: Io.Dir,
|
||||
sub_path: []const u8,
|
||||
flags: Io.File.OpenFlags,
|
||||
) Io.File.OpenError!Io.File {
|
||||
const t: *Threaded = @ptrCast(@alignCast(userdata));
|
||||
try t.checkCancel();
|
||||
|
||||
const w = windows;
|
||||
const sub_path_w_array = try w.sliceToPrefixedFileW(dir.handle, sub_path);
|
||||
const sub_path_w = sub_path_w_array.span();
|
||||
|
||||
const handle = try w.OpenFile(sub_path_w, .{
|
||||
.dir = dir.handle,
|
||||
.access_mask = w.SYNCHRONIZE |
|
||||
(if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) |
|
||||
(if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0),
|
||||
.creation = w.FILE_OPEN,
|
||||
});
|
||||
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 dirOpenFileWasi(
|
||||
userdata: ?*anyopaque,
|
||||
dir: Io.Dir,
|
||||
|
||||
@ -138,12 +138,6 @@ pub fn makeDirAbsoluteZ(absolute_path_z: [*:0]const u8) !void {
|
||||
|
||||
test makeDirAbsoluteZ {}
|
||||
|
||||
/// Same as `makeDirAbsolute` except the parameter is a null-terminated WTF-16 LE-encoded string.
|
||||
pub fn makeDirAbsoluteW(absolute_path_w: [*:0]const u16) !void {
|
||||
assert(path.isAbsoluteWindowsW(absolute_path_w));
|
||||
return posix.mkdirW(mem.span(absolute_path_w), Dir.default_mode);
|
||||
}
|
||||
|
||||
/// Same as `Dir.deleteDir` except the path is absolute.
|
||||
/// On Windows, `dir_path` should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
|
||||
/// On WASI, `dir_path` should be encoded as valid UTF-8.
|
||||
@ -159,12 +153,6 @@ pub fn deleteDirAbsoluteZ(dir_path: [*:0]const u8) !void {
|
||||
return posix.rmdirZ(dir_path);
|
||||
}
|
||||
|
||||
/// Same as `deleteDirAbsolute` except the path parameter is WTF-16 and target OS is assumed Windows.
|
||||
pub fn deleteDirAbsoluteW(dir_path: [*:0]const u16) !void {
|
||||
assert(path.isAbsoluteWindowsW(dir_path));
|
||||
return posix.rmdirW(mem.span(dir_path));
|
||||
}
|
||||
|
||||
/// Same as `Dir.rename` except the paths are absolute.
|
||||
/// On Windows, both paths should be encoded as [WTF-8](https://wtf-8.codeberg.page/).
|
||||
/// On WASI, both paths should be encoded as valid UTF-8.
|
||||
@ -182,13 +170,6 @@ pub fn renameAbsoluteZ(old_path: [*:0]const u8, new_path: [*:0]const u8) !void {
|
||||
return posix.renameZ(old_path, new_path);
|
||||
}
|
||||
|
||||
/// Same as `renameAbsolute` except the path parameters are WTF-16 and target OS is assumed Windows.
|
||||
pub fn renameAbsoluteW(old_path: [*:0]const u16, new_path: [*:0]const u16) !void {
|
||||
assert(path.isAbsoluteWindowsW(old_path));
|
||||
assert(path.isAbsoluteWindowsW(new_path));
|
||||
return posix.renameW(old_path, new_path);
|
||||
}
|
||||
|
||||
/// Same as `Dir.rename`, except `new_sub_path` is relative to `new_dir`
|
||||
pub fn rename(old_dir: Dir, old_sub_path: []const u8, new_dir: Dir, new_sub_path: []const u8) !void {
|
||||
return posix.renameat(old_dir.fd, old_sub_path, new_dir.fd, new_sub_path);
|
||||
@ -199,12 +180,6 @@ pub fn renameZ(old_dir: Dir, old_sub_path_z: [*:0]const u8, new_dir: Dir, new_su
|
||||
return posix.renameatZ(old_dir.fd, old_sub_path_z, new_dir.fd, new_sub_path_z);
|
||||
}
|
||||
|
||||
/// Same as `rename` except the parameters are WTF16LE, NT prefixed.
|
||||
/// This function is Windows-only.
|
||||
pub fn renameW(old_dir: Dir, old_sub_path_w: []const u16, new_dir: Dir, new_sub_path_w: []const u16) !void {
|
||||
return posix.renameatW(old_dir.fd, old_sub_path_w, new_dir.fd, new_sub_path_w, windows.TRUE);
|
||||
}
|
||||
|
||||
/// Returns a handle to the current working directory. It is not opened with iteration capability.
|
||||
/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
|
||||
/// On POSIX targets, this function is comptime-callable.
|
||||
@ -241,12 +216,6 @@ pub fn openDirAbsoluteZ(absolute_path_c: [*:0]const u8, flags: Dir.OpenOptions)
|
||||
assert(path.isAbsoluteZ(absolute_path_c));
|
||||
return cwd().openDirZ(absolute_path_c, flags);
|
||||
}
|
||||
/// Same as `openDirAbsolute` but the path parameter is null-terminated.
|
||||
pub fn openDirAbsoluteW(absolute_path_c: [*:0]const u16, flags: Dir.OpenOptions) File.OpenError!Dir {
|
||||
assert(path.isAbsoluteWindowsW(absolute_path_c));
|
||||
return cwd().openDirW(absolute_path_c, flags);
|
||||
}
|
||||
|
||||
/// Opens a file for reading or writing, without attempting to create a new file, based on an absolute path.
|
||||
/// Call `File.close` to release the resource.
|
||||
/// Asserts that the path is absolute. See `Dir.openFile` for a function that
|
||||
@ -261,12 +230,6 @@ pub fn openFileAbsolute(absolute_path: []const u8, flags: File.OpenFlags) File.O
|
||||
return cwd().openFile(absolute_path, flags);
|
||||
}
|
||||
|
||||
/// Same as `openFileAbsolute` but the path parameter is WTF-16-encoded.
|
||||
pub fn openFileAbsoluteW(absolute_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File {
|
||||
assert(path.isAbsoluteWindowsWtf16(absolute_path_w));
|
||||
return cwd().openFileW(absolute_path_w, flags);
|
||||
}
|
||||
|
||||
/// Test accessing `path`.
|
||||
/// Be careful of Time-Of-Check-Time-Of-Use race conditions when using this function.
|
||||
/// For example, instead of testing if a file exists and then opening it, just
|
||||
@ -279,12 +242,6 @@ pub fn accessAbsolute(absolute_path: []const u8, flags: Io.Dir.AccessOptions) Di
|
||||
assert(path.isAbsolute(absolute_path));
|
||||
try cwd().access(absolute_path, flags);
|
||||
}
|
||||
/// Same as `accessAbsolute` but the path parameter is WTF-16 encoded.
|
||||
pub fn accessAbsoluteW(absolute_path: [*:0]const u16, flags: File.OpenFlags) Dir.AccessError!void {
|
||||
assert(path.isAbsoluteWindowsW(absolute_path));
|
||||
try cwd().accessW(absolute_path, flags);
|
||||
}
|
||||
|
||||
/// Creates, opens, or overwrites a file with write access, based on an absolute path.
|
||||
/// Call `File.close` to release the resource.
|
||||
/// Asserts that the path is absolute. See `Dir.createFile` for a function that
|
||||
@ -311,12 +268,6 @@ pub fn deleteFileAbsolute(absolute_path: []const u8) Dir.DeleteFileError!void {
|
||||
return cwd().deleteFile(absolute_path);
|
||||
}
|
||||
|
||||
/// Same as `deleteFileAbsolute` except the parameter is WTF-16 encoded.
|
||||
pub fn deleteFileAbsoluteW(absolute_path_w: [*:0]const u16) Dir.DeleteFileError!void {
|
||||
assert(path.isAbsoluteWindowsW(absolute_path_w));
|
||||
return cwd().deleteFileW(mem.span(absolute_path_w));
|
||||
}
|
||||
|
||||
/// Removes a symlink, file, or directory.
|
||||
/// This is equivalent to `Dir.deleteTree` with the base directory.
|
||||
/// Asserts that the path is absolute. See `Dir.deleteTree` for a function that
|
||||
@ -348,13 +299,6 @@ pub fn readLinkAbsolute(pathname: []const u8, buffer: *[max_path_bytes]u8) ![]u8
|
||||
return posix.readlink(pathname, buffer);
|
||||
}
|
||||
|
||||
/// Windows-only. Same as `readlinkW`, except the path parameter is null-terminated, WTF16
|
||||
/// encoded.
|
||||
pub fn readlinkAbsoluteW(pathname_w: [*:0]const u16, buffer: *[max_path_bytes]u8) ![]u8 {
|
||||
assert(path.isAbsoluteWindowsW(pathname_w));
|
||||
return posix.readlinkW(mem.span(pathname_w), buffer);
|
||||
}
|
||||
|
||||
/// Creates a symbolic link named `sym_link_path` which contains the string `target_path`.
|
||||
/// A symbolic link (also known as a soft link) may point to an existing file or to a nonexistent
|
||||
/// one; the latter case is known as a dangling link.
|
||||
|
||||
@ -846,60 +846,13 @@ pub fn close(self: *Dir) void {
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
/// Opens a file for reading or writing, without attempting to create a new file.
|
||||
/// To create a new file, see `createFile`.
|
||||
/// Call `File.close` to release the resource.
|
||||
/// 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.openFile`.
|
||||
pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
|
||||
if (native_os == .windows) {
|
||||
const path_w = try windows.sliceToPrefixedFileW(self.fd, sub_path);
|
||||
return self.openFileW(path_w.span(), flags);
|
||||
}
|
||||
var threaded: Io.Threaded = .init_single_threaded;
|
||||
const io = threaded.io();
|
||||
return .adaptFromNewApi(try Io.Dir.openFile(self.adaptToNewApi(), io, sub_path, flags));
|
||||
}
|
||||
|
||||
/// Same as `openFile` but Windows-only and the path parameter is
|
||||
/// [WTF-16](https://wtf-8.codeberg.page/#potentially-ill-formed-utf-16) encoded.
|
||||
pub fn openFileW(self: Dir, sub_path_w: []const u16, flags: File.OpenFlags) File.OpenError!File {
|
||||
const w = windows;
|
||||
const file: File = .{
|
||||
.handle = try w.OpenFile(sub_path_w, .{
|
||||
.dir = self.fd,
|
||||
.access_mask = w.SYNCHRONIZE |
|
||||
(if (flags.isRead()) @as(u32, w.GENERIC_READ) else 0) |
|
||||
(if (flags.isWrite()) @as(u32, w.GENERIC_WRITE) else 0),
|
||||
.creation = w.FILE_OPEN,
|
||||
}),
|
||||
};
|
||||
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.createFile`.
|
||||
pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
|
||||
var threaded: Io.Threaded = .init_single_threaded;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user