source: MondoRescue/branches/2.2.5/mindi-busybox/util-linux/hwclock.c @ 1765

Last change on this file since 1765 was 1765, checked in by Bruno Cornec, 13 years ago

Update to busybox 1.7.2

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