svlogd: fix compat problem: svlogd -tt should timestanp stderr too
[busybox.git] / util-linux / hwclock.c
blobf91379bed90f8b1b224326445e38d49b43d8fdba
1 /* vi: set sw=4 ts=4: */
2 /*
3 * Mini hwclock implementation for busybox
5 * Copyright (C) 2002 Robert Griebl <griebl@gmx.de>
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */
10 #include <sys/utsname.h>
11 #include <getopt.h>
12 #include "libbb.h"
14 /* Copied from linux/rtc.h to eliminate the kernel dependency */
15 struct linux_rtc_time {
16 int tm_sec;
17 int tm_min;
18 int tm_hour;
19 int tm_mday;
20 int tm_mon;
21 int tm_year;
22 int tm_wday;
23 int tm_yday;
24 int tm_isdst;
27 #define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time */
28 #define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time */
30 #if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
31 # ifndef _GNU_SOURCE
32 # define _GNU_SOURCE
33 # endif
34 #endif
36 static const char *rtcname;
38 static int xopen_rtc(int flags)
40 int rtc;
42 if (!rtcname) {
43 rtc = open("/dev/rtc", flags);
44 if (rtc >= 0)
45 return rtc;
46 rtc = open("/dev/rtc0", flags);
47 if (rtc >= 0)
48 return rtc;
49 rtcname = "/dev/misc/rtc";
51 return xopen(rtcname, flags);
54 static time_t read_rtc(int utc)
56 struct tm tm;
57 char *oldtz = 0;
58 time_t t = 0;
59 int rtc = xopen_rtc(O_RDONLY);
61 memset(&tm, 0, sizeof(struct tm));
62 xioctl(rtc, RTC_RD_TIME, &tm);
63 tm.tm_isdst = -1; /* not known */
65 close(rtc);
67 if (utc) {
68 oldtz = getenv("TZ");
69 putenv((char*)"TZ=UTC0");
70 tzset();
73 t = mktime(&tm);
75 if (utc) {
76 unsetenv("TZ");
77 if (oldtz)
78 putenv(oldtz - 3);
79 tzset();
81 return t;
84 static void write_rtc(time_t t, int utc)
86 struct tm tm;
87 int rtc = xopen_rtc(O_WRONLY);
89 tm = *(utc ? gmtime(&t) : localtime(&t));
90 tm.tm_isdst = 0;
92 xioctl(rtc, RTC_SET_TIME, &tm);
94 close(rtc);
97 static void show_clock(int utc)
99 //struct tm *ptm;
100 time_t t;
101 char *cp;
103 t = read_rtc(utc);
104 //ptm = localtime(&t); /* Sets 'tzname[]' */
106 cp = ctime(&t);
107 if (cp[0])
108 cp[strlen(cp) - 1] = '\0';
110 //printf("%s %.6f seconds %s\n", cp, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0]));
111 printf("%s 0.000000 seconds\n", cp);
114 static void to_sys_clock(int utc)
116 struct timeval tv;
117 const struct timezone tz = { timezone/60 - 60*daylight, 0 };
119 tv.tv_sec = read_rtc(utc);
120 tv.tv_usec = 0;
121 if (settimeofday(&tv, &tz))
122 bb_perror_msg_and_die("settimeofday() failed");
125 static void from_sys_clock(int utc)
127 struct timeval tv;
129 gettimeofday(&tv, NULL);
130 //if (gettimeofday(&tv, NULL))
131 // bb_perror_msg_and_die("gettimeofday() failed");
132 write_rtc(tv.tv_sec, utc);
135 #if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
136 # define ADJTIME_PATH "/var/lib/hwclock/adjtime"
137 #else
138 # define ADJTIME_PATH "/etc/adjtime"
139 #endif
140 static int check_utc(void)
142 int utc = 0;
143 FILE *f = fopen(ADJTIME_PATH, "r");
145 if (f) {
146 RESERVE_CONFIG_BUFFER(buffer, 128);
148 while (fgets(buffer, sizeof(buffer), f)) {
149 int len = strlen(buffer);
151 while (len && isspace(buffer[len - 1]))
152 len--;
154 buffer[len] = 0;
156 if (strncmp(buffer, "UTC", 3) == 0) {
157 utc = 1;
158 break;
161 fclose(f);
162 RELEASE_CONFIG_BUFFER(buffer);
164 return utc;
167 #define HWCLOCK_OPT_LOCALTIME 0x01
168 #define HWCLOCK_OPT_UTC 0x02
169 #define HWCLOCK_OPT_SHOW 0x04
170 #define HWCLOCK_OPT_HCTOSYS 0x08
171 #define HWCLOCK_OPT_SYSTOHC 0x10
172 #define HWCLOCK_OPT_RTCFILE 0x20
174 int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
175 int hwclock_main(int argc, char **argv)
177 unsigned opt;
178 int utc;
180 #if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
181 static const char hwclock_longopts[] ALIGN1 =
182 "localtime\0" No_argument "l"
183 "utc\0" No_argument "u"
184 "show\0" No_argument "r"
185 "hctosys\0" No_argument "s"
186 "systohc\0" No_argument "w"
187 "file\0" Required_argument "f"
189 applet_long_options = hwclock_longopts;
190 #endif
191 opt_complementary = "r--ws:w--rs:s--wr:l--u:u--l";
192 opt = getopt32(argv, "lurswf:", &rtcname);
194 /* If -u or -l wasn't given check if we are using utc */
195 if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
196 utc = opt & HWCLOCK_OPT_UTC;
197 else
198 utc = check_utc();
200 if (opt & HWCLOCK_OPT_HCTOSYS) {
201 to_sys_clock(utc);
202 return 0;
204 if (opt & HWCLOCK_OPT_SYSTOHC) {
205 from_sys_clock(utc);
206 return 0;
208 /* default HWCLOCK_OPT_SHOW */
209 show_clock(utc);
210 return 0;