date: add rudimentary support for setting date/time
This commit is contained in:
parent
89ba900988
commit
b3f6728339
81
apps/date.c
81
apps/date.c
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -72,3 +72,4 @@
|
||||
#define SYS_GETGROUPS 69
|
||||
#define SYS_SETGROUPS 70
|
||||
#define SYS_TIMES 71
|
||||
#define SYS_SETTIMEOFDAY 72
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
11
libc/time/settimeofday.c
Normal 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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user