|
|
1.1 ! root 1: /* Copyright (C) 1985 Richard M. Stallman and Dick King ! 2: ! 3: This file is part of GNU Emacs. ! 4: ! 5: GNU Emacs is distributed in the hope that it will be useful, ! 6: but WITHOUT ANY WARRANTY. No author or distributor ! 7: accepts responsibility to anyone for the consequences of using it ! 8: or for whether it serves any particular purpose or works at all, ! 9: unless he says so in writing. Refer to the GNU Emacs General Public ! 10: License for full details. ! 11: ! 12: Everyone is granted permission to copy, modify and redistribute ! 13: GNU Emacs, but only under the conditions described in the ! 14: GNU Emacs General Public License. A copy of this license is ! 15: supposed to have been given to you along with GNU Emacs so you ! 16: can know your rights and responsibilities. It should be in a ! 17: file named COPYING. Among other things, the copyright notice ! 18: and this notice must be preserved on all copies. */ ! 19: ! 20: ! 21: #include "config.h" ! 22: #include "lisp.h" ! 23: #include "paths.h" ! 24: #include "buffer.h" ! 25: #include <sys/types.h> ! 26: #include <sys/stat.h> ! 27: #include <pwd.h> ! 28: #include <errno.h> ! 29: #include <sys/file.h> ! 30: #ifdef USG ! 31: #include <fcntl.h> ! 32: #endif /* USG */ ! 33: ! 34: #ifdef CLASH_DETECTION ! 35: ! 36: /* lock_file locks file fn, ! 37: meaning it serves notice on the world that you intend to edit that file. ! 38: This should be done only when about to modify a file-visiting ! 39: buffer previously unmodified. ! 40: Do not (normally) call lock_buffer for a buffer already modified, ! 41: as either the file is already locked, or the user has already ! 42: decided to go ahead without locking. ! 43: ! 44: When lock_buffer returns, either the lock is locked for us, ! 45: or the user has said to go ahead without locking. ! 46: ! 47: If the file is locked by someone else, lock_buffer calls ! 48: ask-user-about-lock (a Lisp function) with two arguments, ! 49: the file name and the name of the user who did the locking. ! 50: This function can signal an error, or return t meaning ! 51: take away the lock, or return nil meaning ignore the lock. */ ! 52: ! 53: /* The lock file name is the file name with "/" replaced by "!" ! 54: and put in the Emacs lock directory. */ ! 55: /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */ ! 56: ! 57: void ! 58: lock_file (fn) ! 59: register Lisp_Object fn; ! 60: { ! 61: register int fd; ! 62: register Lisp_Object attack; ! 63: register char *lfname; ! 64: struct stat s; ! 65: struct passwd *the_pw; ! 66: extern struct passwd *getpwuid (); ! 67: ! 68: /* Create the name of the lock-file for file fn */ ! 69: lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1); ! 70: fill_in_lock_file_name (lfname, fn); ! 71: ! 72: /* Try to lock the lock. */ ! 73: if (lock_if_free (lfname) <= 0) ! 74: /* Return now if we have locked it, or if lock dir does not exist */ ! 75: return; ! 76: ! 77: /* Else consider breaking the lock */ ! 78: the_pw = 0; ! 79: if (lstat (lfname, &s) == 0) ! 80: the_pw = getpwuid (s.st_uid); ! 81: attack = call2 (intern ("ask-user-about-lock"), fn, ! 82: the_pw == 0 ? Qnil : build_string (the_pw->pw_name)); ! 83: if (!NULL (attack)) ! 84: /* User says take the lock */ ! 85: { ! 86: lock_superlock (lfname); ! 87: lock_file_1 (lfname, O_WRONLY) ; ! 88: unlink (PATH_SUPERLOCK); ! 89: return; ! 90: } ! 91: /* User says ignore the lock */ ! 92: } ! 93: ! 94: fill_in_lock_file_name (lockfile, fn) ! 95: register char *lockfile; ! 96: register Lisp_Object fn; ! 97: { ! 98: register char *p; ! 99: ! 100: strcpy (lockfile, PATH_LOCK); ! 101: ! 102: p = lockfile + strlen (lockfile); ! 103: ! 104: strcpy (p, XSTRING (fn)->data); ! 105: ! 106: for (; *p; p++) ! 107: { ! 108: if (*p == '/') ! 109: *p = '!'; ! 110: } ! 111: } ! 112: ! 113: /* Lock the lock file named LFNAME. ! 114: If MODE is O_WRONLY, we do so even if it is already locked. ! 115: If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free. ! 116: Return 1 if successful, 0 if not. */ ! 117: ! 118: int ! 119: lock_file_1 (lfname, mode) ! 120: int mode; char *lfname; ! 121: { ! 122: register int fd; ! 123: char buf[20]; ! 124: ! 125: if ((fd = open (lfname, mode, 0666)) >= 0) ! 126: { ! 127: fchmod (fd, 0666); ! 128: sprintf (buf, "%d ", getpid ()); ! 129: write (fd, buf, strlen (buf)); ! 130: close (fd); ! 131: return 1; ! 132: } ! 133: else ! 134: return 0; ! 135: } ! 136: ! 137: /* Lock the lock named LFNAME if possible. ! 138: Return 0 in that case. ! 139: Return 1 if lock is really locked by someone else. ! 140: Return -1 if cannot lock for any other reason. */ ! 141: ! 142: int ! 143: lock_if_free (lfname) ! 144: register char *lfname; ! 145: { ! 146: register int clasher; ! 147: extern int errno; ! 148: ! 149: while (lock_file_1 (lfname, O_WRONLY | O_EXCL | O_CREAT) == 0) ! 150: { ! 151: if (errno != EEXIST) ! 152: return -1; ! 153: clasher = current_lock_owner (lfname); ! 154: if (clasher == 0 || (kill (clasher, 0) < 0 && errno == ESRCH)) ! 155: { ! 156: if (unlink (lfname) < 0) ! 157: return -1; ! 158: /* If we delete the lock successfully, try again to lock. */ ! 159: } ! 160: else ! 161: return (clasher != getpid ()); ! 162: } ! 163: return 0; ! 164: } ! 165: ! 166: int ! 167: current_lock_owner (lfname) ! 168: char *lfname; ! 169: { ! 170: register int fd; ! 171: char buf[20]; ! 172: ! 173: fd = open (lfname, O_RDONLY, 0666); ! 174: if (fd < 0) ! 175: return 0; ! 176: ! 177: if (read (fd, buf, sizeof buf) <= 0) ! 178: return 0; ! 179: close (fd); ! 180: return atoi (buf); ! 181: } ! 182: ! 183: void ! 184: unlock_file (fn) ! 185: register Lisp_Object fn; ! 186: { ! 187: register char *lfname; ! 188: ! 189: lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1); ! 190: fill_in_lock_file_name (lfname, fn); ! 191: ! 192: lock_superlock (lfname); ! 193: ! 194: if (current_lock_owner (lfname) == getpid ()) ! 195: unlink (lfname); ! 196: ! 197: unlink (PATH_SUPERLOCK); ! 198: } ! 199: ! 200: lock_superlock (lfname) ! 201: char *lfname; ! 202: { ! 203: register int i, fd; ! 204: extern int errno; ! 205: ! 206: for (i = -20; i < 0 && (fd = open (PATH_SUPERLOCK, ! 207: O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0; ! 208: i++) ! 209: { ! 210: if (errno != EEXIST) ! 211: return; ! 212: sleep (1); ! 213: } ! 214: if (fd >= 0) ! 215: { ! 216: fchmod (fd, 0666); ! 217: write (fd, lfname, strlen (lfname)); ! 218: close (fd); ! 219: } ! 220: } ! 221: ! 222: void ! 223: unlock_all_files () ! 224: { ! 225: register Lisp_Object tail; ! 226: register struct buffer *b; ! 227: ! 228: for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons; ! 229: tail = XCONS (tail)->cdr) ! 230: { ! 231: b = XBUFFER (XCONS (XCONS (tail)->car)->cdr); ! 232: if (!NULL (b->filename) ! 233: && b->save_modified < b->text.modified) ! 234: unlock_file (b->filename); ! 235: } ! 236: } ! 237: ! 238: DEFUN ("lock-buffer", Flock_buffer, Slock_buffer, ! 239: 0, 1, 0, ! 240: "Locks FILE, if current buffer is modified.\n\ ! 241: FILE defaults to current buffer's visited file,\n\ ! 242: or else nothing is done if current buffer isn't visiting a file.") ! 243: (fn) ! 244: Lisp_Object fn; ! 245: { ! 246: if (NULL (fn)) ! 247: fn = bf_cur->filename; ! 248: else ! 249: CHECK_STRING (fn, 0); ! 250: if (bf_cur->save_modified < bf_modified ! 251: && !NULL (fn)) ! 252: lock_file (fn); ! 253: return Qnil; ! 254: } ! 255: ! 256: DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer, ! 257: 0, 0, 0, ! 258: "Unlocks the file visited in the current buffer,\n\ ! 259: if it should normally be locked.") ! 260: () ! 261: { ! 262: if (bf_cur->save_modified < bf_modified ! 263: && !NULL (bf_cur->filename)) ! 264: unlock_file (bf_cur->filename); ! 265: return Qnil; ! 266: } ! 267: ! 268: syms_of_filelock () ! 269: { ! 270: defsubr (&Sunlock_buffer); ! 271: defsubr (&Slock_buffer); ! 272: } ! 273: ! 274: #endif /* CLASH_DETECTION */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.