blob: 6dff57f094a5ff9192337f6c3278938cbf960642 [file] [log] [blame]
Robert Griebl1cd04452002-07-21 16:50:49 +00001/* vi: set sw=4 ts=4: */
2/*
Robert Griebl6859d762002-08-05 02:57:12 +00003 * Mini hwclock implementation for busybox
4 *
Robert Griebl1cd04452002-07-21 16:50:49 +00005 * Copyright (C) 2002 Robert Griebl <griebl@gmx.de>
6 *
Bernhard Reutner-Fischer5cf905a2006-03-31 22:36:15 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Robert Griebl6859d762002-08-05 02:57:12 +00008*/
Robert Griebl1cd04452002-07-21 16:50:49 +00009
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000010#include "libbb.h"
Denys Vlasenko043b1e52009-09-06 12:47:55 +020011/* After libbb.h, since it needs sys/types.h on some systems */
12#include <sys/utsname.h>
Mike Frysinger6b160e42008-02-15 02:27:19 +000013#include "rtc_.h"
Eric Andersen8882ea52002-12-11 03:41:28 +000014
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +000015#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
Robert Griebl1cd04452002-07-21 16:50:49 +000016# ifndef _GNU_SOURCE
17# define _GNU_SOURCE
18# endif
19#endif
20
Denis Vlasenko673d4bb2007-03-07 23:02:50 +000021static const char *rtcname;
22
Denis Vlasenko92258542006-11-01 10:25:35 +000023static time_t read_rtc(int utc)
24{
Mike Frysinger6b160e42008-02-15 02:27:19 +000025 time_t ret;
26 int fd;
Robert Griebl1cd04452002-07-21 16:50:49 +000027
Mike Frysinger977bc6a2008-02-15 07:19:03 +000028 fd = rtc_xopen(&rtcname, O_RDONLY);
Mike Frysinger6b160e42008-02-15 02:27:19 +000029 ret = rtc_read_time(fd, utc);
30 close(fd);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000031
Mike Frysinger6b160e42008-02-15 02:27:19 +000032 return ret;
Robert Griebl1cd04452002-07-21 16:50:49 +000033}
34
Glenn L McGrath689e4b92004-02-22 09:11:33 +000035static void write_rtc(time_t t, int utc)
Robert Griebl1cd04452002-07-21 16:50:49 +000036{
Robert Griebl1cd04452002-07-21 16:50:49 +000037 struct tm tm;
Mike Frysinger977bc6a2008-02-15 07:19:03 +000038 int rtc = rtc_xopen(&rtcname, O_WRONLY);
Robert Griebl1cd04452002-07-21 16:50:49 +000039
Denys Vlasenko73b71f32009-07-18 03:40:35 +020040 if (utc)
41 gmtime_r(&t, &tm);
42 else
43 localtime_r(&t, &tm);
Bernhard Reutner-Fischer5cf905a2006-03-31 22:36:15 +000044 tm.tm_isdst = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000045
Denis Vlasenkofb79a2e2007-07-14 22:07:14 +000046 xioctl(rtc, RTC_SET_TIME, &tm);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000047
Denis Vlasenko92258542006-11-01 10:25:35 +000048 close(rtc);
Robert Griebl1cd04452002-07-21 16:50:49 +000049}
50
Denis Vlasenko459be352007-06-17 19:09:05 +000051static void show_clock(int utc)
Robert Griebl1cd04452002-07-21 16:50:49 +000052{
Denis Vlasenko459be352007-06-17 19:09:05 +000053 //struct tm *ptm;
Robert Griebl1cd04452002-07-21 16:50:49 +000054 time_t t;
Denis Vlasenko459be352007-06-17 19:09:05 +000055 char *cp;
Robert Griebl1cd04452002-07-21 16:50:49 +000056
Denis Vlasenko92258542006-11-01 10:25:35 +000057 t = read_rtc(utc);
Denis Vlasenko459be352007-06-17 19:09:05 +000058 //ptm = localtime(&t); /* Sets 'tzname[]' */
Eric Andersenc7bda1c2004-03-15 08:29:22 +000059
Denis Vlasenko459be352007-06-17 19:09:05 +000060 cp = ctime(&t);
61 if (cp[0])
62 cp[strlen(cp) - 1] = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +000063
Denis Vlasenko459be352007-06-17 19:09:05 +000064 //printf("%s %.6f seconds %s\n", cp, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0]));
65 printf("%s 0.000000 seconds\n", cp);
Robert Griebl1cd04452002-07-21 16:50:49 +000066}
67
Denis Vlasenko459be352007-06-17 19:09:05 +000068static void to_sys_clock(int utc)
Robert Griebl1cd04452002-07-21 16:50:49 +000069{
Denis Vlasenko459be352007-06-17 19:09:05 +000070 struct timeval tv;
Denys Vlasenko043b1e52009-09-06 12:47:55 +020071 struct timezone tz;
72
73 tz.tz_minuteswest = timezone/60 - 60*daylight;
74 tz.tz_dsttime = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000075
Denis Vlasenko92258542006-11-01 10:25:35 +000076 tv.tv_sec = read_rtc(utc);
Denis Vlasenko459be352007-06-17 19:09:05 +000077 tv.tv_usec = 0;
Denis Vlasenko92258542006-11-01 10:25:35 +000078 if (settimeofday(&tv, &tz))
79 bb_perror_msg_and_die("settimeofday() failed");
Robert Griebl1cd04452002-07-21 16:50:49 +000080}
81
Denis Vlasenko459be352007-06-17 19:09:05 +000082static void from_sys_clock(int utc)
Robert Griebl1cd04452002-07-21 16:50:49 +000083{
Denis Vlasenko459be352007-06-17 19:09:05 +000084 struct timeval tv;
Robert Griebl1cd04452002-07-21 16:50:49 +000085
Denis Vlasenko459be352007-06-17 19:09:05 +000086 gettimeofday(&tv, NULL);
87 //if (gettimeofday(&tv, NULL))
88 // bb_perror_msg_and_die("gettimeofday() failed");
Denis Vlasenko92258542006-11-01 10:25:35 +000089 write_rtc(tv.tv_sec, utc);
Robert Griebl1cd04452002-07-21 16:50:49 +000090}
91
Denis Vlasenko92258542006-11-01 10:25:35 +000092#define HWCLOCK_OPT_LOCALTIME 0x01
93#define HWCLOCK_OPT_UTC 0x02
94#define HWCLOCK_OPT_SHOW 0x04
95#define HWCLOCK_OPT_HCTOSYS 0x08
96#define HWCLOCK_OPT_SYSTOHC 0x10
Denis Vlasenko673d4bb2007-03-07 23:02:50 +000097#define HWCLOCK_OPT_RTCFILE 0x20
Glenn L McGrath689e4b92004-02-22 09:11:33 +000098
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000099int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000100int hwclock_main(int argc UNUSED_PARAM, char **argv)
Robert Griebl1cd04452002-07-21 16:50:49 +0000101{
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000102 unsigned opt;
Robert Griebl6bb80872004-03-22 21:27:39 +0000103 int utc;
Robert Griebl1cd04452002-07-21 16:50:49 +0000104
Bernhard Reutner-Fischer01d23ad2006-05-26 20:19:22 +0000105#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000106 static const char hwclock_longopts[] ALIGN1 =
Denis Vlasenkobdc88fd2007-07-23 17:14:14 +0000107 "localtime\0" No_argument "l"
108 "utc\0" No_argument "u"
109 "show\0" No_argument "r"
110 "hctosys\0" No_argument "s"
111 "systohc\0" No_argument "w"
112 "file\0" Required_argument "f"
Denis Vlasenko990d0f62007-07-24 15:54:42 +0000113 ;
Denis Vlasenkobdc88fd2007-07-23 17:14:14 +0000114 applet_long_options = hwclock_longopts;
Robert Griebl1cd04452002-07-21 16:50:49 +0000115#endif
Denis Vlasenko09196572007-07-21 13:27:44 +0000116 opt_complementary = "r--ws:w--rs:s--wr:l--u:u--l";
Denis Vlasenkofe7cd642007-08-18 15:32:12 +0000117 opt = getopt32(argv, "lurswf:", &rtcname);
Robert Griebl1cd04452002-07-21 16:50:49 +0000118
Robert Griebl6bb80872004-03-22 21:27:39 +0000119 /* If -u or -l wasn't given check if we are using utc */
Mike Frysingerb31566e2005-04-16 04:48:48 +0000120 if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
Mike Frysinger6b160e42008-02-15 02:27:19 +0000121 utc = (opt & HWCLOCK_OPT_UTC);
Robert Griebl6bb80872004-03-22 21:27:39 +0000122 else
Mike Frysinger6b160e42008-02-15 02:27:19 +0000123 utc = rtc_adjtime_is_utc();
Mike Frysingerb31566e2005-04-16 04:48:48 +0000124
Mike Frysinger6b160e42008-02-15 02:27:19 +0000125 if (opt & HWCLOCK_OPT_HCTOSYS)
Denis Vlasenko459be352007-06-17 19:09:05 +0000126 to_sys_clock(utc);
Mike Frysinger6b160e42008-02-15 02:27:19 +0000127 else if (opt & HWCLOCK_OPT_SYSTOHC)
Denis Vlasenko459be352007-06-17 19:09:05 +0000128 from_sys_clock(utc);
Mike Frysinger6b160e42008-02-15 02:27:19 +0000129 else
130 /* default HWCLOCK_OPT_SHOW */
131 show_clock(utc);
132
Denis Vlasenko459be352007-06-17 19:09:05 +0000133 return 0;
Robert Griebl1cd04452002-07-21 16:50:49 +0000134}