]> git.proxmox.com Git - systemd.git/blame - src/shared/clock-util.c
Imported Upstream version 217
[systemd.git] / src / shared / clock-util.c
CommitLineData
663996b3
MS
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
22#include <assert.h>
23#include <string.h>
24#include <unistd.h>
25#include <errno.h>
26#include <stdlib.h>
27#include <signal.h>
28#include <stdio.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <sys/ioctl.h>
33#include <stdarg.h>
34#include <ctype.h>
35#include <sys/prctl.h>
36#include <sys/time.h>
37#include <linux/rtc.h>
38
39#include "macro.h"
40#include "util.h"
41#include "log.h"
42#include "strv.h"
60f067b4 43#include "clock-util.h"
663996b3
MS
44#include "fileio.h"
45
60f067b4
JS
46int clock_get_hwclock(struct tm *tm) {
47 _cleanup_close_ int fd = -1;
663996b3
MS
48
49 assert(tm);
50
51 fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
52 if (fd < 0)
53 return -errno;
54
55 /* This leaves the timezone fields of struct tm
56 * uninitialized! */
57 if (ioctl(fd, RTC_RD_TIME, tm) < 0)
60f067b4 58 return -errno;
663996b3
MS
59
60 /* We don't know daylight saving, so we reset this in order not
60f067b4 61 * to confuse mktime(). */
663996b3
MS
62 tm->tm_isdst = -1;
63
60f067b4 64 return 0;
663996b3
MS
65}
66
60f067b4
JS
67int clock_set_hwclock(const struct tm *tm) {
68 _cleanup_close_ int fd = -1;
663996b3
MS
69
70 assert(tm);
71
72 fd = open("/dev/rtc", O_RDONLY|O_CLOEXEC);
73 if (fd < 0)
74 return -errno;
75
76 if (ioctl(fd, RTC_SET_TIME, tm) < 0)
60f067b4 77 return -errno;
663996b3 78
60f067b4 79 return 0;
663996b3
MS
80}
81
60f067b4 82int clock_is_localtime(void) {
663996b3
MS
83 _cleanup_fclose_ FILE *f;
84
85 /*
86 * The third line of adjtime is "UTC" or "LOCAL" or nothing.
87 * # /etc/adjtime
88 * 0.0 0 0
89 * 0
90 * UTC
91 */
92 f = fopen("/etc/adjtime", "re");
93 if (f) {
94 char line[LINE_MAX];
95 bool b;
96
97 b = fgets(line, sizeof(line), f) &&
98 fgets(line, sizeof(line), f) &&
99 fgets(line, sizeof(line), f);
100 if (!b)
101 return -EIO;
102
103 truncate_nl(line);
104 return streq(line, "LOCAL");
105
106 } else if (errno != ENOENT)
107 return -errno;
108
109 return 0;
110}
111
60f067b4 112int clock_set_timezone(int *min) {
663996b3
MS
113 const struct timeval *tv_null = NULL;
114 struct timespec ts;
115 struct tm *tm;
116 int minutesdelta;
117 struct timezone tz;
118
119 assert_se(clock_gettime(CLOCK_REALTIME, &ts) == 0);
120 assert_se(tm = localtime(&ts.tv_sec));
121 minutesdelta = tm->tm_gmtoff / 60;
122
123 tz.tz_minuteswest = -minutesdelta;
124 tz.tz_dsttime = 0; /* DST_NONE*/
125
126 /*
5eef597e
MP
127 * If the RTC does not run in UTC but in local time, the very first
128 * call to settimeofday() will set the kernel's timezone and will warp the
129 * system clock, so that it runs in UTC instead of the local time we
130 * have read from the RTC.
663996b3
MS
131 */
132 if (settimeofday(tv_null, &tz) < 0)
133 return -errno;
134 if (min)
135 *min = minutesdelta;
136 return 0;
137}
138
5eef597e 139int clock_reset_timewarp(void) {
663996b3
MS
140 const struct timeval *tv_null = NULL;
141 struct timezone tz;
142
143 tz.tz_minuteswest = 0;
144 tz.tz_dsttime = 0; /* DST_NONE*/
145
146 /*
5eef597e
MP
147 * The very first call to settimeofday() does time warp magic. Do a
148 * dummy call here, so the time warping is sealed and all later calls
149 * behave as expected.
663996b3
MS
150 */
151 if (settimeofday(tv_null, &tz) < 0)
152 return -errno;
153
154 return 0;
155}