|
|
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.