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 */