blob: d6c90520e7b5bb1df1adc2d93ba16fcb3cca6dfc [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#include <stdio.h>
2#include <stdlib.h>
Olivier Baillyb93e5812010-11-17 11:47:23 -08003#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08004#include <fcntl.h>
5#include <string.h>
6#include <errno.h>
7#include <time.h>
8#include <linux/android_alarm.h>
Greg Hackmann4a7bc602013-12-17 14:00:03 -08009#include <linux/rtc.h>
Olivier Baillyb93e5812010-11-17 11:47:23 -080010#include <sys/ioctl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080011
Greg Hackmann4a7bc602013-12-17 14:00:03 -080012static 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
Benoit Gobyd3407342014-01-09 18:59:23 -080019 ret = ioctl(fd, ANDROID_ALARM_SET_RTC, ts);
Greg Hackmann4a7bc602013-12-17 14:00:03 -080020 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080086static void settime(char *s) {
87 struct tm tm;
88 int day = atoi(s);
89 int hour;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080090
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
Greg Hackmann4a7bc602013-12-17 14:00:03 -0800107 if (settime_alarm_tm(&tm) < 0)
108 settime_rtc_tm(&tm);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109}
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);
Greg Hackmannc0575032013-12-17 13:59:06 -0800185 printf("time %s -> %lu.%lu\n", argv[optind], tv.tv_sec, tv.tv_usec);
Greg Hackmann4a7bc602013-12-17 14:00:03 -0800186 res = settime_alarm_timeval(&tv);
187 if (res < 0)
188 res = settime_rtc_timeval(&tv);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189 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}