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 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 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 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 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 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 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 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 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