From 0e4fa9ff0d82735042fbfa4bfff77a5fdf3c4950 Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Sun, 14 Jun 2026 15:01:00 -0500 Subject: [PATCH] test: promote the win32-repairing systemf wrapper to all systemf calls --- tar/test/test_option_mtime.c | 17 ----------------- test_utils/test_main.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/tar/test/test_option_mtime.c b/tar/test/test_option_mtime.c index 75cdb8390..8e337a46d 100644 --- a/tar/test/test_option_mtime.c +++ b/tar/test/test_option_mtime.c @@ -6,23 +6,6 @@ */ #include "test.h" -#if defined(_WIN32) && !defined(__CYGWIN__) -/* system() on Windows runs its arguments through CMD.EXE, which has - * notoriously unfriendly quoting rules. The current best documented way around - * them is to wrap your *entire commandline* in sacrificial quotes. - * - * See CMD.EXE /? for more information. Excerpted here: - * | Otherwise, old behavior is to see if the first character is - * | a quote character and if so, strip the leading character and - * | remove the last quote character on the command line, preserving - * | any text after the last quote character. - * - * Since this test makes heavy use of systemf() with quoted arguments inside - * the commandline, this macro is unfortunately an easier workaround. - */ -#define systemf(command, ...) systemf("\"" command "\"", __VA_ARGS__) -#endif - DEFINE_TEST(test_option_mtime) { /* Create three files with different mtimes. */ diff --git a/test_utils/test_main.c b/test_utils/test_main.c index d2fcb09f9..f5de428f2 100644 --- a/test_utils/test_main.c +++ b/test_utils/test_main.c @@ -3056,11 +3056,41 @@ systemf(const char *fmt, ...) pid_t pid; #endif va_list ap; + size_t off = 0, avail = sizeof(buff); int r; +#if defined(_WIN32) && !defined(__CYGWIN__) + /* system() on Windows runs its arguments through CMD.EXE, which has + * notoriously unfriendly quoting rules. The current best documented way around + * them is to wrap your *entire commandline* in sacrificial quotes. + * + * See CMD.EXE /? for more information. Excerpted here: + * | Otherwise, old behavior is to see if the first character is + * | a quote character and if so, strip the leading character and + * | remove the last quote character on the command line, preserving + * | any text after the last quote character. + * + * Since these tests often make use of systemf() with quoted arguments inside + * the commandline, wrap every formatted commandline in quotes. + */ + avail -= 2; + off++; + buff[0] = '"'; +#endif + va_start(ap, fmt); - vsnprintf(buff, sizeof(buff), fmt, ap); + r = vsnprintf(buff + off, avail, fmt, ap); va_end(ap); + + if (r < 0 || (size_t)r > avail) { + return (-1); + } + +#if defined(_WIN32) && !defined(__CYGWIN__) + buff[off + r] = '"'; + buff[off + r + 1] = '\0'; +#endif + if (verbosity > VERBOSITY_FULL) logprintf("Cmd: %s\n", buff); #if USE_POSIX_SPAWN -- 2.47.3