From fc6f84f3f08aca0d4e2352091cc2db2ca5779c7d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 21 Oct 2019 20:58:53 -0400 Subject: [PATCH] fix os.unlinkatW implementation --- lib/std/os.zig | 22 ++++++++++++++++++---- lib/std/os/windows/status.zig | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 2d8ddb0abc..7a5eeda82c 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1045,11 +1045,24 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatErro w.ULONG(w.FILE_DELETE_ON_CLOSE) else w.ULONG(w.FILE_DELETE_ON_CLOSE | w.FILE_NON_DIRECTORY_FILE); - var nt_name: w.UNICODE_STRING = undefined; - if (w.ntdll.RtlDosPathNameToNtPathName_U(sub_path_w, &nt_name, null, null) == 0) { - return error.FileNotFound; + + const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2); + var nt_name = w.UNICODE_STRING{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + // The Windows API makes this mutable, but it will not mutate here. + .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)), + }; + + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + // Windows does not recognize this, but it does work with empty string. + nt_name.Length = 0; } - defer w.ntdll.RtlFreeUnicodeString(&nt_name); + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { + // Can't remove the parent directory with an open handle. + return error.FileBusy; + } + var attr = w.OBJECT_ATTRIBUTES{ .Length = @sizeOf(w.OBJECT_ATTRIBUTES), @@ -1082,6 +1095,7 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatErro w.STATUS.OBJECT_NAME_INVALID => unreachable, w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound, w.STATUS.INVALID_PARAMETER => unreachable, + w.STATUS.FILE_IS_A_DIRECTORY => return error.IsDir, else => return w.unexpectedStatus(rc), } } diff --git a/lib/std/os/windows/status.zig b/lib/std/os/windows/status.zig index 424cae5e29..5f38948620 100644 --- a/lib/std/os/windows/status.zig +++ b/lib/std/os/windows/status.zig @@ -10,3 +10,4 @@ pub const OBJECT_NAME_INVALID = 0xC0000033; pub const OBJECT_NAME_NOT_FOUND = 0xC0000034; pub const OBJECT_PATH_NOT_FOUND = 0xC000003A; pub const OBJECT_PATH_SYNTAX_BAD = 0xC000003B; +pub const FILE_IS_A_DIRECTORY = 0xC00000BA;