(gud-display-line): Don't crash if BUFFER is nil.
[bpt/emacs.git] / src / filelock.c
CommitLineData
3a22ee35 1/* Copyright (C) 1985, 1986, 1987, 1993, 1994 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>
bfb61299
JB
29#endif
30
8489eb67
RS
31#include <errno.h>
32#include <sys/file.h>
33#ifdef USG
34#include <fcntl.h>
35#endif /* USG */
36
8489eb67 37#include "lisp.h"
2a6b3537 38#include <paths.h>
8489eb67
RS
39#include "buffer.h"
40
25bef3dd
KH
41#ifdef SYSV_SYSTEM_DIR
42#include <dirent.h>
43#else /* not SYSV_SYSTEM_DIR */
44#ifdef NONSYSTEM_DIR_LIBRARY
45#include "ndir.h"
46#else /* not NONSYSTEM_DIR_LIBRARY */
47#ifdef MSDOS
48#include <dirent.h>
49#else
50#include <sys/dir.h>
51#endif
52#endif /* not NONSYSTEM_DIR_LIBRARY */
53#ifndef MSDOS
54extern DIR *opendir ();
55#endif /* not MSDOS */
56#endif /* not SYSV_SYSTEM_DIR */
57
8489eb67
RS
58extern int errno;
59
32676c08 60extern char *egetenv ();
d8cafeb5 61extern char *strcpy ();
32676c08 62
a35e9c82 63#ifdef DECLARE_GETPWUID_WITH_UID_T
46013500
RS
64extern struct passwd *getpwuid (uid_t);
65#else
79941276
RS
66extern struct passwd *getpwuid ();
67#endif
68
8489eb67
RS
69#ifdef CLASH_DETECTION
70
71/* If system does not have symbolic links, it does not have lstat.
72 In that case, use ordinary stat instead. */
73
74#ifndef S_IFLNK
75#define lstat stat
76#endif
77
32676c08
JB
78
79/* The name of the directory in which we keep lock files, with a '/'
80 appended. */
7b92975f 81char *lock_dir;
32676c08
JB
82
83/* The name of the file in the lock directory which is used to
84 arbitrate access to the entire directory. */
85#define SUPERLOCK_NAME "!!!SuperLock!!!"
86
7b92975f
RS
87/* The name of the superlock file. This is SUPERLOCK_NAME appended to
88 lock_dir. */
89char *superlock_file;
32676c08
JB
90
91/* Set LOCK to the name of the lock file for the filename FILE.
92 char *LOCK; Lisp_Object FILE; */
e31fbc7a 93
6c10d0cd 94#ifndef HAVE_LONG_FILE_NAMES
e31fbc7a 95
7b92975f
RS
96#define MAKE_LOCK_NAME(lock, file) \
97 (lock = (char *) alloca (14 + strlen (lock_dir) + 1), \
e31fbc7a
RS
98 fill_in_lock_short_file_name (lock, (file)))
99
100
101fill_in_lock_short_file_name (lockfile, fn)
102 register char *lockfile;
103 register Lisp_Object fn;
104{
105 register union
106 {
107 unsigned int word [2];
108 unsigned char byte [8];
109 } crc;
110 register unsigned char *p, new;
111
112 /* 7-bytes cyclic code for burst correction on byte-by-byte basis.
113 the used polynomial is D^7 + D^6 + D^3 +1. pot@cnuce.cnr.it */
114
115 crc.word[0] = crc.word[1] = 0;
116
117 for (p = XSTRING (fn)->data; new = *p++; )
118 {
953d263e 119 new += crc.byte[6];
e31fbc7a
RS
120 crc.byte[6] = crc.byte[5] + new;
121 crc.byte[5] = crc.byte[4];
122 crc.byte[4] = crc.byte[3];
123 crc.byte[3] = crc.byte[2] + new;
124 crc.byte[2] = crc.byte[1];
125 crc.byte[1] = crc.byte[0];
126 crc.byte[0] = new;
127 }
7b92975f 128 sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", lock_dir,
e31fbc7a
RS
129 crc.byte[0], crc.byte[1], crc.byte[2], crc.byte[3],
130 crc.byte[4], crc.byte[5], crc.byte[6]);
131}
132
6c10d0cd 133#else /* defined HAVE_LONG_FILE_NAMES */
e31fbc7a 134
7b92975f
RS
135#define MAKE_LOCK_NAME(lock, file) \
136 (lock = (char *) alloca (XSTRING (file)->size + strlen (lock_dir) + 1), \
32676c08
JB
137 fill_in_lock_file_name (lock, (file)))
138
e31fbc7a 139
32676c08
JB
140fill_in_lock_file_name (lockfile, fn)
141 register char *lockfile;
142 register Lisp_Object fn;
143{
144 register char *p;
145
7b92975f 146 strcpy (lockfile, lock_dir);
32676c08
JB
147
148 p = lockfile + strlen (lockfile);
149
150 strcpy (p, XSTRING (fn)->data);
151
152 for (; *p; p++)
153 {
154 if (*p == '/')
155 *p = '!';
156 }
157}
6c10d0cd 158#endif /* !defined HAVE_LONG_FILE_NAMES */
32676c08 159
8489eb67
RS
160static Lisp_Object
161lock_file_owner_name (lfname)
162 char *lfname;
163{
164 struct stat s;
165 struct passwd *the_pw;
8489eb67
RS
166
167 if (lstat (lfname, &s) == 0)
168 the_pw = getpwuid (s.st_uid);
169 return (the_pw == 0 ? Qnil : build_string (the_pw->pw_name));
170}
171
172
173/* lock_file locks file fn,
174 meaning it serves notice on the world that you intend to edit that file.
175 This should be done only when about to modify a file-visiting
176 buffer previously unmodified.
177 Do not (normally) call lock_buffer for a buffer already modified,
178 as either the file is already locked, or the user has already
179 decided to go ahead without locking.
180
181 When lock_buffer returns, either the lock is locked for us,
182 or the user has said to go ahead without locking.
183
184 If the file is locked by someone else, lock_buffer calls
185 ask-user-about-lock (a Lisp function) with two arguments,
186 the file name and the name of the user who did the locking.
187 This function can signal an error, or return t meaning
188 take away the lock, or return nil meaning ignore the lock. */
189
190/* The lock file name is the file name with "/" replaced by "!"
191 and put in the Emacs lock directory. */
192/* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
193
6c10d0cd 194/* If HAVE_LONG_FILE_NAMES is not defined, the lock file name is the hex
e31fbc7a
RS
195 representation of a 14-bytes CRC generated from the file name
196 and put in the Emacs lock directory (not very nice, but it works).
953d263e 197 (ie., /ka/king/junk.tex -> /!/12a82c62f1c6da). */
e31fbc7a 198
8489eb67
RS
199void
200lock_file (fn)
201 register Lisp_Object fn;
202{
5383bc6d 203 register Lisp_Object attack, orig_fn;
8489eb67
RS
204 register char *lfname;
205
5383bc6d 206 orig_fn = fn;
1e89de84
KH
207 fn = Fexpand_file_name (fn, Qnil);
208
7b92975f 209 MAKE_LOCK_NAME (lfname, fn);
8489eb67 210
32676c08
JB
211 /* See if this file is visited and has changed on disk since it was
212 visited. */
8489eb67 213 {
a57bc488 214 register Lisp_Object subject_buf;
5383bc6d 215 subject_buf = get_truename_buffer (orig_fn);
265a9e55
JB
216 if (!NILP (subject_buf)
217 && NILP (Fverify_visited_file_modtime (subject_buf))
218 && !NILP (Ffile_exists_p (fn)))
8489eb67
RS
219 call1 (intern ("ask-user-about-supersession-threat"), fn);
220 }
221
222 /* Try to lock the lock. */
223 if (lock_if_free (lfname) <= 0)
224 /* Return now if we have locked it, or if lock dir does not exist */
225 return;
226
227 /* Else consider breaking the lock */
228 attack = call2 (intern ("ask-user-about-lock"), fn,
229 lock_file_owner_name (lfname));
265a9e55 230 if (!NILP (attack))
8489eb67
RS
231 /* User says take the lock */
232 {
233 lock_superlock (lfname);
234 lock_file_1 (lfname, O_WRONLY) ;
7b92975f 235 unlink (superlock_file);
8489eb67
RS
236 return;
237 }
238 /* User says ignore the lock */
239}
240
8489eb67
RS
241/* Lock the lock file named LFNAME.
242 If MODE is O_WRONLY, we do so even if it is already locked.
243 If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
244 Return 1 if successful, 0 if not. */
245
246int
247lock_file_1 (lfname, mode)
248 int mode; char *lfname;
249{
250 register int fd;
251 char buf[20];
252
253 if ((fd = open (lfname, mode, 0666)) >= 0)
254 {
255#ifdef USG
256 chmod (lfname, 0666);
257#else
258 fchmod (fd, 0666);
259#endif
260 sprintf (buf, "%d ", getpid ());
261 write (fd, buf, strlen (buf));
262 close (fd);
263 return 1;
264 }
265 else
266 return 0;
267}
268
269/* Lock the lock named LFNAME if possible.
270 Return 0 in that case.
271 Return positive if lock is really locked by someone else.
272 Return -1 if cannot lock for any other reason. */
273
274int
275lock_if_free (lfname)
276 register char *lfname;
277{
278 register int clasher;
279
280 while (lock_file_1 (lfname, O_WRONLY | O_EXCL | O_CREAT) == 0)
281 {
282 if (errno != EEXIST)
283 return -1;
284 clasher = current_lock_owner (lfname);
285 if (clasher != 0)
286 if (clasher != getpid ())
287 return (clasher);
288 else return (0);
289 /* Try again to lock it */
290 }
291 return 0;
292}
293
294/* Return the pid of the process that claims to own the lock file LFNAME,
295 or 0 if nobody does or the lock is obsolete,
296 or -1 if something is wrong with the locking mechanism. */
297
298int
299current_lock_owner (lfname)
300 char *lfname;
301{
302 int owner = current_lock_owner_1 (lfname);
303 if (owner == 0 && errno == ENOENT)
304 return (0);
305 /* Is it locked by a process that exists? */
306 if (owner != 0 && (kill (owner, 0) >= 0 || errno == EPERM))
307 return (owner);
308 if (unlink (lfname) < 0)
309 return (-1);
310 return (0);
311}
312
313int
314current_lock_owner_1 (lfname)
315 char *lfname;
316{
317 register int fd;
318 char buf[20];
319 int tem;
320
321 fd = open (lfname, O_RDONLY, 0666);
322 if (fd < 0)
323 return 0;
324 tem = read (fd, buf, sizeof buf);
325 close (fd);
326 return (tem <= 0 ? 0 : atoi (buf));
327}
328
329\f
330void
331unlock_file (fn)
332 register Lisp_Object fn;
333{
334 register char *lfname;
335
1e89de84
KH
336 fn = Fexpand_file_name (fn, Qnil);
337
7b92975f 338 MAKE_LOCK_NAME (lfname, fn);
8489eb67
RS
339
340 lock_superlock (lfname);
341
342 if (current_lock_owner_1 (lfname) == getpid ())
343 unlink (lfname);
344
7b92975f 345 unlink (superlock_file);
8489eb67
RS
346}
347
348lock_superlock (lfname)
349 char *lfname;
350{
351 register int i, fd;
25bef3dd 352 DIR *lockdir;
8489eb67 353
7b92975f 354 for (i = -20; i < 0 && (fd = open (superlock_file,
8489eb67
RS
355 O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
356 i++)
357 {
358 if (errno != EEXIST)
359 return;
25bef3dd
KH
360
361 /* This seems to be necessary to prevent Emacs from hanging when the
362 competing process has already deleted the superlock, but it's still
363 in the NFS cache. So we force NFS to synchronize the cache. */
7b92975f 364 if (lockdir = opendir (lock_dir))
25bef3dd
KH
365 closedir (lockdir);
366
8489eb67
RS
367 sleep (1);
368 }
369 if (fd >= 0)
370 {
371#ifdef USG
7b92975f 372 chmod (superlock_file, 0666);
8489eb67
RS
373#else
374 fchmod (fd, 0666);
375#endif
376 write (fd, lfname, strlen (lfname));
377 close (fd);
378 }
379}
380
381void
382unlock_all_files ()
383{
384 register Lisp_Object tail;
385 register struct buffer *b;
386
4e6c9d9e 387 for (tail = Vbuffer_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
8489eb67
RS
388 {
389 b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
5757b805
RS
390 if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
391 unlock_file (b->file_truename);
8489eb67
RS
392 }
393}
394
395\f
396DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
397 0, 1, 0,
398 "Lock FILE, if current buffer is modified.\n\
399FILE defaults to current buffer's visited file,\n\
400or else nothing is done if current buffer isn't visiting a file.")
e9319ef2
EN
401 (file)
402 Lisp_Object file;
8489eb67 403{
e9319ef2
EN
404 if (NILP (file))
405 file = current_buffer->file_truename;
8489eb67 406 else
e9319ef2 407 CHECK_STRING (file, 0);
6a140159 408 if (SAVE_MODIFF < MODIFF
e9319ef2
EN
409 && !NILP (file))
410 lock_file (file);
8489eb67
RS
411 return Qnil;
412}
413
414DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
415 0, 0, 0,
416 "Unlock the file visited in the current buffer,\n\
417if it should normally be locked.")
418 ()
419{
6a140159 420 if (SAVE_MODIFF < MODIFF
5757b805
RS
421 && STRINGP (current_buffer->file_truename))
422 unlock_file (current_buffer->file_truename);
8489eb67
RS
423 return Qnil;
424}
425
426\f
427/* Unlock the file visited in buffer BUFFER. */
428
429unlock_buffer (buffer)
430 struct buffer *buffer;
431{
6a140159 432 if (BUF_SAVE_MODIFF (buffer) < BUF_MODIFF (buffer)
5757b805
RS
433 && STRINGP (buffer->file_truename))
434 unlock_file (buffer->file_truename);
8489eb67
RS
435}
436
437DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
438 "Return nil if the FILENAME is not locked,\n\
439t if it is locked by you, else a string of the name of the locker.")
e9319ef2
EN
440 (filename)
441 Lisp_Object filename;
8489eb67
RS
442{
443 register char *lfname;
444 int owner;
445
e9319ef2 446 filename = Fexpand_file_name (filename, Qnil);
8489eb67 447
e9319ef2 448 MAKE_LOCK_NAME (lfname, filename);
8489eb67
RS
449
450 owner = current_lock_owner (lfname);
451 if (owner <= 0)
452 return (Qnil);
453 else if (owner == getpid ())
454 return (Qt);
455
456 return (lock_file_owner_name (lfname));
457}
458
32676c08
JB
459\f
460/* Initialization functions. */
461
462init_filelock ()
463{
66e7fd46 464 char *new_name;
8600e6ed 465
7b92975f
RS
466 lock_dir = egetenv ("EMACSLOCKDIR");
467 if (! lock_dir)
468 lock_dir = PATH_LOCK;
32676c08 469
7b92975f
RS
470 /* Copy the name in case egetenv got it from a Lisp string. */
471 new_name = (char *) xmalloc (strlen (lock_dir) + 2);
472 strcpy (new_name, lock_dir);
473 lock_dir = new_name;
8600e6ed 474
32676c08 475 /* Make sure it ends with a slash. */
7b92975f
RS
476 if (lock_dir[strlen (lock_dir) - 1] != '/')
477 strcat (lock_dir, "/");
32676c08 478
7b92975f 479 superlock_file = (char *) xmalloc ((strlen (lock_dir)
32676c08 480 + sizeof (SUPERLOCK_NAME)));
7b92975f
RS
481 strcpy (superlock_file, lock_dir);
482 strcat (superlock_file, SUPERLOCK_NAME);
32676c08
JB
483}
484
8489eb67
RS
485syms_of_filelock ()
486{
487 defsubr (&Sunlock_buffer);
488 defsubr (&Slock_buffer);
489 defsubr (&Sfile_locked_p);
490}
491
492#endif /* CLASH_DETECTION */