What am I doing wrong here? I expect settimeofday()
to change the system time, not return EINVAL
.
$ uname -a
Linux io 4.3.5-300.fc23.x86_64 #1 SMP Mon Feb 1 03:18:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ cat settimeofday.c
#include <sys/time.h>
#include <stdio.h>
int main()
{
struct timeval tv = {0, 0};
if (settimeofday(&tv, 0) == -1)
perror("settimeofday");
}
$ gcc settimeofday.c
$ sudo ./a.out
settimeofday: Invalid argument
The error is coming from a Thinkpad T450 running Fedora 23. The same code runs fine on OS X.
EDIT
To clarify, the command is being executed as root:
# whoami
root
# sudo ./a.out
settimeofday: Invalid argument
As expected, I get EPERM not EINVAL if I run the program as a regular user:
$ ./a.out
settimeofday: Operation not permitted
Commit e1d7ba was introduced to the Linux kernel in mid-2015 and restricts the value of the tv_sec field. The restriction is influenced by system uptime -- see the commit message and related LKML discussion for details.
That's what was causing the settimeofday
call to return EINVAL
and explains why the code runs on OS X and older Linux machines.