~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to hwclock/rtc.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* rtc.c - Use /dev/rtc for clock access */
2
 
#include <unistd.h>             /* for close() */
3
 
#include <fcntl.h>              /* for O_RDONLY */
 
1
/*
 
2
 * rtc.c - Use /dev/rtc for clock access
 
3
 */
 
4
#include <asm/ioctl.h>
4
5
#include <errno.h>
 
6
#include <fcntl.h>
 
7
#include <stdio.h>
 
8
#include <stdlib.h>
5
9
#include <sysexits.h>
6
10
#include <sys/ioctl.h>
7
 
#include <sys/time.h>           /* for struct timeval */
 
11
#include <sys/select.h>
 
12
#include <sys/time.h>
 
13
#include <time.h>
 
14
#include <unistd.h>
8
15
 
9
16
#include "clock.h"
10
17
#include "nls.h"
12
19
/*
13
20
 * Get defines for rtc stuff.
14
21
 *
15
 
 * Getting the rtc defines is nontrivial.
16
 
 * The obvious way is by including <linux/mc146818rtc.h>
17
 
 * but that again includes <asm/io.h> which again includes ...
18
 
 * and on sparc and alpha this gives compilation errors for
19
 
 * many kernel versions. So, we give the defines ourselves here.
20
 
 * Moreover, some Sparc person decided to be incompatible, and
21
 
 * used a struct rtc_time different from that used in mc146818rtc.h.
 
22
 * Getting the rtc defines is nontrivial. The obvious way is by including
 
23
 * <linux/mc146818rtc.h> but that again includes <asm/io.h> which again
 
24
 * includes ... and on sparc and alpha this gives compilation errors for
 
25
 * many kernel versions. So, we give the defines ourselves here. Moreover,
 
26
 * some Sparc person decided to be incompatible, and used a struct rtc_time
 
27
 * different from that used in mc146818rtc.h.
22
28
 */
23
29
 
24
 
/* On Sparcs, there is a <asm/rtc.h> that defines different ioctls
25
 
   (that are required on my machine). However, this include file
26
 
   does not exist on other architectures. */
 
30
/*
 
31
 * On Sparcs, there is a <asm/rtc.h> that defines different ioctls (that are
 
32
 * required on my machine). However, this include file does not exist on
 
33
 * other architectures.
 
34
 */
27
35
/* One might do:
28
36
#ifdef __sparc__
29
 
#include <asm/rtc.h>
 
37
# include <asm/rtc.h>
30
38
#endif
31
39
 */
32
40
/* The following is roughly equivalent */
33
41
struct sparc_rtc_time
34
42
{
35
 
        int     sec;    /* Seconds (0-59) */
36
 
        int     min;    /* Minutes (0-59) */
37
 
        int     hour;   /* Hour (0-23) */
38
 
        int     dow;    /* Day of the week (1-7) */
39
 
        int     dom;    /* Day of the month (1-31) */
40
 
        int     month;  /* Month of year (1-12) */
41
 
        int     year;   /* Year (0-99) */
 
43
        int sec;        /* Seconds              0-59 */
 
44
        int min;        /* Minutes              0-59 */
 
45
        int hour;       /* Hour                 0-23 */
 
46
        int dow;        /* Day of the week      1-7  */
 
47
        int dom;        /* Day of the month     1-31 */
 
48
        int month;      /* Month of year        1-12 */
 
49
        int year;       /* Year                 0-99 */
42
50
};
43
51
 
44
52
#define RTCGET _IOR('p', 20, struct sparc_rtc_time)
45
53
#define RTCSET _IOW('p', 21, struct sparc_rtc_time)
46
54
 
47
 
 
48
55
/* non-sparc stuff */
49
56
#if 0
50
 
#include <linux/version.h>
51
 
/* Check if the /dev/rtc interface is available in this version of
52
 
   the system headers.  131072 is linux 2.0.0. */
53
 
#if LINUX_VERSION_CODE >= 131072
54
 
#include <linux/mc146818rtc.h>
55
 
#endif
 
57
# include <linux/version.h>
 
58
/*
 
59
 * Check if the /dev/rtc interface is available in this version of the
 
60
 * system headers. 131072 is linux 2.0.0.
 
61
 */
 
62
# if LINUX_VERSION_CODE >= 131072
 
63
#  include <linux/mc146818rtc.h>
 
64
# endif
56
65
#endif
57
66
 
