Commit cfd8a834 authored by Alessandro Rubini's avatar Alessandro Rubini

tools: added adjtime

This simple tool requests a time adjustment, specified in seconds
expressed as a floating point values ("0.001", "-.2", "-4" ...).

It can be used to force time differences between hosts while checking
how ppsi (or other time daemons) work.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 4a05e2de
......@@ -11,7 +11,7 @@ OBJDUMP = $(CROSS_COMPILE)objdump
CFLAGS = -Wall -ggdb -I../include/ppsi
PROGS = ptpdump
PROGS = ptpdump adjtime
all: $(PROGS)
......
/* CERN 2013 (author A. Rubini), part of the ppsi project, GPL v2 or later */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include "convert.h"
/*
* This is a simple tools to slightly change the system time, in order
* to check when (and how) PTP resynchronizes it
*/
int main(int argc, char **argv)
{
struct timeval tv, otv;
if (argc != 2) {
fprintf(stderr, "%s: use \"%s <delta>\"\n"
" <delta> is a floating-point number of seconds\n",
argv[0], argv[0]);
exit(1);
}
if (str_to_tv(argv[1], &tv) < 0) {
fprintf(stderr, "%s: not a time (float) number \"%s\"\n",
argv[0], argv[1]);
exit(1);
}
fprintf(stderr, "Requesting adjustment: %s seconds\n", tv_to_str(&tv));
if (adjtime(&tv, &otv) < 0) {
fprintf(stderr, "%s: adjtime(): %s\n", argv[0],
strerror(errno));
exit(1);
}
fprintf(stderr, "Previous adjustment: %s seconds\n", tv_to_str(&otv));
exit(0);
}
/* CERN 2013 (author A. Rubini), part of the ppsi project, GPL v2 or later */
/*
* Conversions are boring stuff: we can't use floats or doubles (because
* 0.3 becomes 0.29999) and we need to ensure the fraction is positive.
*/
static inline int str_to_tv(char *s, struct timeval *tv)
{
int i, sign = 1, micro = 0, sec = 0;
char *smicro = NULL;
char c;
if (strlen(s) > 32)
return -1;
if (s[0] == '-') {
sign = -1;
s++;
}
if (sscanf(s, "%d.%d%c", &sec, &micro, &c) > 2)
return -1;
smicro = strchr(s, '.');
if (smicro) {
smicro++;
if (sscanf(smicro, "%d%c", &micro, &c) != 1)
return -1;
}
/* now we have sign, sec, and smicro (string of microseconds) */
if (smicro) {
/* check how long it is and scale*/
i = strlen(smicro);
if (i > 6)
return -1;
while (i < 6) {
micro *= 10;
i++;
}
}
tv->tv_sec = sec * sign;
tv->tv_usec = micro;
if (sign < 0 && micro) { /* "-1.2" -> -2 + .8 */
tv->tv_sec--;
tv->tv_usec = 1000 * 1000 - micro;
}
return 0;
}
/* returns static storage */
static inline char *tv_to_str(struct timeval *origtv)
{
static char res[32];
struct timeval localtv = *origtv;
struct timeval *tv = &localtv;
char *s = res;
if (tv->tv_usec < 0) {
tv->tv_sec--;
tv->tv_usec += 1000 * 1000;
}
if (tv->tv_usec < 0 || tv->tv_usec > 1000 * 1000)
return "(error)";
if (tv->tv_sec < 0) {
*(s++) = '-';
if (tv->tv_usec) { /* -2 + .8 --> "-1.2" */
tv->tv_sec++;
tv->tv_usec = 1000 * 1000 - tv->tv_usec;
}
tv->tv_sec *= -1;
}
sprintf(s, "%d.%06d", (int)tv->tv_sec, (int)tv->tv_usec);
return res;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment