From 587101a1ea92be6a0105e964609e37fe7b1a3620 Mon Sep 17 00:00:00 2001 From: Wertzui123 <46199283+Wertzui123@users.noreply.github.com> Date: Thu, 23 Jun 2022 02:36:15 +0200 Subject: [PATCH] os: fix `find_abs_path_of_executable` function (on Windows) (#14835) --- vlib/os/find_abs_path_of_executable_test.v | 46 ++++++++++++++++++++++ vlib/os/os.c.v | 2 +- vlib/os/os.js.v | 2 + vlib/os/os.v | 37 ++++++++++------- vlib/os/os_nix.c.v | 2 + vlib/os/os_windows.c.v | 2 + 6 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 vlib/os/find_abs_path_of_executable_test.v diff --git a/vlib/os/find_abs_path_of_executable_test.v b/vlib/os/find_abs_path_of_executable_test.v new file mode 100644 index 0000000000..59a75e1571 --- /dev/null +++ b/vlib/os/find_abs_path_of_executable_test.v @@ -0,0 +1,46 @@ +module os + +fn test_find_abs_path_of_executable() ? { + tfolder := join_path(temp_dir(), 'v', 'tests', 'filepath_test') + rmdir_all(tfolder) or {} + assert !is_dir(tfolder) + mkdir_all(tfolder)? + defer { + rmdir_all(tfolder) or {} + } + // + original_path := getenv('PATH') + original_wdir := getwd() + defer { + chdir(original_wdir) or {} + } + // + new_path := tfolder + path_delimiter + original_path + setenv('PATH', new_path, true) + // + mut myclang_file := 'myclang' + $if windows { + myclang_file += '.bat' + } + // + chdir(tfolder)? + write_file(myclang_file, 'echo hello')? + chmod(myclang_file, 0o0777)? + dump(real_path(myclang_file)) + dump(is_executable(myclang_file)) + defer { + rm(myclang_file) or {} + } + // + fpath := find_abs_path_of_executable('myclang') or { + assert false + return + } + dump(fpath) + // + setenv('PATH', original_path, true) + if x := find_abs_path_of_executable('myclang') { + eprintln('> find_abs_path_of_executable should have failed, but instead it found: $x') + assert false + } +} diff --git a/vlib/os/os.c.v b/vlib/os/os.c.v index 87de130b07..8c1986288c 100644 --- a/vlib/os/os.c.v +++ b/vlib/os/os.c.v @@ -404,7 +404,7 @@ pub fn is_executable(path string) bool { // 04 Read-only // 06 Read and write p := real_path(path) - return exists(p) && p.ends_with('.exe') + return exists(p) && (p.ends_with('.exe') || p.ends_with('.bat')) } $if solaris { statbuf := C.stat{} diff --git a/vlib/os/os.js.v b/vlib/os/os.js.v index 66552b9ab8..95c2394a1e 100644 --- a/vlib/os/os.js.v +++ b/vlib/os/os.js.v @@ -12,6 +12,8 @@ pub const ( args = []string{} ) +const executable_suffixes = [''] + fn get_path_delimiter() string { delimiter := ':' $if js_node { diff --git a/vlib/os/os.v b/vlib/os/os.v index da38aa89be..24a884cf29 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -452,27 +452,34 @@ fn error_failed_to_find_executable() IError { return IError(&ExecutableNotFoundError{}) } -// find_exe_path walks the environment PATH, just like most shell do, it returns +// find_abs_path_of_executable walks the environment PATH, just like most shell do, it returns // the absolute path of the executable if found pub fn find_abs_path_of_executable(exepath string) ?string { if exepath == '' { return error('expected non empty `exepath`') } - if is_abs_path(exepath) { - return real_path(exepath) - } - mut res := '' - path := getenv('PATH') - paths := path.split(path_delimiter) - for p in paths { - found_abs_path := join_path_single(p, exepath) - if exists(found_abs_path) && is_executable(found_abs_path) { - res = found_abs_path - break + + for suffix in executable_suffixes { + fexepath := exepath + suffix + if is_abs_path(fexepath) { + return real_path(fexepath) + } + mut res := '' + path := getenv('PATH') + paths := path.split(path_delimiter) + for p in paths { + found_abs_path := join_path_single(p, fexepath) + $if trace_find_abs_path_of_executable ? { + dump(found_abs_path) + } + if exists(found_abs_path) && is_executable(found_abs_path) { + res = found_abs_path + break + } + } + if res.len > 0 { + return real_path(res) } - } - if res.len > 0 { - return real_path(res) } return error_failed_to_find_executable() } diff --git a/vlib/os/os_nix.c.v b/vlib/os/os_nix.c.v index 8e371f4648..81544f31f6 100644 --- a/vlib/os/os_nix.c.v +++ b/vlib/os/os_nix.c.v @@ -17,6 +17,8 @@ pub const ( path_delimiter = ':' ) +const executable_suffixes = [''] + const ( stdin_value = 0 stdout_value = 1 diff --git a/vlib/os/os_windows.c.v b/vlib/os/os_windows.c.v index d4dadbb546..9a9d1811e0 100644 --- a/vlib/os/os_windows.c.v +++ b/vlib/os/os_windows.c.v @@ -14,6 +14,8 @@ fn C.CreateHardLinkW(&u16, &u16, C.SECURITY_ATTRIBUTES) int fn C._getpid() int +const executable_suffixes = ['.exe', '.bat', ''] + pub const ( path_separator = '\\' path_delimiter = ';'