Home | History | Annotate | Download | only in toolbox
      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