Commit 9d5f15fe3d

Andrew Kelley <superjoe30@gmail.com>
2017-10-09 03:40:33
implement os.getCwd for windows
1 parent 7cfab2f
Changed files (3)
std/os/windows/index.zig
@@ -13,6 +13,8 @@ pub extern "kernel32" stdcallcc fn GetCommandLine() -> LPTSTR;
 
 pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool;
 
+pub extern "kernel32" stdcallcc fn GetCurrentDirectoryA(nBufferLength: WORD, lpBuffer: ?LPTSTR) -> DWORD;
+
 /// Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis.
 /// Multiple threads do not overwrite each other's last-error code.
 pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD;
@@ -50,7 +52,7 @@ pub extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lp
 pub const PROV_RSA_FULL = 1;
 
 pub const UNICODE = false;
-pub const LPTSTR = if (unicode) LPWSTR else LPSTR;
+pub const LPTSTR = if (UNICODE) LPWSTR else LPSTR;
 pub const LPWSTR = &WCHAR;
 pub const LPSTR = &CHAR;
 pub const CHAR = u8;
@@ -59,6 +61,7 @@ pub const SIZE_T = usize;
 
 pub const BOOL = bool;
 pub const BYTE = u8;
+pub const WORD = u16;
 pub const DWORD = u32;
 pub const FLOAT = f32;
 pub const HANDLE = &c_void;
std/os/index.zig
@@ -476,10 +476,23 @@ pub const args = struct {
 pub fn getCwd(allocator: &Allocator) -> %[]u8 {
     switch (builtin.os) {
         Os.windows => {
-            @panic("implement getCwd for windows");
-            //if (windows.GetCurrentDirectoryA(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) {
-            //    zig_panic("GetCurrentDirectory failed");
-            //}
+            var buf = %return allocator.alloc(u8, 256);
+            %defer allocator.free(buf);
+
+            while (true) {
+                const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr);
+
+                if (result == 0) {
+                    return error.Unexpected;
+                }
+
+                if (result > buf.len) {
+                    buf = %return allocator.realloc(u8, buf, result);
+                    continue;
+                }
+
+                return buf[0..result];
+            }
         },
         else => {
             var buf = %return allocator.alloc(u8, 1024);
std/os/path.zig
@@ -176,25 +176,13 @@ test "os.path.networkShare" {
     assert(networkShare("\\\\a\\") == null);
 }
 
-pub fn root(path: []const u8) -> []const u8 {
-    if (is_windows) {
-        return rootWindows(path);
-    } else {
-        return rootPosix(path);
-    }
-}
+pub fn diskDesignator(path: []const u8) -> []const u8 {
+    if (!is_windows)
+        return "";
 
-pub fn rootWindows(path: []const u8) -> []const u8 {
     return drive(path) ?? (networkShare(path) ?? []u8{});
 }
 
-pub fn rootPosix(path: []const u8) -> []const u8 {
-    if (path.len == 0 or path[0] != '/')
-        return []u8{};
-
-    return path[0..1];
-}
-
 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
 fn networkShareServersEql(ns1: []const u8, ns2: []const u8) -> bool {
     const sep1 = ns1[0];
@@ -346,7 +334,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
         mem.copy(u8, result, cwd);
         result_index += cwd.len;
 
-        root_slice = rootWindows(result[0..result_index]);
+        root_slice = diskDesignator(result[0..result_index]);
     }
     %defer allocator.free(result);
 
@@ -362,7 +350,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8
                 continue;
             }
         }
-        var it = mem.split(p[rootWindows(p).len..], "/\\");
+        var it = mem.split(p[diskDesignator(p).len..], "/\\");
         while (it.next()) |component| {
             if (mem.eql(u8, component, ".")) {
                 continue;
@@ -517,7 +505,7 @@ pub fn dirnameWindows(path: []const u8) -> []const u8 {
     if (path.len == 0)
         return path[0..0];
 
-    const root_slice = rootWindows(path);
+    const root_slice = diskDesignator(path);
     if (path.len == root_slice.len)
         return path;