fix regressions in windows std lib tests

master
Andrew Kelley 2020-05-02 01:25:22 -04:00
parent 2272a07ca0
commit 43f7856bac
4 changed files with 86 additions and 113 deletions

View File

@ -328,14 +328,14 @@ pub const WindowsDynLib = struct {
pub fn open(path: []const u8) !WindowsDynLib {
const path_w = try windows.sliceToPrefixedFileW(path);
return openW(&path_w);
return openW(path_w.span().ptr);
}
pub const openC = @compileError("deprecated: renamed to openZ");
pub fn openZ(path_c: [*:0]const u8) !WindowsDynLib {
const path_w = try windows.cStrToPrefixedFileW(path_c);
return openW(&path_w);
return openW(path_w.span().ptr);
}
pub fn openW(path_w: [*:0]const u16) !WindowsDynLib {

View File

@ -199,7 +199,7 @@ pub const AtomicFile = struct {
if (std.Target.current.os.tag == .windows) {
const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_basename);
const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
try os.renameatW(self.dir.fd, &tmp_path_w, self.dir.fd, &dest_path_w, os.windows.TRUE);
try os.renameatW(self.dir.fd, tmp_path_w.span(), self.dir.fd, dest_path_w.span(), os.windows.TRUE);
self.file_exists = false;
} else {
const dest_path_c = try os.toPosixPath(self.dest_basename);
@ -582,7 +582,7 @@ pub const Dir = struct {
pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
if (builtin.os.tag == .windows) {
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.openFileW(&path_w, flags);
return self.openFileW(path_w.span(), flags);
}
const path_c = try os.toPosixPath(sub_path);
return self.openFileZ(&path_c, flags);
@ -594,7 +594,7 @@ pub const Dir = struct {
pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File {
if (builtin.os.tag == .windows) {
const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
return self.openFileW(&path_w, flags);
return self.openFileW(path_w.span(), flags);
}
// Use the O_ locking flags if the os supports them
@ -669,7 +669,7 @@ pub const Dir = struct {
pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
if (builtin.os.tag == .windows) {
const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.createFileW(&path_w, flags);
return self.createFileW(path_w.span(), flags);
}
const path_c = try os.toPosixPath(sub_path);
return self.createFileZ(&path_c, flags);
@ -681,7 +681,7 @@ pub const Dir = struct {
pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {
if (builtin.os.tag == .windows) {
const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
return self.createFileW(&path_w, flags);
return self.createFileW(path_w.span(), flags);
}
// Use the O_ locking flags if the os supports them
@ -832,7 +832,7 @@ pub const Dir = struct {
pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.openDirW(&sub_path_w, args);
return self.openDirW(sub_path_w.span().ptr, args);
} else {
const sub_path_c = try os.toPosixPath(sub_path);
return self.openDirZ(&sub_path_c, args);
@ -845,7 +845,7 @@ pub const Dir = struct {
pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
return self.openDirW(&sub_path_w, args);
return self.openDirW(sub_path_w.span().ptr, args);
} else if (!args.iterate) {
const O_PATH = if (@hasDecl(os, "O_PATH")) os.O_PATH else 0;
return self.openDirFlagsZ(sub_path_c, os.O_DIRECTORY | os.O_RDONLY | os.O_CLOEXEC | O_PATH);
@ -987,7 +987,7 @@ pub const Dir = struct {
pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.deleteDirW(&sub_path_w);
return self.deleteDirW(sub_path_w.span().ptr);
}
const sub_path_c = try os.toPosixPath(sub_path);
return self.deleteDirZ(&sub_path_c);
@ -1246,7 +1246,7 @@ pub const Dir = struct {
pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
return self.accessW(&sub_path_w, flags);
return self.accessW(sub_path_w.span().ptr, flags);
}
const path_c = try os.toPosixPath(sub_path);
return self.accessZ(&path_c, flags);
@ -1256,7 +1256,7 @@ pub const Dir = struct {
pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void {
if (builtin.os.tag == .windows) {
const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);
return self.accessW(&sub_path_w, flags);
return self.accessW(sub_path_w.span().ptr, flags);
}
const os_mode = if (flags.write and flags.read)
@as(u32, os.R_OK | os.W_OK)
@ -1596,7 +1596,7 @@ pub fn openSelfExe() OpenSelfExeError!File {
if (builtin.os.tag == .windows) {
const wide_slice = selfExePathW();
const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice);
return cwd().openFileW(&prefixed_path_w, .{});
return cwd().openFileW(prefixed_path_w.span(), .{});
}
var buf: [MAX_PATH_BYTES]u8 = undefined;
const self_exe_path = try selfExePath(&buf);

View File

@ -857,7 +857,7 @@ pub const OpenError = error{
pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
if (std.Target.current.os.tag == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
return openW(&file_path_w, flags, perm);
return openW(file_path_w.span(), flags, perm);
}
const file_path_c = try toPosixPath(file_path);
return openZ(&file_path_c, flags, perm);
@ -870,7 +870,7 @@ pub const openC = @compileError("deprecated: renamed to openZ");
pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
if (std.Target.current.os.tag == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
return openW(&file_path_w, flags, perm);
return openW(file_path_w.span(), flags, perm);
}
while (true) {
const rc = system.open(file_path, flags, perm);
@ -1317,7 +1317,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
if (builtin.os.tag == .windows) {
const target_path_w = try windows.sliceToPrefixedFileW(target_path);
const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);
return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0);
} else {
const target_path_c = try toPosixPath(target_path);
const sym_link_path_c = try toPosixPath(sym_link_path);
@ -1333,7 +1333,7 @@ pub fn symlinkZ(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLin
if (builtin.os.tag == .windows) {
const target_path_w = try windows.cStrToPrefixedFileW(target_path);
const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);
return windows.CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, 0);
}
switch (errno(system.symlink(target_path, sym_link_path))) {
0 => return,
@ -1409,7 +1409,7 @@ pub const UnlinkError = error{
pub fn unlink(file_path: []const u8) UnlinkError!void {
if (builtin.os.tag == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
return windows.DeleteFileW(&file_path_w);
return windows.DeleteFileW(file_path_w.span().ptr);
} else {
const file_path_c = try toPosixPath(file_path);
return unlinkZ(&file_path_c);
@ -1422,7 +1422,7 @@ pub const unlinkC = @compileError("deprecated: renamed to unlinkZ");
pub fn unlinkZ(file_path: [*:0]const u8) UnlinkError!void {
if (builtin.os.tag == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path);
return windows.DeleteFileW(&file_path_w);
return windows.DeleteFileW(file_path_w.span().ptr);
}
switch (errno(system.unlink(file_path))) {
0 => return,
@ -1453,7 +1453,7 @@ pub const UnlinkatError = UnlinkError || error{
pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void {
if (builtin.os.tag == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
return unlinkatW(dirfd, &file_path_w, flags);
return unlinkatW(dirfd, file_path_w.span().ptr, flags);
}
const file_path_c = try toPosixPath(file_path);
return unlinkatZ(dirfd, &file_path_c, flags);
@ -1465,7 +1465,7 @@ pub const unlinkatC = @compileError("deprecated: renamed to unlinkatZ");
pub fn unlinkatZ(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void {
if (builtin.os.tag == .windows) {
const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
return unlinkatW(dirfd, &file_path_w, flags);
return unlinkatW(dirfd, file_path_w.span().ptr, flags);
}
switch (errno(system.unlinkat(dirfd, file_path_c, flags))) {
0 => return,
@ -1580,7 +1580,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
if (builtin.os.tag == .windows) {
const old_path_w = try windows.sliceToPrefixedFileW(old_path);
const new_path_w = try windows.sliceToPrefixedFileW(new_path);
return renameW(&old_path_w, &new_path_w);
return renameW(old_path_w.span().ptr, new_path_w.span().ptr);
} else {
const old_path_c = try toPosixPath(old_path);
const new_path_c = try toPosixPath(new_path);
@ -1595,7 +1595,7 @@ pub fn renameZ(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!voi
if (builtin.os.tag == .windows) {
const old_path_w = try windows.cStrToPrefixedFileW(old_path);
const new_path_w = try windows.cStrToPrefixedFileW(new_path);
return renameW(&old_path_w, &new_path_w);
return renameW(old_path_w.span().ptr, new_path_w.span().ptr);
}
switch (errno(system.rename(old_path, new_path))) {
0 => return,
@ -1638,7 +1638,7 @@ pub fn renameat(
if (builtin.os.tag == .windows) {
const old_path_w = try windows.sliceToPrefixedFileW(old_path);
const new_path_w = try windows.sliceToPrefixedFileW(new_path);
return renameatW(old_dir_fd, &old_path_w, new_dir_fd, &new_path_w, windows.TRUE);
return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE);
} else {
const old_path_c = try toPosixPath(old_path);
const new_path_c = try toPosixPath(new_path);
@ -1656,7 +1656,7 @@ pub fn renameatZ(
if (builtin.os.tag == .windows) {
const old_path_w = try windows.cStrToPrefixedFileW(old_path);
const new_path_w = try windows.cStrToPrefixedFileW(new_path);
return renameatW(old_dir_fd, &old_path_w, new_dir_fd, &new_path_w, windows.TRUE);
return renameatW(old_dir_fd, old_path_w.span(), new_dir_fd, new_path_w.span(), windows.TRUE);
}
switch (errno(system.renameat(old_dir_fd, old_path, new_dir_fd, new_path))) {
@ -1760,7 +1760,7 @@ pub const MakeDirError = error{
pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void {
if (builtin.os.tag == .windows) {
const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path);
return mkdiratW(dir_fd, &sub_dir_path_w, mode);
return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode);
} else {
const sub_dir_path_c = try toPosixPath(sub_dir_path);
return mkdiratZ(dir_fd, &sub_dir_path_c, mode);
@ -1772,7 +1772,7 @@ pub const mkdiratC = @compileError("deprecated: renamed to mkdiratZ");
pub fn mkdiratZ(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
if (builtin.os.tag == .windows) {
const sub_dir_path_w = try windows.cStrToPrefixedFileW(sub_dir_path);
return mkdiratW(dir_fd, &sub_dir_path_w, mode);
return mkdiratW(dir_fd, sub_dir_path_w.span().ptr, mode);
}
switch (errno(system.mkdirat(dir_fd, sub_dir_path, mode))) {
0 => return,
@ -1816,7 +1816,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
if (builtin.os.tag == .windows) {
const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
const sub_dir_handle = try windows.CreateDirectoryW(null, &dir_path_w, null);
const sub_dir_handle = try windows.CreateDirectoryW(null, dir_path_w.span().ptr, null);
windows.CloseHandle(sub_dir_handle);
return;
}
@ -1857,7 +1857,7 @@ pub const DeleteDirError = error{
pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
if (builtin.os.tag == .windows) {
const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
return windows.RemoveDirectoryW(&dir_path_w);
return windows.RemoveDirectoryW(dir_path_w.span().ptr);
} else {
const dir_path_c = try toPosixPath(dir_path);
return rmdirZ(&dir_path_c);
@ -1870,7 +1870,7 @@ pub const rmdirC = @compileError("deprecated: renamed to rmdirZ");
pub fn rmdirZ(dir_path: [*:0]const u8) DeleteDirError!void {
if (builtin.os.tag == .windows) {
const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
return windows.RemoveDirectoryW(&dir_path_w);
return windows.RemoveDirectoryW(dir_path_w.span().ptr);
}
switch (errno(system.rmdir(dir_path))) {
0 => return,
@ -2880,7 +2880,7 @@ pub const AccessError = error{
pub fn access(path: []const u8, mode: u32) AccessError!void {
if (builtin.os.tag == .windows) {
const path_w = try windows.sliceToPrefixedFileW(path);
_ = try windows.GetFileAttributesW(&path_w);
_ = try windows.GetFileAttributesW(path_w.span().ptr);
return;
}
const path_c = try toPosixPath(path);
@ -2893,7 +2893,7 @@ pub const accessC = @compileError("Deprecated in favor of `accessZ`");
pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
if (builtin.os.tag == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
_ = try windows.GetFileAttributesW(&path_w);
_ = try windows.GetFileAttributesW(path_w.span().ptr);
return;
}
switch (errno(system.access(path, mode))) {
@ -2934,7 +2934,7 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v
pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void {
if (builtin.os.tag == .windows) {
const path_w = try windows.sliceToPrefixedFileW(path);
return faccessatW(dirfd, &path_w, mode, flags);
return faccessatW(dirfd, path_w.span().ptr, mode, flags);
}
const path_c = try toPosixPath(path);
return faccessatZ(dirfd, &path_c, mode, flags);
@ -2944,7 +2944,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr
pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void {
if (builtin.os.tag == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
return faccessatW(dirfd, &path_w, mode, flags);
return faccessatW(dirfd, path_w.span().ptr, mode, flags);
}
switch (errno(system.faccessat(dirfd, path, mode, flags))) {
0 => return,
@ -3299,7 +3299,7 @@ pub const RealPathError = error{
pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
if (builtin.os.tag == .windows) {
const pathname_w = try windows.sliceToPrefixedFileW(pathname);
return realpathW(&pathname_w, out_buffer);
return realpathW(pathname_w.span().ptr, out_buffer);
}
const pathname_c = try toPosixPath(pathname);
return realpathZ(&pathname_c, out_buffer);
@ -3311,7 +3311,7 @@ pub const realpathC = @compileError("deprecated: renamed realpathZ");
pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
if (builtin.os.tag == .windows) {
const pathname_w = try windows.cStrToPrefixedFileW(pathname);
return realpathW(&pathname_w, out_buffer);
return realpathW(pathname_w.span().ptr, out_buffer);
}
if (builtin.os.tag == .linux and !builtin.link_libc) {
const fd = openZ(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0) catch |err| switch (err) {

View File

@ -59,7 +59,7 @@ pub fn CreateFile(
hTemplateFile: ?HANDLE,
) CreateFileError!HANDLE {
const file_path_w = try sliceToPrefixedFileW(file_path);
return CreateFileW(&file_path_w, desired_access, share_mode, lpSecurityAttributes, creation_disposition, flags_and_attrs, hTemplateFile);
return CreateFileW(file_path_w.span().ptr, desired_access, share_mode, lpSecurityAttributes, creation_disposition, flags_and_attrs, hTemplateFile);
}
pub fn CreateFileW(
@ -116,10 +116,10 @@ pub const OpenFileOptions = struct {
/// TODO when share_access_nonblocking is false, this implementation uses
/// untinterruptible sleep() to block. This is not the final iteration of the API.
pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HANDLE {
if (mem.eql(u16, sub_path_w, ".")) {
if (mem.eql(u16, sub_path_w, &[_]u16{'.'})) {
return error.IsDir;
}
if (mem.eql(u16, sub_path_w, "..")) {
if (mem.eql(u16, sub_path_w, &[_]u16{ '.', '.' })) {
return error.IsDir;
}
@ -199,7 +199,7 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
pub fn CreateEventEx(attributes: ?*SECURITY_ATTRIBUTES, name: []const u8, flags: DWORD, desired_access: DWORD) !HANDLE {
const nameW = try sliceToPrefixedFileW(name);
return CreateEventExW(attributes, &nameW, flags, desired_access);
return CreateEventExW(attributes, nameW.span().ptr, flags, desired_access);
}
pub fn CreateEventExW(attributes: ?*SECURITY_ATTRIBUTES, nameW: [*:0]const u16, flags: DWORD, desired_access: DWORD) !HANDLE {
@ -332,42 +332,6 @@ pub fn WaitForMultipleObjectsEx(handles: []const HANDLE, waitAll: bool, millisec
}
}
pub const FindFirstFileError = error{
FileNotFound,
InvalidUtf8,
BadPathName,
NameTooLong,
Unexpected,
};
pub fn FindFirstFile(dir_path: []const u8, find_file_data: *WIN32_FIND_DATAW) FindFirstFileError!HANDLE {
const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, [_]u16{ '\\', '*' });
const handle = kernel32.FindFirstFileW(&dir_path_w, find_file_data);
if (handle == INVALID_HANDLE_VALUE) {
switch (kernel32.GetLastError()) {
.FILE_NOT_FOUND => return error.FileNotFound,
.PATH_NOT_FOUND => return error.FileNotFound,
else => |err| return unexpectedError(err),
}
}
return handle;
}
pub const FindNextFileError = error{Unexpected};
/// Returns `true` if there was another file, `false` otherwise.
pub fn FindNextFile(handle: HANDLE, find_file_data: *WIN32_FIND_DATAW) FindNextFileError!bool {
if (kernel32.FindNextFileW(handle, find_file_data) == 0) {
switch (kernel32.GetLastError()) {
.NO_MORE_FILES => return false,
else => |err| return unexpectedError(err),
}
}
return true;
}
pub const CreateIoCompletionPortError = error{Unexpected};
pub fn CreateIoCompletionPort(
@ -644,7 +608,7 @@ pub fn CreateSymbolicLink(
) CreateSymbolicLinkError!void {
const sym_link_path_w = try sliceToPrefixedFileW(sym_link_path);
const target_path_w = try sliceToPrefixedFileW(target_path);
return CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, flags);
return CreateSymbolicLinkW(sym_link_path_w.span().ptr, target_path_w.span().ptr, flags);
}
pub fn CreateSymbolicLinkW(
@ -669,7 +633,7 @@ pub const DeleteFileError = error{
pub fn DeleteFile(filename: []const u8) DeleteFileError!void {
const filename_w = try sliceToPrefixedFileW(filename);
return DeleteFileW(&filename_w);
return DeleteFileW(filename_w.span().ptr);
}
pub fn DeleteFileW(filename: [*:0]const u16) DeleteFileError!void {
@ -691,7 +655,7 @@ pub const MoveFileError = error{Unexpected};
pub fn MoveFileEx(old_path: []const u8, new_path: []const u8, flags: DWORD) MoveFileError!void {
const old_path_w = try sliceToPrefixedFileW(old_path);
const new_path_w = try sliceToPrefixedFileW(new_path);
return MoveFileExW(&old_path_w, &new_path_w, flags);
return MoveFileExW(old_path_w.span().ptr, new_path_w.span().ptr, flags);
}
pub fn MoveFileExW(old_path: [*:0]const u16, new_path: [*:0]const u16, flags: DWORD) MoveFileError!void {
@ -716,7 +680,7 @@ pub const CreateDirectoryError = error{
/// Returns an open directory handle which the caller is responsible for closing with `CloseHandle`.
pub fn CreateDirectory(dir: ?HANDLE, pathname: []const u8, sa: ?*SECURITY_ATTRIBUTES) CreateDirectoryError!HANDLE {
const pathname_w = try sliceToPrefixedFileW(pathname);
return CreateDirectoryW(dir, &pathname_w, sa);
return CreateDirectoryW(dir, pathname_w.span().ptr, sa);
}
/// Same as `CreateDirectory` except takes a WTF-16 encoded path.
@ -784,7 +748,7 @@ pub const RemoveDirectoryError = error{
pub fn RemoveDirectory(dir_path: []const u8) RemoveDirectoryError!void {
const dir_path_w = try sliceToPrefixedFileW(dir_path);
return RemoveDirectoryW(&dir_path_w);
return RemoveDirectoryW(dir_path_w.span().ptr);
}
pub fn RemoveDirectoryW(dir_path_w: [*:0]const u16) RemoveDirectoryError!void {
@ -913,7 +877,7 @@ pub const GetFileAttributesError = error{
pub fn GetFileAttributes(filename: []const u8) GetFileAttributesError!DWORD {
const filename_w = try sliceToPrefixedFileW(filename);
return GetFileAttributesW(&filename_w);
return GetFileAttributesW(filename_w.span().ptr);
}
pub fn GetFileAttributesW(lpFileName: [*:0]const u16) GetFileAttributesError!DWORD {
@ -1253,34 +1217,22 @@ pub fn nanoSecondsToFileTime(ns: i64) FILETIME {
};
}
pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
pub const PathSpace = struct {
data: [PATH_MAX_WIDE:0]u16,
len: usize,
pub fn span(self: PathSpace) [:0]const u16 {
return self.data[0..self.len :0];
}
};
pub fn cStrToPrefixedFileW(s: [*:0]const u8) !PathSpace {
return sliceToPrefixedFileW(mem.spanZ(s));
}
pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE:0]u16 {
return sliceToPrefixedSuffixedFileW(s, &[_]u16{});
}
/// Assumes an absolute path.
pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE:0]u16 {
pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace {
// TODO https://github.com/ziglang/zig/issues/2765
var result: [PATH_MAX_WIDE:0]u16 = undefined;
const start_index = if (mem.startsWith(u16, s, &[_]u16{ '\\', '?' })) 0 else blk: {
const prefix = [_]u16{ '\\', '?', '?', '\\' };
mem.copy(u16, result[0..], &prefix);
break :blk prefix.len;
};
const end_index = start_index + s.len;
if (end_index + 1 > result.len) return error.NameTooLong;
mem.copy(u16, result[start_index..], s);
result[end_index] = 0;
return result;
}
pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len:0]u16 {
// TODO https://github.com/ziglang/zig/issues/2765
var result: [PATH_MAX_WIDE + suffix.len:0]u16 = undefined;
var path_space: PathSpace = undefined;
for (s) |byte| {
switch (byte) {
'*', '?', '"', '<', '>', '|' => return error.BadPathName,
@ -1289,25 +1241,46 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
}
const start_index = if (mem.startsWith(u8, s, "\\?") or !std.fs.path.isAbsolute(s)) 0 else blk: {
const prefix = [_]u16{ '\\', '?', '?', '\\' };
mem.copy(u16, result[0..], &prefix);
mem.copy(u16, path_space.data[0..], &prefix);
break :blk prefix.len;
};
const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);
if (end_index + suffix.len > result.len) return error.NameTooLong;
path_space.len = start_index + try std.unicode.utf8ToUtf16Le(path_space.data[start_index..], s);
if (path_space.len > path_space.data.len) return error.NameTooLong;
// > File I/O functions in the Windows API convert "/" to "\" as part of
// > converting the name to an NT-style name, except when using the "\\?\"
// > prefix as detailed in the following sections.
// from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
// Because we want the larger maximum path length for absolute paths, we
// convert forward slashes to backward slashes here.
for (result[0..end_index]) |*elem| {
for (path_space.data[0..path_space.len]) |*elem| {
if (elem.* == '/') {
elem.* = '\\';
}
}
mem.copy(u16, result[end_index..], suffix);
result[end_index + suffix.len] = 0;
return result;
path_space.data[path_space.len] = 0;
return path_space;
}
/// Assumes an absolute path.
pub fn wToPrefixedFileW(s: []const u16) !PathSpace {
// TODO https://github.com/ziglang/zig/issues/2765
var path_space: PathSpace = undefined;
const start_index = if (mem.startsWith(u16, s, &[_]u16{ '\\', '?' })) 0 else blk: {
const prefix = [_]u16{ '\\', '?', '?', '\\' };
mem.copy(u16, path_space.data[0..], &prefix);
break :blk prefix.len;
};
path_space.len = start_index + s.len;
if (path_space.len > path_space.data.len) return error.NameTooLong;
mem.copy(u16, path_space.data[start_index..], s);
for (path_space.data[0..path_space.len]) |*elem| {
if (elem.* == '/') {
elem.* = '\\';
}
}
path_space.data[path_space.len] = 0;
return path_space;
}
inline fn MAKELANGID(p: c_ushort, s: c_ushort) LANGID {