rdate: make it do something remotely sane, facing 32-bit time overflow
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 20 Jan 2017 15:03:48 +0000 (16:03 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 20 Jan 2017 15:03:48 +0000 (16:03 +0100)
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
util-linux/rdate.c

index 4d0ab2e0d300d859c8fe0023a329eeb15ca610f9..612284e760f18edff7c8bef84b2e383d5822a6f5 100644 (file)
@@ -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)
index 8dd784d3d68e91cc1d6cb398d81a299809486016..a625919140c39c1a13b7fc29b2d7767b31cbe428 100644 (file)
 //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;