Contents of /trunk/mkinitrd-magellan/busybox/util-linux/hwclock.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4299 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4299 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Mini hwclock implementation for busybox |
4 | * |
5 | * Copyright (C) 2002 Robert Griebl <griebl@gmx.de> |
6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ |
9 | |
10 | |
11 | #include <sys/ioctl.h> |
12 | #include <sys/utsname.h> |
13 | #include <getopt.h> |
14 | #include "busybox.h" |
15 | |
16 | /* Copied from linux/rtc.h to eliminate the kernel dependency */ |
17 | struct linux_rtc_time { |
18 | int tm_sec; |
19 | int tm_min; |
20 | int tm_hour; |
21 | int tm_mday; |
22 | int tm_mon; |
23 | int tm_year; |
24 | int tm_wday; |
25 | int tm_yday; |
26 | int tm_isdst; |
27 | }; |
28 | |
29 | #define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time */ |
30 | #define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time */ |
31 | |
32 | #if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS |
33 | # ifndef _GNU_SOURCE |
34 | # define _GNU_SOURCE |
35 | # endif |
36 | #endif |
37 | |
38 | static int xopen_rtc(int flags) |
39 | { |
40 | int rtc; |
41 | rtc = open("/dev/rtc", flags); |
42 | if (rtc < 0) { |
43 | rtc = open("/dev/misc/rtc", flags); |
44 | if (rtc < 0) |
45 | bb_perror_msg_and_die("cannot access RTC"); |
46 | } |
47 | return rtc; |
48 | } |
49 | |
50 | static time_t read_rtc(int utc) |
51 | { |
52 | struct tm tm; |
53 | char *oldtz = 0; |
54 | time_t t = 0; |
55 | int rtc = xopen_rtc(O_RDONLY); |
56 | |
57 | memset(&tm, 0, sizeof(struct tm)); |
58 | if (ioctl(rtc, RTC_RD_TIME, &tm) < 0 ) |
59 | bb_perror_msg_and_die("cannot read time from RTC"); |
60 | tm.tm_isdst = -1; /* not known */ |
61 | |
62 | close(rtc); |
63 | |
64 | if (utc) { |
65 | oldtz = getenv("TZ"); |
66 | setenv("TZ", "UTC 0", 1); |
67 | tzset(); |
68 | } |
69 | |
70 | t = mktime(&tm); |
71 | |
72 | if (utc) { |
73 | if (oldtz) |
74 | setenv("TZ", oldtz, 1); |
75 | else |
76 | unsetenv("TZ"); |
77 | tzset(); |
78 | } |
79 | return t; |
80 | } |
81 | |
82 | static void write_rtc(time_t t, int utc) |
83 | { |
84 | struct tm tm; |
85 | int rtc = xopen_rtc(O_WRONLY); |
86 | |
87 | tm = *(utc ? gmtime(&t) : localtime(&t)); |
88 | tm.tm_isdst = 0; |
89 | |
90 | if (ioctl(rtc, RTC_SET_TIME, &tm) < 0) |
91 | bb_perror_msg_and_die("cannot set the RTC time"); |
92 | |
93 | close(rtc); |
94 | } |
95 | |
96 | static int show_clock(int utc) |
97 | { |
98 | struct tm *ptm; |
99 | time_t t; |
100 | RESERVE_CONFIG_BUFFER(buffer, 64); |
101 | |
102 | t = read_rtc(utc); |
103 | ptm = localtime(&t); /* Sets 'tzname[]' */ |
104 | |
105 | safe_strncpy(buffer, ctime(&t), 64); |
106 | if (buffer[0]) |
107 | buffer[strlen(buffer) - 1] = 0; |
108 | |
109 | //printf("%s %.6f seconds %s\n", buffer, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0])); |
110 | printf( "%s %.6f seconds\n", buffer, 0.0); |
111 | RELEASE_CONFIG_BUFFER(buffer); |
112 | |
113 | return 0; |
114 | } |
115 | |
116 | static int to_sys_clock(int utc) |
117 | { |
118 | struct timeval tv = { 0, 0 }; |
119 | const struct timezone tz = { timezone/60 - 60*daylight, 0 }; |
120 | |
121 | tv.tv_sec = read_rtc(utc); |
122 | |
123 | if (settimeofday(&tv, &tz)) |
124 | bb_perror_msg_and_die("settimeofday() failed"); |
125 | |
126 | return 0; |
127 | } |
128 | |
129 | static int from_sys_clock(int utc) |
130 | { |
131 | struct timeval tv = { 0, 0 }; |
132 | struct timezone tz = { 0, 0 }; |
133 | |
134 | if (gettimeofday(&tv, &tz)) |
135 | bb_perror_msg_and_die("gettimeofday() failed"); |
136 | |
137 | write_rtc(tv.tv_sec, utc); |
138 | return 0; |
139 | } |
140 | |
141 | #ifdef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS |
142 | # define ADJTIME_PATH "/var/lib/hwclock/adjtime" |
143 | #else |
144 | # define ADJTIME_PATH "/etc/adjtime" |
145 | #endif |
146 | static int check_utc(void) |
147 | { |
148 | int utc = 0; |
149 | FILE *f = fopen(ADJTIME_PATH, "r"); |
150 | |
151 | if (f) { |
152 | RESERVE_CONFIG_BUFFER(buffer, 128); |
153 | |
154 | while (fgets(buffer, sizeof(buffer), f)) { |
155 | int len = strlen(buffer); |
156 | |
157 | while (len && isspace(buffer[len - 1])) |
158 | len--; |
159 | |
160 | buffer[len] = 0; |
161 | |
162 | if (strncmp(buffer, "UTC", 3) == 0 ) { |
163 | utc = 1; |
164 | break; |
165 | } |
166 | } |
167 | fclose(f); |
168 | RELEASE_CONFIG_BUFFER(buffer); |
169 | } |
170 | return utc; |
171 | } |
172 | |
173 | #define HWCLOCK_OPT_LOCALTIME 0x01 |
174 | #define HWCLOCK_OPT_UTC 0x02 |
175 | #define HWCLOCK_OPT_SHOW 0x04 |
176 | #define HWCLOCK_OPT_HCTOSYS 0x08 |
177 | #define HWCLOCK_OPT_SYSTOHC 0x10 |
178 | |
179 | int hwclock_main(int argc, char **argv ) |
180 | { |
181 | unsigned opt; |
182 | int utc; |
183 | |
184 | #if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS |
185 | static const struct option hwclock_long_options[] = { |
186 | { "localtime", 0, 0, 'l' }, |
187 | { "utc", 0, 0, 'u' }, |
188 | { "show", 0, 0, 'r' }, |
189 | { "hctosys", 0, 0, 's' }, |
190 | { "systohc", 0, 0, 'w' }, |
191 | { 0, 0, 0, 0 } |
192 | }; |
193 | applet_long_options = hwclock_long_options; |
194 | #endif |
195 | opt_complementary = "?:r--ws:w--rs:s--wr:l--u:u--l"; |
196 | opt = getopt32(argc, argv, "lursw"); |
197 | |
198 | /* If -u or -l wasn't given check if we are using utc */ |
199 | if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME)) |
200 | utc = opt & HWCLOCK_OPT_UTC; |
201 | else |
202 | utc = check_utc(); |
203 | |
204 | if (opt & HWCLOCK_OPT_HCTOSYS) { |
205 | return to_sys_clock(utc); |
206 | } |
207 | else if (opt & HWCLOCK_OPT_SYSTOHC) { |
208 | return from_sys_clock(utc); |
209 | } else { |
210 | /* default HWCLOCK_OPT_SHOW */ |
211 | return show_clock(utc); |
212 | } |
213 | } |