]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/clock-util.c
build-sys: split internal basic/ library from shared/
[thirdparty/systemd.git] / src / basic / clock-util.c
CommitLineData
bbc98d32
KS
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010-2012 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
bbc98d32 22#include <errno.h>
bbc98d32 23#include <stdio.h>
bbc98d32
KS
24#include <fcntl.h>
25#include <sys/ioctl.h>
bbc98d32
KS
26#include <sys/time.h>
27#include <linux/rtc.h>
28
29#include "macro.h"
30#include "util.h"
24efb112 31#include "clock-util.h"
bbc98d32 32
60989612 33int clock_get_hwclock(struct tm *tm) {
8e64fd11 34 _cleanup_close_ int fd = -1;
bbc98d32
KS
35
36 assert(tm);
37
67fb4482 38 fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
bbc98d32
KS
39 if (fd < 0)
40 return -errno;
41
42 /* This leaves the timezone fields of struct tm
43 * uninitialized! */
44 if (ioctl(fd, RTC_RD_TIME, tm) < 0)
8e64fd11 45 return -errno;
bbc98d32
KS
46
47 /* We don't know daylight saving, so we reset this in order not
2f6a5907 48 * to confuse mktime(). */
bbc98d32
KS
49 tm->tm_isdst = -1;
50
8e64fd11 51 return 0;
bbc98d32
KS
52}
53
60989612 54int clock_set_hwclock(const struct tm *tm) {
8e64fd11 55 _cleanup_close_ int fd = -1;
bbc98d32
KS
56
57 assert(tm);
58
67fb4482 59 fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
bbc98d32
KS
60 if (fd < 0)
61 return -errno;
62
63 if (ioctl(fd, RTC_SET_TIME, tm) < 0)
8e64fd11 64 return -errno;
bbc98d32 65
8e64fd11 66 return 0;
bbc98d32 67}
a866073d 68
24efb112 69int clock_is_localtime(void) {
7fd1b19b 70 _cleanup_fclose_ FILE *f;
bbc98d32
KS
71
72 /*
73 * The third line of adjtime is "UTC" or "LOCAL" or nothing.
74 * # /etc/adjtime
75 * 0.0 0 0
76 * 0
77 * UTC
78 */
79 f = fopen("/etc/adjtime", "re");
80 if (f) {
81 char line[LINE_MAX];
82 bool b;
83
84 b = fgets(line, sizeof(line), f) &&
85 fgets(line, sizeof(line), f) &&
86 fgets(line, sizeof(line), f);
bbc98d32
KS
87 if (!b)
88 return -EIO;
89
90 truncate_nl(line);
8e2f9ebf 91 return streq(line, "LOCAL");
bbc98d32 92
bcb161b0 93 } else if (errno != ENOENT)
bbc98d32
KS
94 return -errno;
95
8e2f9ebf 96 return 0;
bbc98d32
KS
97}
98
24efb112 99int clock_set_timezone(int *min) {
bbc98d32
KS
100 const struct timeval *tv_null = NULL;
101 struct timespec ts;
102 struct tm *tm;
19e65613 103 int minutesdelta;
bbc98d32
KS
104 struct timezone tz;
105
106 assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
107 assert_se(tm = localtime(&ts.tv_sec));
19e65613 108 minutesdelta = tm->tm_gmtoff / 60;
bbc98d32 109
19e65613 110 tz.tz_minuteswest = -minutesdelta;
cc13b327 111 tz.tz_dsttime = 0; /* DST_NONE */
bbc98d32
KS
112
113 /*
c264aeab
KS
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.
bbc98d32
KS
118 */
119 if (settimeofday(tv_null, &tz) < 0)
120 return -errno;
121 if (min)
19e65613 122 *min = minutesdelta;
bbc98d32
KS
123 return 0;
124}
125
c264aeab 126int clock_reset_timewarp(void) {
bbc98d32
KS
127 const struct timeval *tv_null = NULL;
128 struct timezone tz;
129
130 tz.tz_minuteswest = 0;
cc13b327 131 tz.tz_dsttime = 0; /* DST_NONE */
bbc98d32 132
72edcff5 133 /*
c264aeab
KS
134 * The very first call to settimeofday() does time warp magic. Do a
135 * dummy call here, so the time warping is sealed and all later calls
136 * behave as expected.
72edcff5 137 */
bbc98d32
KS
138 if (settimeofday(tv_null, &tz) < 0)
139 return -errno;
140
141 return 0;
142}