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