symbol plist accessor
[bpt/emacs.git] / src / filelock.c
CommitLineData
b97771fc 1/* Lock files for editing.
72311017
GM
2
3Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2014
4 Free Software Foundation, Inc.
5
6Author: Richard King
7 (according to authors.el)
8489eb67
RS
8
9This file is part of GNU Emacs.
10
9ec0b715 11GNU Emacs is free software: you can redistribute it and/or modify
8489eb67 12it under the terms of the GNU General Public License as published by
9ec0b715
GM
13the Free Software Foundation, either version 3 of the License, or
14(at your option) any later version.
8489eb67
RS
15
16GNU Emacs is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
9ec0b715 22along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
8489eb67
RS
23
24
68c45bf0 25#include <config.h>
8489eb67
RS
26#include <sys/types.h>
27#include <sys/stat.h>
dfcf069d 28#include <signal.h>
2decc5a9 29#include <stdio.h>
bfb61299 30
5b9c0a1d 31#ifdef HAVE_PWD_H
8489eb67 32#include <pwd.h>
5b9c0a1d 33#endif
bfb61299 34
8489eb67 35#include <sys/file.h>
8489eb67 36#include <fcntl.h>
dfcf069d 37#include <unistd.h>
dfcf069d 38
f805a125 39#ifdef __FreeBSD__
f805a125
KH
40#include <sys/sysctl.h>
41#endif /* __FreeBSD__ */
42
e5ef3cdf 43#include <errno.h>
e5ef3cdf 44
70743157
PE
45#include <c-ctype.h>
46
8489eb67 47#include "lisp.h"
d2f6dae8 48#include "character.h"
e5560ff7 49#include "buffer.h"
f4a4528d 50#include "coding.h"
9177d978 51#include "systime.h"
343a2aef 52#ifdef WINDOWSNT
531e70ec 53#include <share.h>
1d442672 54#include <sys/socket.h> /* for fcntl */
343a2aef
EZ
55#include "w32.h" /* for dostounix_filename */
56#endif
8489eb67 57
c6d09b8d 58#ifdef HAVE_UTMP_H
e788eecc 59#include <utmp.h>
c6d09b8d 60#endif
77e544a4 61
a48de9b2
PE
62/* A file whose last-modified time is just after the most recent boot.
63 Define this to be NULL to disable checking for this file. */
64#ifndef BOOT_TIME_FILE
65#define BOOT_TIME_FILE "/var/run/random-seed"
66#endif
67
77e544a4
RS
68#ifndef WTMP_FILE
69#define WTMP_FILE "/var/log/wtmp"
70#endif
177c0ea7 71
70743157 72/* Normally use a symbolic link to represent a lock.
b5029e23 73 The strategy: to lock a file FN, create a symlink .#FN in FN's
8dbbc384
RS
74 directory, with link data `user@host.pid'. This avoids a single
75 mount (== failure) point for lock files.
76
77 When the host in the lock data is the current host, we can check if
78 the pid is valid with kill.
177c0ea7 79
8dbbc384
RS
80 Otherwise, we could look at a separate file that maps hostnames to
81 reboot times to see if the remote pid can possibly be valid, since we
82 don't want Emacs to have to communicate via pipes or sockets or
83 whatever to other processes, either locally or remotely; rms says
84 that's too unreliable. Hence the separate file, which could
85 theoretically be updated by daemons running separately -- but this
86 whole idea is unimplemented; in practice, at least in our
1c4f857c 87 environment, it seems such stale locks arise fairly infrequently, and
8dbbc384
RS
88 Emacs' standard methods of dealing with clashes suffice.
89
90 We use symlinks instead of normal files because (1) they can be
91 stored more efficiently on the filesystem, since the kernel knows
92 they will be small, and (2) all the info about the lock can be read
93 in a single system call (readlink). Although we could use regular
1c4f857c 94 files to be useful on old systems lacking symlinks, nowadays
8dbbc384
RS
95 virtually all such systems are probably single-user anyway, so it
96 didn't seem worth the complication.
177c0ea7 97
8dbbc384
RS
98 Similarly, we don't worry about a possible 14-character limit on
99 file names, because those are all the same systems that don't have
100 symlinks.
177c0ea7 101
8dbbc384
RS
102 This is compatible with the locking scheme used by Interleaf (which
103 has contributed this implementation for Emacs), and was designed by
104 Ethan Jacobson, Kimbo Mundy, and others.
177c0ea7 105
b5029e23
PE
106 --karl@cs.umb.edu/karl@hq.ileaf.com.
107
70743157
PE
108 On some file systems, notably those of MS-Windows, symbolic links
109 do not work well, so instead of a symlink .#FN -> 'user@host.pid',
110 the lock is a regular file .#FN with contents 'user@host.pid'. To
111 establish a lock, a nonce file is created and then renamed to .#FN.
112 On MS-Windows this renaming is atomic unless the lock is forcibly
113 acquired. On other systems the renaming is atomic if the lock is
114 forcibly acquired; if not, the renaming is done via hard links,
115 which is good enough for lock-file purposes.
116
117 To summarize, race conditions can occur with either:
118
119 * Forced locks on MS-Windows systems.
120
121 * Non-forced locks on non-MS-Windows systems that support neither
122 hard nor symbolic links. */
8489eb67 123
8dbbc384 124\f
15e88d21
RS
125/* Return the time of the last system boot. */
126
127static time_t boot_time;
f75d7a91 128static bool boot_time_initialized;
15e88d21 129
2f2500ef 130#ifdef BOOT_TIME
f75d7a91 131static void get_boot_time_1 (const char *, bool);
2f2500ef
DL
132#endif
133
15e88d21 134static time_t
971de7fb 135get_boot_time (void)
15e88d21 136{
9d2818d6 137#if defined (BOOT_TIME)
9177d978 138 int counter;
2decc5a9 139#endif
15e88d21 140
b97771fc 141 if (boot_time_initialized)
15e88d21 142 return boot_time;
b97771fc 143 boot_time_initialized = 1;
15e88d21 144
f805a125
KH
145#if defined (CTL_KERN) && defined (KERN_BOOTTIME)
146 {
147 int mib[2];
148 size_t size;
149 struct timeval boottime_val;
150
151 mib[0] = CTL_KERN;
152 mib[1] = KERN_BOOTTIME;
153 size = sizeof (boottime_val);
154
155 if (sysctl (mib, 2, &boottime_val, &size, NULL, 0) >= 0)
156 {
157 boot_time = boottime_val.tv_sec;
158 return boot_time;
159 }
160 }
161#endif /* defined (CTL_KERN) && defined (KERN_BOOTTIME) */
9177d978 162
a48de9b2
PE
163 if (BOOT_TIME_FILE)
164 {
165 struct stat st;
166 if (stat (BOOT_TIME_FILE, &st) == 0)
167 {
168 boot_time = st.st_mtime;
169 return boot_time;
170 }
171 }
172
9d2818d6 173#if defined (BOOT_TIME)
b97771fc
RS
174#ifndef CANNOT_DUMP
175 /* The utmp routines maintain static state.
176 Don't touch that state unless we are initialized,
177 since it might not survive dumping. */
178 if (! initialized)
179 return boot_time;
180#endif /* not CANNOT_DUMP */
181
182 /* Try to get boot time from utmp before wtmp,
183 since utmp is typically much smaller than wtmp.
184 Passing a null pointer causes get_boot_time_1
185 to inspect the default file, namely utmp. */
7d652d97 186 get_boot_time_1 (0, 0);
b97771fc
RS
187 if (boot_time)
188 return boot_time;
189
9177d978 190 /* Try to get boot time from the current wtmp file. */
b97771fc 191 get_boot_time_1 (WTMP_FILE, 1);
9177d978
RS
192
193 /* If we did not find a boot time in wtmp, look at wtmp, and so on. */
b97771fc 194 for (counter = 0; counter < 20 && ! boot_time; counter++)
9177d978 195 {
882f0d81 196 char cmd_string[sizeof WTMP_FILE ".19.gz"];
9177d978 197 Lisp_Object tempname, filename;
f75d7a91 198 bool delete_flag = 0;
9177d978
RS
199
200 filename = Qnil;
201
a8290ec3
DA
202 tempname = make_formatted_string
203 (cmd_string, "%s.%d", WTMP_FILE, counter);
29a2adb0 204 if (! NILP (Ffile_exists_p (tempname)))
9177d978
RS
205 filename = tempname;
206 else
207 {
a8290ec3
DA
208 tempname = make_formatted_string (cmd_string, "%s.%d.gz",
209 WTMP_FILE, counter);
9177d978
RS
210 if (! NILP (Ffile_exists_p (tempname)))
211 {
212 Lisp_Object args[6];
f1d367aa
GM
213
214 /* The utmp functions on mescaline.gnu.org accept only
215 file names up to 8 characters long. Choose a 2
216 character long prefix, and call make_temp_file with
217 second arg non-zero, so that it will add not more
218 than 6 characters to the prefix. */
882f0d81 219 filename = Fexpand_file_name (build_string ("wt"),
5f8d6a10 220 Vtemporary_file_directory);
882f0d81
PE
221 filename = make_temp_name (filename, 1);
222 args[0] = build_string ("gzip");
9177d978 223 args[1] = Qnil;
882f0d81 224 args[2] = list2 (QCfile, filename);
9177d978 225 args[3] = Qnil;
882f0d81
PE
226 args[4] = build_string ("-cd");
227 args[5] = tempname;
9177d978 228 Fcall_process (6, args);
9177d978
RS
229 delete_flag = 1;
230 }
231 }
232
233 if (! NILP (filename))
234 {
42a5b22f 235 get_boot_time_1 (SSDATA (filename), 1);
9177d978 236 if (delete_flag)
42a5b22f 237 unlink (SSDATA (filename));
9177d978
RS
238 }
239 }
240
241 return boot_time;
242#else
243 return 0;
244#endif
245}
246
e9f22ced 247#ifdef BOOT_TIME
9177d978
RS
248/* Try to get the boot time from wtmp file FILENAME.
249 This succeeds if that file contains a reboot record.
9177d978 250
b97771fc
RS
251 If FILENAME is zero, use the same file as before;
252 if no FILENAME has ever been specified, this is the utmp file.
f75d7a91 253 Use the newest reboot record if NEWEST,
b97771fc
RS
254 the first reboot record otherwise.
255 Ignore all reboot records on or before BOOT_TIME.
256 Success is indicated by setting BOOT_TIME to a larger value. */
257
2f2500ef 258void
f75d7a91 259get_boot_time_1 (const char *filename, bool newest)
9177d978
RS
260{
261 struct utmp ut, *utp;
77e544a4 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. */
5e679a2c 267 if (faccessat (AT_FDCWD, filename, R_OK, AT_EACCESS) != 0)
b97771fc
RS
268 return;
269
b97771fc
RS
270 utmpname (filename);
271 }
9177d978 272
c321b190 273 setutent ();
b97771fc 274
c321b190
RS
275 while (1)
276 {
277 /* Find the next reboot record. */
278 ut.ut_type = BOOT_TIME;
279 utp = getutid (&ut);
280 if (! utp)
281 break;
282 /* Compare reboot times and use the newest one. */
283 if (utp->ut_time > boot_time)
b97771fc
RS
284 {
285 boot_time = utp->ut_time;
286 if (! newest)
287 break;
288 }
c321b190
RS
289 /* Advance on element in the file
290 so that getutid won't repeat the same one. */
291 utp = getutent ();
292 if (! utp)
293 break;
294 }
15e88d21 295 endutent ();
15e88d21 296}
e9f22ced 297#endif /* BOOT_TIME */
15e88d21 298\f
70743157
PE
299/* An arbitrary limit on lock contents length. 8 K should be plenty
300 big enough in practice. */
301enum { MAX_LFINFO = 8 * 1024 };
302
8dbbc384 303/* Here is the structure that stores information about a lock. */
32676c08 304
8dbbc384
RS
305typedef struct
306{
70743157
PE
307 /* Location of '@', '.', ':' in USER. If there's no colon, COLON
308 points to the end of USER. */
309 char *at, *dot, *colon;
e31fbc7a 310
70743157
PE
311 /* Lock file contents USER@HOST.PID with an optional :BOOT_TIME
312 appended. This memory is used as a lock file contents buffer, so
313 it needs room for MAX_LFINFO + 1 bytes. A string " (pid NNNN)"
314 may be appended to the USER@HOST while generating a diagnostic,
315 so make room for its extra bytes (as opposed to ".NNNN") too. */
316 char user[MAX_LFINFO + 1 + sizeof " (pid )" - sizeof "."];
317} lock_info_type;
e31fbc7a 318
b5029e23 319/* Write the name of the lock file for FNAME into LOCKNAME. Length
70743157
PE
320 will be that of FNAME plus two more for the leading ".#", plus one
321 for the null. */
b5029e23 322#define MAKE_LOCK_NAME(lockname, fname) \
70743157 323 (lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + 1), \
b5029e23
PE
324 fill_in_lock_file_name (lockname, fname))
325
8dbbc384 326static void
b5029e23 327fill_in_lock_file_name (char *lockfile, Lisp_Object fn)
e31fbc7a 328{
b5029e23
PE
329 char *last_slash = memrchr (SSDATA (fn), '/', SBYTES (fn));
330 char *base = last_slash + 1;
331 ptrdiff_t dirlen = base - SSDATA (fn);
332 memcpy (lockfile, SSDATA (fn), dirlen);
333 lockfile[dirlen] = '.';
334 lockfile[dirlen + 1] = '#';
70743157 335 strcpy (lockfile + dirlen + 2, base);
8dbbc384 336}
e31fbc7a 337
70743157
PE
338/* For some reason Linux kernels return EPERM on file systems that do
339 not support hard or symbolic links. This symbol documents the quirk.
340 There is no way to tell whether a symlink call fails due to
341 permissions issues or because links are not supported, but luckily
342 the lock file code should work either way. */
343enum { LINKS_MIGHT_NOT_WORK = EPERM };
344
345/* Rename OLD to NEW. If FORCE, replace any existing NEW.
346 It is OK if there are temporarily two hard links to OLD.
347 Return 0 if successful, -1 (setting errno) otherwise. */
343a2aef 348static int
70743157 349rename_lock_file (char const *old, char const *new, bool force)
343a2aef 350{
343a2aef 351#ifdef WINDOWSNT
70743157
PE
352 return sys_rename_replace (old, new, force);
353#else
354 if (! force)
355 {
356 struct stat st;
343a2aef 357
70743157
PE
358 if (link (old, new) == 0)
359 return unlink (old) == 0 || errno == ENOENT ? 0 : -1;
360 if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK)
361 return -1;
362
363 /* 'link' does not work on this file system. This can occur on
364 a GNU/Linux host mounting a FAT32 file system. Fall back on
365 'rename' after checking that NEW does not exist. There is a
366 potential race condition since some other process may create
367 NEW immediately after the existence check, but it's the best
368 we can portably do here. */
369 if (lstat (new, &st) == 0 || errno == EOVERFLOW)
370 {
371 errno = EEXIST;
372 return -1;
373 }
374 if (errno != ENOENT)
375 return -1;
376 }
377
378 return rename (old, new);
379#endif
380}
381
1b6006a5 382/* Create the lock file LFNAME with contents LOCK_INFO_STR. Return 0 if
70743157 383 successful, an errno value on failure. If FORCE, remove any
1b6006a5 384 existing LFNAME if necessary. */
70743157
PE
385
386static int
387create_lock_file (char *lfname, char *lock_info_str, bool force)
388{
389#ifdef WINDOWSNT
390 /* Symlinks are supported only by later versions of Windows, and
391 creating them is a privileged operation that often triggers
392 User Account Control elevation prompts. Avoid the problem by
393 pretending that 'symlink' does not work. */
394 int err = ENOSYS;
343a2aef 395#else
70743157
PE
396 int err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
397#endif
398
399 if (err == EEXIST && force)
343a2aef
EZ
400 {
401 unlink (lfname);
70743157 402 err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
343a2aef 403 }
70743157
PE
404
405 if (err == ENOSYS || err == LINKS_MIGHT_NOT_WORK || err == ENAMETOOLONG)
406 {
407 static char const nonce_base[] = ".#-emacsXXXXXX";
408 char *last_slash = strrchr (lfname, '/');
409 ptrdiff_t lfdirlen = last_slash + 1 - lfname;
410 USE_SAFE_ALLOCA;
411 char *nonce = SAFE_ALLOCA (lfdirlen + sizeof nonce_base);
412 int fd;
70743157
PE
413 memcpy (nonce, lfname, lfdirlen);
414 strcpy (nonce + lfdirlen, nonce_base);
415
067428c1 416 fd = mkostemp (nonce, O_BINARY | O_CLOEXEC);
70743157
PE
417 if (fd < 0)
418 err = errno;
419 else
420 {
067428c1 421 ptrdiff_t lock_info_len;
e0fdb694
PE
422 if (! O_CLOEXEC)
423 fcntl (fd, F_SETFD, FD_CLOEXEC);
067428c1 424 lock_info_len = strlen (lock_info_str);
70743157 425 err = 0;
3f5bef16
PE
426 /* Use 'write', not 'emacs_write', as garbage collection
427 might signal an error, which would leak FD. */
428 if (write (fd, lock_info_str, lock_info_len) != lock_info_len
5c97beae 429 || fchmod (fd, S_IRUSR | S_IRGRP | S_IROTH) != 0)
70743157 430 err = errno;
cbee2131
PE
431 /* There is no need to call fsync here, as the contents of
432 the lock file need not survive system crashes. */
70743157
PE
433 if (emacs_close (fd) != 0)
434 err = errno;
435 if (!err && rename_lock_file (nonce, lfname, force) != 0)
436 err = errno;
437 if (err)
438 unlink (nonce);
439 }
440
441 SAFE_FREE ();
442 }
443
343a2aef
EZ
444 return err;
445}
446
8dbbc384 447/* Lock the lock file named LFNAME.
f75d7a91 448 If FORCE, do so even if it is already locked.
70743157 449 Return 0 if successful, an error number on failure. */
e31fbc7a 450
70743157 451static int
f75d7a91 452lock_file_1 (char *lfname, bool force)
8dbbc384 453{
4ba93ac0 454 /* Call this first because it can GC. */
98c6f1e3
PE
455 printmax_t boot = get_boot_time ();
456
457 Lisp_Object luser_name = Fuser_login_name (Qnil);
458 char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : "";
459 Lisp_Object lhost_name = Fsystem_name ();
460 char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : "";
70743157 461 char lock_info_str[MAX_LFINFO + 1];
98c6f1e3 462 printmax_t pid = getpid ();
8dbbc384 463
8762e524
JD
464 if (boot)
465 {
466 if (sizeof lock_info_str
467 <= snprintf (lock_info_str, sizeof lock_info_str,
468 "%s@%s.%"pMd":%"pMd,
469 user_name, host_name, pid, boot))
470 return ENAMETOOLONG;
471 }
472 else if (sizeof lock_info_str
473 <= snprintf (lock_info_str, sizeof lock_info_str,
474 "%s@%s.%"pMd,
475 user_name, host_name, pid))
70743157 476 return ENAMETOOLONG;
e31fbc7a 477
70743157 478 return create_lock_file (lfname, lock_info_str, force);
8dbbc384 479}
e31fbc7a 480
f75d7a91 481/* Return true if times A and B are no more than one second apart. */
32676c08 482
f75d7a91 483static bool
971de7fb 484within_one_second (time_t a, time_t b)
9177d978
RS
485{
486 return (a - b >= -1 && a - b <= 1);
487}
8dbbc384 488\f
70743157
PE
489/* On systems lacking ELOOP, test for an errno value that shouldn't occur. */
490#ifndef ELOOP
491# define ELOOP (-1)
492#endif
343a2aef 493
70743157
PE
494/* Read the data for the lock file LFNAME into LFINFO. Read at most
495 MAX_LFINFO + 1 bytes. Return the number of bytes read, or -1
496 (setting errno) on error. */
343a2aef 497
70743157
PE
498static ptrdiff_t
499read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
500{
501 ptrdiff_t nbytes;
343a2aef 502
70743157
PE
503 while ((nbytes = readlinkat (AT_FDCWD, lfname, lfinfo, MAX_LFINFO + 1)) < 0
504 && errno == EINVAL)
343a2aef 505 {
70743157
PE
506 int fd = emacs_open (lfname, O_RDONLY | O_BINARY | O_NOFOLLOW, 0);
507 if (0 <= fd)
508 {
5e679a2c
PE
509 /* Use read, not emacs_read, since FD isn't unwind-protected. */
510 ptrdiff_t read_bytes = read (fd, lfinfo, MAX_LFINFO + 1);
70743157
PE
511 int read_errno = errno;
512 if (emacs_close (fd) != 0)
513 return -1;
514 errno = read_errno;
515 return read_bytes;
516 }
517
518 if (errno != ELOOP)
519 return -1;
520
521 /* readlinkat saw a non-symlink, but emacs_open saw a symlink.
522 The former must have been removed and replaced by the latter.
523 Try again. */
524 QUIT;
343a2aef 525 }
70743157
PE
526
527 return nbytes;
343a2aef
EZ
528}
529
8dbbc384
RS
530/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
531 1 if another process owns it (and set OWNER (if non-null) to info),
532 2 if the current process owns it,
533 or -1 if something is wrong with the locking mechanism. */
e31fbc7a 534
8dbbc384 535static int
971de7fb 536current_lock_owner (lock_info_type *owner, char *lfname)
32676c08 537{
d1fdcab7 538 int ret;
882f0d81 539 lock_info_type local_owner;
70743157
PE
540 ptrdiff_t lfinfolen;
541 intmax_t pid, boot_time;
542 char *at, *dot, *lfinfo_end;
177c0ea7 543
8dbbc384 544 /* Even if the caller doesn't want the owner info, we still have to
882f0d81 545 read it to determine return value. */
8dbbc384 546 if (!owner)
882f0d81 547 owner = &local_owner;
177c0ea7 548
70743157
PE
549 /* If nonexistent lock file, all is well; otherwise, got strange error. */
550 lfinfolen = read_lock_data (lfname, owner->user);
551 if (lfinfolen < 0)
552 return errno == ENOENT ? 0 : -1;
553 if (MAX_LFINFO < lfinfolen)
554 return -1;
555 owner->user[lfinfolen] = 0;
556
15e88d21 557 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */
50624218 558 /* The USER is everything before the last @. */
70743157
PE
559 owner->at = at = memrchr (owner->user, '@', lfinfolen);
560 if (!at)
561 return -1;
562 owner->dot = dot = strrchr (at, '.');
563 if (!dot)
8654f9d7 564 return -1;
177c0ea7 565
15e88d21 566 /* The PID is everything from the last `.' to the `:'. */
70743157
PE
567 if (! c_isdigit (dot[1]))
568 return -1;
882f0d81 569 errno = 0;
70743157
PE
570 pid = strtoimax (dot + 1, &owner->colon, 10);
571 if (errno == ERANGE)
572 pid = -1;
882f0d81 573
15e88d21 574 /* After the `:', if there is one, comes the boot time. */
70743157 575 switch (owner->colon[0])
882f0d81 576 {
70743157
PE
577 case 0:
578 boot_time = 0;
579 lfinfo_end = owner->colon;
580 break;
581
582 case ':':
583 if (! c_isdigit (owner->colon[1]))
584 return -1;
585 boot_time = strtoimax (owner->colon + 1, &lfinfo_end, 10);
586 break;
587
588 default:
589 return -1;
882f0d81 590 }
70743157
PE
591 if (lfinfo_end != owner->user + lfinfolen)
592 return -1;
177c0ea7 593
8dbbc384 594 /* On current host? */
70743157
PE
595 if (STRINGP (Vsystem_name)
596 && dot - (at + 1) == SBYTES (Vsystem_name)
597 && memcmp (at + 1, SSDATA (Vsystem_name), SBYTES (Vsystem_name)) == 0)
32676c08 598 {
70743157 599 if (pid == getpid ())
8dbbc384 600 ret = 2; /* We own it. */
70743157
PE
601 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
602 && (kill (pid, 0) >= 0 || errno == EPERM)
603 && (boot_time == 0
604 || (boot_time <= TYPE_MAXIMUM (time_t)
605 && within_one_second (boot_time, get_boot_time ()))))
8dbbc384 606 ret = 1; /* An existing process on this machine owns it. */
70743157 607 /* The owner process is dead or has a strange pid, so try to
8dbbc384 608 zap the lockfile. */
72dcef0e 609 else
70743157 610 return unlink (lfname);
32676c08 611 }
8dbbc384
RS
612 else
613 { /* If we wanted to support the check for stale locks on remote machines,
614 here's where we'd do it. */
615 ret = 1;
616 }
177c0ea7 617
8dbbc384 618 return ret;
32676c08
JB
619}
620
8dbbc384
RS
621\f
622/* Lock the lock named LFNAME if possible.
623 Return 0 in that case.
624 Return positive if some other process owns the lock, and info about
625 that process in CLASHER.
626 Return -1 if cannot lock for any other reason. */
8489eb67 627
8dbbc384 628static int
70743157 629lock_if_free (lock_info_type *clasher, char *lfname)
8dbbc384 630{
70743157
PE
631 int err;
632 while ((err = lock_file_1 (lfname, 0)) == EEXIST)
8dbbc384 633 {
70743157
PE
634 switch (current_lock_owner (clasher, lfname))
635 {
636 case 2:
637 return 0; /* We ourselves locked it. */
638 case 1:
639 return 1; /* Someone else has it. */
640 case -1:
641 return -1; /* current_lock_owner returned strange error. */
642 }
8dbbc384 643
cfc01fa7 644 /* We deleted a stale lock; try again to lock the file. */
8dbbc384 645 }
70743157
PE
646
647 return err ? -1 : 0;
8489eb67
RS
648}
649
8dbbc384 650/* lock_file locks file FN,
8489eb67
RS
651 meaning it serves notice on the world that you intend to edit that file.
652 This should be done only when about to modify a file-visiting
653 buffer previously unmodified.
8dbbc384 654 Do not (normally) call this for a buffer already modified,
8489eb67
RS
655 as either the file is already locked, or the user has already
656 decided to go ahead without locking.
657
8dbbc384 658 When this returns, either the lock is locked for us,
b5029e23 659 or lock creation failed,
8489eb67
RS
660 or the user has said to go ahead without locking.
661
8dbbc384 662 If the file is locked by someone else, this calls
8489eb67 663 ask-user-about-lock (a Lisp function) with two arguments,
8dbbc384 664 the file name and info about the user who did the locking.
8489eb67
RS
665 This function can signal an error, or return t meaning
666 take away the lock, or return nil meaning ignore the lock. */
667
8489eb67 668void
971de7fb 669lock_file (Lisp_Object fn)
8489eb67 670{
2db41375
PE
671 Lisp_Object orig_fn, encoded_fn;
672 char *lfname;
8dbbc384 673 lock_info_type lock_info;
3edc33a4 674 struct gcpro gcpro1;
b5cd1905 675 USE_SAFE_ALLOCA;
8489eb67 676
836d29b3
DA
677 /* Don't do locking if the user has opted out. */
678 if (! create_lockfiles)
679 return;
680
33bae690
RS
681 /* Don't do locking while dumping Emacs.
682 Uncompressing wtmp files uses call-process, which does not work
683 in an uninitialized Emacs. */
684 if (! NILP (Vpurify_flag))
685 return;
686
5383bc6d 687 orig_fn = fn;
8af8a9ca 688 GCPRO1 (fn);
1e89de84 689 fn = Fexpand_file_name (fn, Qnil);
343a2aef
EZ
690#ifdef WINDOWSNT
691 /* Ensure we have only '/' separators, to avoid problems with
692 looking (inside fill_in_lock_file_name) for backslashes in file
693 names encoded by some DBCS codepage. */
1fd201bb 694 dostounix_filename (SSDATA (fn));
343a2aef 695#endif
f4a4528d 696 encoded_fn = ENCODE_FILE (fn);
1e89de84 697
8dbbc384 698 /* Create the name of the lock-file for file fn */
f4a4528d 699 MAKE_LOCK_NAME (lfname, encoded_fn);
8489eb67 700
32676c08
JB
701 /* See if this file is visited and has changed on disk since it was
702 visited. */
8489eb67 703 {
a57bc488 704 register Lisp_Object subject_buf;
3036594f 705
5383bc6d 706 subject_buf = get_truename_buffer (orig_fn);
3036594f 707
265a9e55
JB
708 if (!NILP (subject_buf)
709 && NILP (Fverify_visited_file_modtime (subject_buf))
710 && !NILP (Ffile_exists_p (fn)))
8489eb67 711 call1 (intern ("ask-user-about-supersession-threat"), fn);
3036594f 712
8489eb67 713 }
8489eb67 714
2db41375
PE
715 /* Try to lock the lock. */
716 if (0 < lock_if_free (&lock_info, lfname))
8489eb67 717 {
2db41375 718 /* Someone else has the lock. Consider breaking it. */
2db41375 719 Lisp_Object attack;
70743157
PE
720 char *dot = lock_info.dot;
721 ptrdiff_t pidlen = lock_info.colon - (dot + 1);
722 static char const replacement[] = " (pid ";
723 int replacementlen = sizeof replacement - 1;
724 memmove (dot + replacementlen, dot + 1, pidlen);
725 strcpy (dot + replacementlen + pidlen, ")");
726 memcpy (dot, replacement, replacementlen);
727 attack = call2 (intern ("ask-user-about-lock"), fn,
728 build_string (lock_info.user));
2db41375
PE
729 /* Take the lock if the user said so. */
730 if (!NILP (attack))
731 lock_file_1 (lfname, 1);
8489eb67 732 }
2db41375
PE
733
734 UNGCPRO;
735 SAFE_FREE ();
8489eb67
RS
736}
737
8489eb67 738void
b5029e23 739unlock_file (Lisp_Object fn)
8489eb67 740{
b5029e23
PE
741 char *lfname;
742 USE_SAFE_ALLOCA;
8489eb67 743
1e89de84 744 fn = Fexpand_file_name (fn, Qnil);
88eace34 745 fn = ENCODE_FILE (fn);
1e89de84 746
7b92975f 747 MAKE_LOCK_NAME (lfname, fn);
8489eb67 748
8dbbc384 749 if (current_lock_owner (0, lfname) == 2)
8489eb67 750 unlink (lfname);
b5029e23
PE
751
752 SAFE_FREE ();
8489eb67
RS
753}
754
755void
971de7fb 756unlock_all_files (void)
8489eb67 757{
8f3a2c26 758 register Lisp_Object tail, buf;
8489eb67
RS
759 register struct buffer *b;
760
8f3a2c26 761 FOR_EACH_LIVE_BUFFER (tail, buf)
8489eb67 762 {
8f3a2c26
DA
763 b = XBUFFER (buf);
764 if (STRINGP (BVAR (b, file_truename))
765 && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
766 unlock_file (BVAR (b, file_truename));
8489eb67
RS
767 }
768}
8489eb67
RS
769\f
770DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
335c5470
PJ
771 0, 1, 0,
772 doc: /* Lock FILE, if current buffer is modified.
773FILE defaults to current buffer's visited file,
0b4fe078
GM
774or else nothing is done if current buffer isn't visiting a file.
775
776If the option `create-lockfiles' is nil, this does nothing. */)
5842a27b 777 (Lisp_Object file)
8489eb67 778{
e9319ef2 779 if (NILP (file))
4b4deea2 780 file = BVAR (current_buffer, file_truename);
8489eb67 781 else
b7826503 782 CHECK_STRING (file);
6a140159 783 if (SAVE_MODIFF < MODIFF
e9319ef2
EN
784 && !NILP (file))
785 lock_file (file);
177c0ea7 786 return Qnil;
8489eb67
RS
787}
788
a7ca3326 789DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
335c5470 790 0, 0, 0,
3bfb8921
RS
791 doc: /* Unlock the file visited in the current buffer.
792If the buffer is not modified, this does nothing because the file
793should not be locked in that case. */)
5842a27b 794 (void)
8489eb67 795{
6a140159 796 if (SAVE_MODIFF < MODIFF
4b4deea2
TT
797 && STRINGP (BVAR (current_buffer, file_truename)))
798 unlock_file (BVAR (current_buffer, file_truename));
8489eb67
RS
799 return Qnil;
800}
801
8489eb67
RS
802/* Unlock the file visited in buffer BUFFER. */
803
d07e0802 804void
971de7fb 805unlock_buffer (struct buffer *buffer)
8489eb67 806{
6a140159 807 if (BUF_SAVE_MODIFF (buffer) < BUF_MODIFF (buffer)
4b4deea2
TT
808 && STRINGP (BVAR (buffer, file_truename)))
809 unlock_file (BVAR (buffer, file_truename));
8489eb67
RS
810}
811
8105cbf7 812DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 1, 1, 0,
3bfb8921
RS
813 doc: /* Return a value indicating whether FILENAME is locked.
814The value is nil if the FILENAME is not locked,
815t if it is locked by you, else a string saying which user has locked it. */)
5842a27b 816 (Lisp_Object filename)
8489eb67 817{
8dbbc384 818 Lisp_Object ret;
b5029e23 819 char *lfname;
8489eb67 820 int owner;
8dbbc384 821 lock_info_type locker;
b5029e23 822 USE_SAFE_ALLOCA;
8489eb67 823
e9319ef2 824 filename = Fexpand_file_name (filename, Qnil);
8489eb67 825
e9319ef2 826 MAKE_LOCK_NAME (lfname, filename);
8489eb67 827
8dbbc384 828 owner = current_lock_owner (&locker, lfname);
8489eb67 829 if (owner <= 0)
8dbbc384
RS
830 ret = Qnil;
831 else if (owner == 2)
832 ret = Qt;
833 else
70743157 834 ret = make_string (locker.user, locker.at - locker.user);
8dbbc384 835
b5029e23 836 SAFE_FREE ();
8dbbc384 837 return ret;
8489eb67 838}
a3fd58aa 839
dfcf069d 840void
971de7fb 841syms_of_filelock (void)
8489eb67 842{
fe6aa7a1
BT
843#include "filelock.x"
844
29208e82 845 DEFVAR_LISP ("temporary-file-directory", Vtemporary_file_directory,
335c5470 846 doc: /* The directory for writing temporary files. */);
5f8d6a10
RS
847 Vtemporary_file_directory = Qnil;
848
836d29b3
DA
849 DEFVAR_BOOL ("create-lockfiles", create_lockfiles,
850 doc: /* Non-nil means use lockfiles to avoid editing collisions. */);
851 create_lockfiles = 1;
8489eb67 852}