platform_system_core/toolbox/date.c
Benoit Goby d340734cd7 toolbox: Fix date tool with /dev/alarm
Change-Id: I6f8ad2149244c89690d5d5caae8ec55429462210
Signed-off-by: Benoit Goby <benoit@android.com>
2014-01-09 18:59:23 -08:00

200 lines
4.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <linux/android_alarm.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
static int settime_alarm(struct timespec *ts) {
int fd, ret;
fd = open("/dev/alarm", O_RDWR);
if (fd < 0)
return fd;
ret = ioctl(fd, ANDROID_ALARM_SET_RTC, ts);
close(fd);
return ret;
}
static int settime_alarm_tm(struct tm *tm) {
time_t t;
struct timespec ts;
t = mktime(tm);
ts.tv_sec = t;
ts.tv_nsec = 0;
return settime_alarm(&ts);
}
static int settime_alarm_timeval(struct timeval *tv) {
struct timespec ts;
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
return settime_alarm(&ts);
}
static int settime_rtc_tm(struct tm *tm) {
int fd, ret;
struct timeval tv;
struct rtc_time rtc;
fd = open("/dev/rtc0", O_RDWR);
if (fd < 0)
return fd;
tv.tv_sec = mktime(tm);
tv.tv_usec = 0;
ret = settimeofday(&tv, NULL);
if (ret < 0)
goto done;
memset(&rtc, 0, sizeof(rtc));
rtc.tm_sec = tm->tm_sec;
rtc.tm_min = tm->tm_min;
rtc.tm_hour = tm->tm_hour;
rtc.tm_mday = tm->tm_mday;
rtc.tm_mon = tm->tm_mon;
rtc.tm_year = tm->tm_year;
rtc.tm_wday = tm->tm_wday;
rtc.tm_yday = tm->tm_yday;
rtc.tm_isdst = tm->tm_isdst;
ret = ioctl(fd, RTC_SET_TIME, rtc);
done:
close(fd);
return ret;
}
static int settime_rtc_timeval(struct timeval *tv) {
struct tm tm, *err;
time_t t = tv->tv_sec;
err = gmtime_r(&t, &tm);
if (!err)
return -1;
return settime_rtc_tm(&tm);
}
static void settime(char *s) {
struct tm tm;
int day = atoi(s);
int hour;
while (*s && *s != '.')
s++;
if (*s)
s++;
hour = atoi(s);
tm.tm_year = day / 10000 - 1900;
tm.tm_mon = (day % 10000) / 100 - 1;
tm.tm_mday = (day % 100);
tm.tm_hour = hour / 10000;
tm.tm_min = (hour % 10000) / 100;
tm.tm_sec = (hour % 100);
tm.tm_isdst = -1;
if (settime_alarm_tm(&tm) < 0)
settime_rtc_tm(&tm);
}
int date_main(int argc, char *argv[])
{
int c;
int res;
struct tm tm;
time_t t;
struct timeval tv;
struct timespec ts;
char strbuf[260];
int fd;
int useutc = 0;
tzset();
do {
c = getopt(argc, argv, "us:");
if (c == EOF)
break;
switch (c) {
case 'u':
useutc = 1;
break;
case 's':
settime(optarg);
break;
case '?':
fprintf(stderr, "%s: invalid option -%c\n",
argv[0], optopt);
exit(1);
}
} while (1);
if(optind + 2 < argc) {
fprintf(stderr,"%s [-u] [date]\n", argv[0]);
return 1;
}
int hasfmt = argc == optind + 1 && argv[optind][0] == '+';
if(optind == argc || hasfmt) {
char buf[2000];
time(&t);
if (useutc) {
gmtime_r(&t, &tm);
strftime(strbuf, sizeof(strbuf),
(hasfmt ? argv[optind] + 1 : "%a %b %e %H:%M:%S GMT %Y"),
&tm);
} else {
localtime_r(&t, &tm);
strftime(strbuf, sizeof(strbuf),
(hasfmt ? argv[optind] + 1 : "%a %b %e %H:%M:%S %Z %Y"),
&tm);
}
printf("%s\n", strbuf);
}
else if(optind + 1 == argc) {
#if 0
struct tm *tmptr;
tmptr = getdate(argv[optind]);
if(tmptr == NULL) {
fprintf(stderr,"getdate_r failed\n");
return 1;
}
tm = *tmptr;
#if 0
if(getdate_r(argv[optind], &tm) < 0) {
fprintf(stderr,"getdate_r failed %s\n", strerror(errno));
return 1;
}
#endif
#endif
//strptime(argv[optind], NULL, &tm);
//tv.tv_sec = mktime(&tm);
//tv.tv_usec = 0;
strtotimeval(argv[optind], &tv);
printf("time %s -> %lu.%lu\n", argv[optind], tv.tv_sec, tv.tv_usec);
res = settime_alarm_timeval(&tv);
if (res < 0)
res = settime_rtc_timeval(&tv);
if(res < 0) {
fprintf(stderr,"settimeofday failed %s\n", strerror(errno));
return 1;
}
}
else {
fprintf(stderr,"%s [-s 20070325.123456] [-u] [date]\n", argv[0]);
return 1;
}
return 0;
}