master xplshn/aruu / cmd / linux / hwclock.c
  1/* See LICENSE file for copyright and license details. */
  2
  3#include <sys/ioctl.h>
  4#include <sys/stat.h>
  5#include <sys/time.h>
  6#include <sys/types.h>
  7
  8#include <fcntl.h>
  9#include <stdio.h>
 10#include <stdlib.h>
 11#include <string.h>
 12#include <time.h>
 13#include <unistd.h>
 14
 15#include "paths.h"
 16#include "rtc.h"
 17#include "util.h"
 18
 19static void
 20readrtctm(struct tm *tm, int fd)
 21{
 22  struct rtc_time rt;
 23
 24  memset(&rt, 0, sizeof(rt));
 25  if (ioctl(fd, (int)RTC_RD_TIME, &rt) < 0)
 26    eprintf("RTC_RD_TIME:");
 27  tm->tm_sec   = rt.tm_sec;
 28  tm->tm_min   = rt.tm_min;
 29  tm->tm_hour  = rt.tm_hour;
 30  tm->tm_mday  = rt.tm_mday;
 31  tm->tm_mon   = rt.tm_mon;
 32  tm->tm_year  = rt.tm_year;
 33  tm->tm_wday  = rt.tm_wday;
 34  tm->tm_yday  = rt.tm_yday;
 35  tm->tm_isdst = rt.tm_isdst;
 36}
 37
 38static void
 39writertctm(struct tm *tm, int fd)
 40{
 41  struct rtc_time rt;
 42
 43  rt.tm_sec   = tm->tm_sec;
 44  rt.tm_min   = tm->tm_min;
 45  rt.tm_hour  = tm->tm_hour;
 46  rt.tm_mday  = tm->tm_mday;
 47  rt.tm_mon   = tm->tm_mon;
 48  rt.tm_year  = tm->tm_year;
 49  rt.tm_wday  = tm->tm_wday;
 50  rt.tm_yday  = tm->tm_yday;
 51  rt.tm_isdst = tm->tm_isdst;
 52  if (ioctl(fd, (int)RTC_SET_TIME, &rt) < 0)
 53    eprintf("RTC_SET_TIME:");
 54}
 55
 56static void
 57show(char *dev)
 58{
 59  struct tm tm;
 60  time_t    t;
 61  int       fd;
 62
 63  fd = open(dev, O_RDONLY);
 64  if (fd < 0)
 65    eprintf("open %s:", dev);
 66  readrtctm(&tm, fd);
 67  t = mktime(&tm);
 68  printf("%s", asctime(localtime(&t)));
 69  close(fd);
 70}
 71
 72static void
 73hctosys(char *dev)
 74{
 75  struct timeval tv;
 76  struct tm      tm;
 77  int            r;
 78  int            fd;
 79
 80  fd = open(dev, O_RDONLY);
 81  if (fd < 0)
 82    eprintf("open %s:", dev);
 83  readrtctm(&tm, fd);
 84  tv.tv_sec  = mktime(&tm);
 85  tv.tv_usec = 0;
 86  r          = settimeofday(&tv, NULL);
 87  if (r < 0)
 88    eprintf("settimeofday:");
 89  close(fd);
 90}
 91
 92static void
 93systohc(char *dev)
 94{
 95  struct timeval tv;
 96  struct tm     *tm;
 97  time_t         t;
 98  int            fd;
 99
100  fd = open(dev, O_WRONLY);
101  if (fd < 0)
102    eprintf("open %s:", dev);
103  gettimeofday(&tv, NULL);
104  t  = tv.tv_sec;
105  tm = gmtime(&t);
106  weprintf("warning: assuming UTC for systohc\n");
107  writertctm(tm, fd);
108  close(fd);
109}
110
111static void
112usage(void)
113{
114  eprintf("usage: %s [-rsw] [-u] [dev]\n", argv0);
115}
116
117// ?man hwclock: query or set the hardware clock
118// ?man arguments: dev
119// ?man view or adjust the hardware real time clock
120int
121main(int argc, char *argv[])
122{
123  char *dev   = ARUU_PATH_DEV "/rtc";
124  int   rflag = 0;
125  int   sflag = 0;
126  int   wflag = 0;
127
128  ARGBEGIN
129  {
130    // ?man -r: operate recursively
131    case 'r':
132      rflag = 1;
133      break;
134    // ?man -s: silent mode or print summary
135    case 's':
136      sflag = 1;
137      break;
138    // ?man -w: wait for completion
139    case 'w':
140      wflag = 1;
141      break;
142    // ?man -u: unbuffered output
143    case 'u':
144      break;
145    default:
146      usage();
147  }
148  ARGEND;
149
150  if (argc > 1)
151    usage();
152  else if (argc == 1)
153    dev = argv[0];
154
155  if ((rflag ^ sflag ^ wflag) == 0)
156    eprintf("missing or incompatible function\n");
157
158  /* Only UTC support at the moment */
159  setenv("TZ", "UTC0", 1);
160  tzset();
161
162  if (rflag == 1)
163    show(dev);
164  else if (sflag == 1)
165    hctosys(dev);
166  else if (wflag == 1)
167    systohc(dev);
168
169  return 0;
170}