[PATCH v2 2/3] syslogd: Unify messages with client timestamps when both PRECISE and UTC are enabled.
Grant Erickson
gerickson at nuovations.com
Wed Apr 2 14:43:52 UTC 2025
This unifies the handling of messages with a client-generated
timestamps when both ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS and
ENABLE_FEATURE_SYSLOGD_UTC are asserted.
In particular, to support the intermix of client-generated and
server-generated timestamps, the former are zero-padded such that the
timestamp "column" of a log file is consistent in format.
Signed-off-by: Grant Erickson <gerickson at nuovations.com>
---
sysklogd/syslogd.c | 125 +++++++++++++++++++++++++++++----------------
1 file changed, 82 insertions(+), 43 deletions(-)
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index fb097bc7e596..287b70e45d19 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -833,25 +833,47 @@ static void parse_fac_prio_20(int pri, char *res20)
snprintf(res20, 20, "<%d>", pri);
}
-static char *timestamp_from_time(const time_t *time)
+static void get_time(struct timeval *tvp)
{
- char *timestamp = NULL;
+ if (tvp) {
+#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_ISO8601FMT
+ xgettimeofday(tvp);
+#else
+ time(&tvp->tv_sec);
+#endif
+ }
+}
+
+static struct tm * decompose_time(struct timeval *tvp, struct tm *tmp)
+{
+ struct tm *tm;
- if (time) {
#if ENABLE_FEATURE_SYSLOGD_UTC
- if (option_mask32 & OPT_utc)
- timestamp = asctime(gmtime(time));
- else
- timestamp = asctime(localtime(time));
+ if (option_mask32 & OPT_utc)
+ tm = gmtime_r(&tvp->tv_sec, tmp);
+ else
+ tm = localtime_r(&tvp->tv_sec, tmp);
#else
- timestamp = ctime(time);
+ tm = localtime_r(&tvp->tv_sec, tmp);
#endif
- timestamp += 4; /* skip day of week */
+
+ return tm;
+}
+
+static struct tm * generate_time(struct timeval *tvp, struct tm *tmp)
+{
+ struct tm *tm = NULL;
+
+ if (tvp && tmp) {
+ get_time(tvp);
+
+ tm = decompose_time(tvp, tmp);
}
- return timestamp;
+ return tm;
}
+
/* len parameter is used only for "is there a timestamp?" check.
* NB: some callers cheat and supply len==0 when they know
* that there is no timestamp, short-circuiting the test. */
@@ -863,56 +885,73 @@ static void timestamp_and_log(int pri, char *msg, int len)
msg[ 3] == ' ' && msg[ 6] == ' ' &&
msg[ 9] == ':' && msg[12] == ':' &&
msg[15] == ' ');
+ const char *format="%h %e %T";
char *timestamp = NULL;
- time_t now;
+ char timestampbuf[20];
+ /* MMM DD hh:mm:ss default */
+ /* 0123456789012345 - 16 */
+ /* MMM DD hh:mm:ss.mmm ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS */
+ /* 01234567890123456789 - 20 */
+ struct timeval tvnow;
+#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC
+ struct tm parsed;
+#endif
+ struct tm tmnow, *tmp = NULL;
+ size_t n = 0;
if (msg_has_timestamp) {
if (!(option_mask32 & OPT_timestamp)) {
/* use message timestamp */
+#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC
+ struct tm local;
+ get_time(&tvnow);
+ localtime_r(&tvnow.tv_sec, &local);
+ if (strptime(msg, format, &parsed) != NULL) {
+ parsed.tm_gmtoff = local.tm_gmtoff;
+ parsed.tm_zone = local.tm_zone;
+ parsed.tm_year = local.tm_year;
+ parsed.tm_isdst = local.tm_isdst;
+
+ tvnow.tv_sec = mktime(&parsed);
+ tvnow.tv_usec = 0;
+
#if ENABLE_FEATURE_SYSLOGD_UTC
- if (option_mask32 & OPT_utc) {
- struct tm parsed, local;
- now = time(NULL);
- localtime_r(&now, &local);
- if (strptime(msg, "%h %e %T", &parsed) != NULL) {
- parsed.tm_gmtoff = local.tm_gmtoff;
- parsed.tm_zone = local.tm_zone;
- parsed.tm_year = local.tm_year;
- parsed.tm_isdst = local.tm_isdst;
- now = mktime(&parsed);
- timestamp = asctime(gmtime(&now)) + 4;
+ if (option_mask32 & OPT_utc) {
+ tmp = gmtime_r(&tvnow.tv_sec, &tmnow);
} else {
- timestamp = msg;
+ tmp = &parsed;
}
+#else
+ tmp = &parsed;
+#endif /* ENABLE_FEATURE_SYSLOGD_UTC */
} else {
- timestamp = msg;
- now = 0;
+ tmp = decompose_time(&tvnow, &tmnow);
}
#else
timestamp = msg;
- now = 0;
-#endif
+ timestamp[15] = '\0';
+ tvnow.tv_sec = 0;
+ tvnow.tv_usec = 0;
+#endif /* ENABLE_FEATURE_SYSLOGD_UTC */
}
msg += 16;
}
+ if (!tmp) {
+ tmp = generate_time(&tvnow, &tmnow);
+ }
+
#if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
- if (!timestamp) {
- struct timeval tv;
- xgettimeofday(&tv);
- now = tv.tv_sec;
- timestamp = timestamp_from_time(&now);
- /* overwrite year by milliseconds, zero terminate */
- sprintf(timestamp + 15, ".%03u", (unsigned)tv.tv_usec / 1000u);
- } else {
- timestamp[15] = '\0';
+ if (tmp && !timestamp) {
+ n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp);
+ snprintf(timestampbuf + n, sizeof(timestampbuf) - n, ".%03lu", tvnow.tv_usec / 1000u);
+ timestamp = timestampbuf;
}
#else
- if (!timestamp) {
- time(&now);
- timestamp = timestamp_from_time(&now);
- }
- timestamp[15] = '\0';
+ if (tmp && !timestamp) {
+ strftime(timestampbuf + n, sizeof(timestampbuf) - n, format, tmp);
+ timestamp = timestampbuf;
+ }
#endif
if (option_mask32 & OPT_kmsg) {
@@ -938,7 +977,7 @@ static void timestamp_and_log(int pri, char *msg, int len)
for (rule = G.log_rules; rule; rule = rule->next) {
if (rule->enabled_facility_priomap[facility] & prio_bit) {
- log_locally(now, G.printbuf, rule->file);
+ log_locally(tvnow.tv_sec, G.printbuf, rule->file);
match = 1;
}
}
@@ -953,7 +992,7 @@ static void timestamp_and_log(int pri, char *msg, int len)
return;
}
#endif
- log_locally(now, G.printbuf, &G.logFile);
+ log_locally(tvnow.tv_sec, G.printbuf, &G.logFile);
}
}
--
2.45.0
More information about the busybox
mailing list