aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-03-02 12:41:53 -0800
committerPaul Eggert2013-03-02 12:41:53 -0800
commitb5029e230d10ea412e4ff1d4867a0c884d130039 (patch)
tree98c424b27b043f8289e215d06ec6a09de6c7e2c3 /src
parent06b583dec7cbde714c8fb991a1e123f612b66e3a (diff)
downloademacs-b5029e230d10ea412e4ff1d4867a0c884d130039.tar.gz
emacs-b5029e230d10ea412e4ff1d4867a0c884d130039.zip
The lock for FILE is now .#FILE or .#-FILE.
The old approach, which fell back on DIR/.#FILE.0 through DIR/.#FILE.9, had race conditions that could not be easily fixed. If DIR/.#FILE is a non-symlink file, Emacs now does not create a lock file for DIR/FILE; that is, DIR/FILE is no longer partly protected by a lock if DIR/.#FILE is a non-symlink file ("partly" because the locking mechanism was never reliable in that case). This patch fixes this and other bugs discovered by a code inspection that was prompted by <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00531.html>. Also, this patch switches to .#-FILE (not .#FILE) on MS-Windows, to avoid interoperability problems between the MS-Windows and non-MS-Windows implementations. MS-Windows and non-MS-Windows instances of Emacs now ignore each others' locks. * etc/NEWS: Document this. * src/filelock.c (defined_WINDOWSNT): New constant. (MAKE_LOCK_NAME, fill_in_lock_file_name): Don't create DIR/.#FILE.0 through DIR/.#FILE.9. Instead, create DIR/.#FILE symlinks on non-MS-Windows hosts, and DIR/.#-FILE regular files on MS-Windows hosts. (MAKE_LOCK_NAME, unlock_file, Ffile_locked_p): Use SAFE_ALLOCA to avoid problems with long file names. (MAX_LFINFO): Now a local constant, not a global macro. (IS_LOCK_FILE): Remove. (lock_file_1): Don't inspect errno if symlink call succeeds; that's not portable. (lock_file): Document that this function can return if lock creation fails. Fixes: debbugs:13807
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog30
-rw-r--r--src/filelock.c92
2 files changed, 71 insertions, 51 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d8b2833b2fa..7afae3df6f5 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,33 @@
12013-03-02 Paul Eggert <eggert@cs.ucla.edu>
2
3 The lock for FILE is now .#FILE or .#-FILE (Bug#13807).
4 The old approach, which fell back on DIR/.#FILE.0 through
5 DIR/.#FILE.9, had race conditions that could not be easily fixed.
6 If DIR/.#FILE is a non-symlink file, Emacs now does not create a
7 lock file for DIR/FILE; that is, DIR/FILE is no longer partly
8 protected by a lock if DIR/.#FILE is a non-symlink file ("partly"
9 because the locking mechanism was never reliable in that case).
10 This patch fixes this and other bugs discovered by a code
11 inspection that was prompted by
12 <http://lists.gnu.org/archive/html/emacs-devel/2013-02/msg00531.html>.
13 Also, this patch switches to .#-FILE (not .#FILE) on MS-Windows,
14 to avoid interoperability problems between the MS-Windows and
15 non-MS-Windows implementations. MS-Windows and non-MS-Windows
16 instances of Emacs now ignore each others' locks.
17 * filelock.c (defined_WINDOWSNT): New constant.
18 (MAKE_LOCK_NAME, fill_in_lock_file_name):
19 Don't create DIR/.#FILE.0 through DIR/.#FILE.9. Instead, create
20 DIR/.#FILE symlinks on non-MS-Windows hosts, and DIR/.#-FILE
21 regular files on MS-Windows hosts.
22 (MAKE_LOCK_NAME, unlock_file, Ffile_locked_p):
23 Use SAFE_ALLOCA to avoid problems with long file names.
24 (MAX_LFINFO): Now a local constant, not a global macro.
25 (IS_LOCK_FILE): Remove.
26 (lock_file_1): Don't inspect errno if symlink call succeeds;
27 that's not portable.
28 (lock_file): Document that this function can return if lock
29 creation fails.
30
12013-03-02 Andreas Schwab <schwab@linux-m68k.org> 312013-03-02 Andreas Schwab <schwab@linux-m68k.org>
2 32
3 * lisp.h (XPNTR) [!USE_LSB_TAG]: Remove extra paren. (Bug#13734) 33 * lisp.h (XPNTR) [!USE_LSB_TAG]: Remove extra paren. (Bug#13734)
diff --git a/src/filelock.c b/src/filelock.c
index 78cd60a12e1..d52e9faeb44 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -64,7 +64,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
64#define WTMP_FILE "/var/log/wtmp" 64#define WTMP_FILE "/var/log/wtmp"
65#endif 65#endif
66 66
67/* The strategy: to lock a file FN, create a symlink .#FN in FN's 67/* On non-MS-Windows systems, use a symbolic link to represent a lock.
68 The strategy: to lock a file FN, create a symlink .#FN in FN's
68 directory, with link data `user@host.pid'. This avoids a single 69 directory, with link data `user@host.pid'. This avoids a single
69 mount (== failure) point for lock files. 70 mount (== failure) point for lock files.
70 71
@@ -97,7 +98,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
97 has contributed this implementation for Emacs), and was designed by 98 has contributed this implementation for Emacs), and was designed by
98 Ethan Jacobson, Kimbo Mundy, and others. 99 Ethan Jacobson, Kimbo Mundy, and others.
99 100
100 --karl@cs.umb.edu/karl@hq.ileaf.com. */ 101 --karl@cs.umb.edu/karl@hq.ileaf.com.
102
103 On MS-Windows, symbolic links do not work well, so instead of a
104 symlink .#FN -> 'user@host.pid', the lock is a regular file .#-FN
105 with contents 'user@host.pid'. MS-Windows and non-MS-Windows
106 versions of Emacs ignore each other's locks. */
101 107
102 108
103/* Return the time of the last system boot. */ 109/* Return the time of the last system boot. */
@@ -291,55 +297,31 @@ typedef struct
291/* Free the two dynamically-allocated pieces in PTR. */ 297/* Free the two dynamically-allocated pieces in PTR. */
292#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) 298#define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0)
293 299
294
295/* Write the name of the lock file for FNAME into LOCKNAME. Length
296 will be that of FN plus two more for the leading `.#' plus 1 for
297 the trailing period plus one for the digit after it plus one for
298 the null. */
299#define MAKE_LOCK_NAME(LOCKNAME, FNAME) \
300 (LOCKNAME = alloca (SBYTES (FNAME) + 2 + 1 + 1 + 1), \
301 fill_in_lock_file_name (LOCKNAME, (FNAME)))
302
303#ifdef WINDOWSNT 300#ifdef WINDOWSNT
304/* 256 chars for user, 1024 chars for host, 10 digits for each of 2 int's. */ 301enum { defined_WINDOWSNT = 1 };
305#define MAX_LFINFO (256 + 1024 + 10 + 10 + 2)
306 /* min size: .@PID */
307#define IS_LOCK_FILE(ST) (MAX_LFINFO >= (ST).st_size && (ST).st_size >= 3)
308#else 302#else
309#define IS_LOCK_FILE(ST) S_ISLNK ((ST).st_mode) 303enum { defined_WINDOWSNT = 0 };
310#endif 304#endif
311 305
306/* Write the name of the lock file for FNAME into LOCKNAME. Length
307 will be that of FNAME plus two more for the leading ".#",
308 plus one for "-" if MS-Windows, plus one for the null. */
309#define MAKE_LOCK_NAME(lockname, fname) \
310 (lockname = SAFE_ALLOCA (SBYTES (fname) + 2 + defined_WINDOWSNT + 1), \
311 fill_in_lock_file_name (lockname, fname))
312
312static void 313static void
313fill_in_lock_file_name (register char *lockfile, register Lisp_Object fn) 314fill_in_lock_file_name (char *lockfile, Lisp_Object fn)
314{ 315{
315 ptrdiff_t length = SBYTES (fn); 316 char *last_slash = memrchr (SSDATA (fn), '/', SBYTES (fn));
316 register char *p; 317 char *base = last_slash + 1;
317 struct stat st; 318 ptrdiff_t dirlen = base - SSDATA (fn);
318 int count = 0; 319 memcpy (lockfile, SSDATA (fn), dirlen);
319 320 lockfile[dirlen] = '.';
320 strcpy (lockfile, SSDATA (fn)); 321 lockfile[dirlen + 1] = '#';
321 322 if (defined_WINDOWSNT)
322 /* Shift the nondirectory part of the file name (including the null) 323 lockfile[dirlen + 2] = '-';
323 right two characters. Here is one of the places where we'd have to 324 strcpy (lockfile + dirlen + 2 + defined_WINDOWSNT, base);
324 do something to support 14-character-max file names. */
325 for (p = lockfile + length; p != lockfile && *p != '/'; p--)
326 p[2] = *p;
327
328 /* Insert the `.#'. */
329 p[1] = '.';
330 p[2] = '#';
331
332 p = lockfile + length + 2;
333
334 while (lstat (lockfile, &st) == 0 && !IS_LOCK_FILE (st))
335 {
336 if (count > 9)
337 {
338 *p = '\0';
339 return;
340 }
341 sprintf (p, ".%d", count++);
342 }
343} 325}
344 326
345static int 327static int
@@ -356,8 +338,8 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
356 { 338 {
357 /* Deny everybody else any kind of access to the file until we are 339 /* Deny everybody else any kind of access to the file until we are
358 done writing it and close the handle. This makes the entire 340 done writing it and close the handle. This makes the entire
359 open/write/close operation atomic, as far as other processes 341 open/write/close operation atomic, as far as other WINDOWSNT
360 are concerned. */ 342 processes are concerned. */
361 int fd = _sopen (lfname, 343 int fd = _sopen (lfname,
362 _O_WRONLY | _O_BINARY | _O_CREAT | _O_EXCL | _O_NOINHERIT, 344 _O_WRONLY | _O_BINARY | _O_CREAT | _O_EXCL | _O_NOINHERIT,
363 _SH_DENYRW, S_IREAD | S_IWRITE); 345 _SH_DENYRW, S_IREAD | S_IWRITE);
@@ -380,7 +362,7 @@ create_lock_file (char *lfname, char *lock_info_str, bool force)
380 } 362 }
381#else 363#else
382 err = symlink (lock_info_str, lfname); 364 err = symlink (lock_info_str, lfname);
383 if (errno == EEXIST && force) 365 if (err != 0 && errno == EEXIST && force)
384 { 366 {
385 unlink (lfname); 367 unlink (lfname);
386 err = symlink (lock_info_str, lfname); 368 err = symlink (lock_info_str, lfname);
@@ -440,6 +422,8 @@ read_lock_data (char *lfname)
440#else 422#else
441 int fd = emacs_open (lfname, O_RDONLY | O_BINARY, S_IREAD); 423 int fd = emacs_open (lfname, O_RDONLY | O_BINARY, S_IREAD);
442 ssize_t nbytes; 424 ssize_t nbytes;
425 /* 256 chars for user, 1024 chars for host, 10 digits for each of 2 int's. */
426 enum { MAX_LFINFO = 256 + 1024 + 10 + 10 + 2 };
443 char lfinfo[MAX_LFINFO + 1]; 427 char lfinfo[MAX_LFINFO + 1];
444 428
445 if (fd < 0) 429 if (fd < 0)
@@ -601,6 +585,7 @@ lock_if_free (lock_info_type *clasher, register char *lfname)
601 decided to go ahead without locking. 585 decided to go ahead without locking.
602 586
603 When this returns, either the lock is locked for us, 587 When this returns, either the lock is locked for us,
588 or lock creation failed,
604 or the user has said to go ahead without locking. 589 or the user has said to go ahead without locking.
605 590
606 If the file is locked by someone else, this calls 591 If the file is locked by someone else, this calls
@@ -686,9 +671,10 @@ lock_file (Lisp_Object fn)
686} 671}
687 672
688void 673void
689unlock_file (register Lisp_Object fn) 674unlock_file (Lisp_Object fn)
690{ 675{
691 register char *lfname; 676 char *lfname;
677 USE_SAFE_ALLOCA;
692 678
693 fn = Fexpand_file_name (fn, Qnil); 679 fn = Fexpand_file_name (fn, Qnil);
694 fn = ENCODE_FILE (fn); 680 fn = ENCODE_FILE (fn);
@@ -697,6 +683,8 @@ unlock_file (register Lisp_Object fn)
697 683
698 if (current_lock_owner (0, lfname) == 2) 684 if (current_lock_owner (0, lfname) == 2)
699 unlink (lfname); 685 unlink (lfname);
686
687 SAFE_FREE ();
700} 688}
701 689
702void 690void
@@ -762,9 +750,10 @@ t if it is locked by you, else a string saying which user has locked it. */)
762 (Lisp_Object filename) 750 (Lisp_Object filename)
763{ 751{
764 Lisp_Object ret; 752 Lisp_Object ret;
765 register char *lfname; 753 char *lfname;
766 int owner; 754 int owner;
767 lock_info_type locker; 755 lock_info_type locker;
756 USE_SAFE_ALLOCA;
768 757
769 filename = Fexpand_file_name (filename, Qnil); 758 filename = Fexpand_file_name (filename, Qnil);
770 759
@@ -781,6 +770,7 @@ t if it is locked by you, else a string saying which user has locked it. */)
781 if (owner > 0) 770 if (owner > 0)
782 FREE_LOCK_INFO (locker); 771 FREE_LOCK_INFO (locker);
783 772
773 SAFE_FREE ();
784 return ret; 774 return ret;
785} 775}
786 776