58
 
/* struct rtc_time is present since 1.3.99 */
59
 
/* Earlier (since 1.3.89), a struct tm was used. */
 
67
/*
 
68
 * struct rtc_time is present since 1.3.99.
 
69
 * Earlier (since 1.3.89), a struct tm was used.
 
70
 */
60
71
struct linux_rtc_time {
61
 
        int tm_sec;
62
 
        int tm_min;
63
 
        int tm_hour;
64
 
        int tm_mday;
65
 
        int tm_mon;
66
 
        int tm_year;
67
 
        int tm_wday;
68
 
        int tm_yday;
69
 
        int tm_isdst;
 
72
        int tm_sec;
 
73
        int tm_min;
 
74
        int tm_hour;
 
75
        int tm_mday;
 
76
        int tm_mon;
 
77
        int tm_year;
 
78
        int tm_wday;
 
79
        int tm_yday;
 
80
        int tm_isdst;
70
81
};
71
82
 
72
83
/* RTC_RD_TIME etc have this definition since 1.99.9 (pre2.0-9) */
73
84
#ifndef RTC_RD_TIME
74
 
#define RTC_RD_TIME       _IOR('p', 0x09, struct linux_rtc_time)
75
 
#define RTC_SET_TIME      _IOW('p', 0x0a, struct linux_rtc_time)
76
 
#define RTC_UIE_ON        _IO('p', 0x03)        /* Update int. enable on */
77
 
#define RTC_UIE_OFF       _IO('p', 0x04)        /* Update int. enable off */
 
85
# define RTC_RD_TIME    _IOR('p', 0x09, struct linux_rtc_time)
 
86
# define RTC_SET_TIME   _IOW('p', 0x0a, struct linux_rtc_time)
 
87
# define RTC_UIE_ON     _IO('p', 0x03)  /* Update int. enable on */
 
88
# define RTC_UIE_OFF    _IO('p', 0x04)  /* Update int. enable off */
78
89
#endif
 
90
 
79
91
/* RTC_EPOCH_READ and RTC_EPOCH_SET are present since 2.0.34 and 2.1.89 */
80
92
#ifndef RTC_EPOCH_READ
81
 
#define RTC_EPOCH_READ  _IOR('p', 0x0d, unsigned long)   /* Read epoch */
82
 
#define RTC_EPOCH_SET   _IOW('p', 0x0e, unsigned long)   /* Set epoch */
 
93
# define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long)  /* Read epoch */
 
94
# define RTC_EPOCH_SET  _IOW('p', 0x0e, unsigned long)  /* Set epoch */
83
95
#endif
84
96
 
85
 
/* /dev/rtc is conventionally chardev 10/135
 
97
/*
 
98
 * /dev/rtc is conventionally chardev 10/135
86
99
 * ia64 uses /dev/efirtc, chardev 10/136
87
100
 * devfs (obsolete) used /dev/misc/... for miscdev
88
101
 * new RTC framework + udev uses dynamic major and /dev/rtc0.../dev/rtcN
94
107
 
95
108
static int rtc_dev_fd = -1;
96
109
 
97
 
static void
98
 
close_rtc(void) {
 
110
static void close_rtc(void)
 
111
{
99
112
        if (rtc_dev_fd != -1)
100
113
                close(rtc_dev_fd);
101
114
        rtc_dev_fd = -1;
102
115
}
103
116
 
104
 
static int
105
 
open_rtc(void) {
 
117
static int open_rtc(void)
 
118
{
106
119
        char *fls[] = {
107
120
#ifdef __ia64__
108
121
                "/dev/efirtc",
122
135
        if (rtc_dev_name)
123
136
                rtc_dev_fd = open(rtc_dev_name, O_RDONLY);
124
137
        else {
125
 
                for (p=fls; *p; ++p) {
 
138
                for (p = fls; *p; ++p) {
126
139
                        rtc_dev_fd = open(*p, O_RDONLY);
127
140
 
128
 
                        if (rtc_dev_fd < 0 && (errno == ENOENT || errno == ENODEV))
 
141
                        if (rtc_dev_fd < 0
 
142
                            && (errno == ENOENT || errno == ENODEV))
129
143
                                continue;
130
144
                        rtc_dev_name = *p;
131
145
                        break;
139
153
        return rtc_dev_fd;
140
154
}
141
155
 
142
 
static int
143
 
open_rtc_or_exit(void) {
 
156
static int open_rtc_or_exit(void)
 
157
{
144
158
        int rtc_fd = open_rtc();
145
159
 
146
160
        if (rtc_fd < 0) {
147
 
                outsyserr(_("open() of %s failed"), rtc_dev_name);
 
161
                warn(_("open() of %s failed"), rtc_dev_name);
148
162
                hwclock_exit(EX_OSFILE);
149
163
        }
150
164
        return rtc_fd;
151
165
}
152
166
 
153
 
static int
154
 
do_rtc_read_ioctl(int rtc_fd, struct tm *tm) {
 
167
static int do_rtc_read_ioctl(int rtc_fd, struct tm *tm)
 
168
{
155
169
        int rc = -1;
156
170
        char *ioctlname;
157
171
 
169
183
                tm->tm_mon = stm.month - 1;
170
184
                tm->tm_year = stm.year - 1900;
171
185
                tm->tm_wday = stm.dow - 1;
172
 
                tm->tm_yday = -1;               /* day in the year */
 
