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;