[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