aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2023-08-12 19:39:11 -0700
committerPaul Eggert2023-08-12 19:46:12 -0700
commit5e736ca6ccfa131736ab0b3a298de2cb319e7dfb (patch)
tree65b06f7a73dc2a04c60af430bc95102a347979df /src
parentb35431b218ada2d84eb251d18e5543388b598d80 (diff)
downloademacs-5e736ca6ccfa131736ab0b3a298de2cb319e7dfb.tar.gz
emacs-5e736ca6ccfa131736ab0b3a298de2cb319e7dfb.zip
Improve boot-time gathering
Simplify Emacs proper by using Gnulib’s boot-time module instead of doing it all by hand. This should port Emacs better to obscurish hosts, as Bruno Haible has merged the best of Emacs’s and Gnulib’s boot-time gathering. * lib/boot-time-aux.h, lib/boot-time.c, lib/boot-time.h: * lib/readutmp.h, m4/readutmp.m4: New files, copied from Gnulib. * admin/merge-gnulib (GNULIB_MODULES): Add boot-time. * configure.ac: Do not check for utmp.h; the boot-time module now does this. (BOOT_TIME_FILE): Remove; no longer used. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * src/filelock.c [__FreeBSD__]: Do not include <sys/sysctl.h>. [HAVE_UTMP_H]: Do not include utmp.h. Include boot-time instead: boot-time does the work now. (BOOT_TIME) [HAVE_ANDROID && !ANDROID_STUBIFY]: Don’t undef. (WTMP_FILE): Don’t define. (boot_time, boot_time_initialized, get_boot_time_1, get_boot_time): Remove. (get_boot_sec): New function that simply calls Gnulib get_boot_time. (lock_file_1, current_lock_owner): Use get_boot_sec instead of get_boot_time.
Diffstat (limited to 'src')
-rw-r--r--src/filelock.c172
1 files changed, 10 insertions, 162 deletions
diff --git a/src/filelock.c b/src/filelock.c
index 3b1ff8ad566..d2161f1e58a 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -36,13 +36,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
36#include <sys/file.h> 36#include <sys/file.h>
37#include <fcntl.h> 37#include <fcntl.h>
38#include <unistd.h> 38#include <unistd.h>
39
40#ifdef __FreeBSD__
41#include <sys/sysctl.h>
42#endif /* __FreeBSD__ */
43
44#include <errno.h> 39#include <errno.h>
45 40
41#include <boot-time.h>
46#include <c-ctype.h> 42#include <c-ctype.h>
47 43
48#include "lisp.h" 44#include "lisp.h"
@@ -55,20 +51,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
55 51
56#ifndef MSDOS 52#ifndef MSDOS
57 53
58#ifdef HAVE_UTMP_H
59#include <utmp.h>
60#endif
61
62/* Boot time is not available on Android. */
63
64#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
65#undef BOOT_TIME
66#endif
67
68#if !defined WTMP_FILE && !defined WINDOWSNT && defined BOOT_TIME
69#define WTMP_FILE "/var/log/wtmp"
70#endif
71
72#ifdef HAVE_ANDROID 54#ifdef HAVE_ANDROID
73#include "android.h" /* For `android_is_special_directory'. */ 55#include "android.h" /* For `android_is_special_directory'. */
74#endif /* HAVE_ANDROID */ 56#endif /* HAVE_ANDROID */
@@ -127,153 +109,19 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
127 109
128/* Return the time of the last system boot. */ 110/* Return the time of the last system boot. */
129 111
130static time_t boot_time;
131static bool boot_time_initialized;
132
133#ifdef BOOT_TIME
134static void get_boot_time_1 (const char *, bool);
135#endif
136
137static time_t 112static time_t
138get_boot_time (void) 113get_boot_sec (void)
139{ 114{
140 if (boot_time_initialized) 115 /* get_boot_time maintains static state. Don't touch that state
141 return boot_time;
142 boot_time_initialized = 1;
143
144#if defined (CTL_KERN) && defined (KERN_BOOTTIME)
145 {
146 int mib[2];
147 size_t size;
148 struct timeval boottime_val;
149
150 mib[0] = CTL_KERN;
151 mib[1] = KERN_BOOTTIME;
152 size = sizeof (boottime_val);
153
154 if (sysctl (mib, 2, &boottime_val, &size, NULL, 0) >= 0 && size != 0)
155 {
156 boot_time = boottime_val.tv_sec;
157 return boot_time;
158 }
159 }
160#endif /* defined (CTL_KERN) && defined (KERN_BOOTTIME) */
161
162#ifdef BOOT_TIME_FILE
163 {
164 struct stat st;
165 if (stat (BOOT_TIME_FILE, &st) == 0)
166 {
167 boot_time = st.st_mtime;
168 return boot_time;
169 }
170 }
171#endif /* BOOT_TIME_FILE */
172
173#if defined (BOOT_TIME)
174 /* The utmp routines maintain static state. Don't touch that state
175 if we are going to dump, since it might not survive dumping. */ 116 if we are going to dump, since it might not survive dumping. */
176 if (will_dump_p ()) 117 if (will_dump_p ())
177 return boot_time; 118 return 0;
178
179 /* Try to get boot time from utmp before wtmp,
180 since utmp is typically much smaller than wtmp.
181 Passing a null pointer causes get_boot_time_1
182 to inspect the default file, namely utmp. */
183 get_boot_time_1 (0, 0);
184 if (boot_time)
185 return boot_time;
186
187 /* Try to get boot time from the current wtmp file. */
188 get_boot_time_1 (WTMP_FILE, 1);
189
190 /* If we did not find a boot time in wtmp, look at wtmp.1,
191 wtmp.1.gz, wtmp.2, wtmp.2.gz, and so on. */
192 for (int counter = 0; counter < 20 && ! boot_time; counter++)
193 {
194 Lisp_Object filename = Qnil;
195 bool delete_flag = false;
196 char cmd_string[sizeof WTMP_FILE ".19.gz"];
197 AUTO_STRING_WITH_LEN (tempname, cmd_string,
198 sprintf (cmd_string, "%s.%d", WTMP_FILE, counter));
199 if (! NILP (Ffile_exists_p (tempname)))
200 filename = tempname;
201 else
202 {
203 tempname = make_formatted_string (cmd_string, "%s.%d.gz",
204 WTMP_FILE, counter);
205 if (! NILP (Ffile_exists_p (tempname)))
206 {
207 /* The utmp functions on older systems accept only file
208 names up to 8 bytes long. Choose a 2 byte prefix, so
209 the 6-byte suffix does not make the name too long. */
210 filename = Fmake_temp_file_internal (build_string ("wt"), Qnil,
211 empty_unibyte_string, Qnil);
212 CALLN (Fcall_process, build_string ("gzip"), Qnil,
213 list2 (QCfile, filename), Qnil,
214 build_string ("-cd"), tempname);
215 delete_flag = true;
216 }
217 }
218
219 if (! NILP (filename))
220 {
221 get_boot_time_1 (SSDATA (filename), 1);
222 if (delete_flag)
223 emacs_unlink (SSDATA (filename));
224 }
225 }
226
227 return boot_time;
228#else
229 return 0;
230#endif
231}
232 119
233#ifdef BOOT_TIME 120 struct timespec boot_time;
234/* Try to get the boot time from wtmp file FILENAME. 121 boot_time.tv_sec = 0;
235 This succeeds if that file contains a reboot record. 122 get_boot_time (&boot_time);
236 123 return boot_time.tv_sec;
237 If FILENAME is zero, use the same file as before;
238 if no FILENAME has ever been specified, this is the utmp file.
239 Use the newest reboot record if NEWEST,
240 the first reboot record otherwise.
241 Ignore all reboot records on or before BOOT_TIME.
242 Success is indicated by setting BOOT_TIME to a larger value. */
243
244void
245get_boot_time_1 (const char *filename, bool newest)
246{
247 struct utmp ut, *utp;
248
249 if (filename)
250 utmpname (filename);
251
252 setutent ();
253
254 while (1)
255 {
256 /* Find the next reboot record. */
257 ut.ut_type = BOOT_TIME;
258 utp = getutid (&ut);
259 if (! utp)
260 break;
261 /* Compare reboot times and use the newest one. */
262 if (utp->ut_time > boot_time)
263 {
264 boot_time = utp->ut_time;
265 if (! newest)
266 break;
267 }
268 /* Advance on element in the file
269 so that getutid won't repeat the same one. */
270 utp = getutent ();
271 if (! utp)
272 break;
273 }
274 endutent ();
275} 124}
276#endif /* BOOT_TIME */
277 125
278/* An arbitrary limit on lock contents length. 8 K should be plenty 126/* An arbitrary limit on lock contents length. 8 K should be plenty
279 big enough in practice. */ 127 big enough in practice. */
@@ -418,7 +266,7 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
418static int 266static int
419lock_file_1 (Lisp_Object lfname, bool force) 267lock_file_1 (Lisp_Object lfname, bool force)
420{ 268{
421 intmax_t boot = get_boot_time (); 269 intmax_t boot = get_boot_sec ();
422 Lisp_Object luser_name = Fuser_login_name (Qnil); 270 Lisp_Object luser_name = Fuser_login_name (Qnil);
423 Lisp_Object lhost_name = Fsystem_name (); 271 Lisp_Object lhost_name = Fsystem_name ();
424 272
@@ -604,7 +452,7 @@ current_lock_owner (lock_info_type *owner, Lisp_Object lfname)
604 && (kill (pid, 0) >= 0 || errno == EPERM) 452 && (kill (pid, 0) >= 0 || errno == EPERM)
605 && (boot_time == 0 453 && (boot_time == 0
606 || (boot_time <= TYPE_MAXIMUM (time_t) 454 || (boot_time <= TYPE_MAXIMUM (time_t)
607 && within_one_second (boot_time, get_boot_time ())))) 455 && within_one_second (boot_time, get_boot_sec ()))))
608 return ANOTHER_OWNS_IT; 456 return ANOTHER_OWNS_IT;
609 /* The owner process is dead or has a strange pid, so try to 457 /* The owner process is dead or has a strange pid, so try to
610 zap the lockfile. */ 458 zap the lockfile. */