186
                tm->tm_yday = -1;       /* day in the year */
173
187
        }
174
188
#endif
175
189
        if (rc == -1) {         /* no sparc, or RTCGET failed */
177
191
                rc = ioctl(rtc_fd, RTC_RD_TIME, tm);
178
192
        }
179
193
        if (rc == -1) {
180
 
                perror(ioctlname);
181
 
                fprintf(stderr, _("ioctl() to %s to read the time failed.\n"),
182
 
                        rtc_dev_name);
 
194
                warn(_("ioctl(%s) to %s to read the time failed"),
 
195
                        ioctlname, rtc_dev_name);
183
196
                return -1;
184
197
        }
185
198
 
186
 
        tm->tm_isdst = -1;          /* don't know whether it's dst */
187
 
        return 0;
188
 
}
189
 
 
190
 
static int
191
 
busywait_for_rtc_clock_tick(const int rtc_fd) {
192
 
/*----------------------------------------------------------------------------
193
 
   Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
194
 
   we see it.
195
 
-----------------------------------------------------------------------------*/
196
 
  struct tm start_time;
197
 
    /* The time when we were called (and started waiting) */
198
 
  struct tm nowtime;
199
 
  int rc;
200
 
  struct timeval begin, now;
201
 
 
202
 
  if (debug)
203
 
    printf(_("Waiting in loop for time from %s to change\n"),
204
 
           rtc_dev_name);
205
 
 
206
 
  rc = do_rtc_read_ioctl(rtc_fd, &start_time);
207
 
  if (rc)
208
 
    return 1;
209
 
 
210
 
  /* Wait for change.  Should be within a second, but in case something
211
 
   * weird happens, we have a time limit (1.5s) on this loop to reduce the
212
 
   * impact of this failure.
213
 
   */
214
 
  gettimeofday(&begin, NULL);
215
 
  do {
216
 
    rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
217
 
    if (rc || start_time.tm_sec != nowtime.tm_sec)
218
 
      break;
219
 
    gettimeofday(&now, NULL);
220
 
    if (time_diff(now, begin) > 1.5) {
221
 
      fprintf(stderr, _("Timed out waiting for time change.\n"));
222
 
      return 2;
223
 
    }
224
 
  } while(1);
225
 
 
226
 
  if (rc)
227
 
    return 3;
228
 
  return 0;
229
 
}
230
 
 
231
 
static int
232
 
