2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-03 08:05:21 +00:00

Add isccfg duration utility functions

Add function isccfg_duration_toseconds and isccfg_parse_duration to get
rid of code duplication.
This commit is contained in:
Matthijs Mekking
2022-06-27 16:31:43 +02:00
parent 8e18fa5874
commit d8dae61832
4 changed files with 77 additions and 43 deletions

View File

@@ -28,6 +28,8 @@
#include <isc/string.h>
#include <isc/util.h>
#include <dns/ttl.h>
#include <isccfg/duration.h>
/*
@@ -153,3 +155,48 @@ isccfg_duration_fromtext(isc_textregion_t *source,
duration->iso8601 = true;
return (ISC_R_SUCCESS);
}
isc_result_t
isccfg_parse_duration(isc_textregion_t *source, isccfg_duration_t *duration) {
isc_result_t result;
REQUIRE(duration != NULL);
duration->unlimited = false;
result = isccfg_duration_fromtext(source, duration);
if (result == ISC_R_BADNUMBER) {
/* Fallback to dns_ttl_fromtext. */
uint32_t ttl;
result = dns_ttl_fromtext(source, &ttl);
if (result == ISC_R_SUCCESS) {
/*
* With dns_ttl_fromtext() the information on optional
* units is lost, and is treated as seconds from now on.
*/
duration->iso8601 = false;
duration->parts[6] = ttl;
}
}
return (result);
}
uint32_t
isccfg_duration_toseconds(const isccfg_duration_t *duration) {
uint32_t seconds = 0;
REQUIRE(duration != NULL);
seconds += duration->parts[6]; /* Seconds */
seconds += duration->parts[5] * 60; /* Minutes */
seconds += duration->parts[4] * 3600; /* Hours */
seconds += duration->parts[3] * 86400; /* Days */
seconds += duration->parts[2] * 86400 * 7; /* Weeks */
/*
* The below additions are not entirely correct
* because days may very per month and per year.
*/
seconds += duration->parts[1] * 86400 * 31; /* Months */
seconds += duration->parts[0] * 86400 * 365; /* Years */
return (seconds);
}

View File

@@ -55,4 +55,29 @@ isccfg_duration_fromtext(isc_textregion_t *source, isccfg_duration_t *duration);
*\li DNS_R_BADNUMBER
*/
isc_result_t
isccfg_parse_duration(isc_textregion_t *source, isccfg_duration_t *duration);
/*%<
* Converts a duration string to a ISO 8601 duration.
* If the string does not start with a P (or p), fall back to TTL-style value.
* In that case the duration will be treated in seconds only.
*
* Returns:
*\li ISC_R_SUCCESS
*\li DNS_R_BADNUMBER
*\li DNS_R_BADTTL
*/
uint32_t
isccfg_duration_toseconds(const isccfg_duration_t *duration);
/*%<
* Converts an ISO 8601 duration to seconds.
* The conversion is approximate:
* - Months will be treated as 31 days.
* - Years will be treated as 365 days.
*
* Returns:
*\li The duration in seconds.
*/
ISC_LANG_ENDDECLS

View File

@@ -65,20 +65,9 @@ parse_duration(const char *str) {
DE_CONST(str, tr.base);
tr.length = strlen(tr.base);
result = isccfg_duration_fromtext(&tr, &duration);
if (result == ISC_R_BADNUMBER) {
/* Fallback to dns_ttl_fromtext. */
(void)dns_ttl_fromtext(&tr, &time);
return (time);
}
result = isccfg_parse_duration(&tr, &duration);
if (result == ISC_R_SUCCESS) {
time += duration.parts[6]; /* Seconds */
time += duration.parts[5] * 60; /* Minutes */
time += duration.parts[4] * 3600; /* Hours */
time += duration.parts[3] * 86400; /* Days */
time += duration.parts[2] * 86400 * 7; /* Weaks */
time += duration.parts[1] * 86400 * 31; /* Months */
time += duration.parts[0] * 86400 * 365; /* Years */
time = isccfg_duration_toseconds(&duration);
}
return (time);
}

View File

@@ -1139,19 +1139,7 @@ cfg_obj_isduration(const cfg_obj_t *obj) {
uint32_t
cfg_obj_asduration(const cfg_obj_t *obj) {
REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_duration);
uint32_t duration = 0;
duration += obj->value.duration.parts[6]; /* Seconds */
duration += obj->value.duration.parts[5] * 60; /* Minutes */
duration += obj->value.duration.parts[4] * 3600; /* Hours */
duration += obj->value.duration.parts[3] * 86400; /* Days */
duration += obj->value.duration.parts[2] * 86400 * 7; /* Weaks */
/*
* The below additions are not entirely correct
* because days may very per month and per year.
*/
duration += obj->value.duration.parts[1] * 86400 * 31; /* Months */
duration += obj->value.duration.parts[0] * 86400 * 365; /* Years */
return (duration);
return isccfg_duration_toseconds(&(obj->value.duration));
}
static isc_result_t
@@ -1160,24 +1148,9 @@ parse_duration(cfg_parser_t *pctx, cfg_obj_t **ret) {
cfg_obj_t *obj = NULL;
isccfg_duration_t duration;
duration.unlimited = false;
result = isccfg_duration_fromtext(&pctx->token.value.as_textregion,
result = isccfg_parse_duration(&pctx->token.value.as_textregion,
&duration);
if (result == ISC_R_BADNUMBER) {
/* Fallback to dns_ttl_fromtext. */
uint32_t ttl;
result = dns_ttl_fromtext(&pctx->token.value.as_textregion,
&ttl);
if (result == ISC_R_SUCCESS) {
/*
* With dns_ttl_fromtext() the information on optional
* units is lost, and is treated as seconds from now on.
*/
duration.iso8601 = false;
duration.parts[6] = ttl;
}
}
if (result == ISC_R_RANGE) {
cfg_parser_error(pctx, CFG_LOG_NEAR,
"duration or TTL out of range");