view src/lib/utc-mktime.c @ 22664:fea53c2725c0

director: Fix director_max_parallel_moves/kicks type Should be uint, not time.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 09 Nov 2017 12:24:16 +0200
parents c4584d7dc07e
children cb108f786fb4
line wrap: on
line source

/* Copyright (c) 2007-2017 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "utc-mktime.h"

static int tm_cmp(const struct tm *tm1, const struct tm *tm2)
{
	int diff;

	if ((diff = tm1->tm_year - tm2->tm_year) != 0)
		return diff;
	if ((diff = tm1->tm_mon - tm2->tm_mon) != 0)
		return diff;
	if ((diff = tm1->tm_mday - tm2->tm_mday) != 0)
		return diff;
	if ((diff = tm1->tm_hour - tm2->tm_hour) != 0)
		return diff;
	if ((diff = tm1->tm_min - tm2->tm_min) != 0)
		return diff;
	return tm1->tm_sec - tm2->tm_sec;
}

static inline void adjust_leap_second(struct tm *tm)
{
	if (tm->tm_sec == 60)
		tm->tm_sec = 59;
}

#ifdef HAVE_TIMEGM
/* Normalization done by timegm is considered a failure here, since it means
 * the timestamp is not valid as-is. Leap second 60 is adjusted to 59 before
 * this though. */
time_t utc_mktime(const struct tm *tm)
{
	struct tm leap_adj_tm = *tm;
	adjust_leap_second(&leap_adj_tm);
	struct tm tmp = leap_adj_tm;
	time_t t;

	t = timegm(&tmp);
	if (tm_cmp(&leap_adj_tm, &tmp) != 0)
		return (time_t)-1;
	return t;
}
#else
time_t utc_mktime(const struct tm *tm)
{
	struct tm leap_adj_tm = *tm;
	adjust_leap_second(&leap_adj_tm);
	const struct tm *try_tm;
	time_t t;
	int bits, dir;

	/* we'll do a binary search across the entire valid time_t range.
	   when gmtime()'s output matches the tm parameter, we've found the
	   correct time_t value. this also means that if tm contains invalid
	   values, -1 is returned. */
#ifdef TIME_T_SIGNED
	t = 0;
#else
	t = (time_t)1 << (TIME_T_MAX_BITS - 1);
#endif
	for (bits = TIME_T_MAX_BITS - 2;; bits--) {
		try_tm = gmtime(&t);
		dir = tm_cmp(&leap_adj_tm, try_tm);
		if (dir == 0)
			return t;
		if (bits < 0)
			break;

		if (dir < 0)
			t -= (time_t)1 << bits;
		else
			t += (time_t)1 << bits;
	}

	return (time_t)-1;
}
#endif