|
|
1.1 root 1: /* Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
2:
3: This file is part of GNU Emacs.
4:
5: GNU Emacs is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License as published by
7: the Free Software Foundation; either version 1, or (at your option)
8: any later version.
9:
10: GNU Emacs is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License
16: along with GNU Emacs; see the file COPYING. If not, write to
17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18:
19:
20: #include <sys/types.h>
21: #include <sys/stat.h>
22: #include "config.h"
23: #ifdef hpux
24: /* needed by <pwd.h> */
25: #include <stdio.h>
26: #undef NULL
27: #endif
28: #include "lisp.h"
29: #include "paths.h"
30: #include "buffer.h"
31:
32: #ifdef VMS
33: #include "vms-pwd.h"
34: #else
35: #include <pwd.h>
36: #endif
37:
38: #include <errno.h>
39: #include <sys/file.h>
40: #ifdef USG
41: #include <fcntl.h>
42: #endif /* USG */
43:
44: #include "filetypes.h"
45:
46: extern int errno;
47:
48: #ifdef VMS
49: /* Prevent the file from being totally empty. */
50: static dummy () {}
51: #endif
52:
53: #ifdef CLASH_DETECTION
54:
55: /* If system does not have symbolic links, it does not have lstat.
56: In that case, use ordinary stat instead. */
57:
58: #ifndef S_IFLNK
59: #define lstat stat
60: #endif
61:
62: static Lisp_Object
63: lock_file_owner_name (lfname)
64: char *lfname;
65: {
66: struct stat s;
67: struct passwd *the_pw;
68: extern struct passwd *getpwuid ();
69:
70: if (lstat (lfname, &s) == 0)
71: the_pw = getpwuid (s.st_uid);
72: return (the_pw == 0 ? Qnil : build_string (the_pw->pw_name));
73: }
74:
75:
76: /* lock_file locks file fn,
77: meaning it serves notice on the world that you intend to edit that file.
78: This should be done only when about to modify a file-visiting
79: buffer previously unmodified.
80: Do not (normally) call lock_buffer for a buffer already modified,
81: as either the file is already locked, or the user has already
82: decided to go ahead without locking.
83:
84: When lock_buffer returns, either the lock is locked for us,
85: or the user has said to go ahead without locking.
86:
87: If the file is locked by someone else, lock_buffer calls
88: ask-user-about-lock (a Lisp function) with two arguments,
89: the file name and the name of the user who did the locking.
90: This function can signal an error, or return t meaning
91: take away the lock, or return nil meaning ignore the lock. */
92:
93: /* The lock file name is the file name with "/" replaced by "!"
94: and put in the Emacs lock directory. */
95: /* (ie., /ka/king/junk.tex -> /!/!ka!king!junk.tex). */
96:
97: /* If SHORT_FILE_NAMES is defined, the lock file name is the hex
98: representation of a 14-bytes CRC generated from the file name
99: and put in the Emacs lock directory (not very nice, but it works).
100: (ie., /ka/king/junk.tex -> /!/ec92d3ed24a8f0). */
101:
102: #ifdef SHORT_FILE_NAMES
103:
104: # define CREATE_LOCK_FILE_NAME(lfname, fn) \
105: { lfname = (char *) alloca (14 + strlen (PATH_LOCK) + 1); \
106: fill_in_lock_short_file_name (lfname, fn); }
107:
108: #else
109:
110: # define CREATE_LOCK_FILE_NAME(lfname, fn) \
111: { lfname = (char *) alloca (XSTRING (fn)->size + strlen (PATH_LOCK) + 1); \
112: fill_in_lock_file_name (lfname, fn); }
113:
114: #endif
115:
116:
117:
118: void
119: lock_file (fn)
120: register Lisp_Object fn;
121: {
122: register Lisp_Object attack;
123: register char *lfname;
124:
125: /* Create the name of the lock-file for file fn */
126: CREATE_LOCK_FILE_NAME (lfname, fn);
127:
128: /* See if this file is visited and has changed on disk since it was visited. */
129: {
130: register Lisp_Object subject_buf = Fget_file_buffer (fn);
131: if (!NULL (subject_buf)
132: && NULL (Fverify_visited_file_modtime (subject_buf))
133: && !NULL (Ffile_exists_p (fn)))
134: call1 (intern ("ask-user-about-supersession-threat"), fn);
135: }
136:
137: /* Try to lock the lock. */
138: if (lock_if_free (lfname) <= 0)
139: /* Return now if we have locked it, or if lock dir does not exist */
140: return;
141:
142: /* Else consider breaking the lock */
143: attack = call2 (intern ("ask-user-about-lock"), fn,
144: lock_file_owner_name (lfname));
145: if (!NULL (attack))
146: /* User says take the lock */
147: {
148: lock_superlock (lfname);
149: lock_file_1 (lfname, O_WRONLY) ;
150: unlink (PATH_SUPERLOCK);
151: return;
152: }
153: /* User says ignore the lock */
154: }
155:
156: fill_in_lock_file_name (lockfile, fn)
157: register char *lockfile;
158: register Lisp_Object fn;
159: {
160: register char *p;
161:
162: strcpy (lockfile, PATH_LOCK);
163:
164: p = lockfile + strlen (lockfile);
165:
166: strcpy (p, XSTRING (fn)->data);
167:
168: for (; *p; p++)
169: {
170: if (*p == '/')
171: *p = '!';
172: }
173: }
174:
175: #ifdef SHORT_FILE_NAMES
176: fill_in_lock_short_file_name (lockfile, fn)
177: register char *lockfile;
178: register Lisp_Object fn;
179: {
180: register union
181: {
182: unsigned int word [2];
183: unsigned char byte [8];
184: } crc;
185: register unsigned char *p, new;
186:
187: /* 7-bytes cyclic code for burst correction on byte-by-byte basis.
188: the used polynomial is D^7 + D^6 + D^3 +1. [email protected] */
189:
190: crc.word[0] = crc.word[1] = 0;
191:
192: for (p = XSTRING (fn)->data; new = *p++; )
193: {
194: new += crc.byte[7];
195: crc.byte[7] = crc.byte[6];
196: crc.byte[6] = crc.byte[5] + new;
197: crc.byte[5] = crc.byte[4];
198: crc.byte[4] = crc.byte[3];
199: crc.byte[3] = crc.byte[2] + new;
200: crc.byte[2] = crc.byte[1];
201: crc.byte[1] = crc.byte[0];
202: crc.byte[0] = new;
203: }
204: sprintf (lockfile, "%s%.2x%.2x%.2x%.2x%.2x%.2x%.2x", PATH_LOCK,
205: crc.byte[0], crc.byte[1], crc.byte[2], crc.byte[3],
206: crc.byte[4], crc.byte[5], crc.byte[6]);
207: }
208: #endif /* SHORT_FILE_NAMES */
209:
210: /* Lock the lock file named LFNAME.
211: If MODE is O_WRONLY, we do so even if it is already locked.
212: If MODE is O_WRONLY | O_EXCL | O_CREAT, we do so only if it is free.
213: Return 1 if successful, 0 if not. */
214:
215: int
216: lock_file_1 (lfname, mode)
217: int mode; char *lfname;
218: {
219: register int fd;
220: char buf[20];
221:
222: if ((fd = open (lfname, mode, 0666)) >= 0)
223: {
224: #ifdef NO_FCHMOD
225: chmod (lfname, 0666);
226: #else
227: fchmod (fd, 0666);
228: #endif
229: sprintf (buf, "%d ", getpid ());
230: write (fd, buf, strlen (buf));
231: close (fd);
232: return 1;
233: }
234: else
235: return 0;
236: }
237:
238: /* Lock the lock named LFNAME if possible.
239: Return 0 in that case.
240: Return positive if lock is really locked by someone else.
241: Return -1 if cannot lock for any other reason. */
242:
243: int
244: lock_if_free (lfname)
245: register char *lfname;
246: {
247: register int clasher;
248:
249: while (lock_file_1 (lfname, O_WRONLY | O_EXCL | O_CREAT) == 0)
250: {
251: if (errno != EEXIST)
252: return -1;
253: clasher = current_lock_owner (lfname);
254: if (clasher != 0)
255: if (clasher != getpid ())
256: return (clasher);
257: else return (0);
258: /* Try again to lock it */
259: }
260: return 0;
261: }
262:
263: /* Return the pid of the process that claims to own the lock file LFNAME,
264: or 0 if nobody does or the lock is obsolete,
265: or -1 if something is wrong with the locking mechanism. */
266:
267: int
268: current_lock_owner (lfname)
269: char *lfname;
270: {
271: int owner = current_lock_owner_1 (lfname);
272: if (owner == 0 && errno == ENOENT)
273: return (0);
274: /* Is it locked by a process that exists? */
275: if (owner != 0 && (kill (owner, 0) >= 0 || errno == EPERM))
276: return (owner);
277: if (unlink (lfname) < 0)
278: return (-1);
279: return (0);
280: }
281:
282: int
283: current_lock_owner_1 (lfname)
284: char *lfname;
285: {
286: register int fd;
287: char buf[20];
288: int tem;
289:
290: fd = open (lfname, O_RDONLY, 0666);
291: if (fd < 0)
292: return 0;
293: tem = read (fd, buf, sizeof buf);
294: close (fd);
295: return (tem <= 0 ? 0 : atoi (buf));
296: }
297:
298:
299: void
300: unlock_file (fn)
301: register Lisp_Object fn;
302: {
303: register char *lfname;
304:
305: CREATE_LOCK_FILE_NAME (lfname, fn);
306:
307: lock_superlock (lfname);
308:
309: if (current_lock_owner_1 (lfname) == getpid ())
310: unlink (lfname);
311:
312: unlink (PATH_SUPERLOCK);
313: }
314:
315: lock_superlock (lfname)
316: char *lfname;
317: {
318: register int i, fd;
319:
320: for (i = -20; i < 0 && (fd = open (PATH_SUPERLOCK,
321: O_WRONLY | O_EXCL | O_CREAT, 0666)) < 0;
322: i++)
323: {
324: if (errno != EEXIST)
325: return;
326: sleep (1);
327: }
328: if (fd >= 0)
329: {
330: #ifdef NO_FCHMOD
331: chmod (PATH_SUPERLOCK, 0666);
332: #else
333: fchmod (fd, 0666);
334: #endif
335: write (fd, lfname, strlen (lfname));
336: close (fd);
337: }
338: }
339:
340: void
341: unlock_all_files ()
342: {
343: register Lisp_Object tail;
344: register struct buffer *b;
345:
346: for (tail = Vbuffer_alist; XGCTYPE (tail) == Lisp_Cons;
347: tail = XCONS (tail)->cdr)
348: {
349: b = XBUFFER (XCONS (XCONS (tail)->car)->cdr);
350: if (XTYPE (b->filename) == Lisp_String &&
351: b->save_modified < BUF_MODIFF (b))
352: unlock_file (b->filename);
353: }
354: }
355:
356:
357: DEFUN ("lock-buffer", Flock_buffer, Slock_buffer,
358: 0, 1, 0,
359: "Locks FILE, if current buffer is modified.\n\
360: FILE defaults to current buffer's visited file,\n\
361: or else nothing is done if current buffer isn't visiting a file.")
362: (fn)
363: Lisp_Object fn;
364: {
365: if (NULL (fn))
366: fn = current_buffer->filename;
367: else
368: CHECK_STRING (fn, 0);
369: if (current_buffer->save_modified < MODIFF
370: && !NULL (fn))
371: lock_file (fn);
372: return Qnil;
373: }
374:
375: DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer,
376: 0, 0, 0,
377: "Unlocks the file visited in the current buffer,\n\
378: if it should normally be locked.")
379: ()
380: {
381: if (current_buffer->save_modified < MODIFF &&
382: XTYPE (current_buffer->filename) == Lisp_String)
383: unlock_file (current_buffer->filename);
384: return Qnil;
385: }
386:
387:
388: /* Unlock the file visited in buffer BUFFER. */
389:
390: unlock_buffer (buffer)
391: struct buffer *buffer;
392: {
393: if (buffer->save_modified < BUF_MODIFF (buffer)
394: && XTYPE (buffer->filename) == Lisp_String)
395: unlock_file (buffer->filename);
396: }
397:
398: DEFUN ("file-locked-p", Ffile_locked_p, Sfile_locked_p, 0, 1, 0,
399: "Returns nil if the FILENAME is not locked,\n\
400: t if it is locked by you, else a string of the name of the locker.")
401: (fn)
402: Lisp_Object fn;
403: {
404: register char *lfname;
405: int owner;
406:
407: fn = Fexpand_file_name (fn, Qnil);
408:
409: /* Create the name of the lock-file for file filename */
410: CREATE_LOCK_FILE_NAME (lfname, fn);
411:
412: owner = current_lock_owner (lfname);
413: if (owner <= 0)
414: return (Qnil);
415: else if (owner == getpid ())
416: return (Qt);
417:
418: return (lock_file_owner_name (lfname));
419: }
420:
421: syms_of_filelock ()
422: {
423: defsubr (&Sunlock_buffer);
424: defsubr (&Slock_buffer);
425: defsubr (&Sfile_locked_p);
426: }
427:
428: #endif /* CLASH_DETECTION */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.