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