aboutsummaryrefslogtreecommitdiff
path: root/util-linux/hwclock.c
diff options
context:
space:
mode:
authorsandman <sandman@69ca8d6d-28ef-0310-b511-8ec308f3f277>2002-07-21 16:50:49 +0000
committersandman <sandman@69ca8d6d-28ef-0310-b511-8ec308f3f277>2002-07-21 16:50:49 +0000
commit2d351780fbacf9408d331ddad01e7619e296cca3 (patch)
treed552f7d94cac8240a89a5e498b73c0c60299de2c /util-linux/hwclock.c
parent89025b51201240d76228179ce321fda17f8f285e (diff)
downloadbusybox-w32-2d351780fbacf9408d331ddad01e7619e296cca3.tar.gz
busybox-w32-2d351780fbacf9408d331ddad01e7619e296cca3.tar.bz2
busybox-w32-2d351780fbacf9408d331ddad01e7619e296cca3.zip
Initial checkin of a very primitive hwclock replacement
git-svn-id: svn://busybox.net/trunk/busybox@5072 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'util-linux/hwclock.c')
-rw-r--r--util-linux/hwclock.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c
new file mode 100644
index 000000000..88222e6ba
--- /dev/null
+++ b/util-linux/hwclock.c
@@ -0,0 +1,229 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * really dumb hwclock implementation for busybox
4 * Copyright (C) 2002 Robert Griebl <griebl@gmx.de>
5 *
6 */
7
8
9#include <sys/utsname.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <syslog.h>
13#include <string.h>
14#include <ctype.h>
15#include <fcntl.h>
16#include <sys/time.h>
17#include <time.h>
18#include <linux/rtc.h>
19#include <sys/ioctl.h>
20#include "busybox.h"
21
22#ifdef CONFIG_FEATURE_HWCLOCK_LONGOPTIONS
23# ifndef _GNU_SOURCE
24# define _GNU_SOURCE
25# endif
26#endif
27
28#include <getopt.h>
29
30
31enum OpMode {
32 SHOW,
33 SYSTOHC,
34 HCTOSYS
35};
36
37
38time_t read_rtc ( int utc )
39{
40 int rtc;
41 struct tm tm;
42 char *oldtz = 0;
43 time_t t = 0;
44
45 if (( rtc = open ( "/dev/rtc", O_RDONLY )) < 0 ) {
46 if (( rtc = open ( "/dev/misc/rtc", O_RDONLY )) < 0 )
47 perror_msg_and_die ( "Could not access RTC" );
48 }
49 memset ( &tm, 0, sizeof( struct tm ));
50 if ( ioctl ( rtc, RTC_RD_TIME, &tm ) < 0 )
51 perror_msg_and_die ( "Could not read time from RTC" );
52 tm. tm_isdst = -1; // not known
53
54 close ( rtc );
55
56 if ( utc ) {
57 oldtz = getenv ( "TZ" );
58 setenv ( "TZ", "UTC 0", 1 );
59 tzset ( );
60 }
61
62 t = mktime ( &tm );
63
64 if ( utc ) {
65 if ( oldtz )
66 setenv ( "TZ", oldtz, 1 );
67 else
68 unsetenv ( "TZ" );
69 tzset ( );
70 }
71 return t;
72}
73
74void write_rtc ( time_t t, int utc )
75{
76 int rtc;
77 struct tm tm;
78
79 if (( rtc = open ( "/dev/rtc", O_WRONLY )) < 0 ) {
80 if (( rtc = open ( "/dev/misc/rtc", O_WRONLY )) < 0 )
81 perror_msg_and_die ( "Could not access RTC" );
82 }
83
84 printf ( "1\n" );
85
86 tm = *( utc ? gmtime ( &t ) : localtime ( &t ));
87 tm. tm_isdst = 0;
88
89 printf ( "2\n") ;
90
91 if ( ioctl ( rtc, RTC_SET_TIME, &tm ) < 0 )
92 perror_msg_and_die ( "Could not set the RTC time" );
93
94 close ( rtc );
95}
96
97int show_clock ( int utc )
98{
99 struct tm *ptm;
100 time_t t;
101 char buffer [64];
102
103 t = read_rtc ( utc );
104 ptm = localtime ( &t ); /* Sets 'tzname[]' */
105
106 safe_strncpy ( buffer, ctime ( &t ), sizeof( buffer ));
107 if ( buffer [0] )
108 buffer [xstrlen ( buffer ) - 1] = 0;
109
110 //printf ( "%s %.6f seconds %s\n", buffer, 0.0, utc ? "" : ( ptm-> tm_isdst ? tzname [1] : tzname [0] ));
111 printf ( "%s %.6f seconds\n", buffer, 0.0 );
112
113 return 0;
114}
115
116int 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 perror_msg_and_die ( "settimeofday() failed" );
125
126 return 0;
127}
128
129int 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 perror_msg_and_die ( "gettimeofday() failed" );
136
137 write_rtc ( tv. tv_sec, utc );
138 return 0;
139}
140
141
142int check_utc ( void )
143{
144 int utc = 0;
145 FILE *f = fopen ( "/etc/adjtime", "r" );
146
147 if ( f ) {
148 char buffer [128];
149
150 while ( fgets ( buffer, sizeof( buffer ), f )) {
151 int len = xstrlen ( buffer );
152
153 while ( len && isspace ( buffer [len - 1] ))
154 len--;
155
156 buffer [len] = 0;
157
158 if ( strncmp ( buffer, "UTC", 3 ) == 0 ) {
159 utc = 1;
160 break;
161 }
162 }
163 fclose ( f );
164 }
165 return utc;
166}
167
168extern int hwclock_main ( int argc, char **argv )
169{
170 int opt;
171 enum OpMode mode = SHOW;
172 int utc = 0;
173 int utc_arg = 0;
174
175#ifdef CONFIG_FEATURE_HWCLOCK_LONGOPTIONS
176 struct option long_options[] = {
177 { "show", 0, 0, 'r' },
178 { "utc", 0, 0, 'u' },
179 { "localtime", 0, 0, 'l' },
180 { "hctosys", 0, 0, 's' },
181 { "systohc", 0, 0, 'w' },
182 { 0, 0, 0, 0 }
183 };
184
185 while (( opt = getopt_long ( argc, argv, "rwsul", long_options, 0 )) != EOF ) {
186#else
187 while (( opt = getopt ( argc, argv, "rwsul" )) != EOF ) {
188#endif
189 switch ( opt ) {
190 case 'r':
191 mode = SHOW;
192 break;
193 case 'w':
194 mode = SYSTOHC;
195 break;
196 case 's':
197 mode = HCTOSYS;
198 break;
199 case 'u':
200 utc = 1;
201 utc_arg = 1;
202 break;
203 case 'l': // -l is not supported by the normal hwclock (only --localtime)
204 utc = 0;
205 utc_arg = 1;
206 break;
207 default:
208 show_usage();
209 break;
210 }
211 }
212
213 if ( !utc_arg )
214 utc = check_utc ( );
215
216 switch ( mode ) {
217 case SYSTOHC:
218 return from_sys_clock ( utc );
219
220 case HCTOSYS:
221 return to_sys_clock ( utc );
222
223 case SHOW:
224 default:
225 return show_clock ( utc );
226 }
227}
228
229