xref: /openbsd-src/usr.bin/dig/lib/dns/ttl.c (revision 1fb015a8af3a7e9b85db2510147a155826ef04d9)
15185a700Sflorian /*
25185a700Sflorian  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian  *
45185a700Sflorian  * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian  * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian  * copyright notice and this permission notice appear in all copies.
75185a700Sflorian  *
85185a700Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian  * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian  */
165185a700Sflorian 
17*1fb015a8Sflorian /* $Id: ttl.c,v 1.6 2020/09/14 08:40:43 florian Exp $ */
185185a700Sflorian 
195185a700Sflorian /*! \file */
205185a700Sflorian 
215185a700Sflorian #include <ctype.h>
225185a700Sflorian #include <stdio.h>
234465bcfbSjsg #include <string.h>
245185a700Sflorian 
255185a700Sflorian #include <isc/buffer.h>
265185a700Sflorian #include <isc/region.h>
275185a700Sflorian #include <isc/util.h>
285185a700Sflorian 
295185a700Sflorian #include <dns/ttl.h>
305185a700Sflorian 
315185a700Sflorian #define RETERR(x) do { \
325185a700Sflorian 	isc_result_t _r = (x); \
335185a700Sflorian 	if (_r != ISC_R_SUCCESS) \
345185a700Sflorian 		return (_r); \
355185a700Sflorian 	} while (0)
365185a700Sflorian 
375185a700Sflorian /*
385185a700Sflorian  * Helper for dns_ttl_totext().
395185a700Sflorian  */
405185a700Sflorian static isc_result_t
ttlfmt(unsigned int t,const char * s,int verbose,int space,isc_buffer_t * target)41*1fb015a8Sflorian ttlfmt(unsigned int t, const char *s, int verbose,
42*1fb015a8Sflorian        int space, isc_buffer_t *target)
435185a700Sflorian {
445185a700Sflorian 	char tmp[60];
455185a700Sflorian 	unsigned int len;
465185a700Sflorian 	isc_region_t region;
475185a700Sflorian 
485185a700Sflorian 	if (verbose)
495185a700Sflorian 		len = snprintf(tmp, sizeof(tmp), "%s%u %s%s",
505185a700Sflorian 			       space ? " " : "",
515185a700Sflorian 			       t, s,
525185a700Sflorian 			       t == 1 ? "" : "s");
535185a700Sflorian 	else
545185a700Sflorian 		len = snprintf(tmp, sizeof(tmp), "%u%c", t, s[0]);
555185a700Sflorian 
565185a700Sflorian 	INSIST(len + 1 <= sizeof(tmp));
575185a700Sflorian 	isc_buffer_availableregion(target, &region);
585185a700Sflorian 	if (len > region.length)
595185a700Sflorian 		return (ISC_R_NOSPACE);
605185a700Sflorian 	memmove(region.base, tmp, len);
615185a700Sflorian 	isc_buffer_add(target, len);
625185a700Sflorian 
635185a700Sflorian 	return (ISC_R_SUCCESS);
645185a700Sflorian }
655185a700Sflorian 
665185a700Sflorian /*
675185a700Sflorian  * Derived from bind8 ns_format_ttl().
685185a700Sflorian  */
695185a700Sflorian isc_result_t
dns_ttl_totext(uint32_t src,int verbose,isc_buffer_t * target)70*1fb015a8Sflorian dns_ttl_totext(uint32_t src, int verbose, isc_buffer_t *target) {
715185a700Sflorian 	unsigned secs, mins, hours, days, weeks, x;
725185a700Sflorian 
735185a700Sflorian 	secs = src % 60;   src /= 60;
745185a700Sflorian 	mins = src % 60;   src /= 60;
755185a700Sflorian 	hours = src % 24;  src /= 24;
765185a700Sflorian 	days = src % 7;    src /= 7;
775185a700Sflorian 	weeks = src;       src = 0;
785185a700Sflorian 	POST(src);
795185a700Sflorian 
805185a700Sflorian 	x = 0;
815185a700Sflorian 	if (weeks != 0) {
82*1fb015a8Sflorian 		RETERR(ttlfmt(weeks, "week", verbose, (x > 0), target));
835185a700Sflorian 		x++;
845185a700Sflorian 	}
855185a700Sflorian 	if (days != 0) {
86*1fb015a8Sflorian 		RETERR(ttlfmt(days, "day", verbose, (x > 0), target));
875185a700Sflorian 		x++;
885185a700Sflorian 	}
895185a700Sflorian 	if (hours != 0) {
90*1fb015a8Sflorian 		RETERR(ttlfmt(hours, "hour", verbose, (x > 0), target));
915185a700Sflorian 		x++;
925185a700Sflorian 	}
935185a700Sflorian 	if (mins != 0) {
94*1fb015a8Sflorian 		RETERR(ttlfmt(mins, "minute", verbose, (x > 0), target));
955185a700Sflorian 		x++;
965185a700Sflorian 	}
975185a700Sflorian 	if (secs != 0 ||
985185a700Sflorian 	    (weeks == 0 && days == 0 && hours == 0 && mins == 0)) {
99*1fb015a8Sflorian 		RETERR(ttlfmt(secs, "second", verbose, (x > 0), target));
1005185a700Sflorian 		x++;
1015185a700Sflorian 	}
1025185a700Sflorian 	INSIST (x > 0);
1035185a700Sflorian 	/*
1045185a700Sflorian 	 * If only a single unit letter is printed, print it
1055185a700Sflorian 	 * in upper case. (Why?  Because BIND 8 does that.
1065185a700Sflorian 	 * Presumably it has a reason.)
1075185a700Sflorian 	 */
1085185a700Sflorian 	if (x == 1 && !verbose) {
1095185a700Sflorian 		isc_region_t region;
1105185a700Sflorian 		/*
1115185a700Sflorian 		 * The unit letter is the last character in the
1125185a700Sflorian 		 * used region of the buffer.
1135185a700Sflorian 		 *
1145185a700Sflorian 		 * toupper() does not need its argument to be masked of cast
1155185a700Sflorian 		 * here because region.base is type unsigned char *.
1165185a700Sflorian 		 */
1175185a700Sflorian 		isc_buffer_usedregion(target, &region);
1185185a700Sflorian 		region.base[region.length - 1] =
1195185a700Sflorian 			toupper(region.base[region.length - 1]);
1205185a700Sflorian 	}
1215185a700Sflorian 	return (ISC_R_SUCCESS);
1225185a700Sflorian }
123