Mercurial > hg > xemacs-beta
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; |
