aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorLee Cannon <leecannon@leecannon.xyz>2020-11-06 23:57:54 +0000
committerJakub Konka <kubkon@jakubkonka.com>2020-11-18 15:37:44 +0100
commit80b1e82b1b8706b7654560013751dd4a6fc8ae2a (patch)
tree0522d7b8579c846441685b105e88f2dd9f1443ef /lib
parenta6470088c6629e91edad8390f3f2930f1d7c92b1 (diff)
downloadzig-80b1e82b1b8706b7654560013751dd4a6fc8ae2a.tar.gz
zig-80b1e82b1b8706b7654560013751dd4a6fc8ae2a.zip
Implement chdir and chdirZ for Windows
Diffstat (limited to 'lib')
-rw-r--r--lib/std/os.zig11
-rw-r--r--lib/std/os/windows.zig27
-rw-r--r--lib/std/os/windows/kernel32.zig1
3 files changed, 35 insertions, 4 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 91b88304f7..edb53ec6a3 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -2305,8 +2305,12 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
if (builtin.os.tag == .wasi) {
@compileError("chdir is not supported in WASI");
} else if (builtin.os.tag == .windows) {
- const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
- @compileError("TODO implement chdir for Windows");
+ windows.SetCurrentDirectory(dir_path) catch |err| switch (err) {
+ error.PathNotFound, error.InvalidName, error.InvalidUtf8 => return error.FileNotFound,
+ error.NameTooLong => return error.NameTooLong,
+ error.NotDir => return error.NotDir,
+ error.Unexpected => return error.Unexpected,
+ };
} else {
const dir_path_c = try toPosixPath(dir_path);
return chdirZ(&dir_path_c);
@@ -2318,8 +2322,7 @@ pub const chdirC = @compileError("deprecated: renamed to chdirZ");
/// Same as `chdir` except the parameter is null-terminated.
pub fn chdirZ(dir_path: [*:0]const u8) ChangeCurDirError!void {
if (builtin.os.tag == .windows) {
- const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
- @compileError("TODO implement chdir for Windows");
+ return chdir(mem.spanZ(dir_path));
}
switch (errno(system.chdir(dir_path))) {
0 => return,
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index e7038d0a2a..6bdc858fc2 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -555,6 +555,33 @@ pub fn WriteFile(
}
}
+pub const SetCurrentDirectoryError = error{
+ PathNotFound,
+ InvalidName,
+ InvalidUtf8,
+ NameTooLong,
+ NotDir,
+ Unexpected,
+};
+
+pub fn SetCurrentDirectory(path_name: []const u8) SetCurrentDirectoryError!void {
+ // PATH_MAX_WIDE - 1 as we need to ensure there is space for the null terminator
+ if (path_name.len >= PATH_MAX_WIDE - 1) return error.NameTooLong;
+
+ var utf16le_buf: [PATH_MAX_WIDE]u16 = undefined;
+ const end = try std.unicode.utf8ToUtf16Le(utf16le_buf[0..], path_name);
+ utf16le_buf[end] = 0;
+
+ if (kernel32.SetCurrentDirectoryW(@ptrCast([*:0]const u16, &utf16le_buf)) == 0) {
+ switch (kernel32.GetLastError()) {
+ .PATH_NOT_FOUND, .FILE_NOT_FOUND => return error.PathNotFound,
+ .DIRECTORY => return error.NotDir,
+ .INVALID_NAME => return error.InvalidName,
+ else => |err| return unexpectedError(err),
+ }
+ }
+}
+
pub const GetCurrentDirectoryError = error{
NameTooLong,
Unexpected,
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 5d0b5bb227..9a79f0e728 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -93,6 +93,7 @@ pub extern "kernel32" fn FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCh
pub extern "kernel32" fn FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: DWORD, dwWriteCoord: COORD, lpNumberOfAttrsWritten: LPDWORD) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) callconv(.Stdcall) BOOL;
+pub extern "kernel32" fn SetCurrentDirectoryW(lpPathName: [*:0]const u16) callconv(.Stdcall) BOOL;
pub extern "kernel32" fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: ?[*]WCHAR) callconv(.Stdcall) DWORD;
pub extern "kernel32" fn GetCurrentThread() callconv(.Stdcall) HANDLE;