toybox/toys/other/hwclock.c
<<
>>
Prefs
   1/* hwclock.c - get and set the hwclock
   2 *
   3 * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com>
   4 *
   5 * No standard, but see Documentation/rtc.txt in the linux kernel source..
   6 *
   7USE_HWCLOCK(NEWTOY(hwclock, ">0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]", TOYFLAG_SBIN))
   8
   9config HWCLOCK
  10  bool "hwclock"
  11  default y
  12  help
  13    usage: hwclock [-rswtluf]
  14
  15    Get/set the hardware clock.
  16
  17    -f FILE     Use specified device file instead of /dev/rtc0 (--rtc)
  18    -l  Hardware clock uses localtime (--localtime)
  19    -r  Show hardware clock time (--show)
  20    -s  Set system time from hardware clock (--hctosys)
  21    -t  Set the system time based on the current timezone (--systz)
  22    -u  Hardware clock uses UTC (--utc)
  23    -w  Set hardware clock from system time (--systohc)
  24*/
  25
  26#define FOR_hwclock
  27#include "toys.h"
  28#include <linux/rtc.h>
  29
  30GLOBALS(
  31  char *f;
  32)
  33
  34void hwclock_main()
  35{
  36  struct timezone tzone;
  37  struct timeval timeval;
  38  struct tm tm;
  39  int fd = -1, utc;
  40
  41  if (FLAG(u)) utc = 1;
  42  else if (FLAG(l)) utc = 0;
  43  else utc = !readfile("/etc/adjtime", toybuf, sizeof(toybuf)) ||
  44    !!strstr(toybuf, "UTC");
  45
  46  if (!FLAG(t)) {
  47    if (!TT.f) TT.f = "/dev/rtc0";
  48    fd = xopen(TT.f, O_WRONLY*FLAG(w));
  49
  50    // Get current time in seconds from rtc device. todo: get subsecond time
  51    if (!FLAG(w)) {
  52      xioctl(fd, RTC_RD_TIME, &tm);
  53      timeval.tv_sec = xmktime(&tm, utc);
  54      timeval.tv_usec = 0; // todo: fixit
  55    }
  56  }
  57
  58  if (FLAG(w) || FLAG(t)) {
  59    if (gettimeofday(&timeval, 0)) perror_exit("gettimeofday failed");
  60    if (!(utc ? gmtime_r : localtime_r)(&timeval.tv_sec, &tm))
  61      error_exit(utc ? "gmtime_r failed" : "localtime_r failed");
  62  }
  63
  64  if (FLAG(w)) {
  65    /* The value of tm_isdst is positive if daylight saving time is in effect,
  66     * zero if it is not and negative if the information is not available. 
  67     * todo: so why isn't this negative...? */
  68    tm.tm_isdst = 0;
  69    xioctl(fd, RTC_SET_TIME, &tm);
  70  } else if (FLAG(s)) {
  71    tzone.tz_minuteswest = timezone / 60 - 60 * daylight;
  72  } else if (FLAG(t)) {
  73    // Adjust seconds for timezone and daylight saving time
  74    // extern long timezone is defined in header sys/time.h
  75    tzone.tz_minuteswest = timezone / 60;
  76    if (tm.tm_isdst) tzone.tz_minuteswest -= 60;
  77    if (!utc) timeval.tv_sec += tzone.tz_minuteswest * 60;
  78  } else {
  79    strftime(toybuf, sizeof(toybuf), "%F %T%z", &tm);
  80    xputs(toybuf);
  81  }
  82  if (FLAG(t) || FLAG(s)) {
  83    tzone.tz_dsttime = 0;
  84    if (settimeofday(&timeval, &tzone)) perror_exit("settimeofday failed");
  85  }
  86
  87  xclose(fd);
  88}
  89