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