aboutsummaryrefslogblamecommitdiffstats
path: root/libpatch_create_timestamp.c
blob: 54b6d91c576b11f800e96d25755d21b322b34ab1 (plain) (tree)

























































                                                                                            
/* See LICENSE file for copyright and license details. */
#include "common.h"


size_t
libpatch_create_timestamp(char *buf, size_t bufsize, const struct tm *tm,
                          uintmax_t subseconds, unsigned subseconds_decimals, 
                          unsigned frac, int zone, enum libpatch_style style)
{
	size_t guess, len, r;
	const char *fmt;

	frac = MIN(frac, subseconds_decimals);

	if (style == LIBPATCH_STYLE_COPIED) {
		fmt = "%a %b %e %T %Y";
		guess = sizeof("aaa bbb 00 00:00:00 0000");
	} else if (style == LIBPATCH_STYLE_UNIFIED) {
		fmt = "%Y-%m-%d %H:%M:%S";
		zone = 1;
		guess = sizeof("0000-00-00 00:00:00");
	} else {
		errno = EINVAL;
		return 0;
	}

	if (zone)
		guess += sizeof(" +0000");
	guess += (size_t)frac + (size_t)(frac > 0);

	if (!bufsize)
		return guess;

	while (subseconds_decimals != frac) {
		subseconds /= 10;
		subseconds_decimals -= 1;
	}

	len = strftime(buf, bufsize, fmt, tm);
	if (!len)
		return bufsize < guess ? guess : bufsize + 16U;

	if (frac) {
		if (len < bufsize)
			snprintf(&buf[len], bufsize - len, ".%0*ju", (int)frac, subseconds);
		len += (size_t)frac + (size_t)(frac > 0);
	}

	if (zone) {
		if (len < bufsize)
			return bufsize < len + 7U ? len + 7U : bufsize + 16U;
		len += r = strftime(&buf[len], bufsize - len, " %z", tm);
		if (!r)
			return bufsize < len + 7U ? len + 7U : bufsize + 16U;
	}

	return len + 1;
}