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

Last change on this file since 956 was 821, checked in by bruno, 13 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.