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