date: add rudimentary support for setting date/time

This commit is contained in:
K. Lange 2022-02-25 21:16:30 +09:00
parent 89ba900988
commit b3f6728339
8 changed files with 138 additions and 3 deletions

View File

@ -15,6 +15,7 @@
* Copyright (C) 2018 K. Lange
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
@ -32,6 +33,45 @@ static void show_usage(int argc, char * argv[]) {
"\n", argv[0], argv[0]);
}
int digits(const char * s, int len) {
for (int i = 0; i < len; ++i) {
if (s[i] < '0' || s[i] > '9') return 0;
}
return 1;
}
int mmddhhmm(struct tm * tm, const char * str) {
int month = (str[0]-'0') * 10 + (str[1]-'0');
int day = (str[2]-'0') * 10 + (str[3]-'0');
int hour = (str[4]-'0') * 10 + (str[5]-'0');
int min = (str[6]-'0') * 10 + (str[7]-'0');
if (month < 1 || month > 12) return 0;
if (day < 1 || day > 31) return 0;
if (hour < 0 || hour > 23) return 0;
if (min < 0 || min > 59) return 0;
tm->tm_mon = month - 1;
tm->tm_mday = day;
tm->tm_hour = hour;
tm->tm_min = min;
return 1;
}
int ddyy(struct tm * tm, const char * str) {
int year = (str[0]-'0') * 1000 + (str[1]-'0') * 100 + (str[2]-'0') * 10 + (str[3]-'0');
tm->tm_year = year - 1900;
return 1;
}
int secs(struct tm * tm, const char * str) {
int sec = (str[0]-'0') * 10 + (str[1]-'0');
if (sec < 0 || sec > 59) return 0;
tm->tm_sec = sec;
return 1;
}
int main(int argc, char * argv[]) {
char * format = "%a %d %b %Y %T %Z";
struct tm * timeinfo;
@ -47,12 +87,47 @@ int main(int argc, char * argv[]) {
}
}
gettimeofday(&now, NULL);
timeinfo = localtime((time_t *)&now.tv_sec);
if (optind < argc && *argv[optind] == '+') {
format = &argv[optind][1];
}
} else if (optind < argc) {
gettimeofday(&now, NULL); //time(NULL);
timeinfo = localtime((time_t *)&now.tv_sec);
int len =strlen(argv[optind]);
if (len == 8) {
if (!digits(argv[optind], 8)) goto _invalid;
if (!mmddhhmm(timeinfo, argv[optind])) goto _invalid;
goto set_time;
} else if (len == 11) {
if (argv[optind][8] != '.') goto _invalid;
if (!digits(argv[optind], 8) || !digits(argv[optind]+9,2)) goto _invalid;
if (!mmddhhmm(timeinfo, argv[optind])) goto _invalid;
if (!secs(timeinfo, argv[optind]+9)) goto _invalid;
goto set_time;
} else if (len == 12) {
if (!digits(argv[optind], 12)) goto _invalid;
if (!mmddhhmm(timeinfo, argv[optind])) goto _invalid;
if (!ddyy(timeinfo, argv[optind]+8)) goto _invalid;
goto set_time;
} else if (len == 15) {
if (argv[optind][12] != '.') goto _invalid;
if (!digits(argv[optind], 12) || !digits(argv[optind]+13,2)) goto _invalid;
if (!mmddhhmm(timeinfo, argv[optind])) goto _invalid;
if (!ddyy(timeinfo, argv[optind]+8)) goto _invalid;
if (!secs(timeinfo, argv[optind]+13)) goto _invalid;
goto set_time;
}
_invalid:
fprintf(stderr, "date: only 'MMDDhhmm', 'MMDDhhmm.ss', 'MMDDhhmmCCYY' and 'MMDDhhmmCCYY.ss' are supported for setting time.\n");
return 1;
set_time:
now.tv_usec = 0;
now.tv_sec = mktime(timeinfo);
return settimeofday(&now, NULL);
}
strftime(buf,BUFSIZ,format,timeinfo);
puts(buf);

