~ubuntu-branches/ubuntu/lucid/loop-aes-utils/lucid-security

« back to all changes in this revision

Viewing changes to hwclock/hwclock.c

  • Committer: Bazaar Package Importer
  • Author(s): Max Vozeler
  • Date: 2008-08-22 11:57:17 UTC
  • mfrom: (8.1.3 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080822115717-v8wfa8pxwlfvyje0
Tags: 2.13.1-4
* patches/losetup_add_option_f.dpatch: 
  - Added to support "find next free loop" in losetup.
    (closes: #495682)

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *
16
16
 * Reshuffled things, added sparc code, and re-added alpha stuff
17
17
 * by David Mosberger <davidm@azstarnet.com>
18
 
 * and Jay Estabrook <jestabro@amt.tay1.dec.com> 
 
18
 * and Jay Estabrook <jestabro@amt.tay1.dec.com>
19
19
 * and Martin Ostermann <ost@coments.rwth-aachen.de>, aeb@cwi.nl, 990212.
20
20
 *
21
21
 * Fix for Award 2094 bug, Dave Coffin  (dcoffin@shore.net)  11/12/98
82
82
#include <getopt.h>
83
83
#include <sysexits.h>
84
84
 
85
 
#include "../defines.h"         /* for HAVE_tm_gmtoff */
86
85
#include "clock.h"
87
86
#include "nls.h"
88
87
 
 
88
#ifdef HAVE_LIBAUDIT
 
89
#include <libaudit.h>
 
90
static int hwaudit_fd = -1;
 
91
static int hwaudit_on;
 
92
#endif
 
93
 
89
94
#define MYNAME "hwclock"
90
95
 
91
96
char *progname = MYNAME;
107
112
     adjtime file, so see documentation of that file for details.
108
113
     Exception is <dirty>, which is an indication that what's in this
109
114
     structure is not what's in the disk file (because it has been
110
 
     updated since read from the disk file).  
 
115
     updated since read from the disk file).
111
116
     */
112
117
  bool dirty;
113
118
 
114
119
  /* line 1 */
115
 
  double drift_factor;    
 
120
  double drift_factor;
116
121
  time_t last_adj_time;
117
122
  double not_adjusted;
118
123
 
175
180
  write_date_to_file (tm);
176
181
}
177
182
 
178
 
static double 
 
