From 6a752512b2bb0a81eda16f37f64d4c58ce64d934 Mon Sep 17 00:00:00 2001 From: Stanislav Ershov Date: Fri, 19 Feb 2021 14:20:06 +0500 Subject: [PATCH] os: fix os.real_path on Windows (#8822) --- vlib/builtin/cfns.c.v | 2 ++ vlib/os/os_c.v | 19 ++++++++++++++----- vlib/os/os_test.v | 4 ++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/vlib/builtin/cfns.c.v b/vlib/builtin/cfns.c.v index 2603d7edf3..0907d79f99 100644 --- a/vlib/builtin/cfns.c.v +++ b/vlib/builtin/cfns.c.v @@ -275,6 +275,8 @@ fn C._wgetcwd() int fn C._fullpath() int +fn C.GetFullPathName(voidptr, u32, voidptr, voidptr) u32 + fn C.GetCommandLine() voidptr fn C.LocalFree() diff --git a/vlib/os/os_c.v b/vlib/os/os_c.v index eed279db1e..351bec6f00 100644 --- a/vlib/os/os_c.v +++ b/vlib/os/os_c.v @@ -744,23 +744,32 @@ pub fn getwd() string { // NB: this particular rabbit hole is *deep* ... [manualfree] pub fn real_path(fpath string) string { - mut fullpath := vcalloc(max_path_len) + mut fullpath := byteptr(0) defer { unsafe { free(fullpath) } } - mut ret := charptr(0) + $if windows { - ret = charptr(C._fullpath(charptr(fullpath), charptr(fpath.str), max_path_len)) + fullpath = unsafe { &u16(vcalloc(max_path_len * 2)) } + // TODO: check errors if path len is not enough + ret := C.GetFullPathName(fpath.to_wide(), max_path_len, fullpath, 0) if ret == 0 { return fpath } } $else { - ret = charptr(C.realpath(charptr(fpath.str), charptr(fullpath))) + fullpath = vcalloc(max_path_len) + ret := charptr(C.realpath(charptr(fpath.str), charptr(fullpath))) if ret == 0 { return fpath } } - res := unsafe { fullpath.vstring() } + + mut res := '' + $if windows { + res = unsafe { string_from_wide(fullpath) } + } $else { + res = unsafe { fullpath.vstring() } + } nres := normalize_drive_letter(res) cres := nres.clone() return cres diff --git a/vlib/os/os_test.v b/vlib/os/os_test.v index b301c37bf7..fefac383db 100644 --- a/vlib/os/os_test.v +++ b/vlib/os/os_test.v @@ -271,6 +271,10 @@ fn test_cp_all() { os.cp_all('ex', './', true) or { panic(err) } } +fn test_realpath() { + assert os.real_path('') == '' +} + fn test_tmpdir() { t := os.temp_dir() assert t.len > 0