From 2f32485af0d33a5f658b8dd12e56da28329238b5 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 22:37:49 -0700 Subject: [PATCH 01/26] Refactor: libcrmcommon: Make pcmk__time_get_ywd() library-private Signed-off-by: Reid Wahl --- include/crm/common/iso8601_internal.h | 2 -- lib/common/crmcommon_private.h | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/crm/common/iso8601_internal.h b/include/crm/common/iso8601_internal.h index d4e435d824e..17a2b662aaf 100644 --- a/include/crm/common/iso8601_internal.h +++ b/include/crm/common/iso8601_internal.h @@ -131,8 +131,6 @@ enum pcmk__time_fmt_flags { bool pcmk__time_valid_year(int year); bool pcmk__time_is_initialized(const crm_time_t *dt); long long pcmk__time_get_seconds(const crm_time_t *dt); -void pcmk__time_get_ywd(const crm_time_t *dt, uint32_t *y, uint32_t *w, - uint32_t *d); char *pcmk__time_text(const crm_time_t *dt, int flags); char *pcmk__time_format_hr(const char *format, const crm_time_t *dt, int usec); char *pcmk__epoch2str(const time_t *source, uint32_t flags); diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h index 327ec11fd6c..f0ce2ade07d 100644 --- a/lib/common/crmcommon_private.h +++ b/lib/common/crmcommon_private.h @@ -216,6 +216,10 @@ G_GNUC_INTERNAL void pcmk__time_get_ymd(const crm_time_t *dt, uint32_t *year, uint32_t *month, uint32_t *day); +G_GNUC_INTERNAL +void pcmk__time_get_ywd(const crm_time_t *dt, uint32_t *y, uint32_t *w, + uint32_t *d); + G_GNUC_INTERNAL const char *pcmk__time_component_attr(enum pcmk__time_component component); From d24f815ac0b1fe7f1a2d42917c6ea525922ea319 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 22:43:34 -0700 Subject: [PATCH 02/26] Refactor: libcrmcommon: New pcmk__time_to_unix() To replace crm_time_get_seconds_since_epoch(). The name "pcmk__time_to_unix()" is chosen in order to align with g_date_time_to_unix(), which we plan to adopt eventually. During development, I used an assertion to validate that the new epoch_seconds calculation matches the old EPOCH_SECONDS constant. Signed-off-by: Reid Wahl --- include/crm/common/iso8601_internal.h | 1 + lib/common/iso8601.c | 41 ++++++++++++++++++++++++--- lib/common/scheduler.c | 2 +- lib/pacemaker/pcmk_sched_location.c | 2 +- lib/pengine/utils.c | 2 +- 5 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/crm/common/iso8601_internal.h b/include/crm/common/iso8601_internal.h index 17a2b662aaf..f1f2fc8d249 100644 --- a/include/crm/common/iso8601_internal.h +++ b/include/crm/common/iso8601_internal.h @@ -131,6 +131,7 @@ enum pcmk__time_fmt_flags { bool pcmk__time_valid_year(int year); bool pcmk__time_is_initialized(const crm_time_t *dt); long long pcmk__time_get_seconds(const crm_time_t *dt); +long long pcmk__time_to_unix(const crm_time_t *dt); char *pcmk__time_text(const crm_time_t *dt, int flags); char *pcmk__time_format_hr(const char *format, const crm_time_t *dt, int usec); char *pcmk__epoch2str(const time_t *source, uint32_t flags); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 1db7c49c950..3e39a7a19dc 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -733,7 +733,14 @@ pcmk__time_get_timeofday(const crm_time_t *dt, uint32_t *hours, seconds_to_hms(dt->seconds, hours, minutes, seconds); } -// Time in seconds since 0000-01-01 00:00:00Z +/* + * \internal + * \brief Convert a time object to seconds since 0000-01-01 00:00:00Z + * + * \param[in] dt Time object + * + * \return Number of seconds between 0001-01-01 00:00:00Z and \p dt + */ long long pcmk__time_get_seconds(const crm_time_t *dt) { @@ -777,11 +784,37 @@ pcmk__time_get_seconds(const crm_time_t *dt) return seconds; } -#define EPOCH_SECONDS 62135596800ULL // Calculated using pcmk__time_get_seconds +/* + * \internal + * \brief Convert a time object to seconds since the Unix epoch + * + * \param[in] dt Time object + * + * \return Number of seconds between 1970-01-01 00:00:00Z and \p dt + */ +long long +pcmk__time_to_unix(const crm_time_t *dt) +{ + static long long epoch_seconds = 0; + + if (dt == NULL) { + return 0; + } + + if (epoch_seconds == 0) { + crm_time_t *epoch_dt = crm_time_new("1970-01-01 00:00:00Z"); + + epoch_seconds = pcmk__time_get_seconds(epoch_dt); + free(epoch_dt); + } + + return pcmk__time_get_seconds(dt) - epoch_seconds; +} + long long crm_time_get_seconds_since_epoch(const crm_time_t *dt) { - return (dt == NULL)? 0 : (pcmk__time_get_seconds(dt) - EPOCH_SECONDS); + return pcmk__time_to_unix(dt); } /*! @@ -1047,7 +1080,7 @@ time_as_string_common(const crm_time_t *dt, int usec, uint32_t flags) if (pcmk__is_set(flags, pcmk__time_fmt_seconds)) { seconds = pcmk__time_get_seconds(dt); } else { - seconds = crm_time_get_seconds_since_epoch(dt); + seconds = pcmk__time_to_unix(dt); } if (pcmk__is_set(flags, pcmk__time_fmt_usecs)) { diff --git a/lib/common/scheduler.c b/lib/common/scheduler.c index e9ecfd78d1b..423a6521070 100644 --- a/lib/common/scheduler.c +++ b/lib/common/scheduler.c @@ -285,7 +285,7 @@ pcmk__scheduler_epoch_time(pcmk_scheduler_t *scheduler) pcmk__trace("Scheduler 'now' set to current time"); scheduler->priv->now = crm_time_new(NULL); } - return crm_time_get_seconds_since_epoch(scheduler->priv->now); + return pcmk__time_to_unix(scheduler->priv->now); } /*! diff --git a/lib/pacemaker/pcmk_sched_location.c b/lib/pacemaker/pcmk_sched_location.c index 44891c98240..35df95103df 100644 --- a/lib/pacemaker/pcmk_sched_location.c +++ b/lib/pacemaker/pcmk_sched_location.c @@ -380,7 +380,7 @@ unpack_rsc_location(xmlNode *xml_obj, pcmk_resource_t *rsc, * change, make sure the scheduler is re-run by that time. */ if (pcmk__time_is_initialized(next_change)) { - time_t t = (time_t) crm_time_get_seconds_since_epoch(next_change); + time_t t = (time_t) pcmk__time_to_unix(next_change); pcmk__update_recheck_time(t, rsc->priv->scheduler, "location rule evaluation"); diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index 99f92cf4a26..88f72b945fb 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -724,7 +724,7 @@ pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, hash, next_change, scheduler->input->doc); if (pcmk__time_is_initialized(next_change)) { - time_t recheck = (time_t) crm_time_get_seconds_since_epoch(next_change); + time_t recheck = (time_t) pcmk__time_to_unix(next_change); pcmk__update_recheck_time(recheck, scheduler, "rule evaluation"); } From 4b3b394ddcc4d3ecb21f788f82b3b40cc9e2901a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 22:45:11 -0700 Subject: [PATCH 03/26] API: libcrmcommon: Deprecate crm_time_get_seconds_since_epoch() External callers have no need to inspect a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 3 --- include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 2d2b4566602..3f494d9ba1e 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,9 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); void crm_time_free(crm_time_t * dt); -/* Time in seconds since 1970-01-01 00:00:00Z */ -long long crm_time_get_seconds_since_epoch(const crm_time_t *dt); - /* Returns a new time object */ crm_time_t *pcmk_copy_time(const crm_time_t *source); crm_time_t *crm_time_add(const crm_time_t *dt, const crm_time_t *value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 3c08c6b3388..78a60718052 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -139,6 +139,9 @@ int crm_time_get_ordinal(const crm_time_t *dt, uint32_t *y, uint32_t *d); //! \deprecated Do not use long long crm_time_get_seconds(const crm_time_t *dt); +//! \deprecated Do not use +long long crm_time_get_seconds_since_epoch(const crm_time_t *dt); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 3e39a7a19dc..5963d7ba480 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -811,12 +811,6 @@ pcmk__time_to_unix(const crm_time_t *dt) return pcmk__time_get_seconds(dt) - epoch_seconds; } -long long -crm_time_get_seconds_since_epoch(const crm_time_t *dt) -{ - return pcmk__time_to_unix(dt); -} - /*! * \internal * \brief Convert a time object's years and seconds to year, month, and day @@ -2571,5 +2565,11 @@ crm_time_get_seconds(const crm_time_t *dt) return pcmk__time_get_seconds(dt); } +long long +crm_time_get_seconds_since_epoch(const crm_time_t *dt) +{ + return pcmk__time_to_unix(dt); +} + // LCOV_EXCL_STOP // End deprecated API From 14bc12b5432890ca0a72208fc6c6ae52988ffd6f Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 22:54:04 -0700 Subject: [PATCH 04/26] Refactor: various: Drop crm_time_free() internally It's equivalent to free(). There are no dynamically allocated fields within crm_time_t. Signed-off-by: Reid Wahl --- daemons/controld/controld_control.c | 2 +- daemons/controld/controld_remote_proxy.c | 2 +- lib/cib/cib_utils.c | 2 +- lib/common/alerts.c | 2 +- lib/common/fuzzers/iso8601_fuzzer.c | 2 +- lib/common/iso8601.c | 34 +++++++------- lib/common/rules.c | 28 ++++++------ lib/common/scheduler.c | 2 +- lib/common/strings.c | 2 +- .../tests/iso8601/crm_time_add_days_test.c | 4 +- .../tests/iso8601/crm_time_add_seconds_test.c | 4 +- .../tests/iso8601/crm_time_add_years_test.c | 4 +- .../iso8601/pcmk__add_time_from_xml_test.c | 44 +++++++++---------- .../iso8601/pcmk__set_time_if_earlier_test.c | 18 ++++---- .../nvpair/pcmk__unpack_nvpair_block_test.c | 2 +- .../nvpair/pcmk__unpack_nvpair_blocks_test.c | 20 ++++----- .../rules/pcmk__evaluate_condition_test.c | 10 ++--- .../pcmk__evaluate_date_expression_test.c | 10 ++--- .../rules/pcmk__evaluate_date_spec_test.c | 6 +-- .../tests/rules/pcmk__unpack_duration_test.c | 16 +++---- .../tests/rules/pcmk_evaluate_rule_test.c | 8 ++-- .../xml_element/pcmk__xe_get_datetime_test.c | 6 +-- lib/common/tls.c | 2 +- lib/common/xml_element.c | 2 +- lib/lrmd/lrmd_alerts.c | 2 +- lib/pacemaker/pcmk_sched_location.c | 2 +- lib/pengine/pe_actions.c | 2 +- lib/pengine/status.c | 2 +- lib/pengine/utils.c | 2 +- tools/crm_resource_ban.c | 14 +++--- tools/crm_rule.c | 2 +- tools/iso8601.c | 18 ++++---- 32 files changed, 137 insertions(+), 139 deletions(-) diff --git a/daemons/controld/controld_control.c b/daemons/controld/controld_control.c index 0f916edf63b..5d876436276 100644 --- a/daemons/controld/controld_control.c +++ b/daemons/controld/controld_control.c @@ -593,7 +593,7 @@ config_query_callback(xmlNode * msg, int call_id, int rc, xmlNode * output, void g_hash_table_destroy(config_hash); bail: - crm_time_free(now); + free(now); } /*! diff --git a/daemons/controld/controld_remote_proxy.c b/daemons/controld/controld_remote_proxy.c index 261e5ac68db..ff3c0c7e36a 100644 --- a/daemons/controld/controld_remote_proxy.c +++ b/daemons/controld/controld_remote_proxy.c @@ -272,7 +272,7 @@ remote_config_check(xmlNode *msg, int call_id, int rc, xmlNode *output, lrmd__validate_remote_settings(lrmd, config_hash); g_hash_table_destroy(config_hash); - crm_time_free(now); + free(now); } /*! diff --git a/lib/cib/cib_utils.c b/lib/cib/cib_utils.c index d1cfe422a11..caa017b87d1 100644 --- a/lib/cib/cib_utils.c +++ b/lib/cib/cib_utils.c @@ -146,7 +146,7 @@ read_config(GHashTable *options, xmlNode *current_cib) pcmk__unpack_nvpair_blocks(config, PCMK_XE_CLUSTER_PROPERTY_SET, PCMK_VALUE_CIB_BOOTSTRAP_OPTIONS, &rule_input, options, NULL, config->doc); - crm_time_free(now); + free(now); } static bool diff --git a/lib/common/alerts.c b/lib/common/alerts.c index e3babc1c3b8..7facab42f65 100644 --- a/lib/common/alerts.c +++ b/lib/common/alerts.c @@ -132,7 +132,7 @@ unpack_alert_options(xmlNode *xml, pcmk__alert_t *entry, pcmk__unpack_nvpair_blocks(xml, PCMK_XE_META_ATTRIBUTES, NULL, &rule_input, config_hash, NULL, xml->doc); - crm_time_free(now); + free(now); value = g_hash_table_lookup(config_hash, PCMK_META_ENABLED); if ((value != NULL) && !pcmk__is_true(value)) { diff --git a/lib/common/fuzzers/iso8601_fuzzer.c b/lib/common/fuzzers/iso8601_fuzzer.c index e7c0ecb5b41..60b93d67eee 100644 --- a/lib/common/fuzzers/iso8601_fuzzer.c +++ b/lib/common/fuzzers/iso8601_fuzzer.c @@ -36,7 +36,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) now = pcmk__copy_timet(tv.tv_sec); result = pcmk__time_format_hr(ns, now, (int) (tv.tv_nsec / QB_TIME_NS_IN_USEC)); - crm_time_free(now); + free(now); free(result); free(ns); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 5963d7ba480..90d321ca291 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -610,7 +610,7 @@ parse_date(const char *date_str) return dt; invalid: - crm_time_free(dt); + free(dt); errno = EINVAL; return NULL; } @@ -780,7 +780,7 @@ pcmk__time_get_seconds(const crm_time_t *dt) seconds = dt->seconds + (SECONDS_IN_DAY * days); - crm_time_free(utc); + free(utc); return seconds; } @@ -1147,7 +1147,7 @@ time_as_string_common(const crm_time_t *dt, int usec, uint32_t flags) } done: - crm_time_free(utc); + free(utc); result = pcmk__str_copy(buf->str); g_string_free(buf, TRUE); return result; @@ -1331,8 +1331,7 @@ parse_duration_element(const char **element, const char *duration_s, * ignored) * * \return New time object on success, or \c NULL (and set \c errno) otherwise - * \note It is the caller's responsibility to free the result using - * \c crm_time_free(). + * \note It is the caller's responsibility to free the result using \c free(). */ crm_time_t * pcmk__time_parse_duration(const char *period_s) @@ -1393,7 +1392,7 @@ pcmk__time_parse_duration(const char *period_s) /* @COMPAT Setting errno is required only for backward compatibility with * crm_time_parse_duration() */ - crm_time_free(diff); + free(diff); errno = EINVAL; return NULL; } @@ -1442,8 +1441,7 @@ pcmk_copy_time(const crm_time_t *source) * * \return Newly allocated \c crm_time_t object representing \p source_sec * - * \note The caller is responsible for freeing the return value using - * \c crm_time_free(). + * \note The caller is responsible for freeing the return value using \c free(). */ crm_time_t * pcmk__copy_timet(time_t source_sec) @@ -1509,7 +1507,7 @@ crm_time_add(const crm_time_t *dt, const crm_time_t *value) crm_time_add_days(answer, utc->days); crm_time_add_seconds(answer, utc->seconds); - crm_time_free(utc); + free(utc); return answer; } @@ -1675,7 +1673,7 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) } crm_time_add_seconds(result, -utc->seconds); - crm_time_free(utc); + free(utc); return result; } @@ -1768,8 +1766,8 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) utc1->years, utc1->days, utc1->seconds); done: - crm_time_free(utc1); - crm_time_free(utc2); + free(utc1); + free(utc2); return rc; } @@ -2196,7 +2194,7 @@ pcmk__epoch2str(const time_t *source, uint32_t flags) dt = pcmk__copy_timet(epoch_time); result = pcmk__time_text(dt, flags); - crm_time_free(dt); + free(dt); return result; } @@ -2232,7 +2230,7 @@ pcmk__timespec2str(const struct timespec *ts, uint32_t flags) dt = pcmk__copy_timet(ts->tv_sec); result = time_as_string_common(dt, ts->tv_nsec / QB_TIME_NS_IN_USEC, flags); - crm_time_free(dt); + free(dt); return result; } @@ -2371,7 +2369,7 @@ crm_time_set_timet(crm_time_t *target, const time_t *source_sec) source = pcmk__copy_timet(*source_sec); *target = *source; - crm_time_free(source); + free(source); } int @@ -2398,9 +2396,9 @@ void crm_time_free_period(crm_time_period_t *period) { if (period) { - crm_time_free(period->start); - crm_time_free(period->end); - crm_time_free(period->diff); + free(period->start); + free(period->end); + free(period->diff); free(period); } } diff --git a/lib/common/rules.c b/lib/common/rules.c index 97c14070d57..651fb79edee 100644 --- a/lib/common/rules.c +++ b/lib/common/rules.c @@ -220,7 +220,7 @@ pcmk__evaluate_date_spec(const xmlNode *date_spec, const crm_time_t *now) parent_id, id, \ pcmk__time_component_attr(component), \ pcmk_rc_str(rc)); \ - g_clear_pointer(end, crm_time_free); \ + g_clear_pointer(end, free); \ return rc; \ } \ } while (0) @@ -235,7 +235,7 @@ pcmk__evaluate_date_spec(const xmlNode *date_spec, const crm_time_t *now) * initially) * * \return Standard Pacemaker return code - * \note The caller is responsible for freeing \p *end using crm_time_free(). + * \note The caller is responsible for freeing \p *end using \c free(). */ int pcmk__unpack_duration(const xmlNode *duration, const crm_time_t *start, @@ -302,7 +302,7 @@ evaluate_in_range(const xmlNode *date_expression, const char *id, &end) != pcmk_rc_ok) { pcmk__config_err("Treating " PCMK_XE_DATE_EXPRESSION " %s as not " "passing because " PCMK_XA_END " is invalid", id); - crm_time_free(start); + free(start); return pcmk_rc_unpack_error; } @@ -326,7 +326,7 @@ evaluate_in_range(const xmlNode *date_expression, const char *id, pcmk__config_err("Treating " PCMK_XE_DATE_EXPRESSION " %s as not passing because duration " "is invalid", id); - crm_time_free(start); + free(start); return rc; } } @@ -334,15 +334,15 @@ evaluate_in_range(const xmlNode *date_expression, const char *id, if ((start != NULL) && (pcmk__time_compare(now, start) < 0)) { pcmk__set_time_if_earlier(next_change, start); - crm_time_free(start); - crm_time_free(end); + free(start); + free(end); return pcmk_rc_before_range; } if (end != NULL) { if (pcmk__time_compare(now, end) > 0) { - crm_time_free(start); - crm_time_free(end); + free(start); + free(end); return pcmk_rc_after_range; } @@ -353,8 +353,8 @@ evaluate_in_range(const xmlNode *date_expression, const char *id, } } - crm_time_free(start); - crm_time_free(end); + free(start); + free(end); return pcmk_rc_within_range; } @@ -393,14 +393,14 @@ evaluate_gt(const xmlNode *date_expression, const char *id, } if (pcmk__time_compare(now, start) > 0) { - crm_time_free(start); + free(start); return pcmk_rc_within_range; } // Evaluation doesn't change until second after start time crm_time_add_seconds(start, 1); pcmk__set_time_if_earlier(next_change, start); - crm_time_free(start); + free(start); return pcmk_rc_before_range; } @@ -439,11 +439,11 @@ evaluate_lt(const xmlNode *date_expression, const char *id, if (pcmk__time_compare(now, end) < 0) { pcmk__set_time_if_earlier(next_change, end); - crm_time_free(end); + free(end); return pcmk_rc_within_range; } - crm_time_free(end); + free(end); return pcmk_rc_after_range; } diff --git a/lib/common/scheduler.c b/lib/common/scheduler.c index 423a6521070..ceb283709f3 100644 --- a/lib/common/scheduler.c +++ b/lib/common/scheduler.c @@ -105,7 +105,7 @@ pcmk_reset_scheduler(pcmk_scheduler_t *scheduler) // Do not reset local_node_name or out - g_clear_pointer(&scheduler->priv->now, crm_time_free); + g_clear_pointer(&scheduler->priv->now, free); g_clear_pointer(&scheduler->priv->options, g_hash_table_destroy); scheduler->priv->fence_action = NULL; diff --git a/lib/common/strings.c b/lib/common/strings.c index 1a6b3135ef6..165decff9b2 100644 --- a/lib/common/strings.c +++ b/lib/common/strings.c @@ -377,7 +377,7 @@ pcmk_parse_interval_spec(const char *input, unsigned int *result_ms) if (period_s != NULL) { msec = pcmk__time_get_seconds(period_s); msec = QB_MIN(msec, UINT_MAX / 1000) * 1000; - crm_time_free(period_s); + free(period_s); } } else { diff --git a/lib/common/tests/iso8601/crm_time_add_days_test.c b/lib/common/tests/iso8601/crm_time_add_days_test.c index b7995355b48..21b1106e796 100644 --- a/lib/common/tests/iso8601/crm_time_add_days_test.c +++ b/lib/common/tests/iso8601/crm_time_add_days_test.c @@ -29,8 +29,8 @@ assert_add_days(const char *orig_date_time, int days, crm_time_add_days(orig, days); assert_int_equal(pcmk__time_compare(orig, expected), 0); - crm_time_free(orig); - crm_time_free(expected); + free(orig); + free(expected); } static void diff --git a/lib/common/tests/iso8601/crm_time_add_seconds_test.c b/lib/common/tests/iso8601/crm_time_add_seconds_test.c index 6cb957e689b..2b6d02733a5 100644 --- a/lib/common/tests/iso8601/crm_time_add_seconds_test.c +++ b/lib/common/tests/iso8601/crm_time_add_seconds_test.c @@ -29,8 +29,8 @@ assert_add_seconds(const char *orig_date_time, int seconds, crm_time_add_seconds(orig, seconds); assert_int_equal(pcmk__time_compare(orig, expected), 0); - crm_time_free(orig); - crm_time_free(expected); + free(orig); + free(expected); } static void diff --git a/lib/common/tests/iso8601/crm_time_add_years_test.c b/lib/common/tests/iso8601/crm_time_add_years_test.c index 35831673cdb..f0fa451accb 100644 --- a/lib/common/tests/iso8601/crm_time_add_years_test.c +++ b/lib/common/tests/iso8601/crm_time_add_years_test.c @@ -29,8 +29,8 @@ assert_add_years(const char *orig_date_time, int years, crm_time_add_years(orig, years); assert_int_equal(pcmk__time_compare(orig, expected), 0); - crm_time_free(orig); - crm_time_free(expected); + free(orig); + free(expected); } static void diff --git a/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c b/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c index ebea2842ab6..4fd5a252b72 100644 --- a/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c +++ b/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c @@ -47,8 +47,8 @@ null_xml_ok(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); } static void @@ -72,8 +72,8 @@ missing_attr(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -88,8 +88,8 @@ invalid_attr(void **state) pcmk_rc_unpack_error); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -110,8 +110,8 @@ out_of_range_attr(void **state) assert_int_equal(pcmk__time_compare(t, reference), 0); pcmk__xml_free(xml); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); } static void @@ -125,8 +125,8 @@ add_years(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -141,8 +141,8 @@ add_months(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -157,8 +157,8 @@ add_weeks(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -173,8 +173,8 @@ add_days(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -189,8 +189,8 @@ add_hours(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -205,8 +205,8 @@ add_minutes(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } @@ -221,8 +221,8 @@ add_seconds(void **state) pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } diff --git a/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c b/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c index 86d82cb8bab..6197a3b4a24 100644 --- a/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c +++ b/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c @@ -28,8 +28,8 @@ null_ok(void **state) pcmk__set_time_if_earlier(target, NULL); assert_int_equal(pcmk__time_compare(target, target_copy), 0); - crm_time_free(target); - crm_time_free(target_copy); + free(target); + free(target_copy); } static void @@ -41,8 +41,8 @@ target_undefined(void **state) pcmk__set_time_if_earlier(target, source); assert_int_equal(pcmk__time_compare(target, source), 0); - crm_time_free(source); - crm_time_free(target); + free(source); + free(target); } static void @@ -54,8 +54,8 @@ source_earlier(void **state) pcmk__set_time_if_earlier(target, source); assert_int_equal(pcmk__time_compare(target, source), 0); - crm_time_free(source); - crm_time_free(target); + free(source); + free(target); } static void @@ -68,9 +68,9 @@ source_later(void **state) pcmk__set_time_if_earlier(target, source); assert_int_equal(pcmk__time_compare(target, target_copy), 0); - crm_time_free(source); - crm_time_free(target); - crm_time_free(target_copy); + free(source); + free(target); + free(target_copy); } PCMK__UNIT_TEST(NULL, NULL, diff --git a/lib/common/tests/nvpair/pcmk__unpack_nvpair_block_test.c b/lib/common/tests/nvpair/pcmk__unpack_nvpair_block_test.c index bfb34e03378..8198cef841b 100644 --- a/lib/common/tests/nvpair/pcmk__unpack_nvpair_block_test.c +++ b/lib/common/tests/nvpair/pcmk__unpack_nvpair_block_test.c @@ -127,7 +127,7 @@ with_rules(void **state) assert_unpack_nvpair_block("" XML_NVPAIRS_2 XML_FAILING_RULE "", &unpack_data, 2, "1", "1", NULL); - crm_time_free(now); + free(now); g_hash_table_destroy(unpack_data.values); } diff --git a/lib/common/tests/nvpair/pcmk__unpack_nvpair_blocks_test.c b/lib/common/tests/nvpair/pcmk__unpack_nvpair_blocks_test.c index c2e9e7a9e9a..aea10f42125 100644 --- a/lib/common/tests/nvpair/pcmk__unpack_nvpair_blocks_test.c +++ b/lib/common/tests/nvpair/pcmk__unpack_nvpair_blocks_test.c @@ -74,8 +74,8 @@ null_xml(void **state) &rule_input, values, next_change, NULL); assert_int_equal(g_hash_table_size(values), 0); g_hash_table_destroy(values); - crm_time_free(now); - crm_time_free(next_change); + free(now); + free(next_change); } static void @@ -94,8 +94,8 @@ null_table(void **state) "id1", &rule_input, NULL, next_change, xml->doc)); pcmk__xml_free(xml); - crm_time_free(next_change); - crm_time_free(now); + free(next_change); + free(now); } static void @@ -118,8 +118,8 @@ rule_passes(void **state) assert_string_equal(g_hash_table_lookup(values, "name3"), "3"); pcmk__xml_free(xml); - crm_time_free(next_change); - crm_time_free(now); + free(next_change); + free(now); g_hash_table_destroy(values); } @@ -147,9 +147,9 @@ rule_fails(void **state) assert_int_equal(pcmk__time_compare(next_change, expected_next_change), 0); pcmk__xml_free(xml); - crm_time_free(now); - crm_time_free(next_change); - crm_time_free(expected_next_change); + free(now); + free(next_change); + free(expected_next_change); g_hash_table_destroy(values); } @@ -185,7 +185,7 @@ element_name(void **state) assert_string_equal(g_hash_table_lookup(values, "name3"), "3"); pcmk__xml_free(xml); - crm_time_free(now); + free(now); g_hash_table_destroy(values); } diff --git a/lib/common/tests/rules/pcmk__evaluate_condition_test.c b/lib/common/tests/rules/pcmk__evaluate_condition_test.c index 32d1ab23048..2a09b190596 100644 --- a/lib/common/tests/rules/pcmk__evaluate_condition_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_condition_test.c @@ -53,7 +53,7 @@ null_invalid(void **state) assert_int_equal(pcmk__evaluate_condition(NULL, &rule_input, next_change), EINVAL); - crm_time_free(next_change); + free(next_change); } @@ -68,7 +68,7 @@ invalid_expression(void **state) assert_int_equal(pcmk__evaluate_condition(xml, &rule_input, next_change), pcmk_rc_unpack_error); - crm_time_free(next_change); + free(next_change); pcmk__xml_free(xml); } @@ -133,9 +133,9 @@ date_expression(void **state) assert_int_equal(pcmk__time_compare(next_change, reference), 0); rule_input.now = NULL; - crm_time_free(reference); - crm_time_free(next_change); - crm_time_free(now); + free(reference); + free(next_change); + free(now); } #define EXPR_RESOURCE \ diff --git a/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c b/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c index bed8fc3e998..042fcaabad6 100644 --- a/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_date_expression_test.c @@ -47,14 +47,14 @@ assert_date_expression(const xmlNode *xml, const char *now_s, now = crm_time_new(now_s); assert_int_equal(pcmk__evaluate_date_expression(xml, now, next_change), reference_rc); - crm_time_free(now); + free(now); if (check_next_change) { crm_time_t *reference = crm_time_new(reference_s); assert_int_equal(pcmk__time_compare(next_change, reference), 0); - crm_time_free(reference); - crm_time_free(next_change); + free(reference); + free(next_change); } } @@ -73,7 +73,7 @@ null_invalid(void **state) assert_int_equal(pcmk__evaluate_date_expression(xml, NULL, NULL), EINVAL); assert_int_equal(pcmk__evaluate_date_expression(NULL, t, NULL), EINVAL); - crm_time_free(t); + free(t); pcmk__xml_free(xml); } @@ -237,7 +237,7 @@ range_missing(void **state) assert_int_equal(pcmk__evaluate_date_expression(xml, t, NULL), pcmk_rc_unpack_error); - crm_time_free(t); + free(t); pcmk__xml_free(xml); } diff --git a/lib/common/tests/rules/pcmk__evaluate_date_spec_test.c b/lib/common/tests/rules/pcmk__evaluate_date_spec_test.c index 8522f30be8b..08d9ff3a5d2 100644 --- a/lib/common/tests/rules/pcmk__evaluate_date_spec_test.c +++ b/lib/common/tests/rules/pcmk__evaluate_date_spec_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 the Pacemaker project contributors + * Copyright 2020-2026 the Pacemaker project contributors * * The version control history for this file may have further details. * @@ -24,7 +24,7 @@ run_one_test(const char *t, const char *x, int expected) assert_int_equal(pcmk__evaluate_date_spec(xml, tm), expected); - crm_time_free(tm); + free(tm); pcmk__xml_free(xml); } @@ -40,7 +40,7 @@ null_invalid(void **state) assert_int_equal(pcmk__evaluate_date_spec(xml, NULL), EINVAL); assert_int_equal(pcmk__evaluate_date_spec(NULL, tm), EINVAL); - crm_time_free(tm); + free(tm); pcmk__xml_free(xml); } diff --git a/lib/common/tests/rules/pcmk__unpack_duration_test.c b/lib/common/tests/rules/pcmk__unpack_duration_test.c index 978dd8d1bab..fba62996741 100644 --- a/lib/common/tests/rules/pcmk__unpack_duration_test.c +++ b/lib/common/tests/rules/pcmk__unpack_duration_test.c @@ -42,7 +42,7 @@ null_invalid(void **state) assert_int_equal(pcmk__unpack_duration(NULL, start, &end), EINVAL); assert_int_equal(pcmk__unpack_duration(NULL, NULL, &end), EINVAL); - crm_time_free(start); + free(start); pcmk__xml_free(duration); } @@ -55,8 +55,8 @@ nonnull_end_invalid(void **state) assert_int_equal(pcmk__unpack_duration(duration, start, &end), EINVAL); - crm_time_free(start); - crm_time_free(end); + free(start); + free(end); pcmk__xml_free(duration); } @@ -71,7 +71,7 @@ no_id(void **state) pcmk_rc_unpack_error); assert_null(end); - crm_time_free(start); + free(start); pcmk__xml_free(duration); } @@ -86,7 +86,7 @@ years_invalid(void **state) pcmk_rc_unpack_error); assert_null(end); - crm_time_free(start); + free(start); pcmk__xml_free(duration); } @@ -101,9 +101,9 @@ all_valid(void **state) assert_int_equal(pcmk__unpack_duration(duration, start, &end), pcmk_rc_ok); assert_int_equal(pcmk__time_compare(end, reference), 0); - crm_time_free(start); - crm_time_free(end); - crm_time_free(reference); + free(start); + free(end); + free(reference); pcmk__xml_free(duration); } diff --git a/lib/common/tests/rules/pcmk_evaluate_rule_test.c b/lib/common/tests/rules/pcmk_evaluate_rule_test.c index f0ce9d23b49..072bbf92c15 100644 --- a/lib/common/tests/rules/pcmk_evaluate_rule_test.c +++ b/lib/common/tests/rules/pcmk_evaluate_rule_test.c @@ -55,7 +55,7 @@ null_invalid(void **state) assert_int_equal(pcmk_evaluate_rule(NULL, &rule_input, next_change), EINVAL); - crm_time_free(next_change); + free(next_change); } #define RULE_OP_MISSING_ID \ @@ -74,7 +74,7 @@ id_missing(void **state) assert_int_equal(pcmk_evaluate_rule(xml, &rule_input, next_change), pcmk_rc_unpack_error); - crm_time_free(next_change); + free(next_change); pcmk__xml_free(xml); } @@ -91,7 +91,7 @@ good_idref(void **state) assert_int_equal(pcmk_evaluate_rule(rule_xml, &rule_input, next_change), pcmk_rc_ok); - crm_time_free(next_change); + free(next_change); pcmk__xml_free(parent_xml); } @@ -106,7 +106,7 @@ bad_idref(void **state) assert_int_equal(pcmk_evaluate_rule(rule_xml, &rule_input, next_change), pcmk_rc_unpack_error); - crm_time_free(next_change); + free(next_change); pcmk__xml_free(parent_xml); } diff --git a/lib/common/tests/xml_element/pcmk__xe_get_datetime_test.c b/lib/common/tests/xml_element/pcmk__xe_get_datetime_test.c index 34c4103abd9..9c2b60b6ad9 100644 --- a/lib/common/tests/xml_element/pcmk__xe_get_datetime_test.c +++ b/lib/common/tests/xml_element/pcmk__xe_get_datetime_test.c @@ -55,7 +55,7 @@ nonnull_time_invalid(void **state) assert_int_equal(pcmk__xe_get_datetime(xml, ATTR_PRESENT, &t), EINVAL); - crm_time_free(t); + free(t); pcmk__xml_free(xml); } @@ -81,8 +81,8 @@ attr_valid(void **state) assert_int_equal(pcmk__xe_get_datetime(xml, ATTR_PRESENT, &t), pcmk_rc_ok); assert_int_equal(pcmk__time_compare(t, reference), 0); - crm_time_free(t); - crm_time_free(reference); + free(t); + free(reference); pcmk__xml_free(xml); } diff --git a/lib/common/tls.c b/lib/common/tls.c index 1d834a59812..19906924aff 100644 --- a/lib/common/tls.c +++ b/lib/common/tls.c @@ -475,7 +475,7 @@ pcmk__tls_check_cert_expiration(gnutls_session_t session) pcmk__time_log(LOG_WARNING, "TLS certificate will expire on", expiry_t, pcmk__time_fmt_date|pcmk__time_fmt_time); - crm_time_free(expiry_t); + free(expiry_t); } } diff --git a/lib/common/xml_element.c b/lib/common/xml_element.c index 282b1dfd268..f3a671543b5 100644 --- a/lib/common/xml_element.c +++ b/lib/common/xml_element.c @@ -1624,7 +1624,7 @@ pcmk__xe_set_timeval(xmlNode *xml, const char *sec_attr, const char *usec_attr, * (\p *t must be NULL initially) * * \return Standard Pacemaker return code - * \note The caller is responsible for freeing \p *t using crm_time_free(). + * \note The caller is responsible for freeing \p *t using \c free(). */ int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t) diff --git a/lib/lrmd/lrmd_alerts.c b/lib/lrmd/lrmd_alerts.c index 0f80bc97553..8a922e7575c 100644 --- a/lib/lrmd/lrmd_alerts.c +++ b/lib/lrmd/lrmd_alerts.c @@ -184,7 +184,7 @@ exec_alert_list(lrmd_t *lrmd, const GList *alert_list, } } - crm_time_free(now_dt); + free(now_dt); if (any_failure) { return (any_success? -1 : -2); diff --git a/lib/pacemaker/pcmk_sched_location.c b/lib/pacemaker/pcmk_sched_location.c index 35df95103df..2cb75a9d285 100644 --- a/lib/pacemaker/pcmk_sched_location.c +++ b/lib/pacemaker/pcmk_sched_location.c @@ -385,7 +385,7 @@ unpack_rsc_location(xmlNode *xml_obj, pcmk_resource_t *rsc, pcmk__update_recheck_time(t, rsc->priv->scheduler, "location rule evaluation"); } - crm_time_free(next_change); + free(next_change); } } diff --git a/lib/pengine/pe_actions.c b/lib/pengine/pe_actions.c index 0cc25589d3e..c0303eb3785 100644 --- a/lib/pengine/pe_actions.c +++ b/lib/pengine/pe_actions.c @@ -594,7 +594,7 @@ unpack_interval_origin(const char *value, const xmlNode *xml_obj, // Get seconds since origin (negative if origin is in the future) result = pcmk__time_get_seconds(now) - pcmk__time_get_seconds(origin); - crm_time_free(origin); + free(origin); // Calculate seconds from closest interval to now result = result % interval_sec; diff --git a/lib/pengine/status.c b/lib/pengine/status.c index 6ddfff8867f..92232151fc5 100644 --- a/lib/pengine/status.c +++ b/lib/pengine/status.c @@ -328,7 +328,7 @@ cleanup_calculations(pcmk_scheduler_t *scheduler) pcmk__free_param_checks(scheduler); g_list_free(scheduler->priv->stop_needed); - crm_time_free(scheduler->priv->now); + free(scheduler->priv->now); pcmk__xml_free(scheduler->input); pcmk__xml_free(scheduler->priv->failed); pcmk__xml_free(scheduler->priv->graph); diff --git a/lib/pengine/utils.c b/lib/pengine/utils.c index 88f72b945fb..49003b56909 100644 --- a/lib/pengine/utils.c +++ b/lib/pengine/utils.c @@ -728,7 +728,7 @@ pe__unpack_dataset_nvpairs(const xmlNode *xml_obj, const char *set_name, pcmk__update_recheck_time(recheck, scheduler, "rule evaluation"); } - crm_time_free(next_change); + free(next_change); } bool diff --git a/tools/crm_resource_ban.c b/tools/crm_resource_ban.c index 656cb17cf4e..f87e3309950 100644 --- a/tools/crm_resource_ban.c +++ b/tools/crm_resource_ban.c @@ -45,8 +45,8 @@ parse_cli_lifetime(pcmk__output_t *out, const char *move_lifetime) out->err(out, "Unable to add %s to current time\n" "Please report to " PACKAGE_BUGREPORT " as possible bug", move_lifetime); - crm_time_free(now); - crm_time_free(duration); + free(now); + free(duration); return NULL; } @@ -56,9 +56,9 @@ parse_cli_lifetime(pcmk__output_t *out, const char *move_lifetime) later_s = pcmk__time_text(later, time_flags); out->info(out, "Migration will take effect until: %s", later_s); - crm_time_free(duration); - crm_time_free(later); - crm_time_free(now); + free(duration); + free(later); + free(now); return later_s; } @@ -516,7 +516,7 @@ cli_resource_clear_all_expired(xmlNode *root, cib_t *cib_conn, const char *rsc, pcmk__xml_free(fragment); } - crm_time_free(end); + free(end); } done: @@ -524,6 +524,6 @@ cli_resource_clear_all_expired(xmlNode *root, cib_t *cib_conn, const char *rsc, g_string_free(buf, TRUE); } xmlXPathFreeObject(xpathObj); - crm_time_free(now); + free(now); return rc; } diff --git a/tools/crm_rule.c b/tools/crm_rule.c index dbcbb79833d..1a7f7c2946d 100644 --- a/tools/crm_rule.c +++ b/tools/crm_rule.c @@ -206,7 +206,7 @@ main(int argc, char **argv) g_strfreev(processed_args); pcmk__free_arg_context(context); - crm_time_free(rule_date); + free(rule_date); pcmk__xml_free(input); pcmk__output_and_clear_error(&error, out); diff --git a/tools/iso8601.c b/tools/iso8601.c index f40d0d58150..974f76af045 100644 --- a/tools/iso8601.c +++ b/tools/iso8601.c @@ -362,13 +362,13 @@ parse_period(const char *period_str, crm_time_t **start, crm_time_t **end) goto invalid; } - crm_time_free(diff); + free(diff); return pcmk_rc_ok; invalid: - crm_time_free(diff); - crm_time_free(*start); - crm_time_free(*end); + free(diff); + free(*start); + free(*end); return EINVAL; } @@ -495,8 +495,8 @@ main(int argc, char **argv) } out->message(out, "period", start, end, options.print_options); - crm_time_free(start); - crm_time_free(end); + free(start); + free(end); } if (date_time && duration) { @@ -523,7 +523,7 @@ main(int argc, char **argv) } free(dt_s); } - crm_time_free(later); + free(later); } else if (date_time && options.expected_s) { char *dt_s = pcmk__time_text(date_time, @@ -539,8 +539,8 @@ main(int argc, char **argv) } done: - crm_time_free(date_time); - crm_time_free(duration); + free(date_time); + free(duration); g_strfreev(processed_args); pcmk__free_arg_context(context); From 74dc11f7f60ebe1e12ab2811babee18131449ced Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 22:55:07 -0700 Subject: [PATCH 05/26] API: libcrmcommon: Deprecate crm_time_free() Use free() instead. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 15 ++++++--------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 3f494d9ba1e..d2c0bffc397 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -52,7 +52,6 @@ typedef struct crm_time_s crm_time_t; * A timezone of 'Z' denotes UTC time */ crm_time_t *crm_time_new(const char *string); -void crm_time_free(crm_time_t * dt); /* Returns a new time object */ crm_time_t *pcmk_copy_time(const crm_time_t *source); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 78a60718052..0b068aec27a 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -142,6 +142,9 @@ long long crm_time_get_seconds(const crm_time_t *dt); //! \deprecated Do not use long long crm_time_get_seconds_since_epoch(const crm_time_t *dt); +//! \deprecated Use \c free() instead +void crm_time_free(crm_time_t *dt); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 90d321ca291..3e85d986a35 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -681,15 +681,6 @@ pcmk__time_is_initialized(const crm_time_t *dt) || dt->duration); } -void -crm_time_free(crm_time_t * dt) -{ - if (dt == NULL) { - return; - } - free(dt); -} - void pcmk__time_log_as(const char *file, const char *function, int line, uint8_t level, const char *prefix, const crm_time_t *dt, @@ -2569,5 +2560,11 @@ crm_time_get_seconds_since_epoch(const crm_time_t *dt) return pcmk__time_to_unix(dt); } +void +crm_time_free(crm_time_t *dt) +{ + free(dt); +} + // LCOV_EXCL_STOP // End deprecated API From 439a4dafb65203b1cea15d67c0e433541d5f7fbc Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 22 Jul 2026 14:14:35 -0700 Subject: [PATCH 06/26] Low: libcrmcommon: Handle NULL argument in pcmk_copy_time() Previously it would dereference a NULL argument. Signed-off-by: Reid Wahl --- lib/common/iso8601.c | 7 ++++++- lib/pacemaker/pcmk_scheduler.c | 8 ++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 3e85d986a35..53ae9315cf1 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1418,8 +1418,13 @@ pcmk__set_time_if_earlier(crm_time_t *target, const crm_time_t *source) crm_time_t * pcmk_copy_time(const crm_time_t *source) { - crm_time_t *target = pcmk__assert_alloc(1, sizeof(crm_time_t)); + crm_time_t *target = NULL; + + if (source == NULL) { + return NULL; + } + target = pcmk__assert_alloc(1, sizeof(crm_time_t)); *target = *source; return target; } diff --git a/lib/pacemaker/pcmk_scheduler.c b/lib/pacemaker/pcmk_scheduler.c index 191a4fe2989..e5356181a2b 100644 --- a/lib/pacemaker/pcmk_scheduler.c +++ b/lib/pacemaker/pcmk_scheduler.c @@ -831,12 +831,8 @@ pcmk__init_scheduler(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *da } } - // Make our own copy of the given crm_time_t object; otherwise - // cluster_status() populates with the current time - if (date != NULL) { - // pcmk_copy_time() guarantees non-NULL - new_scheduler->priv->now = pcmk_copy_time(date); - } + // If NULL, cluster_status() populates priv->now with the current time + new_scheduler->priv->now = pcmk_copy_time(date); // Unpack everything cluster_status(new_scheduler); From 15fb03a4b0990ed8696dfc20c6a9299e86dd1679 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 22:58:42 -0700 Subject: [PATCH 07/26] Refactor: libcrmcommon: New pcmk__time_copy() To replace pcmk_copy_time(). Signed-off-by: Reid Wahl --- include/crm/common/iso8601_internal.h | 3 ++ lib/common/iso8601.c | 39 +++++++++++++------ lib/common/rules.c | 2 +- .../iso8601/pcmk__add_time_from_xml_test.c | 8 ++-- .../iso8601/pcmk__set_time_if_earlier_test.c | 4 +- lib/pacemaker/pcmk_scheduler.c | 2 +- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/include/crm/common/iso8601_internal.h b/include/crm/common/iso8601_internal.h index f1f2fc8d249..1393260e7f0 100644 --- a/include/crm/common/iso8601_internal.h +++ b/include/crm/common/iso8601_internal.h @@ -129,6 +129,9 @@ enum pcmk__time_fmt_flags { }; bool pcmk__time_valid_year(int year); + +crm_time_t *pcmk__time_copy(const crm_time_t *source); + bool pcmk__time_is_initialized(const crm_time_t *dt); long long pcmk__time_get_seconds(const crm_time_t *dt); long long pcmk__time_to_unix(const crm_time_t *dt); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 53ae9315cf1..8b9717ebeae 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -662,6 +662,31 @@ crm_time_new(const char *date_time) } /*! + * \internal + * \brief Copy a time object + * + * \param[in] source Time object + * + * \return Newly allocated copy of \p source, or \c NULL if \p source is \c NULL + * + * \note The caller is responsible for freeing the return value using \c free(). + */ +crm_time_t * +pcmk__time_copy(const crm_time_t *source) +{ + crm_time_t *target = NULL; + + if (source == NULL) { + return NULL; + } + + target = pcmk__assert_alloc(1, sizeof(crm_time_t)); + *target = *source; + return target; +} + +/*! + * \internal * \brief Check whether a time object has been initialized yet * * \param[in] dt Time object to check @@ -1418,15 +1443,7 @@ pcmk__set_time_if_earlier(crm_time_t *target, const crm_time_t *source) crm_time_t * pcmk_copy_time(const crm_time_t *source) { - crm_time_t *target = NULL; - - if (source == NULL) { - return NULL; - } - - target = pcmk__assert_alloc(1, sizeof(crm_time_t)); - *target = *source; - return target; + return pcmk__time_copy(source); } /*! @@ -1495,7 +1512,7 @@ crm_time_add(const crm_time_t *dt, const crm_time_t *value) return NULL; } - answer = pcmk_copy_time(dt); + answer = pcmk__time_copy(dt); utc = copy_time_to_utc(value); crm_time_add_years(answer, utc->years); @@ -1638,7 +1655,7 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) return NULL; } - result = (as_duration? copy_time_to_utc(dt1) : pcmk_copy_time(dt1)); + result = (as_duration? copy_time_to_utc(dt1) : pcmk__time_copy(dt1)); result->duration = as_duration; utc = copy_time_to_utc(dt2); diff --git a/lib/common/rules.c b/lib/common/rules.c index 651fb79edee..bc433478a16 100644 --- a/lib/common/rules.c +++ b/lib/common/rules.c @@ -258,7 +258,7 @@ pcmk__unpack_duration(const xmlNode *duration, const crm_time_t *start, return pcmk_rc_unpack_error; } - *end = pcmk_copy_time(start); + *end = pcmk__time_copy(start); ADD_COMPONENT(pcmk__time_years); ADD_COMPONENT(pcmk__time_months); diff --git a/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c b/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c index 4fd5a252b72..0f9be77060d 100644 --- a/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c +++ b/lib/common/tests/iso8601/pcmk__add_time_from_xml_test.c @@ -41,7 +41,7 @@ static void null_xml_ok(void **state) { crm_time_t *t = crm_time_new("2024-01-01 15:00:00"); - crm_time_t *reference = pcmk_copy_time(t); + crm_time_t *reference = pcmk__time_copy(t); assert_int_equal(pcmk__add_time_from_xml(t, pcmk__time_years, NULL), pcmk_rc_ok); @@ -65,7 +65,7 @@ static void missing_attr(void **state) { crm_time_t *t = crm_time_new("2024-01-01 15:00:00"); - crm_time_t *reference = pcmk_copy_time(t); + crm_time_t *reference = pcmk__time_copy(t); xmlNode *xml = pcmk__xml_parse(YEARS_INVALID); assert_int_equal(pcmk__add_time_from_xml(t, pcmk__time_months, xml), @@ -81,7 +81,7 @@ static void invalid_attr(void **state) { crm_time_t *t = crm_time_new("2024-01-01 15:00:00"); - crm_time_t *reference = pcmk_copy_time(t); + crm_time_t *reference = pcmk__time_copy(t); xmlNode *xml = pcmk__xml_parse(YEARS_INVALID); assert_int_equal(pcmk__add_time_from_xml(t, pcmk__time_years, xml), @@ -97,7 +97,7 @@ static void out_of_range_attr(void **state) { crm_time_t *t = crm_time_new("2024-01-01 15:00:00"); - crm_time_t *reference = pcmk_copy_time(t); + crm_time_t *reference = pcmk__time_copy(t); xmlNode *xml = NULL; xml = pcmk__xml_parse(YEARS_TOO_BIG); diff --git a/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c b/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c index 6197a3b4a24..27b48fb9c5b 100644 --- a/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c +++ b/lib/common/tests/iso8601/pcmk__set_time_if_earlier_test.c @@ -18,7 +18,7 @@ static void null_ok(void **state) { crm_time_t *target = crm_time_new("2024-01-01 00:30:00 +01:00"); - crm_time_t *target_copy = pcmk_copy_time(target); + crm_time_t *target_copy = pcmk__time_copy(target); // Should do nothing (just checking it doesn't assert or crash) pcmk__set_time_if_earlier(NULL, NULL); @@ -63,7 +63,7 @@ source_later(void **state) { crm_time_t *source = crm_time_new("2024-01-01 00:31:00 +01:00"); crm_time_t *target = crm_time_new("2024-01-01 00:30:00 +01:00"); - crm_time_t *target_copy = pcmk_copy_time(target); + crm_time_t *target_copy = pcmk__time_copy(target); pcmk__set_time_if_earlier(target, source); assert_int_equal(pcmk__time_compare(target, target_copy), 0); diff --git a/lib/pacemaker/pcmk_scheduler.c b/lib/pacemaker/pcmk_scheduler.c index e5356181a2b..bdbbb083dc2 100644 --- a/lib/pacemaker/pcmk_scheduler.c +++ b/lib/pacemaker/pcmk_scheduler.c @@ -832,7 +832,7 @@ pcmk__init_scheduler(pcmk__output_t *out, xmlNodePtr input, const crm_time_t *da } // If NULL, cluster_status() populates priv->now with the current time - new_scheduler->priv->now = pcmk_copy_time(date); + new_scheduler->priv->now = pcmk__time_copy(date); // Unpack everything cluster_status(new_scheduler); From 4306a19f0d594793597b86002b622d52eab48450 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:02:05 -0700 Subject: [PATCH 08/26] API: libcrmcommon: Deprecate pcmk_copy_time() External callers have no need to copy a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 12 ++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index d2c0bffc397..27faaeda521 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* Returns a new time object */ -crm_time_t *pcmk_copy_time(const crm_time_t *source); crm_time_t *crm_time_add(const crm_time_t *dt, const crm_time_t *value); crm_time_t *crm_time_subtract(const crm_time_t *dt, const crm_time_t *value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 0b068aec27a..407d04e9799 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -145,6 +145,9 @@ long long crm_time_get_seconds_since_epoch(const crm_time_t *dt); //! \deprecated Use \c free() instead void crm_time_free(crm_time_t *dt); +//! \deprecated Do not use +crm_time_t *pcmk_copy_time(const crm_time_t *source); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 8b9717ebeae..237e4b78420 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1440,12 +1440,6 @@ pcmk__set_time_if_earlier(crm_time_t *target, const crm_time_t *source) pcmk__time_log(LOG_TRACE, "target", target, flags); } -crm_time_t * -pcmk_copy_time(const crm_time_t *source) -{ - return pcmk__time_copy(source); -} - /*! * \internal * \brief Convert a \c time_t time to a \c crm_time_t time @@ -2588,5 +2582,11 @@ crm_time_free(crm_time_t *dt) free(dt); } +crm_time_t * +pcmk_copy_time(const crm_time_t *source) +{ + return pcmk__time_copy(source); +} + // LCOV_EXCL_STOP // End deprecated API From 127355dc18bc6dd2867d040a239d2842815c09f7 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:06:45 -0700 Subject: [PATCH 09/26] Refactor: libcrmcommon: New pcmk__time_add() To replace crm_time_add(). Signed-off-by: Reid Wahl --- include/crm/common/iso8601_internal.h | 1 + lib/common/iso8601.c | 34 ++++++++++++++++++++++----- tools/crm_resource_ban.c | 2 +- tools/iso8601.c | 4 ++-- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/include/crm/common/iso8601_internal.h b/include/crm/common/iso8601_internal.h index 1393260e7f0..822fc0673c3 100644 --- a/include/crm/common/iso8601_internal.h +++ b/include/crm/common/iso8601_internal.h @@ -143,6 +143,7 @@ const char *pcmk__readable_interval(unsigned int interval_ms); crm_time_t *pcmk__time_parse_duration(const char *period_s); crm_time_t *pcmk__copy_timet(time_t source_sec); +crm_time_t *pcmk__time_add(const crm_time_t *dt, const crm_time_t *value); int pcmk__time_compare(const crm_time_t *a, const crm_time_t *b); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 237e4b78420..1f6ecf6d24d 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1495,16 +1495,27 @@ pcmk__copy_timet(time_t source_sec) return target; } +/*! + * \internal + * \brief Add one time object to another and return the sum + * + * \param[in] dt Time object to add to + * \param[in] value Value to add to \p dt + * + * \return Newly allocated sum of \p dt and \p value + * + * \note The caller is responsible for freeing the return value using \c free(). + * \note \p dt is treated as a date/time, while \p value is treated as a + * duration. Adding two dates is an ill-defined operation, though it + * allowed. + */ crm_time_t * -crm_time_add(const crm_time_t *dt, const crm_time_t *value) +pcmk__time_add(const crm_time_t *dt, const crm_time_t *value) { crm_time_t *utc = NULL; crm_time_t *answer = NULL; - if ((dt == NULL) || (value == NULL)) { - errno = EINVAL; - return NULL; - } + pcmk__assert((dt != NULL) && (value != NULL)); answer = pcmk__time_copy(dt); utc = copy_time_to_utc(value); @@ -1518,6 +1529,17 @@ crm_time_add(const crm_time_t *dt, const crm_time_t *value) return answer; } +crm_time_t * +crm_time_add(const crm_time_t *dt, const crm_time_t *value) +{ + if ((dt == NULL) || (value == NULL)) { + errno = EINVAL; + return NULL; + } + + return pcmk__time_add(dt, value); +} + /*! * \internal * \brief Return the XML attribute name corresponding to a time component @@ -2473,7 +2495,7 @@ crm_time_parse_period(const char *period_str) period->start = crm_time_subtract(period->end, period->diff); } else if (period->end == NULL) { - period->end = crm_time_add(period->start, period->diff); + period->end = pcmk__time_add(period->start, period->diff); } if (!pcmk__time_valid_year(period->start->years) diff --git a/tools/crm_resource_ban.c b/tools/crm_resource_ban.c index f87e3309950..264c5ee1d2a 100644 --- a/tools/crm_resource_ban.c +++ b/tools/crm_resource_ban.c @@ -40,7 +40,7 @@ parse_cli_lifetime(pcmk__output_t *out, const char *move_lifetime) } now = crm_time_new(NULL); - later = crm_time_add(now, duration); + later = pcmk__time_add(now, duration); if (later == NULL) { out->err(out, "Unable to add %s to current time\n" "Please report to " PACKAGE_BUGREPORT " as possible bug", diff --git a/tools/iso8601.c b/tools/iso8601.c index 974f76af045..df017b4e5ff 100644 --- a/tools/iso8601.c +++ b/tools/iso8601.c @@ -345,7 +345,7 @@ parse_period(const char *period_str, crm_time_t **start, crm_time_t **end) *start = crm_time_subtract(*end, diff); } else if (*end == NULL) { - *end = crm_time_add(*start, diff); + *end = pcmk__time_add(*start, diff); } if (!pcmk__time_valid_year((*start)->years) || !valid_time(*start)) { @@ -500,7 +500,7 @@ main(int argc, char **argv) } if (date_time && duration) { - crm_time_t *later = crm_time_add(date_time, duration); + crm_time_t *later = pcmk__time_add(date_time, duration); if (later == NULL) { exit_code = CRM_EX_SOFTWARE; From 21cf76cd5b6fd993e018da44e14d060166ffe583 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:08:31 -0700 Subject: [PATCH 10/26] API: libcrmcommon: Deprecate crm_time_add() External callers have no need to add to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 27faaeda521..bd05e121a6c 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* Returns a new time object */ -crm_time_t *crm_time_add(const crm_time_t *dt, const crm_time_t *value); crm_time_t *crm_time_subtract(const crm_time_t *dt, const crm_time_t *value); /* All crm_time_add_... functions support negative values */ diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 407d04e9799..ef358931563 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -148,6 +148,9 @@ void crm_time_free(crm_time_t *dt); //! \deprecated Do not use crm_time_t *pcmk_copy_time(const crm_time_t *source); +//! \deprecated Do not use +crm_time_t *crm_time_add(const crm_time_t *dt, const crm_time_t *value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 1f6ecf6d24d..b952d0dfcdf 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1529,17 +1529,6 @@ pcmk__time_add(const crm_time_t *dt, const crm_time_t *value) return answer; } -crm_time_t * -crm_time_add(const crm_time_t *dt, const crm_time_t *value) -{ - if ((dt == NULL) || (value == NULL)) { - errno = EINVAL; - return NULL; - } - - return pcmk__time_add(dt, value); -} - /*! * \internal * \brief Return the XML attribute name corresponding to a time component @@ -2610,5 +2599,16 @@ pcmk_copy_time(const crm_time_t *source) return pcmk__time_copy(source); } +crm_time_t * +crm_time_add(const crm_time_t *dt, const crm_time_t *value) +{ + if ((dt == NULL) || (value == NULL)) { + errno = EINVAL; + return NULL; + } + + return pcmk__time_add(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From 2513d009d3f413601e932eca20be0327a79a8524 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:12:49 -0700 Subject: [PATCH 11/26] Refactor: libcrmcommon: New pcmk__time_subtract() To replace crm_time_subtract(). Signed-off-by: Reid Wahl --- include/crm/common/iso8601_internal.h | 1 + lib/common/iso8601.c | 39 ++++++++++++++++++++++----- tools/iso8601.c | 2 +- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/include/crm/common/iso8601_internal.h b/include/crm/common/iso8601_internal.h index 822fc0673c3..ca3ebed0529 100644 --- a/include/crm/common/iso8601_internal.h +++ b/include/crm/common/iso8601_internal.h @@ -144,6 +144,7 @@ const char *pcmk__readable_interval(unsigned int interval_ms); crm_time_t *pcmk__time_parse_duration(const char *period_s); crm_time_t *pcmk__copy_timet(time_t source_sec); crm_time_t *pcmk__time_add(const crm_time_t *dt, const crm_time_t *value); +crm_time_t *pcmk__time_subtract(const crm_time_t *dt, const crm_time_t *value); int pcmk__time_compare(const crm_time_t *a, const crm_time_t *b); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index b952d0dfcdf..a0ee9cd541b 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1655,10 +1655,7 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) crm_time_t *result = NULL; crm_time_t *utc = NULL; - if ((dt1 == NULL) || (dt2 == NULL)) { - errno = EINVAL; - return NULL; - } + pcmk__assert((dt1 != NULL) && (dt2 != NULL)); result = (as_duration? copy_time_to_utc(dt1) : pcmk__time_copy(dt1)); result->duration = as_duration; @@ -1695,12 +1692,37 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) return result; } +/*! + * \internal + * \brief Subtract one time object from another and return the difference + * + * \param[in] dt Time object to subtract from + * \param[in] value Value to subtract from \p dt + * + * \return Newly allocated difference of \p dt and \p value + * + * \note The caller is responsible for freeing the return value using \c free(). + * \note \p dt is treated as a date/time, while \p value is treated as a + * duration. Subtracting two dates is an ill-defined operation, though it + * allowed. + */ crm_time_t * -crm_time_subtract(const crm_time_t *dt, const crm_time_t *value) +pcmk__time_subtract(const crm_time_t *dt, const crm_time_t *value) { return subtract_time(dt, value, false); } +crm_time_t * +crm_time_subtract(const crm_time_t *dt, const crm_time_t *value) +{ + if ((dt == NULL) || (value == NULL)) { + errno = EINVAL; + return NULL; + } + + return pcmk__time_subtract(dt, value); +} + /*! * \internal * \brief Compare two time objects @@ -2481,7 +2503,7 @@ crm_time_parse_period(const char *period_str) } if (period->start == NULL) { - period->start = crm_time_subtract(period->end, period->diff); + period->start = pcmk__time_subtract(period->end, period->diff); } else if (period->end == NULL) { period->end = pcmk__time_add(period->start, period->diff); @@ -2516,6 +2538,11 @@ crm_time_parse_period(const char *period_str) crm_time_t * crm_time_calculate_duration(const crm_time_t *dt, const crm_time_t *value) { + if ((dt == NULL) || (value == NULL)) { + errno = EINVAL; + return NULL; + } + return subtract_time(dt, value, true); } diff --git a/tools/iso8601.c b/tools/iso8601.c index df017b4e5ff..40bb8c62e0c 100644 --- a/tools/iso8601.c +++ b/tools/iso8601.c @@ -342,7 +342,7 @@ parse_period(const char *period_str, crm_time_t **start, crm_time_t **end) } if (*start == NULL) { - *start = crm_time_subtract(*end, diff); + *start = pcmk__time_subtract(*end, diff); } else if (*end == NULL) { *end = pcmk__time_add(*start, diff); From ccb9560d4ff76eba7349128f1cd26e6a9233acd4 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:13:57 -0700 Subject: [PATCH 12/26] API: libcrmcommon: Deprecate crm_time_subtract() External callers have no need to subtract from a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 3 --- include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index bd05e121a6c..601ea683750 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -53,9 +53,6 @@ typedef struct crm_time_s crm_time_t; */ crm_time_t *crm_time_new(const char *string); -/* Returns a new time object */ -crm_time_t *crm_time_subtract(const crm_time_t *dt, const crm_time_t *value); - /* All crm_time_add_... functions support negative values */ void crm_time_add_seconds(crm_time_t * dt, int value); void crm_time_add_minutes(crm_time_t * dt, int value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index ef358931563..964a7fcf2ff 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -151,6 +151,9 @@ crm_time_t *pcmk_copy_time(const crm_time_t *source); //! \deprecated Do not use crm_time_t *crm_time_add(const crm_time_t *dt, const crm_time_t *value); +//! \deprecated Do not use +crm_time_t *crm_time_subtract(const crm_time_t *dt, const crm_time_t *value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index a0ee9cd541b..af5bf3af3ed 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1712,17 +1712,6 @@ pcmk__time_subtract(const crm_time_t *dt, const crm_time_t *value) return subtract_time(dt, value, false); } -crm_time_t * -crm_time_subtract(const crm_time_t *dt, const crm_time_t *value) -{ - if ((dt == NULL) || (value == NULL)) { - errno = EINVAL; - return NULL; - } - - return pcmk__time_subtract(dt, value); -} - /*! * \internal * \brief Compare two time objects @@ -2637,5 +2626,16 @@ crm_time_add(const crm_time_t *dt, const crm_time_t *value) return pcmk__time_add(dt, value); } +crm_time_t * +crm_time_subtract(const crm_time_t *dt, const crm_time_t *value) +{ + if ((dt == NULL) || (value == NULL)) { + errno = EINVAL; + return NULL; + } + + return pcmk__time_subtract(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From 821032ef632b1e3e1c981fb536fe22ab2e48e40f Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:19:12 -0700 Subject: [PATCH 13/26] Refactor: libcrmcommon: New pcmk__time_add_seconds() To replace crm_time_add_seconds(). Signed-off-by: Reid Wahl --- lib/common/crmcommon_private.h | 3 + lib/common/iso8601.c | 64 +++++++++++-------- lib/common/rules.c | 4 +- lib/common/tests/iso8601/Makefile.am | 2 +- ...s_test.c => pcmk__time_add_seconds_test.c} | 6 +- 5 files changed, 47 insertions(+), 32 deletions(-) rename lib/common/tests/iso8601/{crm_time_add_seconds_test.c => pcmk__time_add_seconds_test.c} (97%) diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h index f0ce2ade07d..368c53cf8a9 100644 --- a/lib/common/crmcommon_private.h +++ b/lib/common/crmcommon_private.h @@ -208,6 +208,9 @@ enum pcmk__time_component { pcmk__time_seconds, }; +G_GNUC_INTERNAL +void pcmk__time_add_seconds(crm_time_t *dt, int value); + G_GNUC_INTERNAL void pcmk__time_get_timeofday(const crm_time_t *dt, uint32_t *hour, uint32_t *minute, uint32_t *second); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index af5bf3af3ed..86e274641c9 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -615,6 +615,35 @@ parse_date(const char *date_str) return NULL; } +/*! + * \internal + * \brief Add a given number of seconds to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of seconds to add (can be negative to subtract) + */ +void +pcmk__time_add_seconds(crm_time_t *dt, int value) +{ + int days = value / SECONDS_IN_DAY; + + pcmk__assert(dt != NULL); + + dt->seconds += value % SECONDS_IN_DAY; + + // Check whether the addition crossed a day boundary + if (dt->seconds > SECONDS_IN_DAY) { + ++days; + dt->seconds -= SECONDS_IN_DAY; + + } else if (dt->seconds < 0) { + --days; + dt->seconds += SECONDS_IN_DAY; + } + + crm_time_add_days(dt, days); +} + // Return value is guaranteed not to be NULL static crm_time_t * copy_time_to_utc(const crm_time_t *dt) @@ -639,7 +668,7 @@ copy_time_to_utc(const crm_time_t *dt) utc->duration = dt->duration; if (dt->offset != 0) { - crm_time_add_seconds(utc, -dt->offset); + pcmk__time_add_seconds(utc, -dt->offset); } else { // Durations (the only things that can include months) never have a TZ @@ -1523,7 +1552,7 @@ pcmk__time_add(const crm_time_t *dt, const crm_time_t *value) crm_time_add_years(answer, utc->years); crm_time_add_months(answer, utc->months); crm_time_add_days(answer, utc->days); - crm_time_add_seconds(answer, utc->seconds); + pcmk__time_add_seconds(answer, utc->seconds); free(utc); return answer; @@ -1601,7 +1630,7 @@ component_fn(enum pcmk__time_component component) return crm_time_add_minutes; case pcmk__time_seconds: - return crm_time_add_seconds; + return pcmk__time_add_seconds; default: return NULL; @@ -1683,10 +1712,10 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) crm_time_add_days(result, -utc->days); if (utc->seconds == INT_MIN) { - crm_time_add_seconds(result, -1); + pcmk__time_add_seconds(result, -1); utc->seconds++; } - crm_time_add_seconds(result, -utc->seconds); + pcmk__time_add_seconds(result, -utc->seconds); free(utc); return result; @@ -1809,26 +1838,7 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) void crm_time_add_seconds(crm_time_t *dt, int value) { - int days = value / SECONDS_IN_DAY; - - pcmk__assert(dt != NULL); - - pcmk__trace("Adding %d seconds (including %d whole day%s) to %d", value, - days, pcmk__plural_s(days), dt->seconds); - - dt->seconds += value % SECONDS_IN_DAY; - - // Check whether the addition crossed a day boundary - if (dt->seconds > SECONDS_IN_DAY) { - ++days; - dt->seconds -= SECONDS_IN_DAY; - - } else if (dt->seconds < 0) { - --days; - dt->seconds += SECONDS_IN_DAY; - } - - crm_time_add_days(dt, days); + pcmk__time_add_seconds(dt, value); } /*! @@ -1911,13 +1921,13 @@ crm_time_add_months(crm_time_t *dt, int value) void crm_time_add_minutes(crm_time_t *dt, int value) { - crm_time_add_seconds(dt, value * SECONDS_IN_MINUTE); + pcmk__time_add_seconds(dt, value * SECONDS_IN_MINUTE); } void crm_time_add_hours(crm_time_t *dt, int value) { - crm_time_add_seconds(dt, value * SECONDS_IN_HOUR); + pcmk__time_add_seconds(dt, value * SECONDS_IN_HOUR); } void diff --git a/lib/common/rules.c b/lib/common/rules.c index bc433478a16..acb6b88a9f5 100644 --- a/lib/common/rules.c +++ b/lib/common/rules.c @@ -348,7 +348,7 @@ evaluate_in_range(const xmlNode *date_expression, const char *id, // Evaluation doesn't change until second after end if (next_change != NULL) { - crm_time_add_seconds(end, 1); + pcmk__time_add_seconds(end, 1); pcmk__set_time_if_earlier(next_change, end); } } @@ -398,7 +398,7 @@ evaluate_gt(const xmlNode *date_expression, const char *id, } // Evaluation doesn't change until second after start time - crm_time_add_seconds(start, 1); + pcmk__time_add_seconds(start, 1); pcmk__set_time_if_earlier(next_change, start); free(start); return pcmk_rc_before_range; diff --git a/lib/common/tests/iso8601/Makefile.am b/lib/common/tests/iso8601/Makefile.am index 8dd1ef06f48..c320fb59ca8 100644 --- a/lib/common/tests/iso8601/Makefile.am +++ b/lib/common/tests/iso8601/Makefile.am @@ -13,11 +13,11 @@ include $(top_srcdir)/mk/unittest.mk # Add "_test" to the end of all test program names to simplify .gitignore. check_PROGRAMS = crm_time_add_days_test -check_PROGRAMS += crm_time_add_seconds_test check_PROGRAMS += crm_time_add_years_test check_PROGRAMS += pcmk__add_time_from_xml_test check_PROGRAMS += pcmk__readable_interval_test check_PROGRAMS += pcmk__set_time_if_earlier_test +check_PROGRAMS += pcmk__time_add_seconds_test check_PROGRAMS += pcmk__time_format_hr_test check_PROGRAMS += pcmk__time_parse_duration_test diff --git a/lib/common/tests/iso8601/crm_time_add_seconds_test.c b/lib/common/tests/iso8601/pcmk__time_add_seconds_test.c similarity index 97% rename from lib/common/tests/iso8601/crm_time_add_seconds_test.c rename to lib/common/tests/iso8601/pcmk__time_add_seconds_test.c index 2b6d02733a5..9cf91ffb641 100644 --- a/lib/common/tests/iso8601/crm_time_add_seconds_test.c +++ b/lib/common/tests/iso8601/pcmk__time_add_seconds_test.c @@ -16,6 +16,8 @@ #include +#include "crmcommon_private.h" // pcmk__time_add_seconds + static void assert_add_seconds(const char *orig_date_time, int seconds, const char *expected_date_time) @@ -26,7 +28,7 @@ assert_add_seconds(const char *orig_date_time, int seconds, assert_non_null(orig); assert_non_null(expected); - crm_time_add_seconds(orig, seconds); + pcmk__time_add_seconds(orig, seconds); assert_int_equal(pcmk__time_compare(orig, expected), 0); free(orig); @@ -36,7 +38,7 @@ assert_add_seconds(const char *orig_date_time, int seconds, static void invalid_argument(void **state) { - pcmk__assert_asserts(crm_time_add_seconds(NULL, 1)); + pcmk__assert_asserts(pcmk__time_add_seconds(NULL, 1)); } static void From a2d4b9ef71f418d085d38275a89be7566123602a Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:20:13 -0700 Subject: [PATCH 14/26] API: libcrmcommon: Deprecate crm_time_add_seconds() External callers have no need to add seconds to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 18 ++++++------------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 601ea683750..2dcfbbeb7e6 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* All crm_time_add_... functions support negative values */ -void crm_time_add_seconds(crm_time_t * dt, int value); void crm_time_add_minutes(crm_time_t * dt, int value); void crm_time_add_hours(crm_time_t * dt, int value); void crm_time_add_days(crm_time_t * dt, int value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 964a7fcf2ff..ffe2d1c5136 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -154,6 +154,9 @@ crm_time_t *crm_time_add(const crm_time_t *dt, const crm_time_t *value); //! \deprecated Do not use crm_time_t *crm_time_subtract(const crm_time_t *dt, const crm_time_t *value); +//! \deprecated Do not use +void crm_time_add_seconds(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 86e274641c9..f7d735be63b 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1829,18 +1829,6 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) return rc; } -/*! - * \brief Add a given number of seconds to a date/time or duration - * - * \param[in,out] dt Date/time or duration to add seconds to - * \param[in] value Number of seconds to add - */ -void -crm_time_add_seconds(crm_time_t *dt, int value) -{ - pcmk__time_add_seconds(dt, value); -} - /*! * \brief Add days to a date/time * @@ -2647,5 +2635,11 @@ crm_time_subtract(const crm_time_t *dt, const crm_time_t *value) return pcmk__time_subtract(dt, value); } +void +crm_time_add_seconds(crm_time_t *dt, int value) +{ + pcmk__time_add_seconds(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From 1fc44db076858b9e58c711c65c246ec162337f63 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 22 Jul 2026 15:33:33 -0700 Subject: [PATCH 15/26] Low: libcrmcommon: Avoid overflow in crm_time_add_minutes() Previously, the (value * SECONDS_IN_MINUTE) computation could overflow. This is not the most efficient implementation; we could avoid the for loops in the common case where the multiplication does not overflow. However, that seems to me like premature optimization. Simplicity and readability seem more important than here. Signed-off-by: Reid Wahl --- lib/common/iso8601.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index f7d735be63b..0532edb4357 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1909,7 +1909,13 @@ crm_time_add_months(crm_time_t *dt, int value) void crm_time_add_minutes(crm_time_t *dt, int value) { - pcmk__time_add_seconds(dt, value * SECONDS_IN_MINUTE); + for (; value > 0; value--) { + pcmk__time_add_seconds(dt, SECONDS_IN_MINUTE); + } + + for (; value < 0; value++) { + pcmk__time_add_seconds(dt, -SECONDS_IN_MINUTE); + } } void From 51b4dcb5f1298cf15594418726f4d6824d574e30 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:23:11 -0700 Subject: [PATCH 16/26] API: libcrmcommon: Deprecate crm_time_add_minutes() External callers have no need to add minutes to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 39 +++++++++++++++++++---------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 2dcfbbeb7e6..18b4be84b75 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* All crm_time_add_... functions support negative values */ -void crm_time_add_minutes(crm_time_t * dt, int value); void crm_time_add_hours(crm_time_t * dt, int value); void crm_time_add_days(crm_time_t * dt, int value); void crm_time_add_weeks(crm_time_t * dt, int value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index ffe2d1c5136..54c058f4f69 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -157,6 +157,9 @@ crm_time_t *crm_time_subtract(const crm_time_t *dt, const crm_time_t *value); //! \deprecated Do not use void crm_time_add_seconds(crm_time_t *dt, int value); +//! \deprecated Do not use +void crm_time_add_minutes(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 0532edb4357..b87212dbe6b 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1597,6 +1597,25 @@ pcmk__time_component_attr(enum pcmk__time_component component) } } +/*! + * \internal + * \brief Add a given number of minutes to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of minutes to add (can be negative to subtract) + */ +static void +add_minutes(crm_time_t *dt, int value) +{ + for (; value > 0; value--) { + pcmk__time_add_seconds(dt, SECONDS_IN_MINUTE); + } + + for (; value < 0; value++) { + pcmk__time_add_seconds(dt, -SECONDS_IN_MINUTE); + } +} + typedef void (*component_fn_t)(crm_time_t *, int); /*! @@ -1627,7 +1646,7 @@ component_fn(enum pcmk__time_component component) return crm_time_add_hours; case pcmk__time_minutes: - return crm_time_add_minutes; + return add_minutes; case pcmk__time_seconds: return pcmk__time_add_seconds; @@ -1906,18 +1925,6 @@ crm_time_add_months(crm_time_t *dt, int value) dt->days = get_ordinal_days(year, month, day); } -void -crm_time_add_minutes(crm_time_t *dt, int value) -{ - for (; value > 0; value--) { - pcmk__time_add_seconds(dt, SECONDS_IN_MINUTE); - } - - for (; value < 0; value++) { - pcmk__time_add_seconds(dt, -SECONDS_IN_MINUTE); - } -} - void crm_time_add_hours(crm_time_t *dt, int value) { @@ -2647,5 +2654,11 @@ crm_time_add_seconds(crm_time_t *dt, int value) pcmk__time_add_seconds(dt, value); } +void +crm_time_add_minutes(crm_time_t *dt, int value) +{ + add_minutes(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From 87c0c8b2f6e6196bf8dbf40a80d2e8671ab938a0 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 22 Jul 2026 15:38:45 -0700 Subject: [PATCH 17/26] Low: libcrmcommon: Avoid overflow in crm_time_add_hours() Previously, the (value * SECONDS_IN_HOUR) computation could overflow. This is not the most efficient implementation; we could avoid the for loops in the common case where the multiplication does not overflow. However, that seems to me like premature optimization. Simplicity and readability seem more important than here. Signed-off-by: Reid Wahl --- lib/common/iso8601.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index b87212dbe6b..07fc5f4176e 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1928,7 +1928,13 @@ crm_time_add_months(crm_time_t *dt, int value) void crm_time_add_hours(crm_time_t *dt, int value) { - pcmk__time_add_seconds(dt, value * SECONDS_IN_HOUR); + for (; value > 0; value--) { + pcmk__time_add_seconds(dt, SECONDS_IN_HOUR); + } + + for (; value < 0; value++) { + pcmk__time_add_seconds(dt, -SECONDS_IN_HOUR); + } } void From 32beaeb02f920f8b999fa0d496b62bca82a0fbb1 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:25:08 -0700 Subject: [PATCH 18/26] API: libcrmcommon: Deprecate crm_time_add_hours() External callers have no need to add hours to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 39 +++++++++++++++++++---------- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 18b4be84b75..330f0439c51 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* All crm_time_add_... functions support negative values */ -void crm_time_add_hours(crm_time_t * dt, int value); void crm_time_add_days(crm_time_t * dt, int value); void crm_time_add_weeks(crm_time_t * dt, int value); void crm_time_add_months(crm_time_t * dt, int value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 54c058f4f69..3d1c02981f6 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -160,6 +160,9 @@ void crm_time_add_seconds(crm_time_t *dt, int value); //! \deprecated Do not use void crm_time_add_minutes(crm_time_t *dt, int value); +//! \deprecated Do not use +void crm_time_add_hours(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 07fc5f4176e..3ac8ab9abb6 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1597,6 +1597,25 @@ pcmk__time_component_attr(enum pcmk__time_component component) } } +/*! + * \internal + * \brief Add a given number of hours to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of hours to add (can be negative to subtract) + */ +static void +add_hours(crm_time_t *dt, int value) +{ + for (; value > 0; value--) { + pcmk__time_add_seconds(dt, SECONDS_IN_HOUR); + } + + for (; value < 0; value++) { + pcmk__time_add_seconds(dt, -SECONDS_IN_HOUR); + } +} + /*! * \internal * \brief Add a given number of minutes to a time object @@ -1643,7 +1662,7 @@ component_fn(enum pcmk__time_component component) return crm_time_add_days; case pcmk__time_hours: - return crm_time_add_hours; + return add_hours; case pcmk__time_minutes: return add_minutes; @@ -1925,18 +1944,6 @@ crm_time_add_months(crm_time_t *dt, int value) dt->days = get_ordinal_days(year, month, day); } -void -crm_time_add_hours(crm_time_t *dt, int value) -{ - for (; value > 0; value--) { - pcmk__time_add_seconds(dt, SECONDS_IN_HOUR); - } - - for (; value < 0; value++) { - pcmk__time_add_seconds(dt, -SECONDS_IN_HOUR); - } -} - void crm_time_add_weeks(crm_time_t *dt, int value) { @@ -2666,5 +2673,11 @@ crm_time_add_minutes(crm_time_t *dt, int value) add_minutes(dt, value); } +void +crm_time_add_hours(crm_time_t *dt, int value) +{ + add_hours(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From d65e8db38982b861a1ff2281fbb191a7fcab0a90 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:31:56 -0700 Subject: [PATCH 19/26] Refactor: libcrmcommon: New pcmk__time_add_days() To replace crm_time_add_days(). Signed-off-by: Reid Wahl --- lib/common/crmcommon_private.h | 3 + lib/common/iso8601.c | 91 +++++++++++-------- lib/common/tests/iso8601/Makefile.am | 4 +- ...days_test.c => pcmk__time_add_days_test.c} | 6 +- 4 files changed, 62 insertions(+), 42 deletions(-) rename lib/common/tests/iso8601/{crm_time_add_days_test.c => pcmk__time_add_days_test.c} (97%) diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h index 368c53cf8a9..848cf072b10 100644 --- a/lib/common/crmcommon_private.h +++ b/lib/common/crmcommon_private.h @@ -208,6 +208,9 @@ enum pcmk__time_component { pcmk__time_seconds, }; +G_GNUC_INTERNAL +void pcmk__time_add_days(crm_time_t *dt, int value); + G_GNUC_INTERNAL void pcmk__time_add_seconds(crm_time_t *dt, int value); diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 3ac8ab9abb6..4265a438870 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -357,6 +357,47 @@ seconds_to_hms(int seconds_i, uint32_t *hours, uint32_t *minutes, } } +/*! + * \internal + * \brief Add days to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of days to add (can be negative to subtract) + */ +void +pcmk__time_add_days(crm_time_t *dt, int value) +{ + pcmk__assert(dt != NULL); + + if (value > 0) { + while ((dt->days + (long long) value) > year_days(dt->years)) { + if (dt->years == INT_MAX) { + // Clip to latest we can handle + dt->days = year_days(dt->years); + return; + } + + value -= year_days(dt->years); + dt->years++; + } + + } else if (value < 0) { + const int min_days = dt->duration? 0 : 1; + + while ((dt->days + (long long) value) < min_days) { + if (dt->years <= 1) { + dt->days = 1; // Clip to earliest we can handle (no BCE) + return; + } + + dt->years--; + value += year_days(dt->years); + } + } + + dt->days += value; +} + /*! * \internal * \brief Parse the time portion of an ISO 8601 date/time string @@ -406,7 +447,7 @@ parse_time(const char *time_str, crm_time_t *a_time) if (a_time->seconds == SECONDS_IN_DAY) { // 24:00:00 == 00:00:00 of next day a_time->seconds = 0; - crm_time_add_days(a_time, 1); + pcmk__time_add_days(a_time, 1); } return true; } @@ -571,15 +612,15 @@ parse_date(const char *date_str) year, jan1, week, day, date_str); dt->years = year; - crm_time_add_days(dt, (week - 1) * 7); + pcmk__time_add_days(dt, (week - 1) * 7); if (jan1 <= 4) { - crm_time_add_days(dt, 1 - jan1); + pcmk__time_add_days(dt, 1 - jan1); } else { - crm_time_add_days(dt, 8 - jan1); + pcmk__time_add_days(dt, 8 - jan1); } - crm_time_add_days(dt, day); + pcmk__time_add_days(dt, day); } goto parse_time_segment; } @@ -641,7 +682,7 @@ pcmk__time_add_seconds(crm_time_t *dt, int value) dt->seconds += SECONDS_IN_DAY; } - crm_time_add_days(dt, days); + pcmk__time_add_days(dt, days); } // Return value is guaranteed not to be NULL @@ -1551,7 +1592,7 @@ pcmk__time_add(const crm_time_t *dt, const crm_time_t *value) crm_time_add_years(answer, utc->years); crm_time_add_months(answer, utc->months); - crm_time_add_days(answer, utc->days); + pcmk__time_add_days(answer, utc->days); pcmk__time_add_seconds(answer, utc->seconds); free(utc); @@ -1659,7 +1700,7 @@ component_fn(enum pcmk__time_component component) return crm_time_add_weeks; case pcmk__time_days: - return crm_time_add_days; + return pcmk__time_add_days; case pcmk__time_hours: return add_hours; @@ -1744,10 +1785,10 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) crm_time_add_months(result, -utc->months); if (utc->days == INT_MIN) { - crm_time_add_days(result, -1); + pcmk__time_add_days(result, -1); utc->days++; } - crm_time_add_days(result, -utc->days); + pcmk__time_add_days(result, -utc->days); if (utc->seconds == INT_MIN) { pcmk__time_add_seconds(result, -1); @@ -1876,33 +1917,7 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) void crm_time_add_days(crm_time_t *dt, int value) { - pcmk__assert(dt != NULL); - - pcmk__trace("Adding %d days to %.4d-%.3d", value, dt->years, dt->days); - - if (value > 0) { - while ((dt->days + (long long) value) > year_days(dt->years)) { - if (dt->years == INT_MAX) { - // Clip to latest we can handle - dt->days = year_days(dt->years); - return; - } - value -= year_days(dt->years); - dt->years++; - } - } else if (value < 0) { - const int min_days = dt->duration? 0 : 1; - - while ((dt->days + (long long) value) < min_days) { - if (dt->years <= 1) { - dt->days = 1; // Clip to earliest we can handle (no BCE) - return; - } - dt->years--; - value += year_days(dt->years); - } - } - dt->days += value; + pcmk__time_add_days(dt, value); } void @@ -1947,7 +1962,7 @@ crm_time_add_months(crm_time_t *dt, int value) void crm_time_add_weeks(crm_time_t *dt, int value) { - crm_time_add_days(dt, value * 7); + pcmk__time_add_days(dt, value * 7); } void diff --git a/lib/common/tests/iso8601/Makefile.am b/lib/common/tests/iso8601/Makefile.am index c320fb59ca8..873accf45f0 100644 --- a/lib/common/tests/iso8601/Makefile.am +++ b/lib/common/tests/iso8601/Makefile.am @@ -12,11 +12,11 @@ include $(top_srcdir)/mk/tap.mk include $(top_srcdir)/mk/unittest.mk # Add "_test" to the end of all test program names to simplify .gitignore. -check_PROGRAMS = crm_time_add_days_test -check_PROGRAMS += crm_time_add_years_test +check_PROGRAMS = crm_time_add_years_test check_PROGRAMS += pcmk__add_time_from_xml_test check_PROGRAMS += pcmk__readable_interval_test check_PROGRAMS += pcmk__set_time_if_earlier_test +check_PROGRAMS += pcmk__time_add_days_test check_PROGRAMS += pcmk__time_add_seconds_test check_PROGRAMS += pcmk__time_format_hr_test check_PROGRAMS += pcmk__time_parse_duration_test diff --git a/lib/common/tests/iso8601/crm_time_add_days_test.c b/lib/common/tests/iso8601/pcmk__time_add_days_test.c similarity index 97% rename from lib/common/tests/iso8601/crm_time_add_days_test.c rename to lib/common/tests/iso8601/pcmk__time_add_days_test.c index 21b1106e796..6efaab17d43 100644 --- a/lib/common/tests/iso8601/crm_time_add_days_test.c +++ b/lib/common/tests/iso8601/pcmk__time_add_days_test.c @@ -16,6 +16,8 @@ #include +#include "crmcommon_private.h" // pcmk__time_add_days + static void assert_add_days(const char *orig_date_time, int days, const char *expected_date_time) @@ -26,7 +28,7 @@ assert_add_days(const char *orig_date_time, int days, assert_non_null(orig); assert_non_null(expected); - crm_time_add_days(orig, days); + pcmk__time_add_days(orig, days); assert_int_equal(pcmk__time_compare(orig, expected), 0); free(orig); @@ -36,7 +38,7 @@ assert_add_days(const char *orig_date_time, int days, static void invalid_argument(void **state) { - pcmk__assert_asserts(crm_time_add_days(NULL, 1)); + pcmk__assert_asserts(pcmk__time_add_days(NULL, 1)); } static void From 7c0d6a3caea42148735ec9c24d833f6d0d275f64 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Thu, 30 Apr 2026 23:33:34 -0700 Subject: [PATCH 20/26] API: libcrmcommon: Deprecate crm_time_add_days() External callers have no need to add days to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 18 ++++++------------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 330f0439c51..bc94822a33d 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* All crm_time_add_... functions support negative values */ -void crm_time_add_days(crm_time_t * dt, int value); void crm_time_add_weeks(crm_time_t * dt, int value); void crm_time_add_months(crm_time_t * dt, int value); void crm_time_add_years(crm_time_t * dt, int value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 3d1c02981f6..a1871dd5049 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -163,6 +163,9 @@ void crm_time_add_minutes(crm_time_t *dt, int value); //! \deprecated Do not use void crm_time_add_hours(crm_time_t *dt, int value); +//! \deprecated Do not use +void crm_time_add_days(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 4265a438870..06bb9a8f355 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1908,18 +1908,6 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) return rc; } -/*! - * \brief Add days to a date/time - * - * \param[in,out] dt Time to modify - * \param[in] value Number of days to add (may be negative to subtract) - */ -void -crm_time_add_days(crm_time_t *dt, int value) -{ - pcmk__time_add_days(dt, value); -} - void crm_time_add_months(crm_time_t *dt, int value) { @@ -2694,5 +2682,11 @@ crm_time_add_hours(crm_time_t *dt, int value) add_hours(dt, value); } +void +crm_time_add_days(crm_time_t *dt, int value) +{ + pcmk__time_add_days(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From 42eeb92409f2fe228e01c7f3fde62c06a8b4014d Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Wed, 22 Jul 2026 15:46:05 -0700 Subject: [PATCH 21/26] Low: libcrmcommon: Avoid overflow in crm_time_add_weeks() Previously, the (value * 7) computation could overflow. This is not the most efficient implementation; we could avoid the for loops in the common case where the multiplication does not overflow. However, that seems to me like premature optimization. Simplicity and readability seem more important than here. Signed-off-by: Reid Wahl --- lib/common/iso8601.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 06bb9a8f355..83f5743de09 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -54,6 +54,7 @@ #define SECONDS_IN_HOUR (SECONDS_IN_MINUTE * MINUTES_IN_HOUR) #define HOURS_IN_DAY 24 #define SECONDS_IN_DAY (SECONDS_IN_HOUR * HOURS_IN_DAY) +#define DAYS_IN_WEEK 7 #define BEGIN_VALID_RANGE_S "0001-01-01T00:00:00" #define END_VALID_RANGE_S "9999-12-31T23:59:59" @@ -181,7 +182,7 @@ year_days(int year) * YY = (Y-1) % 100 * C = (Y-1) - YY * G = YY + YY/4 - * Jan1Weekday = 1 + (((((C / 100) % 4) x 5) + G) % 7) + * Jan1Weekday = 1 + (((((C / 100) % 4) x 5) + G) % DAYS_IN_WEEK) */ static int jan1_day_of_week(int year) @@ -189,7 +190,7 @@ jan1_day_of_week(int year) int YY = (year - 1) % 100; int C = (year - 1) - YY; int G = YY + YY / 4; - int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % 7); + int jan1 = 1 + (((((C / 100) % 4) * 5) + G) % DAYS_IN_WEEK); pcmk__trace("YY=%d, C=%d, G=%d", YY, C, G); pcmk__trace("January 1 %.4d: %d", year, jan1); @@ -612,7 +613,7 @@ parse_date(const char *date_str) year, jan1, week, day, date_str); dt->years = year; - pcmk__time_add_days(dt, (week - 1) * 7); + pcmk__time_add_days(dt, (week - 1) * DAYS_IN_WEEK); if (jan1 <= 4) { pcmk__time_add_days(dt, 1 - jan1); @@ -967,7 +968,7 @@ pcmk__time_get_ywd(const crm_time_t *dt, uint32_t *y, uint32_t *w, uint32_t *d) /* 6. Find the Weekday for Y M D */ h = dt->days + jan1 - 1; - *d = 1 + ((h - 1) % 7); + *d = 1 + ((h - 1) % DAYS_IN_WEEK); /* 7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53 */ if (dt->days <= (8 - jan1) && jan1 > 4) { @@ -994,9 +995,9 @@ pcmk__time_get_ywd(const crm_time_t *dt, uint32_t *y, uint32_t *w, uint32_t *d) /* 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53 */ if (year_num == dt->years) { - int j = dt->days + (7 - *d) + (jan1 - 1); + int j = dt->days + (DAYS_IN_WEEK - *d) + (jan1 - 1); - *w = j / 7; + *w = j / DAYS_IN_WEEK; if (jan1 > 4) { *w -= 1; } @@ -1950,7 +1951,13 @@ crm_time_add_months(crm_time_t *dt, int value) void crm_time_add_weeks(crm_time_t *dt, int value) { - pcmk__time_add_days(dt, value * 7); + for (; value > 0; value--) { + pcmk__time_add_days(dt, DAYS_IN_WEEK); + } + + for (; value < 0; value++) { + pcmk__time_add_days(dt, -DAYS_IN_WEEK); + } } void From edba1a20644220ad4ae55276ecb366ac1b3578e4 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 1 May 2026 00:24:14 -0700 Subject: [PATCH 22/26] API: libcrmcommon: Deprecate crm_time_add_weeks() External callers have no need to add weeks to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 40 +++++++++++++++++++---------- 3 files changed, 29 insertions(+), 15 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index bc94822a33d..665b65952bb 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* All crm_time_add_... functions support negative values */ -void crm_time_add_weeks(crm_time_t * dt, int value); void crm_time_add_months(crm_time_t * dt, int value); void crm_time_add_years(crm_time_t * dt, int value); diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index a1871dd5049..3234869a386 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -166,6 +166,9 @@ void crm_time_add_hours(crm_time_t *dt, int value); //! \deprecated Do not use void crm_time_add_days(crm_time_t *dt, int value); +//! \deprecated Do not use +void crm_time_add_weeks(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 83f5743de09..c774e34cac7 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1639,6 +1639,25 @@ pcmk__time_component_attr(enum pcmk__time_component component) } } +/*! + * \internal + * \brief Add a given number of weeks to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of weeks to add (can be negative to subtract) + */ +static void +add_weeks(crm_time_t *dt, int value) +{ + for (; value > 0; value--) { + pcmk__time_add_days(dt, DAYS_IN_WEEK); + } + + for (; value < 0; value++) { + pcmk__time_add_days(dt, -DAYS_IN_WEEK); + } +} + /*! * \internal * \brief Add a given number of hours to a time object @@ -1698,7 +1717,7 @@ component_fn(enum pcmk__time_component component) return crm_time_add_months; case pcmk__time_weeks: - return crm_time_add_weeks; + return add_weeks; case pcmk__time_days: return pcmk__time_add_days; @@ -1715,7 +1734,6 @@ component_fn(enum pcmk__time_component component) default: return NULL; } - } /*! @@ -1948,18 +1966,6 @@ crm_time_add_months(crm_time_t *dt, int value) dt->days = get_ordinal_days(year, month, day); } -void -crm_time_add_weeks(crm_time_t *dt, int value) -{ - for (; value > 0; value--) { - pcmk__time_add_days(dt, DAYS_IN_WEEK); - } - - for (; value < 0; value++) { - pcmk__time_add_days(dt, -DAYS_IN_WEEK); - } -} - void crm_time_add_years(crm_time_t *dt, int value) { @@ -2695,5 +2701,11 @@ crm_time_add_days(crm_time_t *dt, int value) pcmk__time_add_days(dt, value); } +void +crm_time_add_weeks(crm_time_t *dt, int value) +{ + add_weeks(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From 700a9012924cd96cac0bbaed41d28c3d649317ab Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 1 May 2026 00:32:47 -0700 Subject: [PATCH 23/26] API: libcrmcommon: Deprecate crm_time_add_months() External callers have no need to add months to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 1 - include/crm/common/iso8601_compat.h | 3 + lib/common/iso8601.c | 99 ++++++++++++++++------------- 3 files changed, 59 insertions(+), 44 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 665b65952bb..9bf76f8a6a8 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -54,7 +54,6 @@ typedef struct crm_time_s crm_time_t; crm_time_t *crm_time_new(const char *string); /* All crm_time_add_... functions support negative values */ -void crm_time_add_months(crm_time_t * dt, int value); void crm_time_add_years(crm_time_t * dt, int value); #ifdef __cplusplus diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index 3234869a386..fb1cb89f95b 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -169,6 +169,9 @@ void crm_time_add_days(crm_time_t *dt, int value); //! \deprecated Do not use void crm_time_add_weeks(crm_time_t *dt, int value); +//! \deprecated Do not use +void crm_time_add_months(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index c774e34cac7..0ba773e519b 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1566,6 +1566,52 @@ pcmk__copy_timet(time_t source_sec) return target; } +/*! + * \internal + * \brief Add a given number of months to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of months to add (can be negative to subtract) + */ +static void +add_months(crm_time_t *dt, int value) +{ + uint32_t year = 0; + uint32_t month = 0; + uint32_t day = 0; + int days_in_month = 0; + + pcmk__time_get_ymd(dt, &year, &month, &day); + + if (value > 0) { + for (int i = value; i > 0; i--) { + month++; + if (month == 13) { + month = 1; + year++; + } + } + } else { + for (int i = value; i < 0; i++) { + month--; + if (month == 0) { + month = 12; + year--; + } + } + } + + days_in_month = days_in_month_year(month, year); + + if (days_in_month < day) { + // Preserve day-of-month unless the month doesn't have enough days + day = days_in_month; + } + + dt->years = year; + dt->days = get_ordinal_days(year, month, day); +} + /*! * \internal * \brief Add one time object to another and return the sum @@ -1592,7 +1638,7 @@ pcmk__time_add(const crm_time_t *dt, const crm_time_t *value) utc = copy_time_to_utc(value); crm_time_add_years(answer, utc->years); - crm_time_add_months(answer, utc->months); + add_months(answer, utc->months); pcmk__time_add_days(answer, utc->days); pcmk__time_add_seconds(answer, utc->seconds); @@ -1714,7 +1760,7 @@ component_fn(enum pcmk__time_component component) return crm_time_add_years; case pcmk__time_months: - return crm_time_add_months; + return add_months; case pcmk__time_weeks: return add_weeks; @@ -1798,10 +1844,10 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) crm_time_add_years(result, -utc->years); if (utc->months == INT_MIN) { - crm_time_add_months(result, -1); + add_months(result, -1); utc->months++; } - crm_time_add_months(result, -utc->months); + add_months(result, -utc->months); if (utc->days == INT_MIN) { pcmk__time_add_days(result, -1); @@ -1927,45 +1973,6 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) return rc; } -void -crm_time_add_months(crm_time_t *dt, int value) -{ - uint32_t year = 0; - uint32_t month = 0; - uint32_t day = 0; - int days_in_month = 0; - - pcmk__time_get_ymd(dt, &year, &month, &day); - - if (value > 0) { - for (int i = value; i > 0; i--) { - month++; - if (month == 13) { - month = 1; - year++; - } - } - } else { - for (int i = value; i < 0; i++) { - month--; - if (month == 0) { - month = 12; - year--; - } - } - } - - days_in_month = days_in_month_year(month, year); - - if (days_in_month < day) { - // Preserve day-of-month unless the month doesn't have enough days - day = days_in_month; - } - - dt->years = year; - dt->days = get_ordinal_days(year, month, day); -} - void crm_time_add_years(crm_time_t *dt, int value) { @@ -2707,5 +2714,11 @@ crm_time_add_weeks(crm_time_t *dt, int value) add_weeks(dt, value); } +void +crm_time_add_months(crm_time_t *dt, int value) +{ + add_months(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From cb01a788c0508788ca719cd8ed23e43d5b778561 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 1 May 2026 00:38:26 -0700 Subject: [PATCH 24/26] Refactor: libcrmcommon: New pcmk__time_add_years() To replace crm_time_add_years(). Signed-off-by: Reid Wahl --- lib/common/crmcommon_private.h | 3 ++ lib/common/iso8601.c | 45 ++++++++++++------- lib/common/tests/iso8601/Makefile.am | 4 +- ...ars_test.c => pcmk__time_add_years_test.c} | 6 ++- 4 files changed, 38 insertions(+), 20 deletions(-) rename lib/common/tests/iso8601/{crm_time_add_years_test.c => pcmk__time_add_years_test.c} (92%) diff --git a/lib/common/crmcommon_private.h b/lib/common/crmcommon_private.h index 848cf072b10..685a8043435 100644 --- a/lib/common/crmcommon_private.h +++ b/lib/common/crmcommon_private.h @@ -236,6 +236,9 @@ int pcmk__add_time_from_xml(crm_time_t *t, enum pcmk__time_component component, G_GNUC_INTERNAL void pcmk__set_time_if_earlier(crm_time_t *target, const crm_time_t *source); +G_GNUC_INTERNAL +void pcmk__time_add_years(crm_time_t *dt, int value); + /* * IPC diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index 0ba773e519b..be76c873899 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1511,6 +1511,29 @@ pcmk__set_time_if_earlier(crm_time_t *target, const crm_time_t *source) pcmk__time_log(LOG_TRACE, "target", target, flags); } +/*! + * \internal + * \brief Add years to a time object + * + * \param[in,out] dt Time object + * \param[in] value Number of years to add (can be negative to subtract) + */ +void +pcmk__time_add_years(crm_time_t *dt, int value) +{ + pcmk__assert(dt != NULL); + + if ((value > 0) && ((dt->years + (long long) value) > INT_MAX)) { + dt->years = INT_MAX; + + } else if ((value < 0) && ((dt->years + (long long) value) < 1)) { + dt->years = 1; // Clip to earliest we can handle (no BCE) + + } else { + dt->years += value; + } +} + /*! * \internal * \brief Convert a \c time_t time to a \c crm_time_t time @@ -1533,7 +1556,7 @@ pcmk__copy_timet(time_t source_sec) if (source->tm_year > 0) { // Years since 1900 target->years = 1900; - crm_time_add_years(target, source->tm_year); + pcmk__time_add_years(target, source->tm_year); } if (source->tm_yday >= 0) { @@ -1637,7 +1660,7 @@ pcmk__time_add(const crm_time_t *dt, const crm_time_t *value) answer = pcmk__time_copy(dt); utc = copy_time_to_utc(value); - crm_time_add_years(answer, utc->years); + pcmk__time_add_years(answer, utc->years); add_months(answer, utc->months); pcmk__time_add_days(answer, utc->days); pcmk__time_add_seconds(answer, utc->seconds); @@ -1757,7 +1780,7 @@ component_fn(enum pcmk__time_component component) { switch (component) { case pcmk__time_years: - return crm_time_add_years; + return pcmk__time_add_years; case pcmk__time_months: return add_months; @@ -1838,10 +1861,10 @@ subtract_time(const crm_time_t *dt1, const crm_time_t *dt2, bool as_duration) // Avoid overflow when negating INT_MIN in calculations below if (utc->years == INT_MIN) { - crm_time_add_years(result, -1); + pcmk__time_add_years(result, -1); utc->years++; } - crm_time_add_years(result, -utc->years); + pcmk__time_add_years(result, -utc->years); if (utc->months == INT_MIN) { add_months(result, -1); @@ -1976,17 +1999,7 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) void crm_time_add_years(crm_time_t *dt, int value) { - pcmk__assert(dt != NULL); - - if ((value > 0) && ((dt->years + (long long) value) > INT_MAX)) { - dt->years = INT_MAX; - - } else if ((value < 0) && ((dt->years + (long long) value) < 1)) { - dt->years = 1; // Clip to earliest we can handle (no BCE) - - } else { - dt->years += value; - } + pcmk__time_add_years(dt, value); } static void diff --git a/lib/common/tests/iso8601/Makefile.am b/lib/common/tests/iso8601/Makefile.am index 873accf45f0..77e947fa7bf 100644 --- a/lib/common/tests/iso8601/Makefile.am +++ b/lib/common/tests/iso8601/Makefile.am @@ -12,12 +12,12 @@ include $(top_srcdir)/mk/tap.mk include $(top_srcdir)/mk/unittest.mk # Add "_test" to the end of all test program names to simplify .gitignore. -check_PROGRAMS = crm_time_add_years_test -check_PROGRAMS += pcmk__add_time_from_xml_test +check_PROGRAMS = pcmk__add_time_from_xml_test check_PROGRAMS += pcmk__readable_interval_test check_PROGRAMS += pcmk__set_time_if_earlier_test check_PROGRAMS += pcmk__time_add_days_test check_PROGRAMS += pcmk__time_add_seconds_test +check_PROGRAMS += pcmk__time_add_years_test check_PROGRAMS += pcmk__time_format_hr_test check_PROGRAMS += pcmk__time_parse_duration_test diff --git a/lib/common/tests/iso8601/crm_time_add_years_test.c b/lib/common/tests/iso8601/pcmk__time_add_years_test.c similarity index 92% rename from lib/common/tests/iso8601/crm_time_add_years_test.c rename to lib/common/tests/iso8601/pcmk__time_add_years_test.c index f0fa451accb..c4110c04c69 100644 --- a/lib/common/tests/iso8601/crm_time_add_years_test.c +++ b/lib/common/tests/iso8601/pcmk__time_add_years_test.c @@ -16,6 +16,8 @@ #include +#include "crmcommon_private.h" // pcmk__time_add_days + static void assert_add_years(const char *orig_date_time, int years, const char *expected_date_time) @@ -26,7 +28,7 @@ assert_add_years(const char *orig_date_time, int years, assert_non_null(orig); assert_non_null(expected); - crm_time_add_years(orig, years); + pcmk__time_add_years(orig, years); assert_int_equal(pcmk__time_compare(orig, expected), 0); free(orig); @@ -36,7 +38,7 @@ assert_add_years(const char *orig_date_time, int years, static void invalid_argument(void **state) { - pcmk__assert_asserts(crm_time_add_years(NULL, 1)); + pcmk__assert_asserts(pcmk__time_add_years(NULL, 1)); } static void From 6fbc8180a88858c8e386d844209744b787c94ad5 Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 1 May 2026 00:39:29 -0700 Subject: [PATCH 25/26] API: libcrmcommon: Deprecate crm_time_add_years() External callers have no need to add years to a crm_time_t object. Pacemaker should not be used for general-purpose date/time manipulation. Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 3 --- include/crm/common/iso8601_compat.h | 3 +++ lib/common/iso8601.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index 9bf76f8a6a8..c34af98d331 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -53,9 +53,6 @@ typedef struct crm_time_s crm_time_t; */ crm_time_t *crm_time_new(const char *string); -/* All crm_time_add_... functions support negative values */ -void crm_time_add_years(crm_time_t * dt, int value); - #ifdef __cplusplus } #endif diff --git a/include/crm/common/iso8601_compat.h b/include/crm/common/iso8601_compat.h index fb1cb89f95b..5ef6f6915b2 100644 --- a/include/crm/common/iso8601_compat.h +++ b/include/crm/common/iso8601_compat.h @@ -172,6 +172,9 @@ void crm_time_add_weeks(crm_time_t *dt, int value); //! \deprecated Do not use void crm_time_add_months(crm_time_t *dt, int value); +//! \deprecated Do not use +void crm_time_add_years(crm_time_t *dt, int value); + #ifdef __cplusplus } #endif diff --git a/lib/common/iso8601.c b/lib/common/iso8601.c index be76c873899..398ed9eb2a8 100644 --- a/lib/common/iso8601.c +++ b/lib/common/iso8601.c @@ -1996,12 +1996,6 @@ pcmk__time_compare(const crm_time_t *time1, const crm_time_t *time2) return rc; } -void -crm_time_add_years(crm_time_t *dt, int value) -{ - pcmk__time_add_years(dt, value); -} - static void ha_get_tm_time(struct tm *target, const crm_time_t *source) { @@ -2733,5 +2727,11 @@ crm_time_add_months(crm_time_t *dt, int value) add_months(dt, value); } +void +crm_time_add_years(crm_time_t *dt, int value) +{ + pcmk__time_add_years(dt, value); +} + // LCOV_EXCL_STOP // End deprecated API From eaea3d40681c0bc2786ed7111585282c8d13266d Mon Sep 17 00:00:00 2001 From: Reid Wahl Date: Fri, 1 May 2026 00:41:57 -0700 Subject: [PATCH 26/26] Refactor: libcrmcommon: Drop unused includes from iso8601.h Signed-off-by: Reid Wahl --- include/crm/common/iso8601.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/crm/common/iso8601.h b/include/crm/common/iso8601.h index c34af98d331..caf807b08f6 100644 --- a/include/crm/common/iso8601.h +++ b/include/crm/common/iso8601.h @@ -10,11 +10,6 @@ #ifndef PCMK__CRM_COMMON_ISO8601__H #define PCMK__CRM_COMMON_ISO8601__H -#include -#include // bool -#include // uint32_t -#include - #ifdef __cplusplus extern "C" { #endif