synchronize_to_clock_tick_rtc(void) {
233
 
/*----------------------------------------------------------------------------
234
 
  Same as synchronize_to_clock_tick(), but just for /dev/rtc.
235
 
-----------------------------------------------------------------------------*/
236
 
int rtc_fd;  /* File descriptor of /dev/rtc */
237
 
int ret;
238
 
 
239
 
  rtc_fd = open_rtc();
240
 
  if (rtc_fd == -1) {
241
 
    outsyserr(_("open() of %s failed"), rtc_dev_name);
242
 
    ret = 1;
243
 
  } else {
244
 
    int rc;  /* Return code from ioctl */
245
 
    /* Turn on update interrupts (one per second) */
 
199
        tm->tm_isdst = -1;      /* don't know whether it's dst */
 
200
        return 0;
 
201
}
 
202
 
 
203
/*
 
204
 * Wait for the top of a clock tick by reading /dev/rtc in a busy loop until
 
205
 * we see it.
 
206
 */
 
207
static int busywait_for_rtc_clock_tick(const int rtc_fd)
 
208
{
 
209
        struct tm start_time;
 
210
        /* The time when we were called (and started waiting) */
 
211
        struct tm nowtime;
 
212
        int rc;
 
213
        struct timeval begin, now;
 
214
 
 
215
        if (debug)
 
216
                printf(_("Waiting in loop for time from %s to change\n"),
 
217
                       rtc_dev_name);
 
218
 
 
219
        rc = do_rtc_read_ioctl(rtc_fd, &start_time);
 
220
        if (rc)
 
221
                return 1;
 
222
 
 
223
        /*
 
224
         * Wait for change.  Should be within a second, but in case
 
225
         * something weird happens, we have a time limit (1.5s) on this loop
 
226
         * to reduce the impact of this failure.
 
227
         */
 
228
        gettimeofday(&begin, NULL);
 
229
        do {
 
230
                rc = do_rtc_read_ioctl(rtc_fd, &nowtime);
 
231
                if (rc || start_time.tm_sec != nowtime.tm_sec)
 
232
                        break;
 
233
                gettimeofday(&now, NULL);
 
234
                if (time_diff(now, begin) > 1.5) {
 
235
                        warnx(_("Timed out waiting for time change."));
 
236
                        return 2;
 
237
                }
 
238
        } while (1);
 
239
 
 
240
        if (rc)
 
241
                return 3;
 
242
        return 0;
 
243
}
 
244
 
 
245
/*
 
246
 * Same as synchronize_to_clock_tick(), but just for /dev/rtc.
 
247
 */
 
248
static int synchronize_to_clock_tick_rtc(void)
 
249
{
 
250
        int rtc_fd;             /* File descriptor of /dev/rtc */
 
251
        int ret;
 
252
 
 
253
        rtc_fd = open_rtc();
 
254
        if (rtc_fd == -1) {
 
255
                warn(_("open() of %s failed"), rtc_dev_name);
 
256
                ret = 1;
 
257
        } else {
 
258
                int rc;         /* Return code from ioctl */
 
259
                /* Turn on update interrupts (one per second) */
246
260
#if defined(__alpha__) || defined(__sparc__)
247
 
    /* Not all alpha kernels reject RTC_UIE_ON, but probably they should. */
248
 
    rc = -1;
249
 
    errno = EINVAL;
 
261
                /*
 
262
                 * Not all alpha kernels reject RTC_UIE_ON, but probably
 
263
                 * they should.
 
264
                 */
 
265
                rc = -1;
 
266
                errno = EINVAL;
250
267
#else
251
 
    rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
 
268
                rc = ioctl(rtc_fd, RTC_UIE_ON, 0);
252
269
#endif
253
 
    if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
254
 
      /* This rtc device doesn't have interrupt functions.  This is typical
255
 
         on an Alpha, where the Hardware Clock interrupts are used by the
256
 
         kernel for the system clock, so aren't at the user's disposal.
257
 
         */
258
 
      if (debug)
259
 
              printf(_("%s does not have interrupt functions. "),
260
 
                     rtc_dev_name);
261
 
      ret = busywait_for_rtc_clock_tick(rtc_fd);
262
 
    } else if (rc == 0) {
 
270
                if (rc == -1 && (errno == ENOTTY || errno == EINVAL)) {
 
271
                        /*
 
272
                         * This rtc device doesn't have interrupt functions.
 
273
                         * This is typical on an Alpha, where the Hardware
 
274
                         * Clock interrupts are used by the kernel for the
 
275
                         * system clock, so aren't at the user's disposal.
 
276
                         */
 
277
                        if (debug)
 
278
                                printf(_
 
279
                                       ("%s does not have interrupt functions. "),
 
280
                                       rtc_dev_name);
 
281
                        ret = busywait_for_rtc_clock_tick(rtc_fd);
 
282
                } else if (rc == 0) {
263
283
#ifdef Wait_until_update_interrupt
264
 
      unsigned long dummy;
 
284
                        unsigned long dummy;
265
285
 
266
 
      /* this blocks until the next update interrupt */
267
 
      rc = read(rtc_fd, &dummy, sizeof(dummy));
268
 
      ret = 1;
269
 
      if (rc == -1)
270
 
        outsyserr(_("read() to %s to wait for clock tick failed"),
271
 
                  rtc_dev_name);
272
 
      else
273
 
        ret = 0;
 
286
                        /* this blocks until the next update interrupt */
 
287
                        rc = read(rtc_fd, &dummy, sizeof(dummy));
 
288
                        ret = 1;
 
289
                        if (rc == -1)
 
290
                                warn(_
 
291
                                     ("read() to %s to wait for clock tick failed"),
 
292
                                     rtc_dev_name);
 
293
                        else
 
294
                                ret = 0;
274
295
#else
275
 
      /* Just reading rtc_fd fails on broken hardware: no update
276
 
         interrupt comes and a bootscript with a hwclock call hangs */
277
 
      fd_set rfds;
278
 
      struct timeval tv;
 
296
                        /*
 
297
                         * Just reading rtc_fd fails on broken hardware: no
 
298
                         * update interrupt comes and a bootscript with a
 
299
                         * hwclock call hangs
 
300
                         */
 
301
                        fd_set rfds;
 
302
                        struct timeval tv;
279
303
 
280
 
      /* Wait up to five seconds for the next update interrupt */
281
 
      FD_ZERO(&rfds);
282
 
      FD_SET(rtc_fd, &rfds);
283
 
      tv.tv_sec = 5;
284
 
      tv.tv_usec = 0;
285
 
      rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
286
 
      ret = 1;
287
 
      if (rc == -1)
288
 
        outsyserr(_("select() to %s to wait for clock tick failed"),
289
 
                  rtc_dev_name);
290
 
      else if (rc == 0)
291
 
        fprintf(stderr, _("select() to %s to wait for clock tick timed out\n"),
292
 
                          rtc_dev_name);
293
 
      else
294
 
        ret = 0;
 
304
                        /*
 
305
                         * Wait up to five seconds for the next update
 
306
                         * interrupt
 
307
                         */
 
308
                        FD_ZERO(&rfds);
 
309
                        FD_SET(rtc_fd, &rfds);
 
310
                        tv.tv_sec = 5;
 
311
                        tv.tv_usec = 0;
 
312
                        rc = select(rtc_fd + 1, &rfds, NULL, NULL, &tv);
 
313
                        ret = 1;
 
314
                        if (rc == -1)
 
315
                                warn(_
 
316
                                     ("select() to %s to wait for clock tick failed"),
 
317
                                     rtc_dev_name);
 
318
                        else if (rc == 0)
 
319
                                warn(_
 
320
                                     ("select() to %s to wait for clock tick timed out"),
 
321
                                     rtc_dev_name);
 
322
                        else
 
323
                                ret = 0;
295
324
#endif
296
325
 
297
 
      /* Turn off update interrupts */
298
 
      rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
299
 
      if (rc == -1)
300
 
        outsyserr(_("ioctl() to %s to turn off update interrupts failed"),
301
 
                  rtc_dev_name);
302
 
    } else {
303
 
      outsyserr(_("ioctl() to %s to turn on update interrupts "
304
 
                "failed unexpectedly"), rtc_dev_name);
305
 
      ret = 1;
306
 
    }
307
 
  }
308
 
  return ret;
 
326
                        /* Turn off update interrupts */
 
327
                        rc = ioctl(rtc_fd, RTC_UIE_OFF, 0);
 
328
                        if (rc == -1)
 
329
                                warn(_
 
330
                                     ("ioctl() to %s to turn off update interrupts failed"),
 
331
                                     rtc_dev_name);
 
332
                } else {
 
333
                        warn(_
 
334
                             ("ioctl() to %s to turn on update interrupts "
 
335
                              "failed unexpectedly"), rtc_dev_name);
 
336
                        ret = 1;
 
337
                }
 
338
        }
 
