comparison src/filelock.c @ 406:b8cc9ab3f761 r21-2-33

Import from CVS: tag r21-2-33
author cvs
date Mon, 13 Aug 2007 11:17:09 +0200
parents 2f8bb876ab1d
children 697ef44129c6
comparison
equal deleted inserted replaced
405:0e08f63c74d2 406:b8cc9ab3f761
32 32
33 Lisp_Object Qask_user_about_supersession_threat; 33 Lisp_Object Qask_user_about_supersession_threat;
34 Lisp_Object Qask_user_about_lock; 34 Lisp_Object Qask_user_about_lock;
35 35
36 #ifdef CLASH_DETECTION 36 #ifdef CLASH_DETECTION
37 37
38 /* The strategy: to lock a file FN, create a symlink .#FN in FN's 38 /* The strategy: to lock a file FN, create a symlink .#FN in FN's
39 directory, with link data `user@host.pid'. This avoids a single 39 directory, with link data `user@host.pid'. This avoids a single
40 mount (== failure) point for lock files. 40 mount (== failure) point for lock files.
41 41
42 When the host in the lock data is the current host, we can check if 42 When the host in the lock data is the current host, we can check if
43 the pid is valid with kill. 43 the pid is valid with kill.
44 44
45 Otherwise, we could look at a separate file that maps hostnames to 45 Otherwise, we could look at a separate file that maps hostnames to
46 reboot times to see if the remote pid can possibly be valid, since we 46 reboot times to see if the remote pid can possibly be valid, since we
47 don't want Emacs to have to communicate via pipes or sockets or 47 don't want Emacs to have to communicate via pipes or sockets or
48 whatever to other processes, either locally or remotely; rms says 48 whatever to other processes, either locally or remotely; rms says
49 that's too unreliable. Hence the separate file, which could 49 that's too unreliable. Hence the separate file, which could
61 didn't seem worth the complication. 61 didn't seem worth the complication.
62 62
63 Similarly, we don't worry about a possible 14-character limit on 63 Similarly, we don't worry about a possible 14-character limit on
64 file names, because those are all the same systems that don't have 64 file names, because those are all the same systems that don't have
65 symlinks. 65 symlinks.
66 66
67 This is compatible with the locking scheme used by Interleaf (which 67 This is compatible with the locking scheme used by Interleaf (which
68 has contributed this implementation for Emacs), and was designed by 68 has contributed this implementation for Emacs), and was designed by
69 Ethan Jacobson, Kimbo Mundy, and others. 69 Ethan Jacobson, Kimbo Mundy, and others.
70 70
71 --karl@cs.umb.edu/karl@hq.ileaf.com. */ 71 --karl@cs.umb.edu/karl@hq.ileaf.com. */
72
73 /* Note that muleization is provided by using mule-encapsulated
74 versions of the system calls we use like symlink(), unlink(), etc... */
72 75
73 76
74 /* Here is the structure that stores information about a lock. */ 77 /* Here is the structure that stores information about a lock. */
75 78
76 typedef struct 79 typedef struct
88 #define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0) 91 #define FREE_LOCK_INFO(i) do { xfree ((i).user); xfree ((i).host); } while (0)
89 92
90 /* Write the name of the lock file for FN into LFNAME. Length will be 93 /* Write the name of the lock file for FN into LFNAME. Length will be
91 that of FN plus two more for the leading `.#' plus one for the null. */ 94 that of FN plus two more for the leading `.#' plus one for the null. */
92 #define MAKE_LOCK_NAME(lock, file) \ 95 #define MAKE_LOCK_NAME(lock, file) \
93 (lock = (char *) alloca (XSTRING_LENGTH(file) + 2 + 1), \ 96 (lock = (char *) alloca (XSTRING_LENGTH (file) + 2 + 1), \
94 fill_in_lock_file_name (lock, (file))) 97 fill_in_lock_file_name ((Bufbyte *) (lock), (file)))
95 98
96 static void 99 static void
97 fill_in_lock_file_name (lockfile, fn) 100 fill_in_lock_file_name (Bufbyte *lockfile, Lisp_Object fn)
98 register char *lockfile; 101 {
99 register Lisp_Object fn; 102 Bufbyte *file_name = XSTRING_DATA (fn);
100 { 103 Bufbyte *p;
101 register char *p; 104 size_t dirlen;
102 105
103 strcpy (lockfile, XSTRING_DATA(fn)); 106 for (p = file_name + XSTRING_LENGTH (fn) - 1;
104 107 p > file_name && !IS_ANY_SEP (p[-1]);
105 /* Shift the nondirectory part of the file name (including the null) 108 p--)
106 right two characters. Here is one of the places where we'd have to 109 ;
107 do something to support 14-character-max file names. */ 110 dirlen = p - file_name;
108 for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--) 111
109 p[2] = *p; 112 memcpy (lockfile, file_name, dirlen);
110 113 p = lockfile + dirlen;
111 /* Insert the `.#'. */ 114 *(p++) = '.';
112 p[1] = '.'; 115 *(p++) = '#';
113 p[2] = '#'; 116 memcpy (p, file_name + dirlen, XSTRING_LENGTH (fn) - dirlen + 1);
114 } 117 }
115 118
116 /* Lock the lock file named LFNAME. 119 /* Lock the lock file named LFNAME.
117 If FORCE is nonzero, we do so even if it is already locked. 120 If FORCE is nonzero, we do so even if it is already locked.
118 Return 1 if successful, 0 if not. */ 121 Return 1 if successful, 0 if not. */
119 122
120 static int 123 static int
121 lock_file_1 (char *lfname,int force) 124 lock_file_1 (char *lfname, int force)
122 { 125 {
123 register int err; 126 int err;
124 char *user_name; 127 char *lock_info_str;
125 char *host_name; 128 char *host_name;
126 char *lock_info_str; 129 char *user_name = user_login_name (NULL);
127 130
128 if (STRINGP (Fuser_login_name (Qnil))) 131 if (user_name == NULL)
129 user_name = (char *) XSTRING_DATA (Fuser_login_name (Qnil));
130 else
131 user_name = ""; 132 user_name = "";
132 if (STRINGP (Fsystem_name ())) 133
133 host_name = (char *) XSTRING_DATA (Fsystem_name ()); 134 if (STRINGP (Vsystem_name))
135 host_name = (char *) XSTRING_DATA (Vsystem_name);
134 else 136 else
135 host_name = ""; 137 host_name = "";
138
136 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) 139 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name)
137 + LOCK_PID_MAX + 5); 140 + LOCK_PID_MAX + 5);
138 141
139 sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name, 142 sprintf (lock_info_str, "%s@%s.%lu", user_name, host_name,
140 (unsigned long) getpid ()); 143 (unsigned long) getpid ());
141 144
142 err = symlink (lock_info_str, lfname); 145 err = symlink (lock_info_str, lfname);
143 if (errno == EEXIST && force) 146 if (err != 0 && errno == EEXIST && force)
144 { 147 {
145 unlink (lfname); 148 unlink (lfname);
146 err = symlink (lock_info_str, lfname); 149 err = symlink (lock_info_str, lfname);
147 } 150 }
148 151
155 or -1 if something is wrong with the locking mechanism. */ 158 or -1 if something is wrong with the locking mechanism. */
156 159
157 static int 160 static int
158 current_lock_owner (lock_info_type *owner, char *lfname) 161 current_lock_owner (lock_info_type *owner, char *lfname)
159 { 162 {
160 int o, p, len, ret; 163 int len, ret;
161 int local_owner = 0; 164 int local_owner = 0;
162 char *at, *dot; 165 char *at, *dot;
163 char *lfinfo = 0; 166 char *lfinfo = 0;
164 int bufsize = 50; 167 int bufsize = 50;
165 /* Read arbitrarily-long contents of symlink. Similar code in 168 /* Read arbitrarily-long contents of symlink. Similar code in
169 bufsize *= 2; 172 bufsize *= 2;
170 lfinfo = (char *) xrealloc (lfinfo, bufsize); 173 lfinfo = (char *) xrealloc (lfinfo, bufsize);
171 len = readlink (lfname, lfinfo, bufsize); 174 len = readlink (lfname, lfinfo, bufsize);
172 } 175 }
173 while (len >= bufsize); 176 while (len >= bufsize);
174 177
175 /* If nonexistent lock file, all is well; otherwise, got strange error. */ 178 /* If nonexistent lock file, all is well; otherwise, got strange error. */
176 if (len == -1) 179 if (len == -1)
177 { 180 {
178 xfree (lfinfo); 181 xfree (lfinfo);
179 return errno == ENOENT ? 0 : -1; 182 return errno == ENOENT ? 0 : -1;
180 } 183 }
181 184
182 /* Link info exists, so `len' is its length. Null terminate. */ 185 /* Link info exists, so `len' is its length. Null terminate. */
183 lfinfo[len] = 0; 186 lfinfo[len] = 0;
184 187
185 /* Even if the caller doesn't want the owner info, we still have to 188 /* Even if the caller doesn't want the owner info, we still have to
186 read it to determine return value, so allocate it. */ 189 read it to determine return value, so allocate it. */
187 if (!owner) 190 if (!owner)
188 { 191 {
189 owner = (lock_info_type *) alloca (sizeof (lock_info_type)); 192 owner = (lock_info_type *) alloca (sizeof (lock_info_type));
190 local_owner = 1; 193 local_owner = 1;
191 } 194 }
192 195
193 /* Parse USER@HOST.PID. If can't parse, return -1. */ 196 /* Parse USER@HOST.PID. If can't parse, return -1. */
194 /* The USER is everything before the first @. */ 197 /* The USER is everything before the first @. */
195 at = strchr (lfinfo, '@'); 198 at = strchr (lfinfo, '@');
196 dot = strrchr (lfinfo, '.'); 199 dot = strrchr (lfinfo, '.');
197 if (!at || !dot) { 200 if (!at || !dot) {
200 } 203 }
201 len = at - lfinfo; 204 len = at - lfinfo;
202 owner->user = (char *) xmalloc (len + 1); 205 owner->user = (char *) xmalloc (len + 1);
203 strncpy (owner->user, lfinfo, len); 206 strncpy (owner->user, lfinfo, len);
204 owner->user[len] = 0; 207 owner->user[len] = 0;
205 208
206 /* The PID is everything after the last `.'. */ 209 /* The PID is everything after the last `.'. */
207 owner->pid = atoi (dot + 1); 210 owner->pid = atoi (dot + 1);
208 211
209 /* The host is everything in between. */ 212 /* The host is everything in between. */
210 len = dot - at - 1; 213 len = dot - at - 1;
212 strncpy (owner->host, at + 1, len); 215 strncpy (owner->host, at + 1, len);
213 owner->host[len] = 0; 216 owner->host[len] = 0;
214 217
215 /* We're done looking at the link info. */ 218 /* We're done looking at the link info. */
216 xfree (lfinfo); 219 xfree (lfinfo);
217 220
218 /* On current host? */ 221 /* On current host? */
219 if (STRINGP (Fsystem_name ()) 222 if (STRINGP (Fsystem_name ())
220 && strcmp (owner->host, XSTRING_DATA(Fsystem_name ())) == 0) 223 && strcmp (owner->host, (char *) XSTRING_DATA (Fsystem_name ())) == 0)
221 { 224 {
222 if (owner->pid == getpid ()) 225 if (owner->pid == getpid ())
223 ret = 2; /* We own it. */ 226 ret = 2; /* We own it. */
224 else if (owner->pid > 0 227 else if (owner->pid > 0
225 && (kill (owner->pid, 0) >= 0 || errno == EPERM)) 228 && (kill (owner->pid, 0) >= 0 || errno == EPERM))
234 else 237 else
235 { /* If we wanted to support the check for stale locks on remote machines, 238 { /* If we wanted to support the check for stale locks on remote machines,
236 here's where we'd do it. */ 239 here's where we'd do it. */
237 ret = 1; 240 ret = 1;
238 } 241 }
239 242
240 /* Avoid garbage. */ 243 /* Avoid garbage. */
241 if (local_owner || ret <= 0) 244 if (local_owner || ret <= 0)
242 { 245 {
243 FREE_LOCK_INFO (*owner); 246 FREE_LOCK_INFO (*owner);
244 } 247 }
258 { 261 {
259 int locker; 262 int locker;
260 263
261 if (errno != EEXIST) 264 if (errno != EEXIST)
262 return -1; 265 return -1;
263 266
264 locker = current_lock_owner (clasher, lfname); 267 locker = current_lock_owner (clasher, lfname);
265 if (locker == 2) 268 if (locker == 2)
266 { 269 {
267 FREE_LOCK_INFO (*clasher); 270 FREE_LOCK_INFO (*clasher);
268 return 0; /* We ourselves locked it. */ 271 return 0; /* We ourselves locked it. */
297 { 300 {
298 /* This function can GC. */ 301 /* This function can GC. */
299 /* dmoore - and can destroy current_buffer and all sorts of other 302 /* dmoore - and can destroy current_buffer and all sorts of other
300 mean nasty things with pointy teeth. If you call this make sure 303 mean nasty things with pointy teeth. If you call this make sure
301 you protect things right. */ 304 you protect things right. */
302 /* Somebody updated the code in this function and removed the previous 305 /* Somebody updated the code in this function and removed the previous
303 comment. -slb */ 306 comment. -slb */
304 307
305 register Lisp_Object attack, orig_fn; 308 register Lisp_Object attack, orig_fn;
306 register char *lfname, *locker; 309 register char *lfname, *locker;
307 lock_info_type lock_info; 310 lock_info_type lock_info;
321 subject_buf = get_truename_buffer (orig_fn); 324 subject_buf = get_truename_buffer (orig_fn);
322 if (!NILP (subject_buf) 325 if (!NILP (subject_buf)
323 && NILP (Fverify_visited_file_modtime (subject_buf)) 326 && NILP (Fverify_visited_file_modtime (subject_buf))
324 && !NILP (Ffile_exists_p (fn))) 327 && !NILP (Ffile_exists_p (fn)))
325 call1_in_buffer (XBUFFER(subject_buf), 328 call1_in_buffer (XBUFFER(subject_buf),
326 Qask_user_about_supersession_threat, fn); 329 Qask_user_about_supersession_threat, fn);
327 } 330 }
328 331
329 /* Try to lock the lock. */ 332 /* Try to lock the lock. */
330 if (lock_if_free (&lock_info, lfname) <= 0) 333 if (lock_if_free (&lock_info, lfname) <= 0)
331 /* Return now if we have locked it, or if lock creation failed */ 334 /* Return now if we have locked it, or if lock creation failed */
335 locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host) 338 locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host)
336 + LOCK_PID_MAX + 9); 339 + LOCK_PID_MAX + 9);
337 sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host, 340 sprintf (locker, "%s@%s (pid %lu)", lock_info.user, lock_info.host,
338 lock_info.pid); 341 lock_info.pid);
339 FREE_LOCK_INFO (lock_info); 342 FREE_LOCK_INFO (lock_info);
340 343
341 attack = call2_in_buffer (BUFFERP (subject_buf) ? XBUFFER (subject_buf) : 344 attack = call2_in_buffer (BUFFERP (subject_buf) ? XBUFFER (subject_buf) :
342 current_buffer, Qask_user_about_lock , fn, 345 current_buffer, Qask_user_about_lock , fn,
343 build_string (locker)); 346 build_string (locker));
344 if (!NILP (attack)) 347 if (!NILP (attack))
345 /* User says take the lock */ 348 /* User says take the lock */
354 357
355 void 358 void
356 unlock_file (Lisp_Object fn) 359 unlock_file (Lisp_Object fn)
357 { 360 {
358 register char *lfname; 361 register char *lfname;
362 struct gcpro gcpro1;
363
364 GCPRO1 (fn);
359 365
360 fn = Fexpand_file_name (fn, Qnil); 366 fn = Fexpand_file_name (fn, Qnil);
361 367
362 MAKE_LOCK_NAME (lfname, fn); 368 MAKE_LOCK_NAME (lfname, fn);
363 369
364 if (current_lock_owner (0, lfname) == 2) 370 if (current_lock_owner (0, lfname) == 2)
365 unlink (lfname); 371 unlink (lfname);
372
373 UNGCPRO;
366 } 374 }
367 375
368 void 376 void
369 unlock_all_files (void) 377 unlock_all_files (void)
370 { 378 {
371 register Lisp_Object tail; 379 register Lisp_Object tail;
372 register struct buffer *b;
373 380
374 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail)) 381 for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
375 { 382 {
376 b = XBUFFER (XCDR (XCAR (tail))); 383 struct buffer *b = XBUFFER (XCDR (XCAR (tail)));
377 if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) 384 if (STRINGP (b->file_truename) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b))
378 unlock_file (b->file_truename); 385 unlock_file (b->file_truename);
379 } 386 }
380 } 387 }
381 388
382 DEFUN ("lock-buffer", Flock_buffer, 0, 1, 0, /* 389 DEFUN ("lock-buffer", Flock_buffer, 0, 1, 0, /*
383 Lock FILE, if current buffer is modified.\n\ 390 Lock FILE, if current buffer is modified.
384 FILE defaults to current buffer's visited file,\n\ 391 FILE defaults to current buffer's visited file,
385 or else nothing is done if current buffer isn't visiting a file. 392 or else nothing is done if current buffer isn't visiting a file.
386 */ 393 */
387 (file)) 394 (file))
388 { 395 {
389 if (NILP (file)) 396 if (NILP (file))
390 file = current_buffer->file_truename; 397 file = current_buffer->file_truename;
391 CHECK_STRING (file); 398 CHECK_STRING (file);
392 if (BUF_SAVE_MODIFF (current_buffer) < BUF_MODIFF (current_buffer) 399 if (BUF_SAVE_MODIFF (current_buffer) < BUF_MODIFF (current_buffer)
426 && STRINGP (buffer->file_truename)) 433 && STRINGP (buffer->file_truename))
427 unlock_file (buffer->file_truename); 434 unlock_file (buffer->file_truename);
428 } 435 }
429 436
430 DEFUN ("file-locked-p", Ffile_locked_p, 0, 1, 0, /* 437 DEFUN ("file-locked-p", Ffile_locked_p, 0, 1, 0, /*
431 Return nil if the FILENAME is not locked,\n\ 438 Return nil if the FILENAME is not locked,
432 t if it is locked by you, else a string of the name of the locker. 439 t if it is locked by you, else a string of the name of the locker.
433 */ 440 */
434 (filename)) 441 (filename))
435 { 442 {
436 Lisp_Object ret; 443 Lisp_Object ret;
437 register char *lfname; 444 register char *lfname;
438 int owner; 445 int owner;
439 lock_info_type locker; 446 lock_info_type locker;
447 struct gcpro gcpro1;
448
449 GCPRO1 (filename);
440 450
441 filename = Fexpand_file_name (filename, Qnil); 451 filename = Fexpand_file_name (filename, Qnil);
442 452
443 MAKE_LOCK_NAME (lfname, filename); 453 MAKE_LOCK_NAME (lfname, filename);
444 454
451 ret = build_string (locker.user); 461 ret = build_string (locker.user);
452 462
453 if (owner > 0) 463 if (owner > 0)
454 FREE_LOCK_INFO (locker); 464 FREE_LOCK_INFO (locker);
455 465
466 UNGCPRO;
467
456 return ret; 468 return ret;
457 } 469 }
458 470
459 471
460 /* Initialization functions. */ 472 /* Initialization functions. */