Ejemplo n.º 1
0
/** %a, %c, %t: ctime() */
static int bfs_printf_ctime(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) {
	// Not using ctime() itself because GNU find adds nanoseconds
	static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
	static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

	const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags);
	if (!statbuf) {
		return -1;
	}

	const struct timespec *ts = bfs_stat_time(statbuf, directive->stat_field);
	if (!ts) {
		return -1;
	}

	struct tm tm;
	if (xlocaltime(&ts->tv_sec, &tm) != 0) {
		return -1;
	}

	BFS_PRINTF_BUF(buf, "%s %s %2d %.2d:%.2d:%.2d.%09ld0 %4d",
	               days[tm.tm_wday],
	               months[tm.tm_mon],
	               tm.tm_mday,
	               tm.tm_hour,
	               tm.tm_min,
	               tm.tm_sec,
	               (long)ts->tv_nsec,
	               1900 + tm.tm_year);

	return fprintf(file, directive->str, buf);
}
Ejemplo n.º 2
0
/** %A, %B/%W, %C, %T: strftime() */
static int bfs_printf_strftime(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) {
	const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags);
	if (!statbuf) {
		return -1;
	}

	const struct timespec *ts = bfs_stat_time(statbuf, directive->stat_field);
	if (!ts) {
		return -1;
	}

	struct tm tm;
	if (xlocaltime(&ts->tv_sec, &tm) != 0) {
		return -1;
	}

	int ret;
	char buf[256];
	char format[] = "% ";
	switch (directive->c) {
	// Non-POSIX strftime() features
	case '@':
		ret = snprintf(buf, sizeof(buf), "%lld.%09ld0", (long long)ts->tv_sec, (long)ts->tv_nsec);
		break;
	case '+':
		ret = snprintf(buf, sizeof(buf), "%4d-%.2d-%.2d+%.2d:%.2d:%.2d.%09ld0",
		               1900 + tm.tm_year,
		               tm.tm_mon + 1,
		               tm.tm_mday,
		               tm.tm_hour,
		               tm.tm_min,
		               tm.tm_sec,
		               (long)ts->tv_nsec);
		break;
	case 'k':
		ret = snprintf(buf, sizeof(buf), "%2d", tm.tm_hour);
		break;
	case 'l':
		ret = snprintf(buf, sizeof(buf), "%2d", (tm.tm_hour + 11)%12 + 1);
		break;
	case 's':
		ret = snprintf(buf, sizeof(buf), "%lld", (long long)ts->tv_sec);
		break;
	case 'S':
		ret = snprintf(buf, sizeof(buf), "%.2d.%09ld0", tm.tm_sec, (long)ts->tv_nsec);
		break;
	case 'T':
		ret = snprintf(buf, sizeof(buf), "%.2d:%.2d:%.2d.%09ld0",
			       tm.tm_hour,
			       tm.tm_min,
			       tm.tm_sec,
			       (long)ts->tv_nsec);
		break;

	// POSIX strftime() features
	default:
		format[1] = directive->c;
		ret = strftime(buf, sizeof(buf), format, &tm);
		break;
	}

	assert(ret >= 0 && ret < sizeof(buf));
	(void)ret;

	return fprintf(file, directive->str, buf);
}
Ejemplo n.º 3
0
uschar *
tod_stamp(int type)
{
    time_t now = time(NULL);
    struct tm *t;

    /* Vary log type according to timezone requirement */

    if (type == tod_log) type = log_timezone? tod_log_zone : tod_log_bare;

    /* Styles that don't need local time */

    else if (type == tod_epoch)
    {
        (void) sprintf(CS timebuf, "%d", (int)now);  /* Unix epoch format */
        return timebuf;
    }

    else if (type == tod_zulu)
    {
#if defined(MOSBENCH_NO_TZ_LOCK)
        t = xlocaltime(&now);
#else
        t = gmtime(&now);
#endif
        (void) sprintf(CS timebuf, "%04d%02d%02d%02d%02d%02dZ",
                       1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min,
                       t->tm_sec);
        return timebuf;
    }

    /* Convert to local time or UTC */

#if defined(MOSBENCH_NO_TZ_LOCK)
    t = xlocaltime(&now);
#else
    t = timestamps_utc? gmtime(&now) : localtime(&now);
#endif

    switch(type)
    {
    case tod_log_bare:          /* Format used in logging without timezone */
        (void) sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d",
                       1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday,
                       t->tm_hour, t->tm_min, t->tm_sec);
        break;

    /* Format used as suffix of log file name when 'log_datestamp' is active. For
    testing purposes, it changes the file every second. */

    case tod_log_datestamp:
#ifdef TESTING_LOG_DATESTAMP
        (void) sprintf(CS timebuf, "%04d%02d%02d%02d%02d",
                       1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min);
#else
        (void) sprintf(CS timebuf, "%04d%02d%02d",
                       1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
#endif
        break;

    /* Format used in BSD inbox separator lines. Sort-of documented in RFC 976
    ("UUCP Mail Interchange Format Standard") but only by example, not by
    explicit definition. The examples show no timezone offsets, and some MUAs
    appear to be sensitive to this, so Exim has been changed to remove the
    timezone offsets that originally appeared. */

    case tod_bsdin:
    {
        int len = Ustrftime(timebuf, sizeof(timebuf), "%a %b %d %H:%M:%S", t);
        Ustrftime(timebuf + len, sizeof(timebuf) - len, " %Y", t);
    }
    break;

    /* Other types require the GMT offset to be calculated, or just set up in the
    case of UTC timestamping. We need to take a copy of the local time first. */

    default:
    {
        int diff_hour, diff_min;
        struct tm local;
        memcpy(&local, t, sizeof(struct tm));

        if (timestamps_utc)
        {
            diff_hour = diff_min = 0;
        }
        else
        {
#if defined(MOSBENCH_NO_TZ_LOCK)
            struct tm *gmt = xlocaltime(&now);
#else
            struct tm *gmt = gmtime(&now);
#endif
            diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
            if (local.tm_year != gmt->tm_year)
                diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440;
            else if (local.tm_yday != gmt->tm_yday)
                diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440;
            diff_hour = diff_min/60;
            diff_min  = abs(diff_min - diff_hour*60);
        }

        switch(type)
        {
        case tod_log_zone:          /* Format used in logging with timezone */
            (void) sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+03d%02d",
                           1900 + local.tm_year, 1 + local.tm_mon, local.tm_mday,
                           local.tm_hour, local.tm_min, local.tm_sec,
                           diff_hour, diff_min);
            break;

        case tod_zone:              /* Just the timezone offset */
            (void) sprintf(CS timebuf, "%+03d%02d", diff_hour, diff_min);
            break;

            /* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */

#ifdef SUPPORT_MBX
        case tod_mbx:
        {
            int len;
            (void) sprintf(CS timebuf, "%02d-", local.tm_mday);
            len = Ustrlen(timebuf);
            len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b-%Y %H:%M:%S",
                             &local);
            (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
        }
        break;
#endif

        /* tod_full: format used in Received: headers (use as default just in case
        called with a junk type value) */

        default:
        {
            int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local);
            (void) sprintf(CS timebuf + len, "%02d ", local.tm_mday);
            len += Ustrlen(timebuf + len);
            len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b %Y %H:%M:%S",
                             &local);
            (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
        }
        break;
        }
    }
    break;
    }

    return timebuf;
}