comparison src/filelock.c @ 4990:8f0cf4fd3d2c

Automatic merge
author Ben Wing <ben@xemacs.org>
date Sat, 06 Feb 2010 04:01:46 -0600
parents 16112448d484
children 308d34e9f07d
comparison
equal deleted inserted replaced
4989:d2ec55325515 4990:8f0cf4fd3d2c
1 /* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc. 1 /* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc.
2 Copyright (C) 2001 Ben Wing. 2 Copyright (C) 2001, 2010 Ben Wing.
3 3
4 This file is part of XEmacs. 4 This file is part of XEmacs.
5 5
6 XEmacs is free software; you can redistribute it and/or modify 6 XEmacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
36 Lisp_Object Qask_user_about_lock; 36 Lisp_Object Qask_user_about_lock;
37 int inhibit_clash_detection; 37 int inhibit_clash_detection;
38 38
39 #ifdef CLASH_DETECTION 39 #ifdef CLASH_DETECTION
40 40
41 /* The strategy: to lock a file FN, create a symlink .#FN in FN's 41 /* The strategy: to lock a file FN, create a symlink .#FN# in FN's
42 directory, with link data `user@host.pid'. This avoids a single 42 directory, with link data `user@host.pid'. This avoids a single
43 mount (== failure) point for lock files. 43 mount (== failure) point for lock files.
44 44
45 When the host in the lock data is the current host, we can check if 45 When the host in the lock data is the current host, we can check if
46 the pid is valid with kill. 46 the pid is valid with kill.
65 65
66 Similarly, we don't worry about a possible 14-character limit on 66 Similarly, we don't worry about a possible 14-character limit on
67 file names, because those are all the same systems that don't have 67 file names, because those are all the same systems that don't have
68 symlinks. 68 symlinks.
69 69
70 This is compatible with the locking scheme used by Interleaf (which 70 Originally we used a name .#FN without the final #; this may have been
71 has contributed this implementation for Emacs), and was designed by 71 compatible with the locking scheme used by Interleaf (which has
72 Ethan Jacobson, Kimbo Mundy, and others. 72 contributed this implementation for Emacs), and was designed by Ethan
73 Jacobson, Kimbo Mundy, and others.
73 74
74 --karl@cs.umb.edu/karl@hq.ileaf.com. */ 75 --karl@cs.umb.edu/karl@hq.ileaf.com. */
76
77 /* NOTE: We added the final # in the name .#FN# so that programs
78 that e.g. search for all .c files, such as etags, or try to
79 byte-compile all .el files in a directory (byte-recompile-directory),
80 won't get tripped up by the bogus symlink file. --ben */
75 81
76 82
77 /* Here is the structure that stores information about a lock. */ 83 /* Here is the structure that stores information about a lock. */
78 84
79 typedef struct 85 typedef struct
87 enough for decimal representation plus null. */ 93 enough for decimal representation plus null. */
88 #define LOCK_PID_MAX (4 * sizeof (pid_t)) 94 #define LOCK_PID_MAX (4 * sizeof (pid_t))
89 95
90 /* Free the two dynamically-allocated pieces in PTR. */ 96 /* Free the two dynamically-allocated pieces in PTR. */
91 #define FREE_LOCK_INFO(i) do { \ 97 #define FREE_LOCK_INFO(i) do { \
92 xfree ((i).user, Ibyte *); \ 98 xfree ((i).user); \
93 xfree ((i).host, Ibyte *); \ 99 xfree ((i).host); \
94 } while (0) 100 } while (0)
95 101
96 /* Write the name of the lock file for FN into LFNAME. Length will be 102 /* Write the name of the lock file for FN into LFNAME. Length will be that
97 that of FN plus two more for the leading `.#' plus one for the null. */ 103 of FN plus two more for the leading `.#' plus one for the trailing #
104 plus one for the null. */
98 #define MAKE_LOCK_NAME(lock, file) \ 105 #define MAKE_LOCK_NAME(lock, file) \
99 (lock = alloca_ibytes (XSTRING_LENGTH (file) + 2 + 1), \ 106 (lock = alloca_ibytes (XSTRING_LENGTH (file) + 2 + 1 + 1), \
100 fill_in_lock_file_name (lock, file)) 107 fill_in_lock_file_name (lock, file))
101 108
102 static void 109 static void
103 fill_in_lock_file_name (Ibyte *lockfile, Lisp_Object fn) 110 fill_in_lock_file_name (Ibyte *lockfile, Lisp_Object fn)
104 { 111 {
114 121
115 memcpy (lockfile, file_name, dirlen); 122 memcpy (lockfile, file_name, dirlen);
116 p = lockfile + dirlen; 123 p = lockfile + dirlen;
117 *(p++) = '.'; 124 *(p++) = '.';
118 *(p++) = '#'; 125 *(p++) = '#';
119 memcpy (p, file_name + dirlen, XSTRING_LENGTH (fn) - dirlen + 1); 126 memcpy (p, file_name + dirlen, XSTRING_LENGTH (fn) - dirlen);
127 p += XSTRING_LENGTH (fn) - dirlen;
128 *(p++) = '#';
129 *p = '\0';
120 } 130 }
121 131
122 /* Lock the lock file named LFNAME. 132 /* Lock the lock file named LFNAME.
123 If FORCE is nonzero, we do so even if it is already locked. 133 If FORCE is nonzero, we do so even if it is already locked.
124 Return 1 if successful, 0 if not. */ 134 Return 1 if successful, 0 if not. */
181 while (len >= bufsize); 191 while (len >= bufsize);
182 192
183 /* If nonexistent lock file, all is well; otherwise, got strange error. */ 193 /* If nonexistent lock file, all is well; otherwise, got strange error. */
184 if (len == -1) 194 if (len == -1)
185 { 195 {
186 xfree (lfinfo, Ibyte *); 196 xfree (lfinfo);
187 return errno == ENOENT ? 0 : -1; 197 return errno == ENOENT ? 0 : -1;
188 } 198 }
189 199
190 /* Link info exists, so `len' is its length. Null terminate. */ 200 /* Link info exists, so `len' is its length. Null terminate. */
191 lfinfo[len] = 0; 201 lfinfo[len] = 0;
201 /* Parse USER@HOST.PID. If can't parse, return -1. */ 211 /* Parse USER@HOST.PID. If can't parse, return -1. */
202 /* The USER is everything before the first @. */ 212 /* The USER is everything before the first @. */
203 at = qxestrchr (lfinfo, '@'); 213 at = qxestrchr (lfinfo, '@');
204 dot = qxestrrchr (lfinfo, '.'); 214 dot = qxestrrchr (lfinfo, '.');
205 if (!at || !dot) { 215 if (!at || !dot) {
206 xfree (lfinfo, Ibyte *); 216 xfree (lfinfo);
207 return -1; 217 return -1;
208 } 218 }
209 len = at - lfinfo; 219 len = at - lfinfo;
210 owner->user = xnew_ibytes (len + 1); 220 owner->user = xnew_ibytes (len + 1);
211 qxestrncpy (owner->user, lfinfo, len); 221 qxestrncpy (owner->user, lfinfo, len);
219 owner->host = xnew_ibytes (len + 1); 229 owner->host = xnew_ibytes (len + 1);
220 qxestrncpy (owner->host, at + 1, len); 230 qxestrncpy (owner->host, at + 1, len);
221 owner->host[len] = 0; 231 owner->host[len] = 0;
222 232
223 /* We're done looking at the link info. */ 233 /* We're done looking at the link info. */
224 xfree (lfinfo, Ibyte *); 234 xfree (lfinfo);
225 235
226 /* On current host? */ 236 /* On current host? */
227 if (STRINGP (Fsystem_name ()) 237 if (STRINGP (Fsystem_name ())
228 && qxestrcmp (owner->host, XSTRING_DATA (Fsystem_name ())) == 0) 238 && qxestrcmp (owner->host, XSTRING_DATA (Fsystem_name ())) == 0)
229 { 239 {
356 lock_info.pid); 366 lock_info.pid);
357 FREE_LOCK_INFO (lock_info); 367 FREE_LOCK_INFO (lock_info);
358 368
359 attack = call2_in_buffer (BUFFERP (subject_buf) ? XBUFFER (subject_buf) : 369 attack = call2_in_buffer (BUFFERP (subject_buf) ? XBUFFER (subject_buf) :
360 current_buffer, Qask_user_about_lock , fn, 370 current_buffer, Qask_user_about_lock , fn,
361 build_intstring (locker)); 371 build_istring (locker));
362 if (!NILP (attack) && current_buffer == XBUFFER (old_current_buffer)) 372 if (!NILP (attack) && current_buffer == XBUFFER (old_current_buffer))
363 /* User says take the lock */ 373 /* User says take the lock */
364 { 374 {
365 lock_file_1 (lfname, 1); 375 lock_file_1 (lfname, 1);
366 goto done; 376 goto done;
472 if (owner <= 0) 482 if (owner <= 0)
473 ret = Qnil; 483 ret = Qnil;
474 else if (owner == 2) 484 else if (owner == 2)
475 ret = Qt; 485 ret = Qt;
476 else 486 else
477 ret = build_intstring (locker.user); 487 ret = build_istring (locker.user);
478 488
479 if (owner > 0) 489 if (owner > 0)
480 FREE_LOCK_INFO (locker); 490 FREE_LOCK_INFO (locker);
481 491
482 UNGCPRO; 492 UNGCPRO;