Kill a silly warning
[oweals/busybox.git] / util-linux / hwclock.c
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
31 enum OpMode {
32         SHOW,
33         SYSTOHC,
34         HCTOSYS
35 };
36
37
38 time_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
74 void 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
97 int 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
116 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                 perror_msg_and_die ( "settimeofday() failed" );
125
126         return 0;
127 }
128
129 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                 perror_msg_and_die ( "gettimeofday() failed" );
136
137         write_rtc ( tv. tv_sec, utc );
138         return 0;
139 }
140
141
142 int 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
168 extern 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