master xplshn/aruu / cmd / linux / hwclock.c
  1/* See LICENSE file for copyright and license details. */
  2
  3
  4#include <sys/ioctl.h>
  5#include <sys/stat.h>
  6#include <sys/time.h>
  7#include <sys/types.h>
  8
  9#include <fcntl.h>
 10#include <stdio.h>
 11#include <stdlib.h>
 12#include <string.h>
 13#include <time.h>
 14#include <unistd.h>
 15
 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 = "/dev/rtc";
124	int rflag = 0;
125	int sflag = 0;
126	int wflag = 0;
127
128	ARGBEGIN {
129	// ?man -r: operate recursively
130	case 'r':
131		rflag = 1;
132		break;
133	// ?man -s: silent mode or print summary
134	case 's':
135		sflag = 1;
136		break;
137	// ?man -w: wait for completion
138	case 'w':
139		wflag = 1;
140		break;
141	// ?man -u: unbuffered output
142	case 'u':
143		break;
144	default:
145		usage();
146	} ARGEND;
147
148	if (argc > 1)
149		usage();
150	else if (argc == 1)
151		dev = argv[0];
152
153	if ((rflag ^ sflag ^ wflag) == 0)
154		eprintf("missing or incompatible function\n");
155
156	/* Only UTC support at the moment */
157	setenv("TZ", "UTC0", 1);
158	tzset();
159
160	if (rflag == 1)
161		show(dev);
162	else if (sflag == 1)
163		hctosys(dev);
164	else if (wflag == 1)
165		systohc(dev);
166
167	return 0;
168}