(ediff-autostore-merges): Doc fix.
[bpt/emacs.git] / src / filelock.c
CommitLineData
8dbbc384 1/* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc.
8489eb67
RS
2
3This file is part of GNU Emacs.
4
5GNU Emacs is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
32676c08 7the Free Software Foundation; either version 2, or (at your option)
8489eb67
RS
8any later version.
9
10GNU Emacs is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
17the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18Boston, MA 02111-1307, USA. */
8489eb67
RS
19
20
21#include <sys/types.h>
22#include <sys/stat.h>
18160b98 23#include <config.h>
bfb61299
JB
24
25#ifdef VMS
b350a838 26#include "vms-pwd.h"
bfb61299 27#else
8489eb67 28#include <pwd.h>
8dbbc384 29#endif /* not VMS */
bfb61299 30
8489eb67
RS
31#include <sys/file.h>
32#ifdef USG
33#include <fcntl.h>
8dbbc384 34#include <string.h>
8489eb67
RS
35#endif /* USG */
36
8489eb67 37#include "lisp.h"
8489eb67
RS
38#include "buffer.h"
39
15e88d21 40#include <time.h>
8dbbc384
RS
41#include <errno.h>
42#ifndef errno
8489eb67 43extern int errno;
79941276
RS
44#endif
45
8489eb67 46#ifdef CLASH_DETECTION
e788eecc
KH
47
48#include <utmp.h>
8489eb67 49
8dbbc384
RS
50/* The strategy: to lock a file FN, create a symlink .#FN in FN's
51 directory, with link data `user@host.pid'. This avoids a single
52 mount (== failure) point for lock files.
53
54 When the host in the lock data is the current host, we can check if
55 the pid is valid with kill.
56
57 Otherwise, we could look at a separate file that maps hostnames to
58 reboot times to see if the remote pid can possibly be valid, since we
59 don't want Emacs to have to communicate via pipes or sockets or
60 whatever to other processes, either locally or remotely; rms says
61 that's too unreliable. Hence the separate file, which could
62 theoretically be updated by daemons running separately -- but this
63 whole idea is unimplemented; in practice, at least in our
1c4f857c 64 environment, it seems such stale locks arise fairly infrequently, and
8dbbc384
RS
65 Emacs' standard methods of dealing with clashes suffice.
66
67 We use symlinks instead of normal files because (1) they can be
68 stored more efficiently on the filesystem, since the kernel knows
69 they will be small, and (2) all the info about the lock can be read
70 in a single system call (readlink). Although we could use regular
1c4f857c 71 files to be useful on old systems lacking symlinks, nowadays
8dbbc384
RS
72 virtually all such systems are probably single-user anyway, so it
73 didn't seem worth the complication.
74
75 Similarly, we don't worry about a possible 14-character limit on
76 file names, because those are all the same systems that don't have
77 symlinks.
78
79 This is compatible with the locking scheme used by Interleaf (which
80 has contributed this implementation for Emacs), and was designed by
81 Ethan Jacobson, Kimbo Mundy, and others.
82
83 --karl@cs.umb.edu/karl@hq.ileaf.com. */
8489eb67 84
8dbbc384 85\f
15e88d21
RS
86/* Return the time of the last system boot. */
87
88static time_t boot_time;
89
90static time_t
91get_boot_time ()
92{
bd26d5a3 93#ifdef BOOT_TIME
15e88d21
RS
94 struct utmp ut, *utp;
95
96 if (boot_time)
97 return boot_time;
98
99 utmpname ("/var/log/wtmp");
100 ut.ut_type = BOOT_TIME;
101 utp = getutid (&ut);
102 endutent ();
103
104 if (!utp)
105 return boot_time = 1;
106 return boot_time = utp->ut_time;
bd26d5a3
RS
107#else
108 return 0;
109#endif;
15e88d21
RS
110}
111\f
8dbbc384 112/* Here is the structure that stores information about a lock. */
32676c08 113
8dbbc384
RS
114typedef struct
115{
116 char *user;
117 char *host;
9005cb4f 118 unsigned long pid;
15e88d21 119 time_t boot_time;
8dbbc384 120} lock_info_type;
32676c08 121
49b6d120
RS
122/* When we read the info back, we might need this much more,
123 enough for decimal representation plus null. */
124#define LOCK_PID_MAX (4 * sizeof (unsigned long))
32676c08 125
8dbbc384
RS
126/* Free the two dynamically-allocated pieces in PTR. */
127#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0)
e31fbc7a 128
e31fbc7a 129
8dbbc384
RS
130/* Write the name of the lock file for FN into LFNAME. Length will be
131 that of FN plus two more for the leading `.#' plus one for the null. */
7b92975f 132#define MAKE_LOCK_NAME(lock, file) \
fc932ac6 133 (lock = (char *) alloca (STRING_BYTES (XSTRING (file)) + 2 + 1), \
8dbbc384 134 fill_in_lock_file_name (lock, (file)))
e31fbc7a 135
8dbbc384
RS
136static void
137fill_in_lock_file_name (lockfile, fn)
e31fbc7a
RS
138 register char *lockfile;
139 register Lisp_Object fn;
140{
8dbbc384
RS
141 register char *p;
142
143 strcpy (lockfile, XSTRING (fn)->data);
144
145 /* Shift the nondirectory part of the file name (including the null)
146 right two characters. Here is one of the places where we'd have to
147 do something to support 14-character-max file names. */
148 for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
149 p[2] = *p;
e31fbc7a 150
8dbbc384
RS
151 /* Insert the `.#'. */
152 p[1] = '.';
153 p[2] = '#';
154}
e31fbc7a 155
8dbbc384
RS
156/* Lock the lock file named LFNAME.
157 If FORCE is nonzero, we do so even if it is already locked.
158 Return 1 if successful, 0 if not. */
e31fbc7a 159
8dbbc384
RS
160static int
161lock_file_1 (lfname, force)
162 char *lfname;
163 int force;
164{
165 register int err;
bd26d5a3 166 time_t boot_time;
662c2ef2
RS
167 char *user_name;
168 char *host_name;
169 char *lock_info_str;
170
171 if (STRINGP (Fuser_login_name (Qnil)))
266d7a00 172 user_name = (char *)XSTRING (Fuser_login_name (Qnil))->data;
662c2ef2
RS
173 else
174 user_name = "";
175 if (STRINGP (Fsystem_name ()))
266d7a00 176 host_name = (char *)XSTRING (Fsystem_name ())->data;
662c2ef2
RS
177 else
178 host_name = "";
266d7a00 179 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)
15e88d21 180 + LOCK_PID_MAX + 5);
8dbbc384 181
bd26d5a3
RS
182 boot_time = get_boot_time ();
183 if (boot_time)
184 sprintf (lock_info_str, "%s@%s.%lu:%lu", user_name, host_name,
185 (unsigned long) getpid (), (unsigned long) boot_time);
186 else
187 sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name,
188 (unsigned long) getpid ());
8dbbc384
RS
189
190 err = symlink (lock_info_str, lfname);
191 if (errno == EEXIST && force)
e31fbc7a 192 {
8dbbc384
RS
193 unlink (lfname);
194 err = symlink (lock_info_str, lfname);
e31fbc7a 195 }
e31fbc7a 196
8dbbc384
RS
197 return err == 0;
198}
e31fbc7a 199
32676c08 200
8dbbc384
RS
201\f
202/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
203 1 if another process owns it (and set OWNER (if non-null) to info),
204 2 if the current process owns it,
205 or -1 if something is wrong with the locking mechanism. */
e31fbc7a 206
8dbbc384
RS
207static int
208current_lock_owner (owner, lfname)
209 lock_info_type *owner;
210 char *lfname;
32676c08 211{
8dbbc384
RS
212#ifndef index
213 extern char *rindex (), *index ();
214#endif
215 int o, p, len, ret;
216 int local_owner = 0;
15e88d21 217 char *at, *dot, *colon;
8dbbc384
RS
218 char *lfinfo = 0;
219 int bufsize = 50;
220 /* Read arbitrarily-long contents of symlink. Similar code in
221 file-symlink-p in fileio.c. */
222 do
223 {
224 bufsize *= 2;
225 lfinfo = (char *) xrealloc (lfinfo, bufsize);
226 len = readlink (lfname, lfinfo, bufsize);
227 }
228 while (len >= bufsize);
229
230 /* If nonexistent lock file, all is well; otherwise, got strange error. */
231 if (len == -1)
232 {
233 xfree (lfinfo);
234 return errno == ENOENT ? 0 : -1;
235 }
32676c08 236
8dbbc384
RS
237 /* Link info exists, so `len' is its length. Null terminate. */
238 lfinfo[len] = 0;
239
240 /* Even if the caller doesn't want the owner info, we still have to
241 read it to determine return value, so allocate it. */
242 if (!owner)
243 {
3609a53b 244 owner = (lock_info_type *) alloca (sizeof (lock_info_type));
8dbbc384
RS
245 local_owner = 1;
246 }
247
15e88d21 248 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */
8dbbc384
RS
249 /* The USER is everything before the first @. */
250 at = index (lfinfo, '@');
251 dot = rindex (lfinfo, '.');
15e88d21
RS
252 if (!at || !dot)
253 {
254 xfree (lfinfo);
255 return -1;
256 }
8dbbc384
RS
257 len = at - lfinfo;
258 owner->user = (char *) xmalloc (len + 1);
259 strncpy (owner->user, lfinfo, len);
260 owner->user[len] = 0;
261
15e88d21 262 /* The PID is everything from the last `.' to the `:'. */
8dbbc384 263 owner->pid = atoi (dot + 1);
15e88d21
RS
264 colon = dot;
265 while (*colon && *colon != ':')
266 colon++;
267 /* After the `:', if there is one, comes the boot time. */
268 if (*colon == ':')
269 owner->boot_time = atoi (colon + 1);
270 else
271 owner->boot_time = 0;
32676c08 272
8dbbc384
RS
273 /* The host is everything in between. */
274 len = dot - at - 1;
275 owner->host = (char *) xmalloc (len + 1);
276 strncpy (owner->host, at + 1, len);
277 owner->host[len] = 0;
32676c08 278
8dbbc384
RS
279 /* We're done looking at the link info. */
280 xfree (lfinfo);
281
282 /* On current host? */
662c2ef2
RS
283 if (STRINGP (Fsystem_name ())
284 && strcmp (owner->host, XSTRING (Fsystem_name ())->data) == 0)
32676c08 285 {
8dbbc384
RS
286 if (owner->pid == getpid ())
287 ret = 2; /* We own it. */
72dcef0e 288 else if (owner->pid > 0
15e88d21
RS
289 && (kill (owner->pid, 0) >= 0 || errno == EPERM)
290 && (owner->boot_time == 0
291 || owner->boot_time == get_boot_time ()))
8dbbc384 292 ret = 1; /* An existing process on this machine owns it. */
8dbbc384
RS
293 /* The owner process is dead or has a strange pid (<=0), so try to
294 zap the lockfile. */
72dcef0e 295 else if (unlink (lfname) < 0)
8dbbc384 296 ret = -1;
72dcef0e
RS
297 else
298 ret = 0;
32676c08 299 }
8dbbc384
RS
300 else
301 { /* If we wanted to support the check for stale locks on remote machines,
302 here's where we'd do it. */
303 ret = 1;
304 }
305
306 /* Avoid garbage. */
307 if (local_owner || ret <= 0)
308 {
309 FREE_LOCK_INFO (*owner);
310 }
311 return ret;
32676c08
JB
312}
313
8dbbc384
RS
314\f
315/* Lock the lock named LFNAME if possible.
316 Return 0 in that case.
317 Return positive if some other process owns the lock, and info about
318 that process in CLASHER.
319 Return -1 if cannot lock for any other reason. */
8489eb67 320
8dbbc384
RS
321static int
322lock_if_free (clasher, lfname)
323 lock_info_type *clasher;
324 register char *lfname;
325{
c6c0c4b1 326 if (lock_file_1 (lfname, 0) == 0)
8dbbc384
RS
327 {
328 int locker;
e0e0205b 329
8dbbc384
RS
330 if (errno != EEXIST)
331 return -1;
332
333 locker = current_lock_owner (clasher, lfname);
334 if (locker == 2)
335 {
336 FREE_LOCK_INFO (*clasher);
337 return 0; /* We ourselves locked it. */
338 }
339 else if (locker == 1)
340 return 1; /* Someone else has it. */
8dbbc384 341
c6c0c4b1 342 return -1; /* Something's wrong. */
8dbbc384
RS
343 }
344 return 0;
8489eb67
RS
345}
346
8dbbc384 347/* lock_file locks file FN,
8489eb67
RS
348 meaning it serves notice on the world that you intend to edit that file.
349 This should be done only when about to modify a file-visiting
350 buffer previously unmodified.
8dbbc384 351 Do not (normally) call this for a buffer already modified,
8489eb67
RS
352 as either the file is already locked, or the user has already
353 decided to go ahead without locking.
354
8dbbc384 355 When this returns, either the lock is locked for us,
8489eb67
RS
356 or the user has said to go ahead without locking.
357
8dbbc384 358 If the file is locked by someone else, this calls
8489eb67 359 ask-user-about-lock (a Lisp function) with two arguments,
8dbbc384 360 the file name and info about the user who did the locking.
8489eb67
RS
361 This function can signal an error, or return t meaning
362 take away the lock, or return nil meaning ignore the lock. */
363
8489eb67
RS
364void
365lock_file (fn)
8dbbc384 366 register Lisp_Object fn;
8489eb67 367{
5383bc6d 368 register Lisp_Object attack, orig_fn;
8dbbc384
RS
369 register char *lfname, *locker;
370 lock_info_type lock_info;
8489eb67 371
5383bc6d 372 orig_fn = fn;
1e89de84
KH
373 fn = Fexpand_file_name (fn, Qnil);
374
8dbbc384 375 /* Create the name of the lock-file for file fn */
7b92975f 376 MAKE_LOCK_NAME (lfname, fn);
8489eb67 377
32676c08
JB
378 /* See if this file is visited and has changed on disk since it was
379 visited. */
8489eb67 380 {
a57bc488 381 register Lisp_Object subject_buf;
5383bc6d 382 subject_buf = get_truename_buffer (orig_fn);
265a9e55
JB
383 if (!NILP (subject_buf)
384 && NILP (Fverify_visited_file_modtime (subject_buf))
385 && !NILP (Ffile_exists_p (fn)))
8489eb67
RS
386 call1 (intern ("ask-user-about-supersession-threat"), fn);
387 }
388
389 /* Try to lock the lock. */
8dbbc384
RS
390 if (lock_if_free (&lock_info, lfname) <= 0)
391 /* Return now if we have locked it, or if lock creation failed */
8489eb67
RS
392 return;
393
394 /* Else consider breaking the lock */
266d7a00
RS
395 locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host)
396 + LOCK_PID_MAX + 9);
79e51eeb 397 sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host,
8dbbc384
RS
398 lock_info.pid);
399 FREE_LOCK_INFO (lock_info);
400
401 attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
265a9e55 402 if (!NILP (attack))
8489eb67
RS
403 /* User says take the lock */
404 {
8dbbc384 405 lock_file_1 (lfname, 1);
8489eb67
RS
406 return;
407 }
408 /* User says ignore the lock */
409}
410
8489eb67
RS
411void
412unlock_file (fn)
413 register Lisp_Object fn;
414{
415 register char *lfname;
416
1e89de84
KH
417 fn = Fexpand_file_name (fn, Qnil);
418
7b92975f 419 MAKE_LOCK_NAME (lfname, fn);
8489eb67 420
8dbbc384 421 if (current_lock_owner (0, lfname) == 2)
8489eb67 422 unlink (lfname);
8489eb67
RS
423}
424
425void
426unlock_all_files ()
427{
428 register Lisp_Object tail;
429 register struct buffer *b;
430
4e6c9d9e 431 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
8489eb67
RS
432 {
433 b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
5757b805 434 if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
1c343051
KH
435 {
436 register char *lfname;
437
438 MAKE_LOCK_NAME (lfname, b->file_truename);
439
440 if (current_lock_owner (0, lfname) == 2)
441 unlink (lfname);
442 }
8489eb67
RS
443 }
444}
8489eb67
RS
445\f
446DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
447 0, 1, 0,
448 "Lock FILE, if current buffer is modified.\n\
449FILE defaults to current buffer's visited file,\n\
450or else nothing is done if current buffer isn't visiting a file.")
e9319ef2
EN
451 (file)
452 Lisp_Object file;
8489eb67 453{
e9319ef2
EN
454 if (NILP (file))
455 file = current_buffer->file_truename;
8489eb67 456 else
e9319ef2 457 CHECK_STRING (file, 0);
6a140159 458 if (SAVE_MODIFF < MODIFF
e9319ef2
EN
459 && !NILP (file))
460 lock_file (file);
8489eb67
RS
461 return Qnil;
462}
463
464DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
465 0, 0, 0,
466 "Unlock the file visited in the current buffer,\n\
467if it should normally be locked.")
468 ()
469{
6a140159 470 if (SAVE_MODIFF < MODIFF
5757b805
RS
471 && STRINGP (current_buffer->file_truename))
472 unlock_file (current_buffer->file_truename);
8489eb67
RS
473 return Qnil;
474}
475
8489eb67
RS
476/* Unlock the file visited in buffer BUFFER. */
477
d07e0802 478void
8489eb67
RS
479unlock_buffer (buffer)
480 struct buffer *buffer;
481{
6a140159 482 if (BUF_SAVE_MODIFF (buffer) < BUF_MODIFF (buffer)
5757b805
RS
483 && STRINGP (buffer->file_truename))
484 unlock_file (buffer->file_truename);
8489eb67
RS
485}
486
487DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
488 "Return nil if the FILENAME is not locked,\n\
489t if it is locked by you, else a string of the name of the locker.")
e9319ef2
EN
490 (filename)
491 Lisp_Object filename;
8489eb67 492{
8dbbc384 493 Lisp_Object ret;
8489eb67
RS
494 register char *lfname;
495 int owner;
8dbbc384 496 lock_info_type locker;
8489eb67 497
e9319ef2 498 filename = Fexpand_file_name (filename, Qnil);
8489eb67 499
e9319ef2 500 MAKE_LOCK_NAME (lfname, filename);
8489eb67 501
8dbbc384 502 owner = current_lock_owner (&locker, lfname);
8489eb67 503 if (owner <= 0)
8dbbc384
RS
504 ret = Qnil;
505 else if (owner == 2)
506 ret = Qt;
507 else
508 ret = build_string (locker.user);
509
510 if (owner > 0)
511 FREE_LOCK_INFO (locker);
512
513 return ret;
8489eb67 514}
32676c08
JB
515\f
516/* Initialization functions. */
517
8489eb67
RS
518syms_of_filelock ()
519{
520 defsubr (&Sunlock_buffer);
521 defsubr (&Slock_buffer);
522 defsubr (&Sfile_locked_p);
523}
524
525#endif /* CLASH_DETECTION */