date.c revision 4a7bc60071901dce2af85ec56a088604b6c228ce
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <fcntl.h>
5#include <string.h>
6#include <errno.h>
7#include <time.h>
8#include <linux/android_alarm.h>
9#include <linux/rtc.h>
10#include <sys/ioctl.h>
11
12static int settime_alarm(struct timespec *ts) {
13    int fd, ret;
14
15    fd = open("/dev/alarm", O_RDWR);
16    if (fd < 0)
17        return fd;
18
19    ret = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
20    close(fd);
21    return ret;
22}
23
24static int settime_alarm_tm(struct tm *tm) {
25    time_t t;
26    struct timespec ts;
27
28    t = mktime(tm);
29    ts.tv_sec = t;
30    ts.tv_nsec = 0;
31    return settime_alarm(&ts);
32}
33
34static int settime_alarm_timeval(struct timeval *tv) {
35    struct timespec ts;
36
37    ts.tv_sec = tv->tv_sec;
38    ts.tv_nsec = tv->tv_usec * 1000;
39    return settime_alarm(&ts);
40}
41
42static int settime_rtc_tm(struct tm *tm) {
43    int fd, ret;
44    struct timeval tv;
45    struct rtc_time rtc;
46
47    fd = open("/dev/rtc0", O_RDWR);
48    if (fd < 0)
49        return fd;
50
51    tv.tv_sec = mktime(tm);
52    tv.tv_usec = 0;
53
54    ret = settimeofday(&tv, NULL);
55    if (ret < 0)
56        goto done;
57
58    memset(&rtc, 0, sizeof(rtc));
59    rtc.tm_sec = tm->tm_sec;
60    rtc.tm_min = tm->tm_min;
61    rtc.tm_hour = tm->tm_hour;
62    rtc.tm_mday = tm->tm_mday;
63    rtc.tm_mon = tm->tm_mon;
64    rtc.tm_year = tm->tm_year;
65    rtc.tm_wday = tm->tm_wday;
66    rtc.tm_yday = tm->tm_yday;
67    rtc.tm_isdst = tm->tm_isdst;
68
69    ret = ioctl(fd, RTC_SET_TIME, rtc);
70done:
71    close(fd);
72    return ret;
73}
74
75static int settime_rtc_timeval(struct timeval *tv) {
76    struct tm tm, *err;
77    time_t t = tv->tv_sec;
78
79    err = gmtime_r(&t, &tm);
80    if (!err)
81        return -1;
82
83    return settime_rtc_tm(&tm);
84}
85
86static void settime(char *s) {
87    struct tm tm;
88    int day = atoi(s);
89    int hour;
90
91    while (*s && *s != '.')
92        s++;
93
94    if (*s)
95        s++;
96
97    hour = atoi(s);
98
99    tm.tm_year = day / 10000 - 1900;
100    tm.tm_mon = (day % 10000) / 100 - 1;
101    tm.tm_mday = (day % 100);
102    tm.tm_hour = hour / 10000;
103    tm.tm_min = (hour % 10000) / 100;
104    tm.tm_sec = (hour % 100);
105    tm.tm_isdst = -1;
106
107    if (settime_alarm_tm(&tm) < 0)
108        settime_rtc_tm(&tm);
109}
110
111int date_main(int argc, char *argv[])
112{
113	int c;
114    int res;
115	struct tm tm;
116	time_t t;
117	struct timeval tv;
118    struct timespec ts;
119	char strbuf[260];
120    int fd;
121
122    int useutc = 0;
123
124    tzset();
125
126    do {
127        c = getopt(argc, argv, "us:");
128        if (c == EOF)
129            break;
130        switch (c) {
131        case 'u':
132            useutc = 1;
133            break;
134        case 's':
135            settime(optarg);
136            break;
137        case '?':
138            fprintf(stderr, "%s: invalid option -%c\n",
139                argv[0], optopt);
140            exit(1);
141        }
142    } while (1);
143    if(optind + 2 < argc) {
144        fprintf(stderr,"%s [-u] [date]\n", argv[0]);
145        return 1;
146    }
147
148    int hasfmt = argc == optind + 1 && argv[optind][0] == '+';
149    if(optind == argc || hasfmt) {
150        char buf[2000];
151        time(&t);
152        if (useutc) {
153            gmtime_r(&t, &tm);
154            strftime(strbuf, sizeof(strbuf),
155                     (hasfmt ? argv[optind] + 1 : "%a %b %e %H:%M:%S GMT %Y"),
156                     &tm);
157        } else {
158            localtime_r(&t, &tm);
159            strftime(strbuf, sizeof(strbuf),
160                     (hasfmt ? argv[optind] + 1 : "%a %b %e %H:%M:%S %Z %Y"),
161                     &tm);
162        }
163        printf("%s\n", strbuf);
164    }
165    else if(optind + 1 == argc) {
166#if 0
167        struct tm *tmptr;
168        tmptr = getdate(argv[optind]);
169        if(tmptr == NULL) {
170            fprintf(stderr,"getdate_r failed\n");
171            return 1;
172        }
173        tm = *tmptr;
174#if 0
175        if(getdate_r(argv[optind], &tm) < 0) {
176            fprintf(stderr,"getdate_r failed %s\n", strerror(errno));
177            return 1;
178        }
179#endif
180#endif
181        //strptime(argv[optind], NULL, &tm);
182        //tv.tv_sec = mktime(&tm);
183        //tv.tv_usec = 0;
184        strtotimeval(argv[optind], &tv);
185        printf("time %s -> %lu.%lu\n", argv[optind], tv.tv_sec, tv.tv_usec);
186        res = settime_alarm_timeval(&tv);
187        if (res < 0)
188            res = settime_rtc_timeval(&tv);
189        if(res < 0) {
190            fprintf(stderr,"settimeofday failed %s\n", strerror(errno));
191            return 1;
192        }
193    }
194    else {
195        fprintf(stderr,"%s [-s 20070325.123456] [-u] [date]\n", argv[0]);
196        return 1;
197    }
198
199    return 0;
200}
201