aboutsummaryrefslogtreecommitdiffstats
path: root/src/filelock.c
diff options
context:
space:
mode:
authorEli Zaretskii2013-03-28 20:13:59 +0200
committerEli Zaretskii2013-03-28 20:13:59 +0200
commitd76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e (patch)
tree04fa8bc7bd2058a316a7ee30f8741d25bfd0b060 /src/filelock.c
parent2ef26ceb192c7683754cf0b4aa3087f501254332 (diff)
parente74aeda863cd6896e06e92586f87b45d63d67d15 (diff)
downloademacs-d76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e.tar.gz
emacs-d76bf86f438d4f5f9fe493ab76f02ffc78f3ae2e.zip
Merge from trunk and resolve conflicts.
Diffstat (limited to 'src/filelock.c')
-rw-r--r--src/filelock.c489
1 files changed, 316 insertions, 173 deletions
diff --git a/src/filelock.c b/src/filelock.c
index 17f3f253249..f17d3182eab 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -1,6 +1,6 @@
1/* Lock files for editing. 1/* Lock files for editing.
2 Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2012 2 Copyright (C) 1985-1987, 1993-1994, 1996, 1998-2013 Free Software
3 Free Software Foundation, Inc. 3 Foundation, Inc.
4 4
5This file is part of GNU Emacs. 5This file is part of GNU Emacs.
6 6
@@ -38,11 +38,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
38 38
39#include <errno.h> 39#include <errno.h>
40 40
41#include <c-ctype.h>
42
41#include "lisp.h" 43#include "lisp.h"
42#include "character.h" 44#include "character.h"
43#include "buffer.h" 45#include "buffer.h"
44#include "coding.h" 46#include "coding.h"
45#include "systime.h" 47#include "systime.h"
48#ifdef WINDOWSNT
49#include <share.h>
50#include "w32.h" /* for dostounix_filename */
51#endif
46 52
47#ifdef CLASH_DETECTION 53#ifdef CLASH_DETECTION
48 54
@@ -60,7 +66,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
60#define WTMP_FILE "/var/log/wtmp" 66#define WTMP_FILE "/var/log/wtmp"
61#endif 67#endif
62 68
63/* The strategy: to lock a file FN, create a symlink .#FN in FN's 69/* Normally use a symbolic link to represent a lock.
70 The strategy: to lock a file FN, create a symlink .#FN in FN's
64 directory, with link data `user@host.pid'. This avoids a single 71 directory, with link data `user@host.pid'. This avoids a single
65 mount (== failure) point for lock files. 72 mount (== failure) point for lock files.
66 73
@@ -93,7 +100,23 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
93 has contributed this implementation for Emacs), and was designed by 100 has contributed this implementation for Emacs), and was designed by
94 Ethan Jacobson, Kimbo Mundy, and others. 101 Ethan Jacobson, Kimbo Mundy, and others.
95 102
96 --karl@cs.umb.edu/karl@hq.ileaf.com. */ 103 --karl@cs.umb.edu/karl@hq.ileaf.com.
104
105 On some file systems, notably those of MS-Windows, symbolic links
106 do not work well, so instead of a symlink .#FN -> 'user@host.pid',
107 the lock is a regular file .#FN with contents 'user@host.pid'. To
108 establish a lock, a nonce file is created and then renamed to .#FN.
109 On MS-Windows this renaming is atomic unless the lock is forcibly
110 acquired. On other systems the renaming is atomic if the lock is
111 forcibly acquired; if not, the renaming is done via hard links,
112 which is good enough for lock-file purposes.
113
114 To summarize, race conditions can occur with either:
115
116 * Forced locks on MS-Windows systems.
117
118 * Non-forced locks on non-MS-Windows systems that support neither
119 hard nor symbolic links. */
97 120
98 121
99/* Return the time of the last system boot. */ 122/* Return the time of the last system boot. */
@@ -274,72 +297,175 @@ get_boot_time_1 (const char *filename, bool newest)
274} 297}
275#endif /* BOOT_TIME */ 298#endif /* BOOT_TIME */
276 299
300/* An arbitrary limit on lock contents length. 8 K should be plenty
301 big enough in practice. */
302enum { MAX_LFINFO = 8 * 1024 };
303
277/* Here is the structure that stores information about a lock. */ 304/* Here is the structure that stores information about a lock. */
278 305
279typedef struct 306typedef struct
280{ 307{
281 char *user; 308 /* Location of '@', '.', ':' in USER. If there's no colon, COLON
282 char *host; 309 points to the end of USER. */
283 pid_t pid; 310 char *at, *dot, *colon;
284 time_t boot_time; 311
312 /* Lock file contents USER@HOST.PID with an optional :BOOT_TIME
313 appended. This memory is used as a lock file contents buffer, so
314 it needs room for MAX_LFINFO + 1 bytes. A string " (pid NNNN)"
315 may be appended to the USER@HOST while generating a diagnostic,
316 so make room for its extra bytes (as opposed to ".NNNN") too. */
317 char user[MAX_LFINFO + 1 + sizeof " (pid )" - sizeof "."];
285} lock_info_type; 318} lock_info_type;
286 319
287/* Free the two dynamically-allocated pieces in PTR. */ 320/* Write the name of the lock file for FNAME into LOCKNAME. Length
288#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) 321 will be that of FNAME plus two more for the leading ".#", plus one
322 for the null. */
323#define MAKE_LOCK_NAME(lockname, fname) \
324 (lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + 1), \
325 fill_in_lock_file_name (lockname, fname))
289 326
327static void
328fill_in_lock_file_name (char *lockfile, Lisp_Object fn)
329{
330 char *last_slash = memrchr (SSDATA (fn), '/', SBYTES (fn));
331 char *base = last_slash + 1;
332 ptrdiff_t dirlen = base - SSDATA (fn);
333 memcpy (lockfile, SSDATA (fn), dirlen);
334 lockfile[dirlen] = '.';
335 lockfile[dirlen + 1] = '#';
336 strcpy (lockfile + dirlen + 2, base);
337}
290 338
291/* Write the name of the lock file for FN into LFNAME. Length will be 339/* For some reason Linux kernels return EPERM on file systems that do
292 that of FN plus two more for the leading `.#' plus 1 for the 340 not support hard or symbolic links. This symbol documents the quirk.
293 trailing period plus one for the digit after it plus one for the 341 There is no way to tell whether a symlink call fails due to
294 null. */ 342 permissions issues or because links are not supported, but luckily
295#define MAKE_LOCK_NAME(lock, file) \ 343 the lock file code should work either way. */
296 (lock = alloca (SBYTES (file) + 2 + 1 + 1 + 1), \ 344enum { LINKS_MIGHT_NOT_WORK = EPERM };
297 fill_in_lock_file_name (lock, (file)))
298 345
299static void 346/* Rename OLD to NEW. If FORCE, replace any existing NEW.
300fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) 347 It is OK if there are temporarily two hard links to OLD.
348 Return 0 if successful, -1 (setting errno) otherwise. */
349static int
350rename_lock_file (char const *old, char const *new, bool force)
301{ 351{
302 ptrdiff_t length = SBYTES (fn); 352#ifdef WINDOWSNT
303 register char *p; 353 return sys_rename_replace (old, new, force);
304 struct stat st; 354#else
305 int count = 0; 355 if (! force)
356 {
357 struct stat st;
306 358
307 strcpy (lockfile, SSDATA (fn)); 359 if (link (old, new) == 0)
360 return unlink (old) == 0 || errno == ENOENT ? 0 : -1;
361 if (errno != ENOSYS && errno != LINKS_MIGHT_NOT_WORK)
362 return -1;
308 363
309 /* Shift the nondirectory part of the file name (including the null) 364 /* 'link' does not work on this file system. This can occur on
310 right two characters. Here is one of the places where we'd have to 365 a GNU/Linux host mounting a FAT32 file system. Fall back on
311 do something to support 14-character-max file names. */ 366 'rename' after checking that NEW does not exist. There is a
312 for (p = lockfile + length; p != lockfile && *p != '/'; p--) 367 potential race condition since some other process may create
313 p[2] = *p; 368 NEW immediately after the existence check, but it's the best
369 we can portably do here. */
370 if (lstat (new, &st) == 0 || errno == EOVERFLOW)
371 {
372 errno = EEXIST;
373 return -1;
374 }
375 if (errno != ENOENT)
376 return -1;
377 }
314 378
315 /* Insert the `.#'. */ 379 return rename (old, new);
316 p[1] = '.'; 380#endif
317 p[2] = '#'; 381}
318 382
319 p = p + length + 2; 383/* Create the lock file FILE with contents CONTENTS. Return 0 if
384 successful, an errno value on failure. If FORCE, remove any
385 existing FILE if necessary. */
320 386
321 while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode)) 387static int
388create_lock_file (char *lfname, char *lock_info_str, bool force)
389{
390#ifdef WINDOWSNT
391 /* Symlinks are supported only by later versions of Windows, and
392 creating them is a privileged operation that often triggers
393 User Account Control elevation prompts. Avoid the problem by
394 pretending that 'symlink' does not work. */
395 int err = ENOSYS;
396#else
397 int err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
398#endif
399
400 if (err == EEXIST && force)
401 {
402 unlink (lfname);
403 err = symlink (lock_info_str, lfname) == 0 ? 0 : errno;
404 }
405
406 if (err == ENOSYS || err == LINKS_MIGHT_NOT_WORK || err == ENAMETOOLONG)
322 { 407 {
323 if (count > 9) 408 static char const nonce_base[] = ".#-emacsXXXXXX";
409 char *last_slash = strrchr (lfname, '/');
410 ptrdiff_t lfdirlen = last_slash + 1 - lfname;
411 USE_SAFE_ALLOCA;
412 char *nonce = SAFE_ALLOCA (lfdirlen + sizeof nonce_base);
413 int fd;
414 bool need_fchmod;
415 mode_t world_readable = S_IRUSR | S_IRGRP | S_IROTH;
416 memcpy (nonce, lfname, lfdirlen);
417 strcpy (nonce + lfdirlen, nonce_base);
418
419#if HAVE_MKSTEMP
420 /* Prefer mkstemp if available, as it avoids a race between
421 mktemp and emacs_open. */
422 fd = mkstemp (nonce);
423 need_fchmod = 1;
424#else
425 mktemp (nonce);
426 fd = emacs_open (nonce, O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
427 world_readable);
428 need_fchmod = 0;
429#endif
430
431 if (fd < 0)
432 err = errno;
433 else
324 { 434 {
325 *p = '\0'; 435 ptrdiff_t lock_info_len = strlen (lock_info_str);
326 return; 436 err = 0;
437 if (emacs_write (fd, lock_info_str, lock_info_len) != lock_info_len
438 || (need_fchmod && fchmod (fd, world_readable) != 0))
439 err = errno;
440 else
441 while (fsync (fd) != 0)
442 if (errno != EINTR)
443 {
444 if (errno != EINVAL)
445 err = errno;
446 break;
447 }
448 if (emacs_close (fd) != 0)
449 err = errno;
450 if (!err && rename_lock_file (nonce, lfname, force) != 0)
451 err = errno;
452 if (err)
453 unlink (nonce);
327 } 454 }
328 sprintf (p, ".%d", count++); 455
456 SAFE_FREE ();
329 } 457 }
458
459 return err;
330} 460}
331 461
332/* Lock the lock file named LFNAME. 462/* Lock the lock file named LFNAME.
333 If FORCE, do so even if it is already locked. 463 If FORCE, do so even if it is already locked.
334 Return true if successful. */ 464 Return 0 if successful, an error number on failure. */
335 465
336static bool 466static int
337lock_file_1 (char *lfname, bool force) 467lock_file_1 (char *lfname, bool force)
338{ 468{
339 int err;
340 int symlink_errno;
341 USE_SAFE_ALLOCA;
342
343 /* Call this first because it can GC. */ 469 /* Call this first because it can GC. */
344 printmax_t boot = get_boot_time (); 470 printmax_t boot = get_boot_time ();
345 471
@@ -347,26 +473,16 @@ lock_file_1 (char *lfname, bool force)
347 char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : ""; 473 char const *user_name = STRINGP (luser_name) ? SSDATA (luser_name) : "";
348 Lisp_Object lhost_name = Fsystem_name (); 474 Lisp_Object lhost_name = Fsystem_name ();
349 char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : ""; 475 char const *host_name = STRINGP (lhost_name) ? SSDATA (lhost_name) : "";
350 ptrdiff_t lock_info_size = (strlen (user_name) + strlen (host_name) 476 char lock_info_str[MAX_LFINFO + 1];
351 + 2 * INT_STRLEN_BOUND (printmax_t)
352 + sizeof "@.:");
353 char *lock_info_str = SAFE_ALLOCA (lock_info_size);
354 printmax_t pid = getpid (); 477 printmax_t pid = getpid ();
355 478
356 esprintf (lock_info_str, boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd, 479 if (sizeof lock_info_str
357 user_name, host_name, pid, boot); 480 <= snprintf (lock_info_str, sizeof lock_info_str,
358 481 boot ? "%s@%s.%"pMd":%"pMd : "%s@%s.%"pMd,
359 err = symlink (lock_info_str, lfname); 482 user_name, host_name, pid, boot))
360 if (errno == EEXIST && force) 483 return ENAMETOOLONG;
361 {
362 unlink (lfname);
363 err = symlink (lock_info_str, lfname);
364 }
365 484
366 symlink_errno = errno; 485 return create_lock_file (lfname, lock_info_str, force);
367 SAFE_FREE ();
368 errno = symlink_errno;
369 return err == 0;
370} 486}
371 487
372/* Return true if times A and B are no more than one second apart. */ 488/* Return true if times A and B are no more than one second apart. */
@@ -377,6 +493,46 @@ within_one_second (time_t a, time_t b)
377 return (a - b >= -1 && a - b <= 1); 493 return (a - b >= -1 && a - b <= 1);
378} 494}
379 495
496/* On systems lacking ELOOP, test for an errno value that shouldn't occur. */
497#ifndef ELOOP
498# define ELOOP (-1)
499#endif
500
501/* Read the data for the lock file LFNAME into LFINFO. Read at most
502 MAX_LFINFO + 1 bytes. Return the number of bytes read, or -1
503 (setting errno) on error. */
504
505static ptrdiff_t
506read_lock_data (char *lfname, char lfinfo[MAX_LFINFO + 1])
507{
508 ptrdiff_t nbytes;
509
510 while ((nbytes = readlinkat (AT_FDCWD, lfname, lfinfo, MAX_LFINFO + 1)) < 0
511 && errno == EINVAL)
512 {
513 int fd = emacs_open (lfname, O_RDONLY | O_BINARY | O_NOFOLLOW, 0);
514 if (0 <= fd)
515 {
516 ptrdiff_t read_bytes = emacs_read (fd, lfinfo, MAX_LFINFO + 1);
517 int read_errno = errno;
518 if (emacs_close (fd) != 0)
519 return -1;
520 errno = read_errno;
521 return read_bytes;
522 }
523
524 if (errno != ELOOP)
525 return -1;
526
527 /* readlinkat saw a non-symlink, but emacs_open saw a symlink.
528 The former must have been removed and replaced by the latter.
529 Try again. */
530 QUIT;
531 }
532
533 return nbytes;
534}
535
380/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete, 536/* Return 0 if nobody owns the lock file LFNAME or the lock is obsolete,
381 1 if another process owns it (and set OWNER (if non-null) to info), 537 1 if another process owns it (and set OWNER (if non-null) to info),
382 2 if the current process owns it, 538 2 if the current process owns it,
@@ -386,85 +542,78 @@ static int
386current_lock_owner (lock_info_type *owner, char *lfname) 542current_lock_owner (lock_info_type *owner, char *lfname)
387{ 543{
388 int ret; 544 int ret;
389 ptrdiff_t len;
390 lock_info_type local_owner; 545 lock_info_type local_owner;
391 intmax_t n; 546 ptrdiff_t lfinfolen;
392 char *at, *dot, *colon; 547 intmax_t pid, boot_time;
393 char readlink_buf[READLINK_BUFSIZE]; 548 char *at, *dot, *lfinfo_end;
394 char *lfinfo = emacs_readlink (lfname, readlink_buf);
395
396 /* If nonexistent lock file, all is well; otherwise, got strange error. */
397 if (!lfinfo)
398 return errno == ENOENT ? 0 : -1;
399 549
400 /* Even if the caller doesn't want the owner info, we still have to 550 /* Even if the caller doesn't want the owner info, we still have to
401 read it to determine return value. */ 551 read it to determine return value. */
402 if (!owner) 552 if (!owner)
403 owner = &local_owner; 553 owner = &local_owner;
404 554
555 /* If nonexistent lock file, all is well; otherwise, got strange error. */
556 lfinfolen = read_lock_data (lfname, owner->user);
557 if (lfinfolen < 0)
558 return errno == ENOENT ? 0 : -1;
559 if (MAX_LFINFO < lfinfolen)
560 return -1;
561 owner->user[lfinfolen] = 0;
562
405 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */ 563 /* Parse USER@HOST.PID:BOOT_TIME. If can't parse, return -1. */
406 /* The USER is everything before the last @. */ 564 /* The USER is everything before the last @. */
407 at = strrchr (lfinfo, '@'); 565 owner->at = at = memrchr (owner->user, '@', lfinfolen);
408 dot = strrchr (lfinfo, '.'); 566 if (!at)
409 if (!at || !dot) 567 return -1;
410 { 568 owner->dot = dot = strrchr (at, '.');
411 if (lfinfo != readlink_buf) 569 if (!dot)
412 xfree (lfinfo); 570 return -1;
413 return -1;
414 }
415 len = at - lfinfo;
416 owner->user = xmalloc (len + 1);
417 memcpy (owner->user, lfinfo, len);
418 owner->user[len] = 0;
419 571
420 /* The PID is everything from the last `.' to the `:'. */ 572 /* The PID is everything from the last `.' to the `:'. */
573 if (! c_isdigit (dot[1]))
574 return -1;
421 errno = 0; 575 errno = 0;
422 n = strtoimax (dot + 1, NULL, 10); 576 pid = strtoimax (dot + 1, &owner->colon, 10);
423 owner->pid = 577 if (errno == ERANGE)
424 ((0 <= n && n <= TYPE_MAXIMUM (pid_t) 578 pid = -1;
425 && (TYPE_MAXIMUM (pid_t) < INTMAX_MAX || errno != ERANGE))
426 ? n : 0);
427 579
428 colon = strchr (dot + 1, ':');
429 /* After the `:', if there is one, comes the boot time. */ 580 /* After the `:', if there is one, comes the boot time. */
430 n = 0; 581 switch (owner->colon[0])
431 if (colon)
432 { 582 {
433 errno = 0; 583 case 0:
434 n = strtoimax (colon + 1, NULL, 10); 584 boot_time = 0;
435 } 585 lfinfo_end = owner->colon;
436 owner->boot_time = 586 break;
437 ((0 <= n && n <= TYPE_MAXIMUM (time_t)
438 && (TYPE_MAXIMUM (time_t) < INTMAX_MAX || errno != ERANGE))
439 ? n : 0);
440 587
441 /* The host is everything in between. */ 588 case ':':
442 len = dot - at - 1; 589 if (! c_isdigit (owner->colon[1]))
443 owner->host = xmalloc (len + 1); 590 return -1;
444 memcpy (owner->host, at + 1, len); 591 boot_time = strtoimax (owner->colon + 1, &lfinfo_end, 10);
445 owner->host[len] = 0; 592 break;
446 593
447 /* We're done looking at the link info. */ 594 default:
448 if (lfinfo != readlink_buf) 595 return -1;
449 xfree (lfinfo); 596 }
597 if (lfinfo_end != owner->user + lfinfolen)
598 return -1;
450 599
451 /* On current host? */ 600 /* On current host? */
452 if (STRINGP (Fsystem_name ()) 601 if (STRINGP (Vsystem_name)
453 && strcmp (owner->host, SSDATA (Fsystem_name ())) == 0) 602 && dot - (at + 1) == SBYTES (Vsystem_name)
603 && memcmp (at + 1, SSDATA (Vsystem_name), SBYTES (Vsystem_name)) == 0)
454 { 604 {
455 if (owner->pid == getpid ()) 605 if (pid == getpid ())
456 ret = 2; /* We own it. */ 606 ret = 2; /* We own it. */
457 else if (owner->pid > 0 607 else if (0 < pid && pid <= TYPE_MAXIMUM (pid_t)
458 && (kill (owner->pid, 0) >= 0 || errno == EPERM) 608 && (kill (pid, 0) >= 0 || errno == EPERM)
459 && (owner->boot_time == 0 609 && (boot_time == 0
460 || within_one_second (owner->boot_time, get_boot_time ()))) 610 || (boot_time <= TYPE_MAXIMUM (time_t)
611 && within_one_second (boot_time, get_boot_time ()))))
461 ret = 1; /* An existing process on this machine owns it. */ 612 ret = 1; /* An existing process on this machine owns it. */
462 /* The owner process is dead or has a strange pid (<=0), so try to 613 /* The owner process is dead or has a strange pid, so try to
463 zap the lockfile. */ 614 zap the lockfile. */
464 else if (unlink (lfname) < 0)
465 ret = -1;
466 else 615 else
467 ret = 0; 616 return unlink (lfname);
468 } 617 }
469 else 618 else
470 { /* If we wanted to support the check for stale locks on remote machines, 619 { /* If we wanted to support the check for stale locks on remote machines,
@@ -472,11 +621,6 @@ current_lock_owner (lock_info_type *owner, char *lfname)
472 ret = 1; 621 ret = 1;
473 } 622 }
474 623
475 /* Avoid garbage. */
476 if (owner == &local_owner || ret <= 0)
477 {
478 FREE_LOCK_INFO (*owner);
479 }
480 return ret; 624 return ret;
481} 625}
482 626
@@ -488,29 +632,25 @@ current_lock_owner (lock_info_type *owner, char *lfname)
488 Return -1 if cannot lock for any other reason. */ 632 Return -1 if cannot lock for any other reason. */
489 633
490static int 634static int
491lock_if_free (lock_info_type *clasher, register char *lfname) 635lock_if_free (lock_info_type *clasher, char *lfname)
492{ 636{
493 while (! lock_file_1 (lfname, 0)) 637 int err;
638 while ((err = lock_file_1 (lfname, 0)) == EEXIST)
494 { 639 {
495 int locker; 640 switch (current_lock_owner (clasher, lfname))
496 641 {
497 if (errno != EEXIST) 642 case 2:
498 return -1; 643 return 0; /* We ourselves locked it. */
499 644 case 1:
500 locker = current_lock_owner (clasher, lfname); 645 return 1; /* Someone else has it. */
501 if (locker == 2) 646 case -1:
502 { 647 return -1; /* current_lock_owner returned strange error. */
503 FREE_LOCK_INFO (*clasher); 648 }
504 return 0; /* We ourselves locked it. */
505 }
506 else if (locker == 1)
507 return 1; /* Someone else has it. */
508 else if (locker == -1)
509 return -1; /* current_lock_owner returned strange error. */
510 649
511 /* We deleted a stale lock; try again to lock the file. */ 650 /* We deleted a stale lock; try again to lock the file. */
512 } 651 }
513 return 0; 652
653 return err ? -1 : 0;
514} 654}
515 655
516/* lock_file locks file FN, 656/* lock_file locks file FN,
@@ -522,6 +662,7 @@ lock_if_free (lock_info_type *clasher, register char *lfname)
522 decided to go ahead without locking. 662 decided to go ahead without locking.
523 663
524 When this returns, either the lock is locked for us, 664 When this returns, either the lock is locked for us,
665 or lock creation failed,
525 or the user has said to go ahead without locking. 666 or the user has said to go ahead without locking.
526 667
527 If the file is locked by someone else, this calls 668 If the file is locked by someone else, this calls
@@ -533,11 +674,9 @@ lock_if_free (lock_info_type *clasher, register char *lfname)
533void 674void
534lock_file (Lisp_Object fn) 675lock_file (Lisp_Object fn)
535{ 676{
536 register Lisp_Object attack, orig_fn, encoded_fn; 677 Lisp_Object orig_fn, encoded_fn;
537 register char *lfname, *locker; 678 char *lfname;
538 ptrdiff_t locker_size;
539 lock_info_type lock_info; 679 lock_info_type lock_info;
540 printmax_t pid;
541 struct gcpro gcpro1; 680 struct gcpro gcpro1;
542 USE_SAFE_ALLOCA; 681 USE_SAFE_ALLOCA;
543 682
@@ -554,6 +693,12 @@ lock_file (Lisp_Object fn)
554 orig_fn = fn; 693 orig_fn = fn;
555 GCPRO1 (fn); 694 GCPRO1 (fn);
556 fn = Fexpand_file_name (fn, Qnil); 695 fn = Fexpand_file_name (fn, Qnil);
696#ifdef WINDOWSNT
697 /* Ensure we have only '/' separators, to avoid problems with
698 looking (inside fill_in_lock_file_name) for backslashes in file
699 names encoded by some DBCS codepage. */
700 dostounix_filename (SSDATA (fn), 1);
701#endif
557 encoded_fn = ENCODE_FILE (fn); 702 encoded_fn = ENCODE_FILE (fn);
558 703
559 /* Create the name of the lock-file for file fn */ 704 /* Create the name of the lock-file for file fn */
@@ -572,38 +717,35 @@ lock_file (Lisp_Object fn)
572 call1 (intern ("ask-user-about-supersession-threat"), fn); 717 call1 (intern ("ask-user-about-supersession-threat"), fn);
573 718
574 } 719 }
575 UNGCPRO;
576 720
577 /* Try to lock the lock. */ 721 /* Try to lock the lock. */
578 if (lock_if_free (&lock_info, lfname) <= 0) 722 if (0 < lock_if_free (&lock_info, lfname))
579 /* Return now if we have locked it, or if lock creation failed */
580 return;
581
582 /* Else consider breaking the lock */
583 locker_size = (strlen (lock_info.user) + strlen (lock_info.host)
584 + INT_STRLEN_BOUND (printmax_t)
585 + sizeof "@ (pid )");
586 locker = SAFE_ALLOCA (locker_size);
587 pid = lock_info.pid;
588 esprintf (locker, "%s@%s (pid %"pMd")",
589 lock_info.user, lock_info.host, pid);
590 FREE_LOCK_INFO (lock_info);
591
592 attack = call2 (intern ("ask-user-about-lock"), fn, build_string (locker));
593 SAFE_FREE ();
594 if (!NILP (attack))
595 /* User says take the lock */
596 { 723 {
597 lock_file_1 (lfname, 1); 724 /* Someone else has the lock. Consider breaking it. */
598 return; 725 Lisp_Object attack;
726 char *dot = lock_info.dot;
727 ptrdiff_t pidlen = lock_info.colon - (dot + 1);
728 static char const replacement[] = " (pid ";
729 int replacementlen = sizeof replacement - 1;
730 memmove (dot + replacementlen, dot + 1, pidlen);
731 strcpy (dot + replacementlen + pidlen, ")");
732 memcpy (dot, replacement, replacementlen);
733 attack = call2 (intern ("ask-user-about-lock"), fn,
734 build_string (lock_info.user));
735 /* Take the lock if the user said so. */
736 if (!NILP (attack))
737 lock_file_1 (lfname, 1);
599 } 738 }
600 /* User says ignore the lock */ 739
740 UNGCPRO;
741 SAFE_FREE ();
601} 742}
602 743
603void 744void
604unlock_file (register Lisp_Object fn) 745unlock_file (Lisp_Object fn)
605{ 746{
606 register char *lfname; 747 char *lfname;
748 USE_SAFE_ALLOCA;
607 749
608 fn = Fexpand_file_name (fn, Qnil); 750 fn = Fexpand_file_name (fn, Qnil);
609 fn = ENCODE_FILE (fn); 751 fn = ENCODE_FILE (fn);
@@ -612,6 +754,8 @@ unlock_file (register Lisp_Object fn)
612 754
613 if (current_lock_owner (0, lfname) == 2) 755 if (current_lock_owner (0, lfname) == 2)
614 unlink (lfname); 756 unlink (lfname);
757
758 SAFE_FREE ();
615} 759}
616 760
617void 761void
@@ -677,9 +821,10 @@ t if it is locked by you, else a string saying which user has locked it. */)
677 (Lisp_Object filename) 821 (Lisp_Object filename)
678{ 822{
679 Lisp_Object ret; 823 Lisp_Object ret;
680 register char *lfname; 824 char *lfname;
681 int owner; 825 int owner;
682 lock_info_type locker; 826 lock_info_type locker;
827 USE_SAFE_ALLOCA;
683 828
684 filename = Fexpand_file_name (filename, Qnil); 829 filename = Fexpand_file_name (filename, Qnil);
685 830
@@ -691,11 +836,9 @@ t if it is locked by you, else a string saying which user has locked it. */)
691 else if (owner == 2) 836 else if (owner == 2)
692 ret = Qt; 837 ret = Qt;
693 else 838 else
694 ret = build_string (locker.user); 839 ret = make_string (locker.user, locker.at - locker.user);
695
696 if (owner > 0)
697 FREE_LOCK_INFO (locker);
698 840
841 SAFE_FREE ();
699 return ret; 842 return ret;
700} 843}
701 844