This source file includes following definitions.
- get_linux_uptime
- get_linux_boot_time_fallback
- get_linux_boot_time_final_fallback
- get_android_boot_time
- get_openbsd_boot_time
- get_bsd_boot_time_final_fallback
- get_haiku_boot_time
- get_haiku_boot_time_final_fallback
- get_windows_boot_time
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #define SIZEOF(a) (sizeof(a)/sizeof(a[0]))
20
21 #if defined __linux__ || defined __ANDROID__
22
23
24
25 _GL_ATTRIBUTE_MAYBE_UNUSED
26 static int
27 get_linux_uptime (struct timespec *p_uptime)
28 {
29
30
31
32 # if !defined __GLIBC__ || 2 < __GLIBC__ + (17 <= __GLIBC_MINOR__)
33 if (clock_gettime (CLOCK_BOOTTIME, p_uptime) >= 0)
34 return 0;
35 # endif
36
37
38
39 # if !defined __ANDROID__
40 FILE *fp = fopen ("/proc/uptime", "re");
41 if (fp != NULL)
42 {
43 char buf[32 + 1];
44 size_t n = fread (buf, 1, sizeof (buf) - 1, fp);
45 fclose (fp);
46 if (n > 0)
47 {
48 buf[n] = '\0';
49
50 time_t s = 0;
51 char *p;
52 for (p = buf; '0' <= *p && *p <= '9'; p++)
53 s = 10 * s + (*p - '0');
54 if (buf < p)
55 {
56 long ns = 0;
57 if (*p++ == '.')
58 for (int i = 0; i < 9; i++)
59 ns = 10 * ns + ('0' <= *p && *p <= '9' ? *p++ - '0' : 0);
60 p_uptime->tv_sec = s;
61 p_uptime->tv_nsec = ns;
62 return 0;
63 }
64 }
65 }
66 # endif
67
68 # if HAVE_DECL_SYSINFO
69
70 struct sysinfo info;
71 if (sysinfo (&info) >= 0)
72 {
73 p_uptime->tv_sec = info.uptime;
74 p_uptime->tv_nsec = 0;
75 return 0;
76 }
77 # endif
78
79 return -1;
80 }
81
82 #endif
83
84 #if defined __linux__ && !defined __ANDROID__
85
86 static int
87 get_linux_boot_time_fallback (struct timespec *p_boot_time)
88 {
89
90
91
92
93 const char * const boot_touched_files[] =
94 {
95 "/var/lib/systemd/random-seed",
96 "/var/run/utmp",
97 "/var/lib/random-seed"
98 };
99 for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++)
100 {
101 const char *filename = boot_touched_files[i];
102 struct stat statbuf;
103 if (stat (filename, &statbuf) >= 0)
104 {
105 *p_boot_time = get_stat_mtime (&statbuf);
106 return 0;
107 }
108 }
109 return -1;
110 }
111
112
113
114
115
116
117
118
119 static int
120 get_linux_boot_time_final_fallback (struct timespec *p_boot_time)
121 {
122 struct timespec uptime;
123 if (get_linux_uptime (&uptime) >= 0)
124 {
125 struct timespec result;
126 # if !defined __GLIBC__ || 2 < __GLIBC__ + (16 <= __GLIBC_MINOR__)
127
128
129
130
131 if (! timespec_get (&result, TIME_UTC))
132 return -1;
133 # else
134
135
136 struct timeval tv;
137 int r = gettimeofday (&tv, NULL);
138 if (r < 0)
139 return r;
140 result.tv_sec = tv.tv_sec;
141 result.tv_nsec = tv.tv_usec * 1000;
142 # endif
143
144 if (result.tv_nsec < uptime.tv_nsec)
145 {
146 result.tv_nsec += 1000000000;
147 result.tv_sec -= 1;
148 }
149 result.tv_sec -= uptime.tv_sec;
150 result.tv_nsec -= uptime.tv_nsec;
151 *p_boot_time = result;
152 return 0;
153 }
154 return -1;
155 }
156
157 #endif
158
159 #if defined __ANDROID__
160
161 static int
162 get_android_boot_time (struct timespec *p_boot_time)
163 {
164
165
166
167
168 struct timespec uptime;
169 if (get_linux_uptime (&uptime) >= 0)
170 {
171 struct timespec result;
172 if (clock_gettime (CLOCK_REALTIME, &result) >= 0)
173 {
174 if (result.tv_nsec < uptime.tv_nsec)
175 {
176 result.tv_nsec += 1000000000;
177 result.tv_sec -= 1;
178 }
179 result.tv_sec -= uptime.tv_sec;
180 result.tv_nsec -= uptime.tv_nsec;
181 *p_boot_time = result;
182 return 0;
183 }
184 }
185 return -1;
186 }
187
188 #endif
189
190 #if defined __OpenBSD__
191
192 static int
193 get_openbsd_boot_time (struct timespec *p_boot_time)
194 {
195
196
197
198 const char * const boot_touched_files[] =
199 {
200 "/var/db/host.random",
201 "/var/run/utmp"
202 };
203 for (idx_t i = 0; i < SIZEOF (boot_touched_files); i++)
204 {
205 const char *filename = boot_touched_files[i];
206 struct stat statbuf;
207 if (stat (filename, &statbuf) >= 0)
208 {
209 *p_boot_time = get_stat_mtime (&statbuf);
210 return 0;
211 }
212 }
213 return -1;
214 }
215
216 #endif
217
218 #if HAVE_SYS_SYSCTL_H && HAVE_SYSCTL \
219 && defined CTL_KERN && defined KERN_BOOTTIME \
220 && !defined __minix
221
222
223
224
225
226
227
228 static int
229 get_bsd_boot_time_final_fallback (struct timespec *p_boot_time)
230 {
231 static int request[2] = { CTL_KERN, KERN_BOOTTIME };
232 struct timeval result;
233 size_t result_len = sizeof result;
234
235 if (sysctl (request, 2, &result, &result_len, NULL, 0) >= 0)
236 {
237 p_boot_time->tv_sec = result.tv_sec;
238 p_boot_time->tv_nsec = result.tv_usec * 1000;
239 return 0;
240 }
241 return -1;
242 }
243
244 #endif
245
246 #if defined __HAIKU__
247
248 static int
249 get_haiku_boot_time (struct timespec *p_boot_time)
250 {
251
252
253
254
255
256
257
258
259
260 const char * const boot_touched_file = "/dev/input";
261 struct stat statbuf;
262 if (stat (boot_touched_file, &statbuf) >= 0)
263 {
264 *p_boot_time = get_stat_mtime (&statbuf);
265 return 0;
266 }
267 return -1;
268 }
269
270 #endif
271
272 #if HAVE_OS_H
273
274
275
276
277
278 static int
279 get_haiku_boot_time_final_fallback (struct timespec *p_boot_time)
280 {
281 system_info si;
282
283 get_system_info (&si);
284 p_boot_time->tv_sec = si.boot_time / 1000000;
285 p_boot_time->tv_nsec = (si.boot_time % 1000000) * 1000;
286 return 0;
287 }
288
289 #endif
290
291 #if defined __CYGWIN__ || defined _WIN32
292
293 static int
294 get_windows_boot_time (struct timespec *p_boot_time)
295 {
296
297
298
299
300
301 const char * const boot_touched_file =
302 #if defined __CYGWIN__ && !defined _WIN32
303 "/cygdrive/c/pagefile.sys"
304 #else
305 "C:\\pagefile.sys"
306 #endif
307 ;
308 struct stat statbuf;
309 if (stat (boot_touched_file, &statbuf) >= 0)
310 {
311 *p_boot_time = get_stat_mtime (&statbuf);
312 return 0;
313 }
314 return -1;
315 }
316
317 #endif