[1/2] testbot/testagentd: Add an RPC to set the remote host's system time.

Francois Gouget fgouget at codeweavers.com
Thu Mar 6 08:24:05 CST 2014


---

For bug 33788.
http://bugs.winehq.org/show_bug.cgi?id=33788

 testbot/lib/WineTestBot/TestAgent.pm      | 23 +++++++++++++++++++
 testbot/scripts/TestAgent                 |  8 ++++++-
 testbot/src/testagentd/platform.h         |  6 +++++
 testbot/src/testagentd/platform_unix.c    | 24 ++++++++++++++++++++
 testbot/src/testagentd/platform_windows.c | 37 +++++++++++++++++++++++++++++++
 testbot/src/testagentd/testagentd.c       | 25 ++++++++++++++++++++-
 6 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/testbot/lib/WineTestBot/TestAgent.pm b/testbot/lib/WineTestBot/TestAgent.pm
index dfc86e3..299f63e 100644
--- a/testbot/lib/WineTestBot/TestAgent.pm
+++ b/testbot/lib/WineTestBot/TestAgent.pm
@@ -36,6 +36,7 @@ my $RPC_RUN = 3;
 my $RPC_WAIT = 4;
 my $RPC_RM = 5;
 my $RPC_WAIT2 = 6;
+my $RPC_SETTIME = 7;
 
 my %RpcNames=(
     $RPC_PING => 'ping',
@@ -45,6 +46,7 @@ my %RpcNames=(
     $RPC_WAIT => 'wait',
     $RPC_RM => 'rm',
     $RPC_WAIT2 => 'wait2',
+    $RPC_SETTIME => 'settime',
 );
 
 my $Debug = 0;
@@ -1155,4 +1157,25 @@ sub Rm($@)
   return $self->_RecvErrorList();
 }
 
+sub SetTime($)
+{
+  my ($self) = @_;
+  debug("SetTime\n");
+
+  # Make sure we have the server version
+  return undef if (!$self->{agentversion} and !$self->_Connect());
+
+  # Send the command
+  if (!$self->_StartRPC($RPC_SETTIME) or
+      !$self->_SendListSize(2) or
+      !$self->_SendUInt64(time()) or
+      !$self->_SendUInt32(30))
+  {
+      return undef;
+  }
+
+  # Get the reply
+  return $self->_RecvList('');
+}
+
 1;
diff --git a/testbot/scripts/TestAgent b/testbot/scripts/TestAgent
index bb7dd14..30e2fbc 100755
--- a/testbot/scripts/TestAgent
+++ b/testbot/scripts/TestAgent
@@ -187,7 +187,7 @@ while (@ARGV)
     {
         $Cmd = $arg;
     }
-    elsif ($arg eq "ping")
+    elsif ($arg eq "ping" or $arg eq "settime")
     {
         $Cmd = $arg;
     }
@@ -268,6 +268,7 @@ if (defined $Usage)
     print "or     $name0 [options] <hostname> getfile <serverpath> <localpath>\n";
     print "or     $name0 [options] <hostname> run <command> <arguments>\n";
     print "or     $name0 [options] <hostname> wait <pid>\n";
+    print "or     $name0 [options] <hostname> settime\n";
     print "or     $name0 [options] <hostname> rm <serverfiles>\n";
     print "or     $name0 [options] <hostname> [ping|version]\n";
     print "\n";
@@ -290,6 +291,7 @@ if (defined $Usage)
     print "                  specified server file.\n";
     print "    --run-dntrunc-err Do not truncate the file stderr is redirected to.\n";
     print "  wait          Waits for the specified child process on the server.\n";
+    print "  settime       Set the system time of the remote host.\n";
     print "  rm            Deletes the specified files on the server.\n";
     print "  getversion    Returns the version of the server.\n";
     print "  ping          Makes sure the server is still alive.\n";
@@ -370,6 +372,10 @@ elsif ($Cmd eq "rm")
         $Result = 1;
     }
 }