339
        return ret;
309
340
}
310
341
 
311
 
 
312
 
static int
313
 
read_hardware_clock_rtc(struct tm *tm) {
 
342
static int read_hardware_clock_rtc(struct tm *tm)
 
343
{
314
344
        int rtc_fd, rc;
315
345
 
316
346
        rtc_fd = open_rtc_or_exit();
321
351
        return rc;
322
352
}
323
353
 
324
 
 
325
 
static int
326
 
set_hardware_clock_rtc(const struct tm *new_broken_time) {
327
 
/*-------------------------------------------------------------------------
328
 
  Set the Hardware Clock to the broken down time <new_broken_time>.
329
 
  Use ioctls to "rtc" device /dev/rtc.
330
 
  -------------------------------------------------------------------------*/
 
354
/*
 
355
 * Set the Hardware Clock to the broken down time <new_broken_time>. Use
 
356
 * ioctls to "rtc" device /dev/rtc.
 
357
 */
 
358
static int set_hardware_clock_rtc(const struct tm *new_broken_time)
 
359
{
331
360
        int rc = -1;
332
361
        int rtc_fd;
333
362
        char *ioctlname;
356
385
        }
357
386
 
358
387
        if (rc == -1) {
359
 
                perror(ioctlname);
360
 
                fprintf(stderr, _("ioctl() to %s to set the time failed.\n"),
361
 
                        rtc_dev_name);
 
388
                warn(_("ioctl(%s) to %s to set the time failed."),
 
389
                        ioctlname, rtc_dev_name);
362
390
                hwclock_exit(EX_IOERR);
363
391
        }
364
392
 
368
396
        return 0;
369
397
}
370
398
 
371
 
 
372
 
static int
373
 
get_permissions_rtc(void) {
 
399
static int get_permissions_rtc(void)
 
400
{
374
401
        return 0;
375
402
}
376
403
 
383
410
};
384
411
 
385
412
/* return &rtc if /dev/rtc can be opened, NULL otherwise */
386
 
struct clock_ops *
387
 
probe_for_rtc_clock(){
 
413
struct clock_ops *probe_for_rtc_clock()
 
414
{
388
415
        int rtc_fd = open_rtc();
389
416
        if (rtc_fd >= 0)
390
417
                return &rtc;
391
418
        if (debug)
392
 
                outsyserr(_("Open of %s failed"), rtc_dev_name);
 
419
                warn(_("Open of %s failed"), rtc_dev_name);
393
420
        return NULL;
394
421
}
395
422
 
396
 
 
397
 
 
398
 
int
399
 
get_epoch_rtc(unsigned long *epoch_p, int silent) {
400
 
/*----------------------------------------------------------------------------
401
 
  Get the Hardware Clock epoch setting from the kernel.
402
 
----------------------------------------------------------------------------*/
403
 
  int rtc_fd;
404
 
 
405
 
  rtc_fd = open_rtc();
406
 
  if (rtc_fd < 0) {
407
 
    if (!silent) {
408
 
      if (errno == ENOENT)
409
 
        fprintf(stderr, _(
410
 
                "To manipulate the epoch value in the kernel, we must "
411
 
                "access the Linux 'rtc' device driver via the device special "
412
 
                "file %s.  This file does not exist on this system.\n"),
413
 
                rtc_dev_name);
414
 
      else
415
 
        outsyserr(_("Unable to open %s"), rtc_dev_name);
416
 
    }
417
 
    return 1;
418
 
  }
419
 
 
420
 
  if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
421
 
    if (!silent)
422
 
      outsyserr(_("ioctl(RTC_EPOCH_READ) to %s failed"), rtc_dev_name);
423
 
    return 1;
424
 
  }
425
 
 
426
 
  if (debug)
427
 
          printf(_("we have read epoch %ld from %s "
428
 
                 "with RTC_EPOCH_READ ioctl.\n"), *epoch_p, rtc_dev_name);
429
 
 
430
 
  return 0;
 
423
/*
 
424
 * Get the Hardware Clock epoch setting from the kernel.
 
425
 */
 
426
int get_epoch_rtc(unsigned long *epoch_p, int silent)
 
427
{
 
428
        int rtc_fd;
 
429
 
 
430
        rtc_fd = open_rtc();
 
431
        if (rtc_fd < 0) {
 
432
                if (!silent) {
 
433
                        if (errno == ENOENT)
 
434
                                warnx(_
 
435
                                      ("To manipulate the epoch value in the kernel, we must "
 
436
                                       "access the Linux 'rtc' device driver via the device special "
 
437
                                       "file %s.  This file does not exist on this system."),
 
438
                                      rtc_dev_name);
 
439
                        else
 
440
                                warn(_("Unable to open %s"), rtc_dev_name);
 
441
                }
 
442
                return 1;
 
443
        }
 
444
 
 
445
        if (ioctl(rtc_fd, RTC_EPOCH_READ, epoch_p) == -1) {
 
446
                if (!silent)
 
447
                        warn(_("ioctl(RTC_EPOCH_READ) to %s failed"),
 
448
                                  rtc_dev_name);
 
449
                return 1;
 
450
        }
 
451
 
 
452
        if (debug)
 
453
                printf(_("we have read epoch %ld from %s "
 
454
                         "with RTC_EPOCH_READ ioctl.\n"), *epoch_p,
 
455
                       rtc_dev_name);
 
456
 
 
457
        return 0;
431
458
}
432
459
 
433
 
 
434
 
 
435
 
int
436
 
set_epoch_rtc(unsigned long epoch) {
437
 
/*----------------------------------------------------------------------------
438
 
  Set the Hardware Clock epoch in the kernel.
439
 
----------------------------------------------------------------------------*/
440
 
  int rtc_fd;
441
 
 
442
 
  if (epoch < 1900) {
443
 
    /* kernel would not accept this epoch value */
444
 
    /* Hmm - bad habit, deciding not to do what the user asks
445
 
       just because one believes that the kernel might not like it. */
446
 
    fprintf(stderr, _("The epoch value may not be less than 1900.  "
447
 
            "You requested %ld\n"), epoch);
448
 
    return 1;
449
 
  }
450
 
 
451
 
  rtc_fd = open_rtc();
452
 
  if (rtc_fd < 0) {
453
 
    if (errno == ENOENT)
454
 
      fprintf(stderr, _("To manipulate the epoch value in the kernel, we must "
455
 
              "access the Linux 'rtc' device driver via the device special "
456
 
              "file %s.  This file does not exist on this system.\n"),
457
 
              rtc_dev_name);
458
 
    else
459
 
      outsyserr(_("Unable to open %s"), rtc_dev_name);
460
 
    return 1;
461
 
  }
462
 
 
463
 
  if (debug)
464
 
    printf(_("setting epoch to %ld "
465
 
           "with RTC_EPOCH_SET ioctl to %s.\n"), epoch, rtc_dev_name);
466
 
 
467
 
  if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
468
 
    if (errno == EINVAL)
469
 
      fprintf(stderr, _("The kernel device driver for %s "
470
 
              "does not have the RTC_EPOCH_SET ioctl.\n"), rtc_dev_name);
471
 
    else
472
 
      outsyserr(_("ioctl(RTC_EPOCH_SET) to %s failed"), rtc_dev_name);
473
 
    return 1;
474
 
  }
475
 
 
476
 
  return 0;
 
460
/*
 
461
 * Set the Hardware Clock epoch in the kernel.
 
462
 */
 
463
int set_epoch_rtc(unsigned long epoch)
 
464
{
 
465
        int rtc_fd;
 
466
 
 
467
        if (epoch < 1900) {
 
468
                /* kernel would not accept this epoch value
 
469
                 *
 
470
                 * Bad habit, deciding not to do what the user asks just
 
471
                 * because one believes that the kernel might not like it.
 
472
                 */
 
473
                warnx(_("The epoch value may not be less than 1900.  "
 
474
                        "You requested %ld"), epoch);
 
475
                return 1;
 
476
        }
 
477
 
 
478
        rtc_fd = open_rtc();
 
479
        if (rtc_fd < 0) {
 
480
                if (errno == ENOENT)
 
481
                        warnx(_
 
482
                              ("To manipulate the epoch value in the kernel, we must "
 
483
                               "access the Linux 'rtc' device driver via the device special "
 
484
                               "file %s.  This file does not exist on this system."),
 
485
                              rtc_dev_name);
 
486
                else
 
487
                        warn(_("Unable to open %s"), rtc_dev_name);
 
488
                return 1;
 
489
        }
 
490
 
 
491
        if (debug)
 
492
                printf(_("setting epoch to %ld "
 
493
                         "with RTC_EPOCH_SET ioctl to %s.\n"), epoch,
 
494
                       rtc_dev_name);
 
495
 
 
496
        if (ioctl(rtc_fd, RTC_EPOCH_SET, epoch) == -1) {
 
497
                if (errno == EINVAL)
 
498
                        warnx(_("The kernel device driver for %s "
 
499
                                "does not have the RTC_EPOCH_SET ioctl."),
 
500
                              rtc_dev_name);
 
501
                else
 
502
                        warn(_("ioctl(RTC_EPOCH_SET) to %s failed"),
 
503
                                  rtc_dev_name);
 
504
                return 1;
 
505
        }
 
506
 
 
507
        return 0;
477
508
}