Exemple #1
0
static vbi_bool
localtime_tz			(struct tm *		tm,
				 char **		old_tz,
				 time_t			t,
				 const char *		tz)
{
	int saved_errno;

	*old_tz = NULL;

	/* Some system calls below may not set errno on failure. */
	errno = 0;

	if (NULL != tz) {
		if (unlikely (!change_tz (old_tz, tz)))
			return FALSE;
	}

	CLEAR (*tm);

	if ((time_t) -1 == t) {
		if (unlikely ((time_t) -1 == time (&t))) {
			saved_errno = errno;

			/* We do not ignore errors here because the
			   information that TZ wasn't restored seems
			   more important to me. */
			if (unlikely (!restore_tz (old_tz, tz)))
				return FALSE;

			/* time() can fail but POSIX defines no
			   error code. On Linux EFAULT is possible. */
			if (0 == saved_errno)
				errno = VBI_ERR_NO_TIME;
			else
				errno = saved_errno;
			return FALSE;
		}
	}

	if (unlikely (NULL == localtime_r (&t, tm))) {
		saved_errno = errno;

		if (unlikely (!restore_tz (old_tz, tz)))
			return FALSE;

		errno = saved_errno;
		return FALSE;
	}

	return TRUE;
}
Exemple #2
0
/**
 * @internal
 *
 * Replacement for timegm() on non-GNU systems. Note this function is
 * NOT THREAD SAFE because the C library permits the conversion of a
 * broken-down time in an arbitrary time zone only by setting the TZ
 * environment variable. The function may also fail to restore the
 * value of TZ if insufficient memory is available. Don't call this
 * function directly, we #define timegm.
 */
time_t
_vbi_timegm			(struct tm *		tm)
{
	char *old_tz;
	int saved_errno;
	time_t result;

	if (unlikely (!change_tz (&old_tz, "UTC")))
		return (time_t) -1;

	result = mktime (tm);
	if (unlikely (result <= TIME_MIN
		      || result >= TIME_MAX)) {
		saved_errno = EOVERFLOW;
		result = (time_t) -1;
	} else {
		saved_errno = errno;
	}

	if (unlikely (!restore_tz (&old_tz, "UTC")))
		return (time_t) -1;

	errno = saved_errno;
	return result;
}
Exemple #3
0
static uschar *
time_copy(time_t t, uschar * mod)
{
    uschar * cp;
    size_t len = 32;

    if (mod && Ustrcmp(mod, "int") == 0)
        return string_sprintf("%u", (unsigned)t);

    cp = store_get(len);
    if (timestamps_utc)
    {
        uschar * tz = to_tz(US"GMT0");
        len = strftime(CS cp, len, "%b %e %T %Y %Z", gmtime(&t));
        restore_tz(tz);
    }
    else
        len = strftime(CS cp, len, "%b %e %T %Y %Z", localtime(&t));
    return len > 0 ? cp : NULL;
}
Exemple #4
0
/**
 * @param begin The begin of the validity of the PTY will be stored
 *   here.
 * @param end The end of the validity of the PTY will be stored here.
 * @param last_transm The last time when a program ID with the PTY
 *   in question was broadcast by the network.
 * @param tz A time zone name in the same format as the TZ environment
 *   variable. If @c NULL the current value of TZ will be used.
 *
 * This function calculates the validity time window of a Program Type
 * (PTY) code according to EN 300 231. That is the time window where a
 * network can be expected to broadcast another program with the same
 * PTY, approximately up to four weeks after its last
 * transmission. When the PTY is a series code (>= 0x80) and not
 * transmitted again before @a end, the network may assign the code to
 * another series.
 *
 * @a tz is the time zone of the intended audience of the program.
 * Ideally the time zone would be specified as a geographic area like
 * "Europe/London", such that the function can determine if
 * daylight-saving time is in effect at @a time or at the end of the
 * validity time window. See the documentation of the localtime()
 * function and the TZ environment variable for details. If no time
 * zone name is available "UTC" should be specified, the returned
 * @a end time may be off by one hour in this case.
 *
 * @returns
 * On error the function returns @c FALSE and @a *begin and @a *end
 * remain unchanged:
 * - @a tz is empty or contains an equal sign '='.
 * - The @a end time cannot be represented as a time_t value
 *   (December 2037 is closer than you think!).
 * - Insufficient memory was available.
 *
 * @since 0.2.34
 *
 * @bug
 * This function is not thread safe unless @a tz is @c NULL.
 * That is a limitation of the C library which permits the conversion
 * of a broken-down time in an arbitrary time zone only by setting
 * the TZ environment variable. The function may also fail to restore
 * the value of TZ if insufficient memory is available.
 */