+elsif ($Cmd eq "settime")
+{
+    $Result = $TA->SetTime();
+}
 elsif ($Cmd eq "getversion")
 {
     $Result = $TA->GetVersion();
diff --git a/testbot/src/testagentd/platform.h b/testbot/src/testagentd/platform.h
index fffaa4b..785b3b5 100644
--- a/testbot/src/testagentd/platform.h
+++ b/testbot/src/testagentd/platform.h
@@ -79,6 +79,12 @@ uint64_t platform_run(char** argv, uint32_t flags, char** redirects);
  */
 int platform_wait(SOCKET client, uint64_t pid, uint32_t timeout, uint32_t *childstatus);
 
+/* Sets the system time to the specified Unix epoch. If the system time is
+ * already within leeway seconds of the specified time, then consider that
+ * the system clock is already correct.
+ */
+int platform_settime(uint64_t epoch, uint32_t leeway);
+
 /* Returns a string describing the last socket-related error */
 int sockeintr(void);
 const char* sockerror(void);
diff --git a/testbot/src/testagentd/platform_unix.c b/testbot/src/testagentd/platform_unix.c
index e003135..c9fc7fd 100644
--- a/testbot/src/testagentd/platform_unix.c
+++ b/testbot/src/testagentd/platform_unix.c
@@ -29,6 +29,7 @@
 #include <sys/wait.h>
 #include <signal.h>
 #include <time.h>
+#include <sys/time.h>
 
 #include "platform.h"
 #include "list.h"
@@ -198,6 +199,29 @@ int platform_wait(SOCKET client, uint64_t pid, uint32_t timeout, uint32_t *child
     return 1;
 }
 
+int platform_settime(uint64_t epoch, uint32_t leeway)
+{
+    struct timeval tv;
+
+    if (leeway)
+    {
+        uint64_t offset;
+        gettimeofday(&tv, NULL);
+        offset = llabs(tv.tv_sec-epoch);
+        if (offset <= leeway)
+            return 2;
+    }
+
+    tv.tv_sec = epoch;
+    tv.tv_usec = 0;
+    if (!settimeofday(&tv, NULL))
+    {
+        set_status(ST_ERROR, "failed to set the time: %s", strerror(errno));
+        return 0;
+    }
+    return 1;
+}
+
 int sockeintr(void)
 {
     return errno == EINTR;
diff --git a/testbot/src/testagentd/platform_windows.c b/testbot/src/testagentd/platform_windows.c
index a0dccfa..9dda56a 100644
--- a/testbot/src/testagentd/platform_windows.c
+++ b/testbot/src/testagentd/platform_windows.c
@@ -221,6 +221,43 @@ int platform_wait(SOCKET client, uint64_t pid, uint32_t timeout, uint32_t *child
     return success;
 }
 
+int platform_settime(uint64_t epoch, uint32_t leeway)
+{
+    FILETIME filetime;
+    SYSTEMTIME systemtime;
+
+    /* Where 134774 is the number of days from 1601/1/1 to 1970/1/1 */
+    epoch = (epoch + ((uint64_t)134774) * 24 * 3600 ) * 10000000;
+
+    if (leeway)
+    {
+        ULARGE_INTEGER ul;
+        GetSystemTime(&systemtime);
+        /* in case of an error set the time unconditionally */
+        if (SystemTimeToFileTime(&systemtime, &filetime))
+        {
+            ul.LowPart = filetime.dwLowDateTime;
+            ul.HighPart = filetime.dwHighDateTime;
+            if (llabs(ul.QuadPart-epoch)/10000000 < leeway)
+                return 1;
+        }
+    }
+
+    filetime.dwLowDateTime = (DWORD)epoch;
+    filetime.dwHighDateTime = epoch >> 32;
+    if (!FileTimeToSystemTime(&filetime, &systemtime))
+    {
+        set_status(ST_ERROR, "failed to oconvert the time (%lu)", GetLastError());
+        return 0;
+    }
+    if (!SetSystemTime(&systemtime))
+    {
+        set_status(ST_ERROR, "failed to set the time (%lu)", GetLastError());
+        return 0;
+    }
+    return 1;
+}
+
 int sockretry(void)
 {
     return (WSAGetLastError() == WSAEINTR);
diff --git a/testbot/src/testagentd/testagentd.c b/testbot/src/testagentd/testagentd.c
index e99dcb4..35b42f3 100644
--- a/testbot/src/testagentd/testagentd.c
+++ b/testbot/src/testagentd/testagentd.c
@@ -35,8 +35,9 @@
  * 1.1:  Added the wait2 RPC.
  * 1.2:  Add more redirection options to the run RPC.
  * 1.3:  Fix the zero / infinite timeouts in the wait2 RPC.
+ * 1.4:  Add the settime RPC.
  */
-#define PROTOCOL_VERSION "testagentd 1.3"
+#define PROTOCOL_VERSION "testagentd 1.4"
 
 #define BLOCK_SIZE       65536
 
@@ -82,6 +83,7 @@ enum rpc_ids_t
     RPCID_WAIT,
     RPCID_RM,
     RPCID_WAIT2,
+    RPCID_SETTIME,
 };
 
 /* This is the RPC currently being processed */
@@ -891,6 +893,24 @@ static void do_rm(SOCKET client)
     }
 }
 
+static void do_settime(SOCKET client)
+{
+    uint64_t epoch;
+    uint32_t leeway;
+
+    if (!expect_list_size(client, 2) ||
+        !recv_uint64(client, &epoch) ||
+        !recv_uint32(client, &leeway))
+    {
+        send_error(client);
+        return;
+    }
+    if (platform_settime(epoch, leeway))
+        send_list_size(client, 0);
+    else
+        send_error(client);
+}
+
 static void do_unknown(SOCKET client, uint32_t id)
 {
     uint32_t argc;
@@ -952,6 +972,9 @@ static void process_rpc(SOCKET client)
     case RPCID_RM:
         do_rm(client);
         break;
+    case RPCID_SETTIME:
+        do_settime(client);
+        break;
     default:
         do_unknown(client, rpcid);
     }
-- 
1.8.5.3




More information about the wine-patches mailing list