source: MondoRescue/trunk/mindi-busybox/util-linux/hwclock.c@ 956

Last change on this file since 956 was 821, checked in by Bruno Cornec, 18 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 4.5 KB
Line 
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 <ctype.h>
14#include <fcntl.h>
15#include <getopt.h>
16#include <stdlib.h>
17#include <string.h>
18#include <syslog.h>
19#include <time.h>
20#include <unistd.h>
21#include "busybox.h"
22
23/* Copied from linux/rtc.h to eliminate the kernel dependency */
24struct linux_rtc_time {
25 int tm_sec;
26 int tm_min;
27 int tm_hour;
28 int tm_mday;
29 int tm_mon;
30 int tm_year;
31 int tm_wday;
32 int tm_yday;
33 int tm_isdst;
34};
35
36#define RTC_SET_TIME _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time */
37#define RTC_RD_TIME _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time */
38
39#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
40# ifndef _GNU_SOURCE
41# define _GNU_SOURCE
42# endif
43#endif
44
45static time_t read_rtc(int utc)
46{
47 int rtc;
48 struct tm tm;
49 char *oldtz = 0;
50 time_t t = 0;
51
52 if (( rtc = open ( "/dev/rtc", O_RDONLY )) < 0 ) {
53 if (( rtc = open ( "/dev/misc/rtc", O_RDONLY )) < 0 )
54 bb_perror_msg_and_die ( "Could not access RTC" );
55 }
56 memset ( &tm, 0, sizeof( struct tm ));
57 if ( ioctl ( rtc, RTC_RD_TIME, &tm ) < 0 )
58 bb_perror_msg_and_die ( "Could not read time from RTC" );
59 tm.tm_isdst = -1; /* not known */
60
61 close ( rtc );
62
63 if ( utc ) {
64 oldtz = getenv ( "TZ" );
65 setenv ( "TZ", "UTC 0", 1 );
66 tzset ( );
67 }
68
69 t = mktime ( &tm );
70
71 if ( utc ) {
72 if ( oldtz )
73 setenv ( "TZ", oldtz, 1 );
74 else
75 unsetenv ( "TZ" );
76 tzset ( );
77 }
78 return t;
79}
80
81static void write_rtc(time_t t, int utc)
82{
83 int rtc;
84 struct tm tm;
85
86 if (( rtc = open ( "/dev/rtc", O_WRONLY )) < 0 ) {
87 if (( rtc = open ( "/dev/misc/rtc", O_WRONLY )) < 0 )
88 bb_perror_msg_and_die ( "Could not access RTC" );
89 }
90
91 tm = *( utc ? gmtime ( &t ) : localtime ( &t ));
92 tm.tm_isdst = 0;
93
94 if ( ioctl ( rtc, RTC_SET_TIME, &tm ) < 0 )
95 bb_perror_msg_and_die ( "Could not set the RTC time" );
96
97 close ( rtc );
98}
99
100static int show_clock(int utc)
101{
102 struct tm *ptm;
103 time_t t;
104 RESERVE_CONFIG_BUFFER(buffer, 64);
105
106 t = read_rtc ( utc );
107 ptm = localtime ( &t ); /* Sets 'tzname[]' */
108
109 safe_strncpy ( buffer, ctime ( &t ), 64);
110 if ( buffer [0] )
111 buffer [strlen ( buffer ) - 1] = 0;
112
113 //printf ( "%s %.6f seconds %s\n", buffer, 0.0, utc ? "" : ( ptm-> tm_isdst ? tzname [1] : tzname [0] ));
114 printf ( "%s %.6f seconds\n", buffer, 0.0 );
115 RELEASE_CONFIG_BUFFER(buffer);
116
117 return 0;
118}
119
120static int to_sys_clock(int utc)
121{
122 struct timeval tv = { 0, 0 };
123 const struct timezone tz = { timezone/60 - 60*daylight, 0 };
124
125 tv.tv_sec = read_rtc ( utc );
126
127 if ( settimeofday ( &tv, &tz ))
128 bb_perror_msg_and_die ( "settimeofday() failed" );
129
130 return 0;
131}
132
133static int from_sys_clock(int utc)
134{
135 struct timeval tv = { 0, 0 };
136 struct timezone tz = { 0, 0 };
137
138 if ( gettimeofday ( &tv, &tz ))
139 bb_perror_msg_and_die ( "gettimeofday() failed" );
140
141 write_rtc ( tv.tv_sec, utc );
142 return 0;
143}
144
145#ifdef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
146# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
147#else
148# define ADJTIME_PATH "/etc/adjtime"
149#endif
150static int check_utc(void)
151{
152 int utc = 0;
153 FILE *f = fopen ( ADJTIME_PATH, "r" );
154
155 if ( f ) {
156 RESERVE_CONFIG_BUFFER(buffer, 128);
157
158 while ( fgets ( buffer, sizeof( buffer ), f )) {
159 int len = strlen ( buffer );
160
161 while ( len && isspace ( buffer [len - 1] ))
162 len--;
163
164 buffer [len] = 0;
165
166 if ( strncmp ( buffer, "UTC", 3 ) == 0 ) {
167 utc = 1;
168 break;
169 }
170 }
171 fclose ( f );
172 RELEASE_CONFIG_BUFFER(buffer);
173 }
174 return utc;
175}
176
177#define HWCLOCK_OPT_LOCALTIME 0x01
178#define HWCLOCK_OPT_UTC 0x02
179#define HWCLOCK_OPT_SHOW 0x04
180#define HWCLOCK_OPT_HCTOSYS 0x08
181#define HWCLOCK_OPT_SYSTOHC 0x10
182
183int hwclock_main ( int argc, char **argv )
184{
185 unsigned long opt;
186 int utc;
187
188#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
189static const struct option hwclock_long_options[] = {
190 { "localtime", 0, 0, 'l' },
191 { "utc", 0, 0, 'u' },
192 { "show", 0, 0, 'r' },
193 { "hctosys", 0, 0, 's' },
194 { "systohc", 0, 0, 'w' },
195 { 0, 0, 0, 0 }
196 };
197 bb_applet_long_options = hwclock_long_options;
198#endif
199
200 bb_opt_complementally = "?:r--ws:w--rs:s--wr:l--u:u--l";
201 opt = bb_getopt_ulflags(argc, argv, "lursw");
202
203 /* If -u or -l wasn't given check if we are using utc */
204 if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
205 utc = opt & HWCLOCK_OPT_UTC;
206 else
207 utc = check_utc();
208
209 if (opt & HWCLOCK_OPT_HCTOSYS) {
210 return to_sys_clock ( utc );
211 }
212 else if (opt & HWCLOCK_OPT_SYSTOHC) {
213 return from_sys_clock ( utc );
214 } else {
215 /* default HWCLOCK_OPT_SHOW */
216 return show_clock ( utc );
217 }
218}
Note: See TracBrowser for help on using the repository browser.