vbi_bool
vbi_pty_validity_window		(time_t *		begin,
				 time_t *		end,
				 time_t			last_transm,
				 const char *		tz)
{
	char *old_tz;
	struct tm tm;
	time_t stop;
	int saved_errno;

	assert (NULL != begin);
	assert (NULL != end);

	if (NULL != tz && 0 == strcmp (tz, "UTC")) {
		vbi_bool success;

		success = pty_utc_validity_window (begin, end,
						   last_transm);
#if 2 == VBI_VERSION_MINOR
		errno = 0;
#endif
		return success;
	}

	if (unlikely (!localtime_tz (&tm, &old_tz, last_transm, tz)))
		goto failed;

	tm.tm_mday += 4 * 7 + 1;
	tm.tm_hour = 4;
	tm.tm_min = 0;
	tm.tm_sec = 0;
	tm.tm_isdst = -1; /* unknown */

	stop = mktime (&tm);
	if (unlikely ((time_t) -1 == stop)) {
		saved_errno = errno;

		if (unlikely (!restore_tz (&old_tz, tz)))
			return FALSE;

#if 3 == VBI_VERSION_MINOR
		errno = saved_errno;
#else
		errno = 0;
#endif
		return FALSE;
	}

	if (unlikely (!restore_tz (&old_tz, tz)))
		goto failed;

	*begin = last_transm;
	*end = stop;

	return TRUE;

 failed:
#if 2 == VBI_VERSION_MINOR
	errno = 0;
#endif
	return FALSE;
}
Exemple #5
0
/**
 * @param pil Program Identification Label (PIL) to convert.
 * @param start The most recently announced start time of the
 *   program. If zero the current system time will be used.
 * @param tz A time zone name in the same format as the TZ environment
 *   variable. If @c NULL the current value of TZ will be used.
 *
 * This function converts a PIL to a time_t in the same manner
 * localtime() converts a broken-down time to time_t.
 *
 * Since PILs do not contain a year field, the year is determined from
 * the @a start parameter, that is the most recently announced start
 * time of the program or "AT-1" in EN 300 231 parlance. If @a pil
 * contains a month more than five months after @a start, @a pil is
 * assumed to refer to an earlier date than @a start.
 *
 * @a pil is assumed to be a time in the time zone @a tz. @a start
 * will be converted to a local time in the same time zone to
 * determine the correct year.
 *
 * Teletext packet 8/30 format 2, VPS and DVB PDC descriptors give a
 * PIL relative to the time zone of the intended audience of the
 * program. Ideally the time zone would be specified as a geographic
 * area like "Europe/London", such that the function can determine
 * the correct offset from UTC and if daylight-saving time is in
 * effect at the specified date. See the documentation of the
 * localtime() function and the TZ environment variable for details.
 *
 * XDS Current/Future Program ID packets give a PIL relative to UTC.
 * Just specify time zone "UTC" in this case.
 *
 * @returns
 * The PIL as a time_t, that is the number of seconds since
 * 1970-01-01 00:00 UTC. On error the function
 * returns (time_t) -1:
 * - @a pil does not contain a valid date or time. February 29th is
 *   a valid date only if the estimated year is a leap year.
 * - @a tz is empty or contains an equal sign '='.
 * - @a start is zero and the current system time could not be
 *   determined.
 * - The time specified by @a pil, @a start and @a tz cannot be
 *   represented as a time_t value.
 * - Insufficient memory was available.
 *
 * @since 0.2.34
 *
 * @bug
 * This function is not thread safe unless @a tz is @c NULL. That is
 * a limitation of the C library which permits the conversion of a
 * broken-down time in an arbitrary time zone only by setting the TZ
 * environment variable. The function may also fail to restore the
 * value of TZ if insufficient memory is available.
 */