View File

@ -16,5 +16,6 @@ struct timezone {
};
extern int gettimeofday(struct timeval *p, void *z);
extern int settimeofday(struct timeval *p, void *z);
_End_C_Header

View File

@ -221,6 +221,7 @@ DECL_SYSCALL2(getgroups, int, int*);
DECL_SYSCALL2(setgroups, int, const int*);
DECL_SYSCALL1(times, struct tms*);
DECL_SYSCALL4(ptrace, int, int, void*, void*);
DECL_SYSCALL2(settimeofday, void *, void *);
_End_C_Header

View File

@ -72,3 +72,4 @@
#define SYS_GETGROUPS 69
#define SYS_SETGROUPS 70
#define SYS_TIMES 71
#define SYS_SETTIMEOFDAY 72

View File

@ -24,6 +24,7 @@
#include <kernel/misc.h>
#include <kernel/ptrace.h>
#include <kernel/ksym.h>
#include <errno.h>
#include <sys/ptrace.h>
@ -122,6 +123,20 @@ uint64_t now(void) {
return t.tv_sec;
}
static spin_lock_t _time_set_lock;
int settimeofday(struct timeval * t, void *z) {
if (!t) return -EINVAL;
if (t->tv_sec < 0 || t->tv_usec < 0 || t->tv_usec > 1000000) return -EINVAL;
spin_lock(_time_set_lock);
uint64_t clock_time = now();
arch_boot_time += t->tv_sec - clock_time;
spin_unlock(_time_set_lock);
return 0;
}
void relative_time(unsigned long seconds, unsigned long subseconds, unsigned long * out_seconds, unsigned long * out_subseconds) {
if (!arch_boot_time) {
*out_seconds = 0;

View File

@ -13,6 +13,7 @@
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2021 K. Lange
*/
#include <errno.h>
#include <kernel/printf.h>
#include <kernel/string.h>
#include <kernel/process.h>
@ -324,6 +325,27 @@ uint64_t now(void) {
return t.tv_sec;
}
static spin_lock_t _time_set_lock;
/**
* Set the system clock time
*
* TODO: A lot of this time stuff needs to be made more generic,
* it's shared pretty directly with aarch64...
*/
int settimeofday(struct timeval * t, void *z) {
if (!t) return -EINVAL;
if (t->tv_sec < 0 || t->tv_usec < 0 || t->tv_usec > 1000000) return -EINVAL;
spin_lock(_time_set_lock);
uint64_t clock_time = now();
arch_boot_time += t->tv_sec - clock_time;
spin_unlock(_time_set_lock);
return 0;
}
/**
* @brief Calculate a time in the future.
*

View File

@ -557,6 +557,14 @@ long sys_gettimeofday(struct timeval * tv, void * tz) {
return gettimeofday(tv, tz);
}
long sys_settimeofday(struct timeval * tv, void * tz) {
extern int settimeofday(struct timeval * t, void *z);
if (this_core->current_process->user != USER_ROOT_UID) return -EPERM;
PTR_VALIDATE(tv);
PTR_VALIDATE(tz);
return settimeofday(tv,tz);
}
long sys_getuid(void) {
return (long)this_core->current_process->real_user;
}
@ -1146,6 +1154,7 @@ static long (*syscalls[])() = {
[SYS_SETGROUPS] = sys_setgroups,
[SYS_TIMES] = sys_times,
[SYS_PTRACE] = ptrace_handle,
[SYS_SETTIMEOFDAY] = sys_settimeofday,
[SYS_SOCKET] = net_socket,
[SYS_SETSOCKOPT] = net_setsockopt,

11
libc/time/settimeofday.c Normal file
View File

@ -0,0 +1,11 @@
#include <sys/time.h>
#include <syscall.h>
#include <syscall_nums.h>
DEFN_SYSCALL2(settimeofday, SYS_SETTIMEOFDAY, void *, void *);
int settimeofday(struct timeval *p, void *z){
return syscall_settimeofday(p,z);
}