Skip to content

Commit

Permalink
win/spawn: run executables with no file extension
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleFromKitware committed Dec 4, 2023
1 parent 5e30273 commit 6c88530
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CI-win.yml
Expand Up @@ -91,7 +91,7 @@ jobs:
cmake --install build --prefix "`pwd`/build/usr"
mkdir -p build/usr/test build/usr/bin
cp -av test/fixtures build/usr/test
cp -av build/uv_run_tests_a.exe build/uv_run_tests.exe \
cp -av build/uv_run_tests_a.exe build/uv_run_tests.exe build/uv_run_tests_a_no_ext build/uv_run_tests_no_ext \
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libgcc_s_${{ matrix.config.libgcc }}-1.dll` \
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libwinpthread-1.dll` \
`${{ matrix.config.arch }}-w64-mingw32-gcc -print-file-name=libatomic-1.dll` \
Expand Down
12 changes: 12 additions & 0 deletions CMakeLists.txt
Expand Up @@ -703,6 +703,12 @@ if(LIBUV_BUILD_TESTS)
set_tests_properties(uv_test PROPERTIES ENVIRONMENT
"LIBPATH=${CMAKE_BINARY_DIR}:$ENV{LIBPATH}")
endif()
if(WIN32)
add_custom_command(TARGET uv_run_tests POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:uv_run_tests>"
"$<TARGET_FILE_DIR:uv_run_tests>/uv_run_tests_no_ext")
endif()
add_executable(uv_run_tests_a ${uv_test_sources} uv_win_longpath.manifest)
target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines})
target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags})
Expand All @@ -719,6 +725,12 @@ if(LIBUV_BUILD_TESTS)
set_target_properties(uv_run_tests PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(uv_run_tests_a PROPERTIES LINKER_LANGUAGE CXX)
endif()
if(WIN32)
add_custom_command(TARGET uv_run_tests_a POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:uv_run_tests_a>"
"$<TARGET_FILE_DIR:uv_run_tests_a>/uv_run_tests_a_no_ext")
endif()
endif()

# Now for some gibbering horrors from beyond the stars...
Expand Down
6 changes: 6 additions & 0 deletions Makefile.am
Expand Up @@ -136,6 +136,12 @@ TESTS = test/run-tests
check_PROGRAMS = test/run-tests
test_run_tests_CFLAGS = $(AM_CFLAGS)

if WINNT
check-am: test/run-tests_no_ext
test/run-tests_no_ext: test/run-tests$(EXEEXT)
cp test/run-tests$(EXEEXT) test/run-tests_no_ext
endif

if SUNOS
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
# on other platforms complain that the argument is unused during compilation.
Expand Down
8 changes: 6 additions & 2 deletions src/win/process.c
Expand Up @@ -304,6 +304,8 @@ static WCHAR* path_search_walk_ext(const WCHAR *dir,
* - If there's really only a filename, check the current directory for file,
* then search all path directories.
*
* - If a full path is specified, search for the exact filename first.
*
* - If filename specified has *any* extension, search for the file with the
* specified extension first.
*
Expand Down Expand Up @@ -367,12 +369,14 @@ static WCHAR* search_path(const WCHAR *file,
name_has_ext = (dot != NULL && dot[1] != L'\0');

if (file_has_dir) {
/* The file has a path inside, don't use path */
/* The file has a path inside, don't use path
* Try the exact filename first, and then try standard extensions
*/
result = path_search_walk_ext(
file, file_name_start - file,
file_name_start, file_len - (file_name_start - file),
cwd, cwd_len,
name_has_ext);
1);

} else {
dir_end = path;
Expand Down
4 changes: 4 additions & 0 deletions test/test-list.h
Expand Up @@ -506,6 +506,8 @@ TEST_DECLARE (listen_no_simultaneous_accepts)
TEST_DECLARE (fs_stat_root)
TEST_DECLARE (spawn_with_an_odd_path)
TEST_DECLARE (spawn_no_path)
TEST_DECLARE (spawn_no_ext)
TEST_DECLARE (spawn_path_no_ext)
TEST_DECLARE (ipc_listen_after_bind_twice)
TEST_DECLARE (win32_signum_number)
#else
Expand Down Expand Up @@ -1025,6 +1027,8 @@ TASK_LIST_START
TEST_ENTRY (fs_stat_root)
TEST_ENTRY (spawn_with_an_odd_path)
TEST_ENTRY (spawn_no_path)
TEST_ENTRY (spawn_no_ext)
TEST_ENTRY (spawn_path_no_ext)
TEST_ENTRY (ipc_listen_after_bind_twice)
TEST_ENTRY (win32_signum_number)
#else
Expand Down
58 changes: 58 additions & 0 deletions test/test-spawn.c
Expand Up @@ -1394,6 +1394,64 @@ TEST_IMPL(spawn_no_path) {
MAKE_VALGRIND_HAPPY(uv_default_loop());
return 0;
}


TEST_IMPL(spawn_no_ext) {
char new_exepath[1024];

init_process_options("spawn_helper1", exit_cb);
memcpy(new_exepath, exepath, exepath_size - (sizeof(".exe") - sizeof(char)));
strcpy(new_exepath + exepath_size - (sizeof(".exe") / sizeof(char) - 1), "_no_ext");
options.file = options.args[0] = new_exepath;

ASSERT_OK(uv_spawn(uv_default_loop(), &process, &options));
ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));

ASSERT_EQ(1, exit_cb_called);
ASSERT_EQ(1, close_cb_called);

MAKE_VALGRIND_HAPPY(uv_default_loop());
return 0;
}


TEST_IMPL(spawn_path_no_ext) {
int r;
int len;
int file_len;
char file[64];
char path[1024];
char* env[2];

/* Set up the process, but make sure that the file to run is relative and
* requires a lookup into PATH. */
init_process_options("spawn_helper1", exit_cb);

/* Set up the PATH env variable */
for (len = strlen(exepath), file_len = 0;
exepath[len - 1] != '/' && exepath[len - 1] != '\\';
len--, file_len++);
memcpy(file, exepath + len, file_len - (sizeof(".exe") - sizeof(char)));
strcpy(file + file_len - (sizeof(".exe") / sizeof(char) - 1), "_no_ext");
exepath[len] = 0;
strcpy(path, "PATH=");
strcpy(path + 5, exepath);

env[0] = path;
env[1] = NULL;

options.file = options.args[0] = file;
options.env = env;

r = uv_spawn(uv_default_loop(), &process, &options);
ASSERT(r == UV_ENOENT || r == UV_EACCES);
ASSERT_OK(uv_is_active((uv_handle_t*) &process));
uv_close((uv_handle_t*) &process, NULL);
ASSERT_OK(uv_run(uv_default_loop(), UV_RUN_DEFAULT));

MAKE_VALGRIND_HAPPY(uv_default_loop());
return 0;
}
#endif

#ifndef _WIN32
Expand Down

0 comments on commit 6c88530

Please sign in to comment.