time_t
vbi_pil_to_time			(vbi_pil		pil,
				 time_t			start,
				 const char *		tz)
{
	struct tm tm;
	char *old_tz;
	time_t result;
	int saved_errno;

	if (unlikely (!vbi_pil_is_valid_date (pil))) {
#if 3 == VBI_VERSION_MINOR
		errno = VBI_ERR_INVALID_PIL;
#else
		errno = 0;
#endif
		return (time_t) -1;
	}

	if (NULL != tz && 0 == strcmp (tz, "UTC")) {
		time_t t;

		t = valid_pil_lto_to_time (pil, start,
					   /* seconds_east */ 0);
#if 2 == VBI_VERSION_MINOR
		errno = 0;
#endif
		return t;
	}

	if (unlikely (!localtime_tz (&tm, &old_tz, start, tz))) {
#if 2 == VBI_VERSION_MINOR
		errno = 0;
#endif
		return (time_t) -1;
	}

	if (unlikely (!tm_mon_mday_from_pil (&tm, pil))) {
		saved_errno = EOVERFLOW;
		goto failed;
	}

	if (unlikely (!tm_leap_day_check (&tm))) {
		saved_errno = VBI_ERR_INVALID_PIL;
		goto failed;
	}

	tm.tm_hour = VBI_PIL_HOUR (pil);
	tm.tm_min = VBI_PIL_MINUTE (pil);
	tm.tm_sec = 0;

	tm.tm_isdst = -1; /* unknown */

	result = mktime (&tm);
	if (unlikely ((time_t) -1 == result))
		goto failed;

	if (unlikely (!restore_tz (&old_tz, tz))) {
#if 2 == VBI_VERSION_MINOR
		errno = 0;
#endif
		return (time_t) -1;
	}

	return result;

 failed:
	if (unlikely (!restore_tz (&old_tz, tz))) {
#if 2 == VBI_VERSION_MINOR
		errno = 0;
#endif
		return (time_t) -1;
	}

#if 3 == VBI_VERSION_MINOR
	errno = saved_errno;
#else
	errno = 0;
#endif
	return (time_t) -1;
}
Exemple #6
0
static vbi_bool
valid_pil_validity_window	(time_t *		begin,
				 time_t *		end,
				 vbi_pil		pil,
				 time_t			start,
				 const char *		tz)
{
	char *old_tz;
	struct tm tm;
	struct tm tm2;
	time_t stop;
	int saved_errno;

	/* EN 300 231 Section 9.3 and Annex F. */

	old_tz = NULL;

	if (NULL != tz && 0 == strcmp (tz, "UTC")) {
		return valid_pil_lto_validity_window
			(begin, end, pil, start, /* seconds_east */ 0);
	}

	if (unlikely (!localtime_tz (&tm, &old_tz, start, tz)))
		return FALSE;

	if (unlikely (!tm_mon_mday_from_pil (&tm, pil))) {
		saved_errno = EOVERFLOW;
		goto failed;
	}

	if (unlikely (!tm_leap_day_check (&tm))) {
		/* Annex F: "Invalid days - indefinite time window". */
		if (!restore_tz (&old_tz, tz))
			return FALSE;
		*begin = TIME_MIN;
		*end = TIME_MAX;
		return TRUE;
	}

	tm.tm_hour = 0;
	tm.tm_min = 0;
	tm.tm_sec = 0;
	tm.tm_isdst = -1; /* unknown */

	tm2 = tm;

	if (VBI_PIL_HOUR (pil) < 4) {
		--tm.tm_mday;
		tm.tm_hour = 20;
	}

	start = mktime (&tm);
	if (unlikely ((time_t) -1 == start))
		goto failed;

	tm2.tm_mday += 1;
	tm2.tm_hour = 4;

	stop = mktime (&tm2);
	if (unlikely ((time_t) -1 == stop))
		goto failed;

	if (unlikely (!restore_tz (&old_tz, tz)))
		return FALSE;

	*begin = start;
	*end = stop;

	return TRUE;

 failed:
	if (unlikely (!restore_tz (&old_tz, tz)))
		return FALSE;

	errno = saved_errno;
	return FALSE;
}