183
static double
179
184
time_diff(struct timeval subtrahend, struct timeval subtractor) {
180
185
/*---------------------------------------------------------------------------
181
186
  The difference in seconds between two times in "timeval" format.
236
241
  Return them as the adjtime structure <*adjtime_p>.
237
242
  If there is no /etc/adjtime file, return defaults.
238
243
  If values are missing from the file, return defaults for them.
239
 
  
 
244
 
240
245
  return value 0 if all OK, !=0 otherwise.
241
246
 
242
247
-----------------------------------------------------------------------------*/
267
272
      char line2[81];           /* String: second line of adjtime file */
268
273
      char line3[81];           /* String: third line of adjtime file */
269
274
      long timeval;
270
 
      
271
 
      line1[0] = '\0';          /* In case fgets fails */
272
 
      fgets(line1, sizeof(line1), adjfile);
273
 
      line2[0] = '\0';          /* In case fgets fails */
274
 
      fgets(line2, sizeof(line2), adjfile);
275
 
      line3[0] = '\0';          /* In case fgets fails */
276
 
      fgets(line3, sizeof(line3), adjfile);
277
 
      
 
275
 
 
276
      if (!fgets(line1, sizeof(line1), adjfile))
 
277
        line1[0] = '\0';          /* In case fgets fails */
 
278
      if (!fgets(line2, sizeof(line2), adjfile))
 
279
        line2[0] = '\0';          /* In case fgets fails */
 
280
      if (!fgets(line3, sizeof(line3), adjfile))
 
281
        line3[0] = '\0';          /* In case fgets fails */
 
282
 
278
283
      fclose(adjfile);
279
 
      
 
284
 
280
285
      /* Set defaults in case values are missing from file */
281
286
      adjtime_p->drift_factor = 0;
282
287
      adjtime_p->last_adj_time = 0;
283
288
      adjtime_p->not_adjusted = 0;
284
289
      adjtime_p->last_calib_time = 0;
285
290
      timeval = 0;
286
 
      
287
 
      sscanf(line1, "%lf %ld %lf", 
 
291
 
 
292
      sscanf(line1, "%lf %ld %lf",
288
293
             &adjtime_p->drift_factor,
289
 
             &timeval, 
 
294
             &timeval,
290
295
             &adjtime_p->not_adjusted);
291
296
      adjtime_p->last_adj_time = timeval;
292
297
 
310
315
    adjtime_p->dirty = FALSE;
311
316
 
312
317
    if (debug) {
313
 
      printf(_("Last drift adjustment done at %ld seconds after 1969\n"), 
 
318
      printf(_("Last drift adjustment done at %ld seconds after 1969\n"),
314
319
             (long) adjtime_p->last_adj_time);
315
320
      printf(_("Last calibration done at %ld seconds after 1969\n"),
316
321
             (long) adjtime_p->last_calib_time);
334
339
  once per second, right on the falling edge of the update flag.
335
340
 
336
341
  We wait (up to one second) either blocked waiting for an rtc device
337
 
  or in a CPU spin loop.  The former is probably not very accurate.  
 
342
  or in a CPU spin loop.  The former is probably not very accurate.
338
343
 
339
344
  Return 0 if it worked, nonzero if it didn't.
340
345
-----------------------------------------------------------------------------*/
352
357
 
353
358
 
354
359
static void
355
 
mktime_tz(struct tm tm, const bool universal, 
 
360
mktime_tz(struct tm tm, const bool universal,
356
361
          bool *valid_p, time_t *systime_p) {
357
362
/*-----------------------------------------------------------------------------
358
363
  Convert a time in broken down format (hours, minutes, etc.) into standard
374
379
  time_t mktime_result;  /* The value returned by our mktime() call */
375
380
  char *zone;       /* Local time zone name */
376
381
 
377
 
  /* We use the C library function mktime(), but since it only works on 
378
 
     local time zone input, we may have to fake it out by temporarily 
 
382
  /* We use the C library function mktime(), but since it only works on
 
383
     local time zone input, we may have to fake it out by temporarily
379
384
     changing the local time zone to UTC.
380
385
     */
381
386
  zone = getenv("TZ");  /* remember original time zone */
404
409
  } else {
405
410
    *valid_p = TRUE;
406
411
    *systime_p = mktime_result;
407
 
    if (debug) 
 
412
    if (debug)
408
413
      printf(_("Hw clock time : %4d/%.2d/%.2d %.2d:%.2d:%.2d = "
409
414
               "%ld seconds since 1969\n"),
410
415
             tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
441
446
 
442
447
 
443
448
static void
444
 
set_hardware_clock(const time_t newtime, 
445
 
                   const bool universal, 
 
449
set_hardware_clock(const time_t newtime,
 
450
                   const bool universal,
446
451
                   const bool testing) {
447
452
/*----------------------------------------------------------------------------
448
453
  Set the Hardware Clock to the time <newtime>, in local time zone or UTC,
449
454
  according to <universal>.
450
455
----------------------------------------------------------------------------*/
451
456
  int err;
452
 
  struct tm new_broken_time;  
 
457
  struct tm new_broken_time;
453
458
    /* Time to which we will set Hardware Clock, in broken down format, in
454
459
       the time zone of caller's choice
455
460
       */
459
464
  else
460
465
          new_broken_time = *localtime(&newtime);
461
466
 
462
 
  if (debug) 
 
467
  if (debug)
463
468
    printf(_("Setting Hardware Clock to %.2d:%.2d:%.2d "
464
 
           "= %ld seconds since 1969\n"), 
465
 
           new_broken_time.tm_hour, new_broken_time.tm_min, 
 
469
           "= %ld seconds since 1969\n"),
 
470
           new_broken_time.tm_hour, new_broken_time.tm_min,
466
471
           new_broken_time.tm_sec, (long) newtime);
467
472
 
468
473
  if (testing)
484
489
 
485
490
 
486
491
static void
487
 
set_hardware_clock_exact(const time_t sethwtime, 
 
492
set_hardware_clock_exact(const time_t sethwtime,
488
493
                         const struct timeval refsystime,
489
 
                         const bool universal, 
 
494
                         const bool universal,
490
495
                         const bool testing) {
491
496
/*----------------------------------------------------------------------------
492
497
  Set the Hardware Clock to the time "sethwtime", in local time zone or UTC,
500
505
  to 14:03:07, thus getting a precise and retroactive setting of the clock.
501
506
 
502
507
  (Don't be confused by the fact that the system clock and the Hardware
503
 
  Clock differ by two hours in the above example.  That's just to remind 
 
508
  Clock differ by two hours in the above example.  That's just to remind
504
509
  you that there are two independent time scales here).
505
510
 
506
511
  This function ought to be able to accept set times as fractional times.
513
518
 time_resync:
514
519
  gettimeofday(&beginsystime, NULL);
515
520
  newhwtime = sethwtime + (int) time_diff(beginsystime, refsystime) + 1;
516
 
  if (debug) 
 
521
  if (debug)
517
522
    printf(_("Time elapsed since reference time has been %.6f seconds.\n"
518
523
           "Delaying further to reach the next full second.\n"),
519
524
           time_diff(beginsystime, refsystime));
520
 
  
521
 
  /* Now delay some more until Hardware Clock time newhwtime arrives */
 
525
 
 
526
  /*
 
527
   * Now delay some more until Hardware Clock time newhwtime arrives.  The -500
 
528
   * ms is because the Hardware Clock always sets to your set time plus 500 ms
 
529
   * (because it is designed to update to the next second precisely 500 ms
 
530
   * after you finish the setting).
 
531
   */
522
532
  do {
523
533
          float tdiff;
524
534
          gettimeofday(&nowsystime, NULL);
525
535
          tdiff = time_diff(nowsystime, beginsystime);
526
536
          if (tdiff < 0)
527
537
                  goto time_resync;     /* probably time was reset */
528
 
  } while (time_diff(nowsystime, refsystime) < newhwtime - sethwtime);
529
 
  
 
538
  } while (time_diff(nowsystime, refsystime) - 0.5 < newhwtime - sethwtime);
 
539
 
530
540
  set_hardware_clock(newhwtime, universal, testing);
531
541
}
532
542
 
533
543
 
534
544
 
535
545
static void
536
 
display_time(const bool hclock_valid, const time_t systime, 
 
546
display_time(const bool hclock_valid, const time_t systime,
537
547
             const double sync_duration) {
538
548
/*----------------------------------------------------------------------------
539
549
  Put the time "systime" on standard output in display format.
565
575
  Interpret the value of the --date option, which is something like
566
576
  "13:05:01".  In fact, it can be any of the myriad ASCII strings that specify
567
577
  a time which the "date" program can understand.  The date option value in
568
 
  question is our "dateopt" argument.  
 
578
  question is our "dateopt" argument.
569
579
 
570
580
  The specified time is in the local time zone.
571
581
 
582
592
        FILE *date_child_fp;
583
593
        char date_resp[100];
584
594
        const char magic[]="seconds-into-epoch=";
585
 
        char date_command[100];  
 
595
        char date_command[100];
586
596
        int retcode;  /* our eventual return code */
587
597
        int rc;  /* local return code */
588
598
 
605
615
                return 12;
606
616
        }
607
617
 
608
 
        sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s", 
 
618
        sprintf(date_command, "date --date=\"%s\" +seconds-into-epoch=%%s",
609
619
                date_opt);
610
620
        if (debug)
611
621
                printf(_("Issuing date command: %s\n"), date_command);
617
627
                return 10;
618
628
        }
619
629
 
620
 
        date_resp[0] = '\0';  /* in case fgets fails */
621
 
        fgets(date_resp, sizeof(date_resp), date_child_fp);
 
630
        if (!fgets(date_resp, sizeof(date_resp), date_child_fp))
 
631
                date_resp[0] = '\0';  /* in case fgets fails */
622
632
        if (debug)
623
633
                printf(_("response from date command = %s\n"), date_resp);
624
634
        if (strncmp(date_resp, magic, sizeof(magic)-1) != 0) {
625
635
                fprintf(stderr, _("The date command issued by %s returned "
626
636
                                  "unexpected results.\n"
627
637
                                  "The command was:\n  %s\n"
628
 
                                  "The response was:\n  %s\n"), 
 
638
                                  "The response was:\n  %s\n"),
629
639
                        MYNAME, date_command, date_resp);
630
640
                retcode = 8;
631
641
        } else {
644
654
                } else {
645
655
                        retcode = 0;
646
656
                        *time_p = seconds_since_epoch;
647
 
                        if (debug) 
 
657
                        if (debug)
648
658
                                printf(_("date string %s equates to "
649
659
                                         "%ld seconds since 1969.\n"),
650
660
                                       date_opt, (long) *time_p);
655
665
        return retcode;
656
666
}
657
667
 
658
 
 
659
 
 
660
 
static int 
661
 
set_system_clock(const bool hclock_valid, const time_t newtime, 
 
668
 
 
669
 
 
670
static int
 
671
set_system_clock(const bool hclock_valid, const time_t newtime,
662
672
                 const bool testing) {
663
673
/*----------------------------------------------------------------------------
664
674
   Set the System Clock to time 'newtime'.
665
675
 
666
 
   Also set the kernel time zone value to the value indicated by the 
 
676
   Also set the kernel time zone value to the value indicated by the
667
677
   TZ environment variable and/or /usr/lib/zoneinfo/, interpreted as
668
678
   tzset() would interpret them.
669
679
 
671
681
   saying there is no valid time in the Hardware Clock to which to set
672
682
   the system time.
673
683
 
674
 
   If 'testing' is true, don't actually update anything -- just say we 
 
684
   If 'testing' is true, don't actually update anything -- just say we
675
685
   would have.
676
686
-----------------------------------------------------------------------------*/
677
687
  int retcode;
685
695
    struct tm *broken;
686
696
    int minuteswest;
687
697
    int rc;
688
 
    
 
698
 
689
699
    tv.tv_sec = newtime;
690
700
    tv.tv_usec = 0;
691
 
    
 
701
 
692
702
    broken = localtime(&newtime);
693
 
#ifdef HAVE_tm_gmtoff
 
703
#ifdef HAVE_TM_GMTOFF
694
704
    minuteswest = -broken->tm_gmtoff/60;                /* GNU extension */
695
705
#else
696
706
    minuteswest = timezone/60;
697
707
    if (broken->tm_isdst)
698
708
            minuteswest -= 60;
699
709
#endif
700
 
    
 
710
 
701
711
    if (debug) {
702
712
      printf(_("Calling settimeofday:\n"));
703
713
      printf(_("\ttv.tv_sec = %ld, tv.tv_usec = %ld\n"),
729
739
 
730
740
static void
731
741
adjust_drift_factor(struct adjtime *adjtime_p,
732
 
                    const time_t nowtime, 
 
742
                    const time_t nowtime,
733
743
                    const bool hclock_valid,
734
744
                    const time_t hclocktime,
735
745
                    const double sync_delay) {
814
824
                               (int) (nowtime - adjtime_p->last_calib_time),
815
825
                               adjtime_p->drift_factor,
816
826
                               factor_adjust);
817
 
      
 
827
 
818
828
                adjtime_p->drift_factor += factor_adjust;
819
829
        }
820
830
        adjtime_p->last_calib_time = nowtime;
821
 
  
 
831
 
822
832
        adjtime_p->last_adj_time = nowtime;
823
 
  
 
833
 
824
834
        adjtime_p->not_adjusted = 0;
825
 
    
 
835
 
826
836
        adjtime_p->dirty = TRUE;
827
837
}
828
838
 
830
840
 
831
841
static void
832
842
calculate_adjustment(const double factor,
833
 
                     const time_t last_time, 
 
843
                     const time_t last_time,
834
844
                     const double not_adjusted,
835
845
                     const time_t systime,
836
 
                     int *adjustment_p, 
 
846
                     int *adjustment_p,
837
847
                     double *retro_p,
838
848
                     const int debug ) {
839
849
/*----------------------------------------------------------------------------
842
852
  The way we have to set the clock, we need the adjustment in two parts:
843
853
 
844
854
    1) an integer number of seconds (return as *adjustment_p)
845
 
       
 
855
 
846
856
    2) a positive fraction of a second (less than 1) (return as *retro_p)
847
857
 
848
858
  The sum of these two values is the adjustment needed.  Positive means to
854
864
  exact_adjustment = ((double) (systime - last_time)) * factor / (24 * 60 * 60)
855
865
                     + not_adjusted;
856
866
  *adjustment_p = FLOOR(exact_adjustment);
857
 
  
 
867
 
858
868
  *retro_p = exact_adjustment - (double) *adjustment_p;
859
869
  if (debug) {
860
870
    printf (_("Time since last adjustment is %d seconds\n"),
889
899
 
890
900
    if (testing) {
891
901
      printf(_("Not updating adjtime file because of testing mode.\n"));
892
 
      printf(_("Would have written the following to %s:\n%s"), 
 
902
      printf(_("Would have written the following to %s:\n%s"),
893
903
             ADJPATH, newfile);
894
904
    } else {
895
905
      FILE *adjfile;
922
932
 
923
933
static void
924
934
do_adjustment(struct adjtime *adjtime_p,
925
 
              const bool hclock_valid, const time_t hclocktime, 
 
935
              const bool hclock_valid, const time_t hclocktime,
926
936
              const struct timeval read_time,
927
937
              const bool universal, const bool testing) {
928
938
/*---------------------------------------------------------------------------
929
 
  Do the adjustment requested, by 1) setting the Hardware Clock (if 
 
939
  Do the adjustment requested, by 1) setting the Hardware Clock (if
930
940
  necessary), and 2) updating the last-adjusted time in the adjtime
931
941
  structure.
932
942
 
939
949
  <hclock_valid> means the Hardware Clock contains a valid time, and that
940
950
  time is <hclocktime>.
941
951
 
942
 
  <read_time> is the current system time (to be precise, it is the system 
 
952
  <read_time> is the current system time (to be precise, it is the system
943
953
  time at the time <hclocktime> was read, which due to computational delay
944
954
  could be a short time ago).
945
955
 
967
977
  } else {
968
978
    int adjustment;
969
979
    /* Number of seconds we must insert in the Hardware Clock */
970
 
    double retro;   
 
980
    double retro;
971
981
    /* Fraction of second we have to remove from clock after inserting
972
982
       <adjustment> whole seconds.
973
983
       */
978
988
                         &adjustment, &retro,
979
989
                         debug );
980
990
    if (adjustment > 0 || adjustment < -1) {
981
 
      set_hardware_clock_exact(hclocktime + adjustment, 
 
991
      set_hardware_clock_exact(hclocktime + adjustment,
982
992
                               time_inc(read_time, -retro),
983
993
                               universal, testing);
984
994
      adjtime_p->last_adj_time = hclocktime + adjustment;
985
995
      adjtime_p->not_adjusted = 0;
986
996
      adjtime_p->dirty = TRUE;
987
 
    } else 
988
 
      if (debug) 
 
997
    } else
 
998
      if (debug)
989
999
        printf(_("Needed adjustment is less than one second, "
990
1000
               "so not setting clock.\n"));
991
1001
  }
1021
1031
static int
1022
1032
manipulate_clock(const bool show, const bool adjust, const bool noadjfile,
1023
1033
                 const bool set, const time_t set_time,
1024
 
                 const bool hctosys, const bool systohc, 
1025
 
                 const struct timeval startup_time, 
 
1034
                 const bool hctosys, const bool systohc,
 
1035
                 const struct timeval startup_time,
1026
1036
                 const bool utc, const bool local_opt,
1027
1037
                 const bool testing) {
1028
1038
/*---------------------------------------------------------------------------
1047
1057
              return rc;
1048
1058
    } else {
1049
1059
      /* A little trick to avoid reading the file if we don't have to */
1050
 
      adjtime.dirty = FALSE; 
 
1060
      adjtime.dirty = FALSE;
1051
1061
      rc = 0;
1052
1062
    }
1053
1063
 
1065
1075
              return rc;
1066
1076
 
1067
1077
      {
1068
 
        struct timeval read_time; 
 
1078
        struct timeval read_time;
1069
1079
          /* The time at which we read the Hardware Clock */
1070
1080
 
1071
1081
        bool hclock_valid;
1078
1088
             synchronized to its next clock tick when we started up.
1079
1089
             Defined only if hclock_valid is true.
1080
1090
             */
1081
 
        
 
1091
 
1082
1092
        gettimeofday(&read_time, NULL);
1083
 
        read_hardware_clock(universal, &hclock_valid, &hclocktime); 
1084
 
        
 
1093
        read_hardware_clock(universal, &hclock_valid, &hclocktime);
 
1094
 
1085
1095
        if (show) {
1086
 
          display_time(hclock_valid, hclocktime, 
 
1096
          display_time(hclock_valid, hclocktime,
1087
1097
                       time_diff(read_time, startup_time));
1088
1098
        } else if (set) {
1089
 
          set_hardware_clock_exact(set_time, startup_time, 
 
1099
          set_hardware_clock_exact(set_time, startup_time,
1090
1100
                                      universal, testing);
1091
1101
          adjust_drift_factor(&adjtime, set_time, hclock_valid, hclocktime,
1092
1102
                              time_diff(read_time, startup_time));
1093
1103
        } else if (adjust) {
1094
 
          do_adjustment(&adjtime, hclock_valid, hclocktime, 
 
1104
          do_adjustment(&adjtime, hclock_valid, hclocktime,
1095
1105
                        read_time, universal, testing);
1096
1106
        } else if (systohc) {
1097
1107
          struct timeval nowtime, reftime;
1098
1108
          /* We can only set_hardware_clock_exact to a whole seconds
1099
1109
             time, so we set it with reference to the most recent
1100
 
             whole seconds time.  
 
1110
             whole seconds time.
1101
1111
             */
1102
1112
          gettimeofday(&nowtime, NULL);
1103
1113
          reftime.tv_sec = nowtime.tv_sec;
1104
1114
          reftime.tv_usec = 0;
1105
 
          
1106
 
          set_hardware_clock_exact((time_t) reftime.tv_sec, reftime, 
 
1115
 
 
1116
          set_hardware_clock_exact((time_t) reftime.tv_sec, reftime,
1107
1117
                                   universal, testing);
1108
 
          adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid, 
 
1118
          adjust_drift_factor(&adjtime, (time_t) reftime.tv_sec, hclock_valid,
1109
1119
                              hclocktime, (double) read_time.tv_usec / 1E6);
1110
1120
        } else if (hctosys) {
1111
1121
          rc = set_system_clock(hclock_valid, hclocktime, testing);
1123
1133
 
1124
1134
 
1125
1135
static void
1126
 
manipulate_epoch(const bool getepoch, const bool setepoch, 
 
1136
manipulate_epoch(const bool getepoch, const bool setepoch,
1127
1137
                 const int epoch_opt, const bool testing) {
1128
1138
/*----------------------------------------------------------------------------
1129
1139
   Get or set the Hardware Clock epoch value in the kernel, as appropriate.
1133
1143
 
1134
1144
-----------------------------------------------------------------------------*/
1135
1145
  /*
1136
 
   Maintenance note:  This should work on non-Alpha machines, but the 
 
1146
   Maintenance note:  This should work on non-Alpha machines, but the
1137
1147
   evidence today (98.03.04) indicates that the kernel only keeps the
1138
1148
   epoch value on Alphas.  If that is ever fixed, this function should be
1139
1149
   changed.
1150
1160
 
1151
1161
      if (get_epoch_rtc(&epoch, 0))
1152
1162
        fprintf(stderr, _("Unable to get the epoch value from the kernel.\n"));
1153
 
      else 
 
1163
      else
1154
1164
        printf(_("Kernel is assuming an epoch value of %lu\n"), epoch);
1155
1165
    } else if (setepoch) {
1156
1166
      if (epoch_opt == -1)
1165
1175
#endif
1166
1176
}
1167
1177
 
1168
 
#if __ia64__
 
1178
#ifdef __ia64__
1169
1179
#define RTC_DEV "/dev/efirtc"
1170
1180
#else
1171
1181
#define RTC_DEV "/dev/rtc"
1173
1183
 
1174
1184
static void
1175
1185
out_version(void) {
1176
 
        printf(_("%s from %s\n"), MYNAME, util_linux_version);
 
1186
        printf(_("%s from %s\n"), MYNAME, PACKAGE_STRING);
1177
1187
}
1178
1188
 
1179
1189
/*
1180
1190
    usage - Output (error and) usage information
1181
1191
 
1182
 
    This function is called both directly from main to show usage 
1183
 
    information and as fatal function from shhopt if some argument is 
1184
 
    not understood. In case of normal usage info FMT should be NULL. 
1185
 
    In that case the info is printed to stdout. If FMT is given 
1186
 
    usage will act like fprintf( stderr, fmt, ... ), show a usage 
 
1192
    This function is called both directly from main to show usage
 
1193
    information and as fatal function from shhopt if some argument is
 
1194
    not understood. In case of normal usage info FMT should be NULL.
 
1195
    In that case the info is printed to stdout. If FMT is given
 
1196
    usage will act like fprintf( stderr, fmt, ... ), show a usage
1187
1197
    information and terminate the program afterwards.
1188
1198
*/
1189
 
static void 
 
1199
static void
1190
1200
usage( const char *fmt, ... ) {
1191
1201
  FILE    *usageto;
1192
1202
  va_list ap;
1211
1221
    "\nOptions: \n"
1212
1222
    "  --utc         the hardware clock is kept in coordinated universal time\n"
1213
1223
    "  --localtime   the hardware clock is kept in local time\n"
 
1224
    "  --rtc=path    special /dev/... file to use instead of default\n"
1214
1225
    "  --directisa   access the ISA bus directly instead of %s\n"
1215
1226
    "  --badyear     ignore rtc's year because the bios is broken\n"
1216
1227
    "  --date        specifies the time to which to set the hardware clock\n"
1234
1245
    vfprintf(stderr, fmt, ap);
1235
1246
    va_end(ap);
1236
1247
  }
1237
 
 
1238
 
  exit(fmt ? EX_USAGE : 0);
 
1248
 
 
1249
  hwclock_exit(fmt ? EX_USAGE : 0);
1239
1250
}
1240
1251
 
1241
1252
static const struct option longopts[] = {
1266
1277
        { "test", 0, 0, 135 },
1267
1278
        { "date", 1, 0, 136 },
1268
1279
        { "epoch", 1, 0, 137 },
 
1280
        { "rtc", 1, 0, 'f' },
1269
1281
        { NULL, 0, 0, 0 }
1270
1282
};
1271
1283
 
1278
1290
 *  0: OK (or not)
1279
1291
 *  1: failure
1280
1292
 */
1281
 
int 
 
1293
int
1282
1294
main(int argc, char **argv) {
1283
1295
 
1284
1296
        struct timeval startup_time;
1285
1297
        /* The time we started up, in seconds into the epoch, including
1286
1298
           fractions. */
1287
 
        time_t set_time;  /* Time to which user said to set Hardware Clock */
 
1299
        time_t set_time = 0;  /* Time to which user said to set Hardware Clock */
1288
1300
 
1289
1301
        bool permitted;  /* User is permitted to do the function */
1290
1302
        int rc, c;
1299
1311
        /* Remember what time we were invoked */
1300
1312
        gettimeofday(&startup_time, NULL);
1301
1313
 
 
1314
#ifdef HAVE_LIBAUDIT
 
1315
        hwaudit_fd = audit_open();
 
1316
        if (hwaudit_fd < 0 && !(errno == EINVAL || errno == EPROTONOSUPPORT ||
 
1317
                                errno == EAFNOSUPPORT)) {
 
1318
                /* You get these error codes only when the kernel doesn't have
 
1319
                 * audit compiled in. */
 
1320
                fprintf(stderr, _("%s: Unable to connect to audit system\n"),
 
1321
                                MYNAME);
 
1322
                return EX_NOPERM;
 
1323
        }
 
1324
#endif
1302
1325
        setlocale(LC_ALL, "");
1303
1326
#ifdef LC_NUMERIC
1304
1327
        /* We need LC_CTYPE and LC_TIME and LC_MESSAGES, but must avoid
1315
1338
        ARCconsole = Jensen = SRM = funky_toy = directisa = badyear = FALSE;
1316
1339
        date_opt = NULL;
1317
1340
 
1318
 
        while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSF", longopts, NULL))
 
1341
        while ((c = getopt_long (argc, argv, "?hvVDarsuwAJSFf:", longopts, NULL))
1319
1342
               != -1) {
1320
1343
                switch (c) {
1321
1344
                case 'D':
1380
1403
                case 137:
1381
1404
                        epoch_option = atoi(optarg);    /* --epoch */
1382
1405
                        break;
 
1406
                case 'f':
 
1407
                        rtc_dev_name = optarg;          /* --rtc */
 
1408
                        break;
1383
1409
                case 'v':                               /* --version */
1384
1410
                case 'V':
1385
1411
                        out_version();
1394
1420
        argc -= optind;
1395
1421
        argv += optind;
1396
1422
 
 
1423
#ifdef HAVE_LIBAUDIT
 
1424
        if (testing != TRUE) {
 
1425
                if (adjust == TRUE || hctosys == TRUE || systohc == TRUE ||
 
1426
                                        set == TRUE || setepoch == TRUE) {
 
1427
                        hwaudit_on = TRUE;
 
1428
                }
 
1429
        }
 
1430
#endif
1397
1431
        if (argc > 0) {
1398
1432
                usage(_("%s takes no non-option arguments.  "
1399
1433
                        "You supplied %d.\n"),
1404
1438
                fprintf(stderr, _("You have specified multiple functions.\n"
1405
1439
                                  "You can only perform one function "
1406
1440
                                  "at a time.\n"));
1407
 
                exit(EX_USAGE);
 
1441
                hwclock_exit(EX_USAGE);
1408
1442
        }
1409
1443
 
1410
1444
        if (utc && local_opt) {
1411
1445
                fprintf(stderr, _("%s: The --utc and --localtime options "
1412
1446
                                  "are mutually exclusive.  You specified "
1413
1447
                                  "both.\n"), MYNAME);
1414
 
                exit(EX_USAGE);
 
1448
                hwclock_exit(EX_USAGE);
1415
1449
        }
1416
1450
 
1417
1451
        if (adjust && noadjfile) {
1418
1452
                fprintf(stderr, _("%s: The --adjust and --noadjfile options "
1419
1453
                                  "are mutually exclusive.  You specified "
1420
1454
                                  "both.\n"), MYNAME);
1421
 
                exit(EX_USAGE);
 
1455
                hwclock_exit(EX_USAGE);
1422
1456
        }
1423
1457
 
1424
1458
        if (noadjfile && !(utc || local_opt)) {
1425
1459
                fprintf(stderr, _("%s: With --noadjfile, you must specify "
1426
1460
                                  "either --utc or --localtime\n"), MYNAME);
1427
 
                exit(EX_USAGE);
 
1461
                hwclock_exit(EX_USAGE);
1428
1462
        }
1429
1463
 
1430
1464
#ifdef __alpha__
1438
1472
                if (rc != 0) {
1439
1473
                        fprintf(stderr, _("No usable set-to time.  "
1440
1474
                                          "Cannot set clock.\n"));
1441
 
                        exit(EX_USAGE);
 
1475
                        hwclock_exit(EX_USAGE);
1442
1476
                }
1443
1477
        }
1444
1478
 
1445
 
        if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch)) 
 
1479
        if (!(show | set | systohc | hctosys | adjust | getepoch | setepoch))
1446
1480
                show = 1; /* default to show */
1447
1481
 
1448
 
  
 
1482
 
1449
1483
        if (getuid() == 0)
1450
1484
                permitted = TRUE;
1451
1485
        else {
1452
1486
                /* program is designed to run setuid (in some situations) */
1453
1487
                if (set || hctosys || systohc || adjust) {
1454
 
                        fprintf(stderr, 
 
1488
                        fprintf(stderr,
1455
1489
                                _("Sorry, only the superuser can change "
1456
1490
                                  "the Hardware Clock.\n"));
1457
1491
                        permitted = FALSE;
1461
1495
                                  "the System Clock.\n"));
1462
1496
                        permitted = FALSE;
1463
1497
                } else if (setepoch) {
1464
 
                        fprintf(stderr, 
 
1498
                        fprintf(stderr,
1465
1499
                                _("Sorry, only the superuser can change the "
1466
1500
                                  "Hardware Clock epoch in the kernel.\n"));
1467
1501
                        permitted = FALSE;
1470
1504
        }
1471
1505
 
1472
1506
        if (!permitted)
1473
 
                exit(EX_NOPERM);
 
1507
                hwclock_exit(EX_NOPERM);
1474
1508
 
1475
1509
        if (getepoch || setepoch) {
1476
1510
                manipulate_epoch(getepoch, setepoch, epoch_option, testing);
1477
 
                return 0;
 
1511
                hwclock_exit(0);
1478
1512
        }
1479
1513
 
1480
1514
        if (debug)
1488
1522
                        fprintf(stderr,
1489
1523
                                _("Use the --debug option to see the details "
1490
1524
                                  "of our search for an access method.\n"));
1491
 
                exit(1);
 
1525
                hwclock_exit(1);
1492
1526
        }
1493
1527
 
1494
 
        return manipulate_clock(show, adjust, noadjfile, set, set_time,
 
1528
        rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
1495
1529
                                hctosys, systohc, startup_time, utc,
1496
1530
                                local_opt, testing);
 
1531
        hwclock_exit(rc);
 
1532
        return rc;      /* Not reached */
1497
1533
}
1498
1534
 
1499
1535
/* A single routine for greater uniformity */
1501
1537
outsyserr(char *msg, ...) {
1502
1538
        va_list args;
1503
1539
        int errsv = errno;
1504
 
        
 
1540
 
1505
1541
        fprintf(stderr, "%s: ", progname);
1506
1542
        va_start(args, msg);
1507
1543
        vfprintf(stderr, msg, args);
1510
1546
                errsv, strerror(errsv));
1511
1547
}
1512
1548
 
 
1549
 
 
1550
#ifdef HAVE_LIBAUDIT
 
1551
void
 
1552
hwaudit_exit(int status)
 
1553
{
 
1554
        if (hwaudit_on) {
 
1555
                audit_log_user_message(hwaudit_fd, AUDIT_USYS_CONFIG,
 
1556
                        "changing system time", NULL, NULL, NULL, status ? 0 : 1);
 
1557
                close(hwaudit_fd);
 
1558
        }
 
1559
        exit(status);
 
1560
}
 
1561
#endif
 
1562
 
1513
1563
/****************************************************************************
1514
1564
 
1515
1565
  History of this program:
1516
1566
 
1517
 
  98.08.12 BJH   Version 2.4 
 
1567
  98.08.12 BJH   Version 2.4
1518
1568
 
1519
1569
  Don't use century byte from Hardware Clock.  Add comments telling why.
1520
1570
 
1524
1574
  Make --hctosys set the kernel timezone from TZ environment variable
1525
1575
  and/or /usr/lib/zoneinfo.  From Klaus Ripke (klaus@ripke.com).
1526
1576
 
1527
 
  98.03.05 BJH.  Version 2.2.  
 
1577
  98.03.05 BJH.  Version 2.2.
1528
1578
 
1529
 
  Add --getepoch and --setepoch.  
 
1579
  Add --getepoch and --setepoch.
1530
1580
 
1531
1581
  Fix some word length things so it works on Alpha.
1532
1582
 
1539
1589
  97.06.01: BJH.  Version 2.1.  Read and write the century byte (Byte
1540
1590
  50) of the ISA Hardware Clock when using direct ISA I/O.  Problem
1541
1591
  discovered by job (jei@iclnl.icl.nl).
1542
 
  
 
1592
 
1543
1593
  Use the rtc clock access method in preference to the KDGHWCLK method.
1544
1594
  Problem discovered by Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>.
1545
1595
 
1560
1610
  in this program will be compiled as external references.  Since you
1561
1611
  probably won't be linking with any functions by these names, you will
1562
1612
  have unresolved external references when you link.
1563
 
  
 
1613
 
1564
1614
  The program is designed to run setuid superuser, since we need to be
1565
 
  able to do direct I/O.  (More to the point: we need permission to 
1566
 
  execute the iopl() system call).  (However, if you use one of the 
 
1615
  able to do direct I/O.  (More to the point: we need permission to
 
1616
  execute the iopl() system call).  (However, if you use one of the
1567
1617
  methods other than direct ISA I/O to access the clock, no setuid is
1568
1618
  required).
1569
 
 
 
1619
 
1570
1620
  Here's some info on how we must deal with the time that elapses while
1571
1621
  this program runs: There are two major delays as we run:
1572
1622
 
1587
1637
  So we check the system time as soon as we start up, then run "date"
1588
1638
  and do file I/O if necessary, then wait to synchronize with a
1589
1639
  Hardware Clock edge, then check the system time again to see how
1590
 
  much time we spent.  We immediately read the clock then and (if 
 
1640
  much time we spent.  We immediately read the clock then and (if
1591
1641
  appropriate) report that time, and additionally, the delay we measured.
1592
1642
 
1593
1643
  If we're setting the clock to a time given by the user, we wait some
1608
1658
  complications that might cause, we set the clock as soon as possible
1609
1659
  after an oscillator tick.
1610
1660
 
1611
 
  
 
1661
 
1612
1662
  About synchronizing to the Hardware Clock when reading the time: The
1613
1663
  precision of the Hardware Clock counters themselves is one second.
1614
1664
  You can't read the counters and find out that is 12:01:02.5.  But if
1631
1681
     fail if we miss the goal by more than .1 second, as could happen if
1632
1682
     we get pre-empted (by the kernel dispatcher).
1633
1683
 
1634
 
****************************************************************************/ 
 
1684
****************************************************************************/
1635
1685