LCOV - code coverage report
Current view: top level - shared - clock-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 19 66 28.8 %
Date: 2019-08-23 13:36:53 Functions: 1 6 16.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 13 42 31.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <fcntl.h>
       5                 :            : #include <limits.h>
       6                 :            : #include <stdbool.h>
       7                 :            : #include <time.h>
       8                 :            : #include <linux/rtc.h>
       9                 :            : #include <stdio.h>
      10                 :            : #include <sys/ioctl.h>
      11                 :            : #include <sys/time.h>
      12                 :            : 
      13                 :            : #include "alloc-util.h"
      14                 :            : #include "clock-util.h"
      15                 :            : #include "errno-util.h"
      16                 :            : #include "fd-util.h"
      17                 :            : #include "fileio.h"
      18                 :            : #include "macro.h"
      19                 :            : #include "string-util.h"
      20                 :            : 
      21                 :          0 : int clock_get_hwclock(struct tm *tm) {
      22                 :          0 :         _cleanup_close_ int fd = -1;
      23                 :            : 
      24         [ #  # ]:          0 :         assert(tm);
      25                 :            : 
      26                 :          0 :         fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
      27         [ #  # ]:          0 :         if (fd < 0)
      28                 :          0 :                 return -errno;
      29                 :            : 
      30                 :            :         /* This leaves the timezone fields of struct tm
      31                 :            :          * uninitialized! */
      32         [ #  # ]:          0 :         if (ioctl(fd, RTC_RD_TIME, tm) < 0)
      33                 :          0 :                 return -errno;
      34                 :            : 
      35                 :            :         /* We don't know daylight saving, so we reset this in order not
      36                 :            :          * to confuse mktime(). */
      37                 :          0 :         tm->tm_isdst = -1;
      38                 :            : 
      39                 :          0 :         return 0;
      40                 :            : }
      41                 :            : 
      42                 :          0 : int clock_set_hwclock(const struct tm *tm) {
      43                 :          0 :         _cleanup_close_ int fd = -1;
      44                 :            : 
      45         [ #  # ]:          0 :         assert(tm);
      46                 :            : 
      47                 :          0 :         fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
      48         [ #  # ]:          0 :         if (fd < 0)
      49                 :          0 :                 return -errno;
      50                 :            : 
      51         [ #  # ]:          0 :         if (ioctl(fd, RTC_SET_TIME, tm) < 0)
      52                 :          0 :                 return -errno;
      53                 :            : 
      54                 :          0 :         return 0;
      55                 :            : }
      56                 :            : 
      57                 :         44 : int clock_is_localtime(const char* adjtime_path) {
      58                 :         44 :         _cleanup_fclose_ FILE *f;
      59                 :            :         int r;
      60                 :            : 
      61         [ +  + ]:         44 :         if (!adjtime_path)
      62                 :          4 :                 adjtime_path = "/etc/adjtime";
      63                 :            : 
      64                 :            :         /*
      65                 :            :          * The third line of adjtime is "UTC" or "LOCAL" or nothing.
      66                 :            :          *   # /etc/adjtime
      67                 :            :          *   0.0 0 0
      68                 :            :          *   0
      69                 :            :          *   UTC
      70                 :            :          */
      71                 :         44 :         f = fopen(adjtime_path, "re");
      72         [ +  + ]:         44 :         if (f) {
      73                 :         40 :                 _cleanup_free_ char *line = NULL;
      74                 :            :                 unsigned i;
      75                 :            : 
      76         [ +  + ]:        112 :                 for (i = 0; i < 2; i++) { /* skip the first two lines */
      77                 :         80 :                         r = read_line(f, LONG_LINE_MAX, NULL);
      78         [ -  + ]:         80 :                         if (r < 0)
      79                 :          0 :                                 return r;
      80         [ +  + ]:         80 :                         if (r == 0)
      81                 :          8 :                                 return false; /* less than three lines → default to UTC */
      82                 :            :                 }
      83                 :            : 
      84                 :         32 :                 r = read_line(f, LONG_LINE_MAX, &line);
      85         [ -  + ]:         32 :                 if (r < 0)
      86                 :          0 :                         return r;
      87         [ +  + ]:         32 :                 if (r == 0)
      88                 :          8 :                         return false; /* less than three lines → default to UTC */
      89                 :            : 
      90                 :         24 :                 return streq(line, "LOCAL");
      91                 :            : 
      92         [ -  + ]:          4 :         } else if (errno != ENOENT)
      93                 :          0 :                 return -errno;
      94                 :            : 
      95                 :            :         /* adjtime not present → default to UTC */
      96                 :          4 :         return false;
      97                 :            : }
      98                 :            : 
      99                 :          0 : int clock_set_timezone(int *min) {
     100                 :          0 :         const struct timeval *tv_null = NULL;
     101                 :            :         struct timespec ts;
     102                 :            :         struct tm tm;
     103                 :            :         int minutesdelta;
     104                 :            :         struct timezone tz;
     105                 :            : 
     106         [ #  # ]:          0 :         assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
     107         [ #  # ]:          0 :         assert_se(localtime_r(&ts.tv_sec, &tm));
     108                 :          0 :         minutesdelta = tm.tm_gmtoff / 60;
     109                 :            : 
     110                 :          0 :         tz.tz_minuteswest = -minutesdelta;
     111                 :          0 :         tz.tz_dsttime = 0; /* DST_NONE */
     112                 :            : 
     113                 :            :         /*
     114                 :            :          * If the RTC does not run in UTC but in local time, the very first
     115                 :            :          * call to settimeofday() will set the kernel's timezone and will warp the
     116                 :            :          * system clock, so that it runs in UTC instead of the local time we
     117                 :            :          * have read from the RTC.
     118                 :            :          */
     119         [ #  # ]:          0 :         if (settimeofday(tv_null, &tz) < 0)
     120                 :          0 :                 return negative_errno();
     121                 :            : 
     122         [ #  # ]:          0 :         if (min)
     123                 :          0 :                 *min = minutesdelta;
     124                 :          0 :         return 0;
     125                 :            : }
     126                 :            : 
     127                 :          0 : int clock_reset_timewarp(void) {
     128                 :          0 :         const struct timeval *tv_null = NULL;
     129                 :            :         struct timezone tz;
     130                 :            : 
     131                 :          0 :         tz.tz_minuteswest = 0;
     132                 :          0 :         tz.tz_dsttime = 0; /* DST_NONE */
     133                 :            : 
     134                 :            :         /*
     135                 :            :          * The very first call to settimeofday() does time warp magic. Do a
     136                 :            :          * dummy call here, so the time warping is sealed and all later calls
     137                 :            :          * behave as expected.
     138                 :            :          */
     139         [ #  # ]:          0 :         if (settimeofday(tv_null, &tz) < 0)
     140                 :          0 :                 return -errno;
     141                 :            : 
     142                 :          0 :         return 0;
     143                 :            : }
     144                 :            : 
     145                 :            : #define TIME_EPOCH_USEC ((usec_t) TIME_EPOCH * USEC_PER_SEC)
     146                 :            : 
     147                 :          0 : int clock_apply_epoch(void) {
     148                 :            :         struct timespec ts;
     149                 :            : 
     150         [ #  # ]:          0 :         if (now(CLOCK_REALTIME) >= TIME_EPOCH_USEC)
     151                 :          0 :                 return 0;
     152                 :            : 
     153         [ #  # ]:          0 :         if (clock_settime(CLOCK_REALTIME, timespec_store(&ts, TIME_EPOCH_USEC)) < 0)
     154                 :          0 :                 return -errno;
     155                 :            : 
     156                 :          0 :         return 1;
     157                 :            : }

Generated by: LCOV version 1.14