Mercurial > emacs
comparison src/filelock.c @ 24349:b6c16b67b735
(within_one_second): New function.
(current_lock_owner): Use that.
(get_boot_time): Use /proc/uptime if available.
Otherwise, if nothing found in wtmp, try wtmp.1.gz and so on.
(get_boot_time_1): New subroutine taken from get_boot_time.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Fri, 19 Feb 1999 01:36:29 +0000 |
parents | b7efc1e72e26 |
children | 8cbfa7848416 |
comparison
equal
deleted
inserted
replaced
24348:9365b6b93858 | 24349:b6c16b67b735 |
---|---|
41 | 41 |
42 #include "lisp.h" | 42 #include "lisp.h" |
43 #include "buffer.h" | 43 #include "buffer.h" |
44 #include "charset.h" | 44 #include "charset.h" |
45 #include "coding.h" | 45 #include "coding.h" |
46 #include "systime.h" | |
46 | 47 |
47 #include <time.h> | 48 #include <time.h> |
48 #include <errno.h> | 49 #include <errno.h> |
49 #ifndef errno | 50 #ifndef errno |
50 extern int errno; | 51 extern int errno; |
92 | 93 |
93 /* Return the time of the last system boot. */ | 94 /* Return the time of the last system boot. */ |
94 | 95 |
95 static time_t boot_time; | 96 static time_t boot_time; |
96 | 97 |
98 extern Lisp_Object Vshell_file_name; | |
99 | |
97 static time_t | 100 static time_t |
98 get_boot_time () | 101 get_boot_time () |
99 { | 102 { |
100 #ifdef BOOT_TIME | 103 #ifdef BOOT_TIME |
101 struct utmp ut, *utp; | 104 struct utmp ut, *utp; |
105 int fd; | |
106 EMACS_TIME time_before, after; | |
107 int counter; | |
102 | 108 |
103 if (boot_time) | 109 if (boot_time) |
104 return boot_time; | 110 return boot_time; |
105 | 111 |
106 utmpname ("/var/log/wtmp"); | 112 EMACS_GET_TIME (time_before); |
113 | |
114 /* Try calculating the last boot time | |
115 from the uptime as obtained from /proc/uptime. */ | |
116 | |
117 while ((fd = open ("/proc/uptime", O_RDONLY)) >= 0) | |
118 { | |
119 char buf[BUFSIZ]; | |
120 int res; | |
121 double upsecs; | |
122 time_t uptime; | |
123 | |
124 read (fd, buf, BUFSIZ); | |
125 close (fd); | |
126 | |
127 res = sscanf (buf, "%lf", &upsecs); | |
128 | |
129 /* If the current time did not tick while we were getting the | |
130 uptime, we have a valid result. */ | |
131 EMACS_GET_TIME (after); | |
132 if (res == 1 && EMACS_SECS (after) == EMACS_SECS (time_before)) | |
133 { | |
134 boot_time = EMACS_SECS (time_before) - (time_t) upsecs; | |
135 return boot_time; | |
136 } | |
137 | |
138 /* Otherwise, try again to read the uptime. */ | |
139 time_before = after; | |
140 } | |
141 | |
142 /* Try to get boot time from the current wtmp file. */ | |
143 get_boot_time_1 ("/var/log/wtmp"); | |
144 | |
145 /* If we did not find a boot time in wtmp, look at wtmp, and so on. */ | |
146 for (counter = 0; counter < 20 && boot_time == 1; counter++) | |
147 { | |
148 char cmd_string[100]; | |
149 Lisp_Object tempname, filename; | |
150 int delete_flag = 0; | |
151 | |
152 filename = Qnil; | |
153 | |
154 sprintf (cmd_string, "/var/log/wtmp.%d", counter); | |
155 tempname = build_string (cmd_string); | |
156 if (! NILP (Ffile_exists_p (filename))) | |
157 filename = tempname; | |
158 else | |
159 { | |
160 sprintf (cmd_string, "/var/log/wtmp.%d.gz", counter); | |
161 tempname = build_string (cmd_string); | |
162 if (! NILP (Ffile_exists_p (tempname))) | |
163 { | |
164 Lisp_Object args[6]; | |
165 tempname = Fmake_temp_name (build_string ("wtmp")); | |
166 args[0] = Vshell_file_name; | |
167 args[1] = Qnil; | |
168 args[2] = Qnil; | |
169 args[3] = Qnil; | |
170 args[4] = build_string ("-c"); | |
171 sprintf (cmd_string, "gunzip < /var/log/wtmp.%d.gz > %s", | |
172 counter, XSTRING (tempname)->data); | |
173 args[5] = build_string (cmd_string); | |
174 Fcall_process (6, args); | |
175 filename = tempname; | |
176 delete_flag = 1; | |
177 } | |
178 } | |
179 | |
180 if (! NILP (filename)) | |
181 { | |
182 get_boot_time_1 (XSTRING (filename)->data); | |
183 if (delete_flag) | |
184 unlink (XSTRING (filename)->data); | |
185 } | |
186 } | |
187 | |
188 return boot_time; | |
189 #else | |
190 return 0; | |
191 #endif | |
192 } | |
193 | |
194 /* Try to get the boot time from wtmp file FILENAME. | |
195 This succeeds if that file contains a reboot record. | |
196 Success is indicated by setting BOOT_TIME. */ | |
197 | |
198 get_boot_time_1 (filename) | |
199 char *filename; | |
200 { | |
201 struct utmp ut, *utp; | |
202 | |
203 utmpname (filename); | |
107 setutent (); | 204 setutent (); |
108 boot_time = 1; | |
109 while (1) | 205 while (1) |
110 { | 206 { |
111 /* Find the next reboot record. */ | 207 /* Find the next reboot record. */ |
112 ut.ut_type = BOOT_TIME; | 208 ut.ut_type = BOOT_TIME; |
113 utp = getutid (&ut); | 209 utp = getutid (&ut); |
121 utp = getutent (); | 217 utp = getutent (); |
122 if (! utp) | 218 if (! utp) |
123 break; | 219 break; |
124 } | 220 } |
125 endutent (); | 221 endutent (); |
126 | |
127 return boot_time; | |
128 #else | |
129 return 0; | |
130 #endif | |
131 } | 222 } |
132 | 223 |
133 /* Here is the structure that stores information about a lock. */ | 224 /* Here is the structure that stores information about a lock. */ |
134 | 225 |
135 typedef struct | 226 typedef struct |
216 } | 307 } |
217 | 308 |
218 return err == 0; | 309 return err == 0; |
219 } | 310 } |
220 | 311 |
221 | 312 /* Return 1 if times A and B are no more than one second apart. */ |
313 | |
314 int | |
315 within_one_second (a, b) | |
316 time_t a, b; | |
317 { | |
318 return (a - b >= -1 && a - b <= 1); | |
319 } | |
222 | 320 |
223 /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, | 321 /* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, |
224 1 if another process owns it (and set OWNER (if non-null) to info), | 322 1 if another process owns it (and set OWNER (if non-null) to info), |
225 2 if the current process owns it, | 323 2 if the current process owns it, |
226 or -1 if something is wrong with the locking mechanism. */ | 324 or -1 if something is wrong with the locking mechanism. */ |
307 if (owner->pid == getpid ()) | 405 if (owner->pid == getpid ()) |
308 ret = 2; /* We own it. */ | 406 ret = 2; /* We own it. */ |
309 else if (owner->pid > 0 | 407 else if (owner->pid > 0 |
310 && (kill (owner->pid, 0) >= 0 || errno == EPERM) | 408 && (kill (owner->pid, 0) >= 0 || errno == EPERM) |
311 && (owner->boot_time == 0 | 409 && (owner->boot_time == 0 |
312 || owner->boot_time == get_boot_time ())) | 410 || within_one_second (owner->boot_time, get_boot_time ()))) |
313 ret = 1; /* An existing process on this machine owns it. */ | 411 ret = 1; /* An existing process on this machine owns it. */ |
314 /* The owner process is dead or has a strange pid (<=0), so try to | 412 /* The owner process is dead or has a strange pid (<=0), so try to |
315 zap the lockfile. */ | 413 zap the lockfile. */ |
316 else if (unlink (lfname) < 0) | 414 else if (unlink (lfname) < 0) |
317 ret = -1; | 415 ret = -1; |