diff --git a/configure.ac b/configure.ac index 185ada350e1..4204b86fa15 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl dnl autoconf for Pacemaker dnl -dnl Copyright 2009-2025 the Pacemaker project contributors +dnl Copyright 2009-2026 the Pacemaker project contributors dnl dnl The version control history for this file may have further details. dnl @@ -1234,6 +1234,42 @@ AS_IF([test x"$have_sscanf_m" = x"yes"], [AC_DEFINE([HAVE_SSCANF_M], [1], [Define to 1 if sscanf %m modifier is available])]) +AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ + char s[200]; + time_t t; + struct tm *tmp; + size_t rc; + + t = time(NULL); + tmp = localtime(&t); + rc = strftime(s, sizeof(s), "%3S", tmp); + return rc != 3; + ]])], + [have_strftime_width="yes"], + [have_strftime_width="no"], + [have_strftime_width="no"]) +AS_IF([test x"$have_strftime_width" = x"yes"], + [AC_DEFINE([HAVE_STRFTIME_WIDTH], [1], + [Define to 1 if strftime supports field width])]) + +AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ + char s[200]; + time_t t; + struct tm *tmp; + size_t rc; + + t = time(NULL); + tmp = localtime(&t); + rc = strftime(s, sizeof(s), "% abcd", tmp); + return rc != 0; + ]])], + [have_strftime_empty_spec_fails="yes"], + [have_strftime_empty_spec_fails="no"], + [have_strftime_empty_spec_fails="no"]) +AS_IF([test x"$have_strftime_empty_spec_fails" = x"yes"], + [AC_DEFINE([HAVE_STRFTIME_EMPTY_SPEC_FAILS], [1], + [Define to 1 if a percent with no specifier fails])]) + dnl ======================================================================== dnl bzip2 dnl ======================================================================== diff --git a/lib/common/tests/iso8601/pcmk__time_format_hr_test.c b/lib/common/tests/iso8601/pcmk__time_format_hr_test.c index ead23e9c8fc..3e52aea7b8a 100644 --- a/lib/common/tests/iso8601/pcmk__time_format_hr_test.c +++ b/lib/common/tests/iso8601/pcmk__time_format_hr_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2024-2025 the Pacemaker project contributors + * Copyright 2024-2026 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -85,24 +85,43 @@ no_specifiers(void **state) * as "%%". */ assert_hr_format("this has a literal % in it", +#ifdef HAVE_STRFTIME_EMPTY_SPEC_FAILS + NULL, NULL, 0); +#else "this has a literal % in it", // *BSD strftime() strips single % "this has a literal in it", 0); +#endif + assert_hr_format("this has a literal %01 in it", +#ifdef HAVE_STRFTIME_EMPTY_SPEC_FAILS + NULL, NULL, 0); +#else "this has a literal %01 in it", // *BSD strftime() strips %0 "this has a literal 1 in it", 0); +#endif + assert_hr_format("%2 this starts and ends with %", +#ifdef HAVE_STRFTIME_EMPTY_SPEC_FAILS + NULL, NULL, 0); +#else "%2 this starts and ends with %", // *BSD strftime() strips % in front of nonzero number "2 this starts and ends with %", 0); +#endif /* strftime() treats % with a number (and no specifier) as a literal string * to be formatted with a field width (undocumented and probably a bug ...) */ - assert_hr_format("this ends with %10", "this ends with %10", + assert_hr_format("this ends with %10", +#ifdef HAVE_STRFTIME_EMPTY_SPEC_FAILS + NULL, NULL, 0); +#else + "this ends with %10", // *BSD strftime() strips % in front of nonzero number "this ends with 10", 0); +#endif } static void @@ -120,8 +139,20 @@ without_frac(void **state) * g_date_time_format() doesn't support field widths. */ assert_hr_format("%3S seconds", "0" SECOND_S " seconds", - // *BSD strftime() doesn't support field widths +#if defined(HAVE_STRFTIME_WIDTH) + NULL, 0); +#elif defined(__FreeBSD__) + /* FreeBSD doesn't support field width in strftime(). It + * strips the leading % and copies the rest of the specifier + * into the string. + */ "3S seconds", 0); +#else + /* musl (and maybe other c libraries) ignores the field width + * and handle the rest of the specifier normally. + */ + SECOND_S " seconds", 0); +#endif // strftime() treats %% as a literal % assert_hr_format("%%H %%N", "%H %N", NULL, 0);