(x_set_alpha): Set alpha to -1 if nil given.
[bpt/emacs.git] / src / filelock.c
CommitLineData
b97771fc 1/* Lock files for editing.
0b5538bd 2 Copyright (C) 1985, 1986, 1987, 1993, 1994, 1996, 1998, 1999, 2000, 2001,
8cabe764
GM
3 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
8489eb67
RS
5
6This file is part of GNU Emacs.
7
9ec0b715 8GNU Emacs is free software: you can redistribute it and/or modify
8489eb67 9it under the terms of the GNU General Public License as published by
9ec0b715
GM
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
8489eb67
RS
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
9ec0b715 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
8489eb67
RS
20
21
68c45bf0 22#include <config.h>
8489eb67
RS
23#include <sys/types.h>
24#include <sys/stat.h>
dfcf069d 25#include <signal.h>
2decc5a9 26#include <stdio.h>
bfb61299 27
5b9c0a1d 28#ifdef HAVE_PWD_H
8489eb67 29#include <pwd.h>
5b9c0a1d 30#endif
bfb61299 31
8489eb67 32#include <sys/file.h>
e5ef3cdf 33#ifdef HAVE_FCNTL_H
8489eb67 34#include <fcntl.h>
e5ef3cdf
DL
35#endif
36#ifdef HAVE_STRING_H
8dbbc384 37#include <string.h>
e5ef3cdf 38#endif
8489eb67 39
dfcf069d
AS
40#ifdef HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43
f805a125 44#ifdef __FreeBSD__
f805a125
KH
45#include <sys/sysctl.h>
46#endif /* __FreeBSD__ */
47
e5ef3cdf
DL
48#include <errno.h>
49#ifndef errno
50extern int errno;
51#endif
52
8489eb67 53#include "lisp.h"
8489eb67 54#include "buffer.h"
d2f6dae8 55#include "character.h"
f4a4528d 56#include "coding.h"
9177d978 57#include "systime.h"
8489eb67 58
5f8d6a10
RS
59/* The directory for writing temporary files. */
60
61Lisp_Object Vtemporary_file_directory;
62
8489eb67 63#ifdef CLASH_DETECTION
e788eecc
KH
64
65#include <utmp.h>
77e544a4 66
fa5c314d
RS
67#if !defined (S_ISLNK) && defined (S_IFLNK)
68#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
69#endif
70
a48de9b2
PE
71/* A file whose last-modified time is just after the most recent boot.
72 Define this to be NULL to disable checking for this file. */
73#ifndef BOOT_TIME_FILE
74#define BOOT_TIME_FILE "/var/run/random-seed"
75#endif
76
77e544a4
RS
77#ifndef WTMP_FILE
78#define WTMP_FILE "/var/log/wtmp"
79#endif
177c0ea7 80
8dbbc384
RS
81/* The strategy: to lock a file FN, create a symlink .#FN in FN's
82 directory, with link data `user@host.pid'. This avoids a single
83 mount (== failure) point for lock files.
84
85 When the host in the lock data is the current host, we can check if
86 the pid is valid with kill.
177c0ea7 87
8dbbc384
RS
88 Otherwise, we could look at a separate file that maps hostnames to
89 reboot times to see if the remote pid can possibly be valid, since we
90 don't want Emacs to have to communicate via pipes or sockets or
91 whatever to other processes, either locally or remotely; rms says
92 that's too unreliable. Hence the separate file, which could
93 theoretically be updated by daemons running separately -- but this
94 whole idea is unimplemented; in practice, at least in our
1c4f857c 95 environment, it seems such stale locks arise fairly infrequently, and
8dbbc384
RS
96 Emacs' standard methods of dealing with clashes suffice.
97
98 We use symlinks instead of normal files because (1) they can be
99 stored more efficiently on the filesystem, since the kernel knows
100 they will be small, and (2) all the info about the lock can be read
101 in a single system call (readlink). Although we could use regular
1c4f857c 102 files to be useful on old systems lacking symlinks, nowadays
8dbbc384
RS
103 virtually all such systems are probably single-user anyway, so it
104 didn't seem worth the complication.
177c0ea7 105
8dbbc384
RS
106 Similarly, we don't worry about a possible 14-character limit on
107 file names, because those are all the same systems that don't have
108 symlinks.
177c0ea7 109
8dbbc384
RS
110 This is compatible with the locking scheme used by Interleaf (which
111 has contributed this implementation for Emacs), and was designed by
112 Ethan Jacobson, Kimbo Mundy, and others.
177c0ea7 113
8dbbc384 114 --karl@cs.umb.edu/karl@hq.ileaf.com. */
8489eb67 115
8dbbc384 116\f
15e88d21
RS
117/* Return the time of the last system boot. */
118
119static time_t boot_time;
b97771fc 120static int boot_time_initialized;
15e88d21 121
9177d978
RS
122extern Lisp_Object Vshell_file_name;
123
2f2500ef
DL
124#ifdef BOOT_TIME
125static void get_boot_time_1 P_ ((char *, int));
126#endif
127
15e88d21
RS
128static time_t
129get_boot_time ()
130{
9d2818d6 131#if defined (BOOT_TIME)
9177d978 132 int counter;
2decc5a9 133#endif
15e88d21 134
b97771fc 135 if (boot_time_initialized)
15e88d21 136 return boot_time;
b97771fc 137 boot_time_initialized = 1;
15e88d21 138
f805a125
KH
139#if defined (CTL_KERN) && defined (KERN_BOOTTIME)
140 {
141 int mib[2];
142 size_t size;
143 struct timeval boottime_val;
144
145 mib[0] = CTL_KERN;
146 mib[1] = KERN_BOOTTIME;
147 size = sizeof (boottime_val);
148
149 if (sysctl (mib, 2, &boottime_val, &size, NULL, 0) >= 0)
150 {
151 boot_time = boottime_val.tv_sec;
152 return boot_time;
153 }
154 }
155#endif /* defined (CTL_KERN) && defined (KERN_BOOTTIME) */
9177d978 156
a48de9b2
PE
157 if (BOOT_TIME_FILE)
158 {
159 struct stat st;
160 if (stat (BOOT_TIME_FILE, &st) == 0)
161 {
162 boot_time = st.st_mtime;
163 return boot_time;
164 }
165 }
166
9d2818d6 167#if defined (BOOT_TIME)
b97771fc
RS
168#ifndef CANNOT_DUMP
169 /* The utmp routines maintain static state.
170 Don't touch that state unless we are initialized,
171 since it might not survive dumping. */
172 if (! initialized)
173 return boot_time;
174#endif /* not CANNOT_DUMP */
175
176 /* Try to get boot time from utmp before wtmp,
177 since utmp is typically much smaller than wtmp.
178 Passing a null pointer causes get_boot_time_1
179 to inspect the default file, namely utmp. */
180 get_boot_time_1 ((char *) 0, 0);
181 if (boot_time)
182 return boot_time;
183
9177d978 184 /* Try to get boot time from the current wtmp file. */
b97771fc 185 get_boot_time_1 (WTMP_FILE, 1);
9177d978
RS
186
187 /* If we did not find a boot time in wtmp, look at wtmp, and so on. */
b97771fc 188 for (counter = 0; counter < 20 && ! boot_time; counter++)
9177d978
RS
189 {
190 char cmd_string[100];
191 Lisp_Object tempname, filename;
192 int delete_flag = 0;
193
194 filename = Qnil;
195
77e544a4 196 sprintf (cmd_string, "%s.%d", WTMP_FILE, counter);
9177d978 197 tempname = build_string (cmd_string);
29a2adb0 198 if (! NILP (Ffile_exists_p (tempname)))
9177d978
RS
199 filename = tempname;
200 else
201 {
77e544a4 202 sprintf (cmd_string, "%s.%d.gz", WTMP_FILE, counter);
9177d978
RS
203 tempname = build_string (cmd_string);
204 if (! NILP (Ffile_exists_p (tempname)))
205 {
206 Lisp_Object args[6];
f1d367aa
GM
207
208 /* The utmp functions on mescaline.gnu.org accept only
209 file names up to 8 characters long. Choose a 2
210 character long prefix, and call make_temp_file with
211 second arg non-zero, so that it will add not more
212 than 6 characters to the prefix. */
213 tempname = Fexpand_file_name (build_string ("wt"),
5f8d6a10 214 Vtemporary_file_directory);
f1d367aa 215 tempname = make_temp_name (tempname, 1);
9177d978
RS
216 args[0] = Vshell_file_name;
217 args[1] = Qnil;
218 args[2] = Qnil;
219 args[3] = Qnil;
220 args[4] = build_string ("-c");
77e544a4 221 sprintf (cmd_string, "gunzip < %s.%d.gz > %s",
d5db4077 222 WTMP_FILE, counter, SDATA (tempname));
9177d978
RS
223 args[5] = build_string (cmd_string);
224 Fcall_process (6, args);
225 filename = tempname;
226 delete_flag = 1;
227 }
228 }
229
230 if (! NILP (filename))
231 {
d5db4077 232 get_boot_time_1 (SDATA (filename), 1);
9177d978 233 if (delete_flag)
d5db4077 234 unlink (SDATA (filename));
9177d978
RS
235 }
236 }
237
238 return boot_time;
239#else
240 return 0;
241#endif
242}
243
e9f22ced 244#ifdef BOOT_TIME
9177d978
RS
245/* Try to get the boot time from wtmp file FILENAME.
246 This succeeds if that file contains a reboot record.
9177d978 247
b97771fc
RS
248 If FILENAME is zero, use the same file as before;
249 if no FILENAME has ever been specified, this is the utmp file.
250 Use the newest reboot record if NEWEST is nonzero,
251 the first reboot record otherwise.
252 Ignore all reboot records on or before BOOT_TIME.
253 Success is indicated by setting BOOT_TIME to a larger value. */
254
2f2500ef 255void
b97771fc 256get_boot_time_1 (filename, newest)
9177d978 257 char *filename;
b97771fc 258 int newest;
9177d978
RS
259{
260 struct utmp ut, *utp;
77e544a4
RS
261 int desc;
262
b97771fc
RS
263 if (filename)
264 {
265 /* On some versions of IRIX, opening a nonexistent file name
266 is likely to crash in the utmp routines. */
68c45bf0 267 desc = emacs_open (filename, O_RDONLY, 0);
b97771fc
RS
268 if (desc < 0)
269 return;
270
68c45bf0 271 emacs_close (desc);
b97771fc
RS
272
273 utmpname (filename);
274 }
9177d978 275
c321b190 276 setutent ();
b97771fc 277
c321b190
RS
278 while (1)
279 {
280 /* Find the next reboot record. */
281 ut.ut_type = BOOT_TIME;
282 utp = getutid (&ut);
283 if (! utp)
284 break;
285 /* Compare reboot times and use the newest one. */
286 if (utp->ut_time > boot_time)
b97771fc
RS
287 {
288 boot_time = utp->ut_time;
289 if (! newest)
290 break;
291 }
c321b190
RS
292 /* Advance on element in the file
293 so that getutid won't repeat the same one. */
294 utp = getutent ();
295 if (! utp)
296 break;
297 }
15e88d21 298 endutent ();
15e88d21 299}
e9f22ced 300#endif /* BOOT_TIME */
15e88d21 301\f
8dbbc384 302/* Here is the structure that stores information about a lock. */
32676c08 303
8dbbc384
RS
304typedef struct
305{
306 char *user;
307 char *host;
9005cb4f 308 unsigned long pid;
15e88d21 309 time_t boot_time;
8dbbc384 310} lock_info_type;
32676c08 311
49b6d120
RS
312/* When we read the info back, we might need this much more,
313 enough for decimal representation plus null. */
314#define LOCK_PID_MAX (4 * sizeof (unsigned long))
32676c08 315
8dbbc384
RS
316/* Free the two dynamically-allocated pieces in PTR. */
317#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0)
e31fbc7a 318
e31fbc7a 319
8dbbc384 320/* Write the name of the lock file for FN into LFNAME. Length will be
c1355e1f
GM
321 that of FN plus two more for the leading `.#' plus 1 for the
322 trailing period plus one for the digit after it plus one for the
323 null. */
7b92975f 324#define MAKE_LOCK_NAME(lock, file) \
d5db4077 325 (lock = (char *) alloca (SBYTES (file) + 2 + 1 + 1 + 1), \
8dbbc384 326 fill_in_lock_file_name (lock, (file)))
e31fbc7a 327
8dbbc384
RS
328static void
329fill_in_lock_file_name (lockfile, fn)
e31fbc7a
RS
330 register char *lockfile;
331 register Lisp_Object fn;
332{
8dbbc384 333 register char *p;
c1355e1f
GM
334 struct stat st;
335 int count = 0;
8dbbc384 336
d5db4077 337 strcpy (lockfile, SDATA (fn));
8dbbc384
RS
338
339 /* Shift the nondirectory part of the file name (including the null)
340 right two characters. Here is one of the places where we'd have to
341 do something to support 14-character-max file names. */
342 for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
343 p[2] = *p;
177c0ea7 344
8dbbc384
RS
345 /* Insert the `.#'. */
346 p[1] = '.';
347 p[2] = '#';
c1355e1f
GM
348
349 p = p + strlen (p);
350
351 while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode))
352 {
353 if (count > 9)
354 {
355 *p = '\0';
356 return;
357 }
358 sprintf (p, ".%d", count++);
359 }
8dbbc384 360}
e31fbc7a 361
8dbbc384
RS
362/* Lock the lock file named LFNAME.
363 If FORCE is nonzero, we do so even if it is already locked.
364 Return 1 if successful, 0 if not. */
e31fbc7a 365
8dbbc384
RS
366static int
367lock_file_1 (lfname, force)
177c0ea7 368 char *lfname;
8dbbc384
RS
369 int force;
370{
371 register int err;
bd26d5a3 372 time_t boot_time;
662c2ef2
RS
373 char *user_name;
374 char *host_name;
375 char *lock_info_str;
376
4ba93ac0
AS
377 /* Call this first because it can GC. */
378 boot_time = get_boot_time ();
379
662c2ef2 380 if (STRINGP (Fuser_login_name (Qnil)))
d5db4077 381 user_name = (char *)SDATA (Fuser_login_name (Qnil));
662c2ef2
RS
382 else
383 user_name = "";
384 if (STRINGP (Fsystem_name ()))
d5db4077 385 host_name = (char *)SDATA (Fsystem_name ());
662c2ef2
RS
386 else
387 host_name = "";
266d7a00 388 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)
4ba93ac0 389 + LOCK_PID_MAX + 30);
8dbbc384 390
bd26d5a3
RS
391 if (boot_time)
392 sprintf (lock_info_str, "%s@%s.%lu:%lu", user_name, host_name,
393 (unsigned long) getpid (), (unsigned long) boot_time);
394 else
395 sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name,
177c0ea7 396 (unsigned long) getpid ());
8dbbc384
RS
397
398 err = symlink (lock_info_str, lfname);
399 if (errno == EEXIST && force)
e31fbc7a 400 {
8dbbc384
RS
401 unlink (lfname);
402 err = symlink (lock_info_str, lfname);
e31fbc7a 403 }
e31fbc7a 404
8dbbc384
RS
405 return err == 0;
406}
e31fbc7a 407
9177d978 408/* Return 1 if times A and B are no more than one second apart. */
32676c08 409
9177d978
RS
410int
411within_one_second (a, b)
412 time_t a, b;
413{
414 return (a - b >= -1 && a - b <= 1);
415}
8dbbc384
RS
416\f
417/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
418 1 if another process owns it (and set OWNER (if non-null) to info),
419 2 if the current process owns it,
420 or -1 if something is wrong with the locking mechanism. */
e31fbc7a 421
8dbbc384
RS
422static int
423current_lock_owner (owner, lfname)
424 lock_info_type *owner;
425 char *lfname;
32676c08 426{
8dbbc384
RS
427#ifndef index
428 extern char *rindex (), *index ();
429#endif
5f8d6a10 430 int len, ret;
8dbbc384 431 int local_owner = 0;
15e88d21 432 char *at, *dot, *colon;
8dbbc384
RS
433 char *lfinfo = 0;
434 int bufsize = 50;
435 /* Read arbitrarily-long contents of symlink. Similar code in
436 file-symlink-p in fileio.c. */
437 do
438 {
439 bufsize *= 2;
440 lfinfo = (char *) xrealloc (lfinfo, bufsize);
620c4704 441 errno = 0;
8dbbc384 442 len = readlink (lfname, lfinfo, bufsize);
b6e97b0a
GM
443#ifdef ERANGE
444 /* HP-UX reports ERANGE if the buffer is too small. */
445 if (len == -1 && errno == ERANGE)
63680feb 446 len = bufsize;
b6e97b0a 447#endif
8dbbc384
RS
448 }
449 while (len >= bufsize);
177c0ea7 450
8dbbc384
RS
451 /* If nonexistent lock file, all is well; otherwise, got strange error. */
452 if (len == -1)
453 {
454 xfree (lfinfo);
455 return errno == ENOENT ? 0 : -1;
456 }
32676c08 457
8dbbc384
RS
458 /* Link info exists, so `len' is its length. Null terminate. */
459 lfinfo[len] = 0;
177c0ea7 460
8dbbc384
RS
461 /* Even if the caller doesn't want the owner info, we still have to
462 read it to determine return value, so allocate it. */
463 if (!owner)
464 {
3609a53b 465 owner = (lock_info_type *) alloca (sizeof (lock_info_type));
8dbbc384
RS
466 local_owner = 1;
467 }
177c0ea7 468
15e88d21 469 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */
50624218
JR
470 /* The USER is everything before the last @. */
471 at = rindex (lfinfo, '@');
8dbbc384 472 dot = rindex (lfinfo, '.');
15e88d21
RS
473 if (!at || !dot)
474 {
475 xfree (lfinfo);
476 return -1;
477 }
8dbbc384
RS
478 len = at - lfinfo;
479 owner->user = (char *) xmalloc (len + 1);
480 strncpy (owner->user, lfinfo, len);
481 owner->user[len] = 0;
177c0ea7 482
15e88d21 483 /* The PID is everything from the last `.' to the `:'. */
8dbbc384 484 owner->pid = atoi (dot + 1);
15e88d21
RS
485 colon = dot;
486 while (*colon && *colon != ':')
487 colon++;
488 /* After the `:', if there is one, comes the boot time. */
489 if (*colon == ':')
490 owner->boot_time = atoi (colon + 1);
491 else
492 owner->boot_time = 0;
32676c08 493
8dbbc384
RS
494 /* The host is everything in between. */
495 len = dot - at - 1;
496 owner->host = (char *) xmalloc (len + 1);
497 strncpy (owner->host, at + 1, len);
498 owner->host[len] = 0;
32676c08 499
8dbbc384
RS
500 /* We're done looking at the link info. */
501 xfree (lfinfo);
177c0ea7 502
8dbbc384 503 /* On current host? */
662c2ef2 504 if (STRINGP (Fsystem_name ())
d5db4077 505 && strcmp (owner->host, SDATA (Fsystem_name ())) == 0)
32676c08 506 {
8dbbc384
RS
507 if (owner->pid == getpid ())
508 ret = 2; /* We own it. */
72dcef0e 509 else if (owner->pid > 0
15e88d21
RS
510 && (kill (owner->pid, 0) >= 0 || errno == EPERM)
511 && (owner->boot_time == 0
9177d978 512 || within_one_second (owner->boot_time, get_boot_time ())))
8dbbc384 513 ret = 1; /* An existing process on this machine owns it. */
8dbbc384
RS
514 /* The owner process is dead or has a strange pid (<=0), so try to
515 zap the lockfile. */
72dcef0e 516 else if (unlink (lfname) < 0)
8dbbc384 517 ret = -1;
72dcef0e
RS
518 else
519 ret = 0;
32676c08 520 }
8dbbc384
RS
521 else
522 { /* If we wanted to support the check for stale locks on remote machines,
523 here's where we'd do it. */
524 ret = 1;
525 }
177c0ea7 526
8dbbc384
RS
527 /* Avoid garbage. */
528 if (local_owner || ret <= 0)
529 {
530 FREE_LOCK_INFO (*owner);
531 }
532 return ret;
32676c08
JB
533}
534
8dbbc384
RS
535\f
536/* Lock the lock named LFNAME if possible.
537 Return 0 in that case.
538 Return positive if some other process owns the lock, and info about
539 that process in CLASHER.
540 Return -1 if cannot lock for any other reason. */
8489eb67 541
8dbbc384
RS
542static int
543lock_if_free (clasher, lfname)
544 lock_info_type *clasher;
177c0ea7 545 register char *lfname;
8dbbc384 546{
cfc01fa7 547 while (lock_file_1 (lfname, 0) == 0)
8dbbc384
RS
548 {
549 int locker;
e0e0205b 550
8dbbc384
RS
551 if (errno != EEXIST)
552 return -1;
177c0ea7 553
8dbbc384
RS
554 locker = current_lock_owner (clasher, lfname);
555 if (locker == 2)
556 {
557 FREE_LOCK_INFO (*clasher);
558 return 0; /* We ourselves locked it. */
559 }
560 else if (locker == 1)
561 return 1; /* Someone else has it. */
5df0b2fa 562 else if (locker == -1)
ae1ef097 563 return -1; /* current_lock_owner returned strange error. */
8dbbc384 564
cfc01fa7 565 /* We deleted a stale lock; try again to lock the file. */
8dbbc384
RS
566 }
567 return 0;
8489eb67
RS
568}
569
8dbbc384 570/* lock_file locks file FN,
8489eb67
RS
571 meaning it serves notice on the world that you intend to edit that file.
572 This should be done only when about to modify a file-visiting
573 buffer previously unmodified.
8dbbc384 574 Do not (normally) call this for a buffer already modified,
8489eb67
RS
575 as either the file is already locked, or the user has already
576 decided to go ahead without locking.
577
8dbbc384 578 When this returns, either the lock is locked for us,
8489eb67
RS
579 or the user has said to go ahead without locking.
580
8dbbc384 581 If the file is locked by someone else, this calls
8489eb67 582 ask-user-about-lock (a Lisp function) with two arguments,
8dbbc384 583 the file name and info about the user who did the locking.
8489eb67
RS
584 This function can signal an error, or return t meaning
585 take away the lock, or return nil meaning ignore the lock. */
586
8489eb67
RS
587void
588lock_file (fn)
eb4b1c05 589 Lisp_Object fn;
8489eb67 590{
f4a4528d 591 register Lisp_Object attack, orig_fn, encoded_fn;
8dbbc384
RS
592 register char *lfname, *locker;
593 lock_info_type lock_info;
3edc33a4 594 struct gcpro gcpro1;
8489eb67 595
33bae690
RS
596 /* Don't do locking while dumping Emacs.
597 Uncompressing wtmp files uses call-process, which does not work
598 in an uninitialized Emacs. */
599 if (! NILP (Vpurify_flag))
600 return;
601
5383bc6d 602 orig_fn = fn;
8af8a9ca 603 GCPRO1 (fn);
1e89de84 604 fn = Fexpand_file_name (fn, Qnil);
f4a4528d 605 encoded_fn = ENCODE_FILE (fn);
1e89de84 606
8dbbc384 607 /* Create the name of the lock-file for file fn */
f4a4528d 608 MAKE_LOCK_NAME (lfname, encoded_fn);
8489eb67 609
32676c08
JB
610 /* See if this file is visited and has changed on disk since it was
611 visited. */
8489eb67 612 {
a57bc488 613 register Lisp_Object subject_buf;
3036594f 614
5383bc6d 615 subject_buf = get_truename_buffer (orig_fn);
3036594f 616
265a9e55
JB
617 if (!NILP (subject_buf)
618 && NILP (Fverify_visited_file_modtime (subject_buf))
619 && !NILP (Ffile_exists_p (fn)))
8489eb67 620 call1 (intern ("ask-user-about-supersession-threat"), fn);
3036594f 621
8489eb67 622 }
8af8a9ca 623 UNGCPRO;
8489eb67
RS
624
625 /* Try to lock the lock. */
8dbbc384
RS
626 if (lock_if_free (&lock_info, lfname) <= 0)
627 /* Return now if we have locked it, or if lock creation failed */
8489eb67
RS
628 return;
629
630 /* Else consider breaking the lock */
266d7a00
RS
631 locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host)
632 + LOCK_PID_MAX + 9);
79e51eeb 633 sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host,
8dbbc384
RS
634 lock_info.pid);
635 FREE_LOCK_INFO (lock_info);
177c0ea7 636
8dbbc384 637 attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
265a9e55 638 if (!NILP (attack))
8489eb67
RS
639 /* User says take the lock */
640 {
8dbbc384 641 lock_file_1 (lfname, 1);
8489eb67
RS
642 return;
643 }
644 /* User says ignore the lock */
645}
646
8489eb67
RS
647void
648unlock_file (fn)
649 register Lisp_Object fn;
650{
651 register char *lfname;
652
1e89de84 653 fn = Fexpand_file_name (fn, Qnil);
88eace34 654 fn = ENCODE_FILE (fn);
1e89de84 655
7b92975f 656 MAKE_LOCK_NAME (lfname, fn);
8489eb67 657
8dbbc384 658 if (current_lock_owner (0, lfname) == 2)
8489eb67 659 unlink (lfname);
8489eb67
RS
660}
661
662void
663unlock_all_files ()
664{
665 register Lisp_Object tail;
666 register struct buffer *b;
667
8e50cc2d 668 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
8489eb67 669 {
03699b14 670 b = XBUFFER (XCDR (XCAR (tail)));
5757b805 671 if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
1c343051 672 {
4fa09beb 673 unlock_file(b->file_truename);
1c343051 674 }
8489eb67
RS
675 }
676}
8489eb67
RS
677\f
678DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
335c5470
PJ
679 0, 1, 0,
680 doc: /* Lock FILE, if current buffer is modified.
681FILE defaults to current buffer's visited file,
682or else nothing is done if current buffer isn't visiting a file. */)
683 (file)
e9319ef2 684 Lisp_Object file;
8489eb67 685{
e9319ef2
EN
686 if (NILP (file))
687 file = current_buffer->file_truename;
8489eb67 688 else
b7826503 689 CHECK_STRING (file);
6a140159 690 if (SAVE_MODIFF < MODIFF
e9319ef2
EN
691 && !NILP (file))
692 lock_file (file);
177c0ea7 693 return Qnil;
8489eb67
RS
694}
695
696DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
335c5470 697 0, 0, 0,
3bfb8921
RS
698 doc: /* Unlock the file visited in the current buffer.
699If the buffer is not modified, this does nothing because the file
700should not be locked in that case. */)
335c5470 701 ()
8489eb67 702{
6a140159 703 if (SAVE_MODIFF < MODIFF
5757b805
RS
704 && STRINGP (current_buffer->file_truename))
705 unlock_file (current_buffer->file_truename);
8489eb67
RS
706 return Qnil;
707}
708
8489eb67
RS
709/* Unlock the file visited in buffer BUFFER. */
710
d07e0802 711void
8489eb67
RS
712unlock_buffer (buffer)
713 struct buffer *buffer;
714{
6a140159 715 if (BUF_SAVE_MODIFF (buffer) < BUF_MODIFF (buffer)
5757b805
RS
716 && STRINGP (buffer->file_truename))
717 unlock_file (buffer->file_truename);
8489eb67
RS
718}
719
8105cbf7 720DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 1, 1, 0,
3bfb8921
RS
721 doc: /* Return a value indicating whether FILENAME is locked.
722The value is nil if the FILENAME is not locked,
723t if it is locked by you, else a string saying which user has locked it. */)
335c5470
PJ
724 (filename)
725 Lisp_Object filename;
8489eb67 726{
8dbbc384 727 Lisp_Object ret;
8489eb67
RS
728 register char *lfname;
729 int owner;
8dbbc384 730 lock_info_type locker;
8489eb67 731
e9319ef2 732 filename = Fexpand_file_name (filename, Qnil);
8489eb67 733
e9319ef2 734 MAKE_LOCK_NAME (lfname, filename);
8489eb67 735
8dbbc384 736 owner = current_lock_owner (&locker, lfname);
8489eb67 737 if (owner <= 0)
8dbbc384
RS
738 ret = Qnil;
739 else if (owner == 2)
740 ret = Qt;
741 else
742 ret = build_string (locker.user);
743
744 if (owner > 0)
745 FREE_LOCK_INFO (locker);
746
747 return ret;
8489eb67 748}
32676c08
JB
749\f
750/* Initialization functions. */
751
a3fd58aa
KH
752void
753init_filelock ()
754{
755 boot_time = 0;
b97771fc 756 boot_time_initialized = 0;
a3fd58aa
KH
757}
758
dfcf069d 759void
8489eb67
RS
760syms_of_filelock ()
761{
5f8d6a10 762 DEFVAR_LISP ("temporary-file-directory", &Vtemporary_file_directory,
335c5470 763 doc: /* The directory for writing temporary files. */);
5f8d6a10
RS
764 Vtemporary_file_directory = Qnil;
765
8489eb67
RS
766 defsubr (&Sunlock_buffer);
767 defsubr (&Slock_buffer);
768 defsubr (&Sfile_locked_p);
769}
770
771#endif /* CLASH_DETECTION */
6b61353c
KH
772
773/* arch-tag: e062676d-50b2-4be0-ab96-197c81b181a1
774 (do not change this comment) */