From 179e88bec91cfe58096900dc5509a080ff37b083 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 20 Jan 2017 16:03:48 +0100
Subject: rdate: make it do something remotely sane, facing 32-bit time
 overflow

function                                             old     new   delta
rdate_main                                           251     254      +3
packed_usage                                       31029   31023      -6

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 networking/inetd.c |  2 +-
 util-linux/rdate.c | 33 +++++++++++++++++++++++++++------
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/networking/inetd.c b/networking/inetd.c
index 4d0ab2e0d..612284e76 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1677,7 +1677,7 @@ static uint32_t machtime(void)
 	struct timeval tv;
 
 	gettimeofday(&tv, NULL);
-	return htonl((uint32_t)(tv.tv_sec + 2208988800));
+	return htonl((uint32_t)(tv.tv_sec + 2208988800U));
 }
 /* ARGSUSED */
 static void FAST_FUNC machtime_stream(int s, servtab_t *sep UNUSED_PARAM)
diff --git a/util-linux/rdate.c b/util-linux/rdate.c
index 8dd784d3d..a62591914 100644
--- a/util-linux/rdate.c
+++ b/util-linux/rdate.c
@@ -21,11 +21,11 @@
 //kbuild:lib-$(CONFIG_RDATE) += rdate.o
 
 //usage:#define rdate_trivial_usage
-//usage:       "[-sp] HOST"
+//usage:       "[-s/-p] HOST"
 //usage:#define rdate_full_usage "\n\n"
-//usage:       "Get and possibly set system time from a remote HOST\n"
-//usage:     "\n	-s	Set system time (default)"
-//usage:     "\n	-p	Print time"
+//usage:       "Set and print time from HOST using RFC 868\n"
+//usage:     "\n	-s	Only set system time"
+//usage:     "\n	-p	Only print time"
 
 #include "libbb.h"
 
@@ -58,8 +58,22 @@ static time_t askremotedate(const char *host)
 	 * the RFC 868 time 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT
 	 * Subtract the RFC 868 time to get Linux epoch.
 	 */
-
-	return ntohl(nett) - RFC_868_BIAS;
+	nett = ntohl(nett) - RFC_868_BIAS;
+
+	if (sizeof(time_t) > 4) {
+		/* Now we have 32-bit lsb of a wider time_t
+		 * Imagine that  nett =   0x00000001,
+		 * current time  cur = 0x123ffffffff.
+		 * Assuming our time is not some 40 years off,
+		 * remote time must be 0x12400000001.
+		 * Need to adjust out time by (int32_t)(nett - cur).
+		 */
+		time_t cur = time(NULL);
+		int32_t adjust = (int32_t)(nett - (uint32_t)cur);
+		return cur + adjust;
+	}
+	/* This is not going to work, but what can we do */
+	return (time_t)nett;
 }
 
 int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -73,6 +87,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv)
 
 	remote_time = askremotedate(argv[optind]);
 
+	/* Manpages of various Unixes are confusing. What happens is:
+	 * (no opts) set and print time
+	 * -s: set time ("do not print the time")
+	 * -p: print time ("do not set, just print the remote time")
+	 * -sp: print time (that's what we do, not sure this is right)
+	 */
+
 	if (!(flags & 2)) { /* no -p (-s may be present) */
 		time_t current_time;
 
-- 
cgit v1.2.3-55-g6feb