Mercurial > hg > xemacs-beta
comparison src/filelock.c @ 771:943eaba38521
[xemacs-hg @ 2002-03-13 08:51:24 by ben]
The big ben-mule-21-5 check-in!
Various files were added and deleted. See CHANGES-ben-mule.
There are still some test suite failures. No crashes, though.
Many of the failures have to do with problems in the test suite itself
rather than in the actual code. I'll be addressing these in the next
day or so -- none of the test suite failures are at all critical.
Meanwhile I'll be trying to address the biggest issues -- i.e. build
or run failures, which will almost certainly happen on various platforms.
All comments should be sent to ben@xemacs.org -- use a Cc: if necessary
when sending to mailing lists. There will be pre- and post- tags,
something like
pre-ben-mule-21-5-merge-in, and
post-ben-mule-21-5-merge-in.
author | ben |
---|---|
date | Wed, 13 Mar 2002 08:54:06 +0000 |
parents | fdefd0186b75 |
children | e38acbeb1cae |
comparison
equal
deleted
inserted
replaced
770:336a418893b5 | 771:943eaba38521 |
---|---|
1 /* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc. | 1 /* Copyright (C) 1985, 86, 87, 93, 94, 96 Free Software Foundation, Inc. |
2 Copyright (C) 2001 Ben Wing. | |
2 | 3 |
3 This file is part of XEmacs. | 4 This file is part of XEmacs. |
4 | 5 |
5 XEmacs is free software; you can redistribute it and/or modify | 6 XEmacs 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 it under the terms of the GNU General Public License as published by |
27 | 28 |
28 #include "sysfile.h" | 29 #include "sysfile.h" |
29 #include "sysdir.h" | 30 #include "sysdir.h" |
30 #include "syspwd.h" | 31 #include "syspwd.h" |
31 #include "syssignal.h" /* for kill */ | 32 #include "syssignal.h" /* for kill */ |
33 #include "sysproc.h" /* for qxe_getpid() */ | |
32 | 34 |
33 Lisp_Object Qask_user_about_supersession_threat; | 35 Lisp_Object Qask_user_about_supersession_threat; |
34 Lisp_Object Qask_user_about_lock; | 36 Lisp_Object Qask_user_about_lock; |
35 int inhibit_clash_detection; | 37 int inhibit_clash_detection; |
36 | 38 |
69 has contributed this implementation for Emacs), and was designed by | 71 has contributed this implementation for Emacs), and was designed by |
70 Ethan Jacobson, Kimbo Mundy, and others. | 72 Ethan Jacobson, Kimbo Mundy, and others. |
71 | 73 |
72 --karl@cs.umb.edu/karl@hq.ileaf.com. */ | 74 --karl@cs.umb.edu/karl@hq.ileaf.com. */ |
73 | 75 |
74 /* Note that muleization is provided by using mule-encapsulated | |
75 versions of the system calls we use like symlink(), unlink(), etc... */ | |
76 | |
77 | 76 |
78 /* Here is the structure that stores information about a lock. */ | 77 /* Here is the structure that stores information about a lock. */ |
79 | 78 |
80 typedef struct | 79 typedef struct |
81 { | 80 { |
82 char *user; | 81 Intbyte *user; |
83 char *host; | 82 Intbyte *host; |
84 pid_t pid; | 83 pid_t pid; |
85 } lock_info_type; | 84 } lock_info_type; |
86 | 85 |
87 /* When we read the info back, we might need this much more, | 86 /* When we read the info back, we might need this much more, |
88 enough for decimal representation plus null. */ | 87 enough for decimal representation plus null. */ |
92 #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) |
93 | 92 |
94 /* 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 |
95 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. */ |
96 #define MAKE_LOCK_NAME(lock, file) \ | 95 #define MAKE_LOCK_NAME(lock, file) \ |
97 (lock = (char *) alloca (XSTRING_LENGTH (file) + 2 + 1), \ | 96 (lock = (Intbyte *) alloca (XSTRING_LENGTH (file) + 2 + 1), \ |
98 fill_in_lock_file_name ((Intbyte *) (lock), (file))) | 97 fill_in_lock_file_name (lock, file)) |
99 | 98 |
100 static void | 99 static void |
101 fill_in_lock_file_name (Intbyte *lockfile, Lisp_Object fn) | 100 fill_in_lock_file_name (Intbyte *lockfile, Lisp_Object fn) |
102 { | 101 { |
103 Intbyte *file_name = XSTRING_DATA (fn); | 102 Intbyte *file_name = XSTRING_DATA (fn); |
120 /* Lock the lock file named LFNAME. | 119 /* Lock the lock file named LFNAME. |
121 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. |
122 Return 1 if successful, 0 if not. */ | 121 Return 1 if successful, 0 if not. */ |
123 | 122 |
124 static int | 123 static int |
125 lock_file_1 (char *lfname, int force) | 124 lock_file_1 (Intbyte *lfname, int force) |
126 { | 125 { |
127 /* Does not GC. */ | 126 /* Does not GC. */ |
128 int err; | 127 int err; |
129 char *lock_info_str; | 128 Intbyte *lock_info_str; |
130 char *host_name; | 129 Intbyte *host_name; |
131 char *user_name = user_login_name (NULL); | 130 Intbyte *user_name = user_login_name (NULL); |
132 | 131 |
133 if (user_name == NULL) | 132 if (user_name == NULL) |
134 user_name = ""; | 133 user_name = (Intbyte *) ""; |
135 | 134 |
136 if (STRINGP (Vsystem_name)) | 135 if (STRINGP (Vsystem_name)) |
137 host_name = (char *) XSTRING_DATA (Vsystem_name); | 136 host_name = XSTRING_DATA (Vsystem_name); |
138 else | 137 else |
139 host_name = ""; | 138 host_name = (Intbyte *) ""; |
140 | 139 |
141 lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) | 140 lock_info_str = |
142 + LOCK_PID_MAX + 5); | 141 (Intbyte *) alloca (qxestrlen (user_name) + qxestrlen (host_name) |
143 | 142 + LOCK_PID_MAX + 5); |
144 sprintf (lock_info_str, "%s@%s.%d", user_name, host_name, getpid ()); | 143 |
145 | 144 qxesprintf (lock_info_str, "%s@%s.%d", user_name, host_name, qxe_getpid ()); |
146 err = symlink (lock_info_str, lfname); | 145 |
146 err = qxe_symlink (lock_info_str, lfname); | |
147 if (err != 0 && errno == EEXIST && force) | 147 if (err != 0 && errno == EEXIST && force) |
148 { | 148 { |
149 unlink (lfname); | 149 qxe_unlink (lfname); |
150 err = symlink (lock_info_str, lfname); | 150 err = qxe_symlink (lock_info_str, lfname); |
151 } | 151 } |
152 | 152 |
153 return err == 0; | 153 return err == 0; |
154 } | 154 } |
155 | 155 |
157 1 if another process owns it (and set OWNER (if non-null) to info), | 157 1 if another process owns it (and set OWNER (if non-null) to info), |
158 2 if the current process owns it, | 158 2 if the current process owns it, |
159 or -1 if something is wrong with the locking mechanism. */ | 159 or -1 if something is wrong with the locking mechanism. */ |
160 | 160 |
161 static int | 161 static int |
162 current_lock_owner (lock_info_type *owner, char *lfname) | 162 current_lock_owner (lock_info_type *owner, Intbyte *lfname) |
163 { | 163 { |
164 /* Does not GC. */ | 164 /* Does not GC. */ |
165 int len, ret; | 165 int len, ret; |
166 int local_owner = 0; | 166 int local_owner = 0; |
167 char *at, *dot; | 167 Intbyte *at, *dot; |
168 char *lfinfo = 0; | 168 Intbyte *lfinfo = 0; |
169 int bufsize = 50; | 169 int bufsize = 50; |
170 /* Read arbitrarily-long contents of symlink. Similar code in | 170 /* Read arbitrarily-long contents of symlink. Similar code in |
171 file-symlink-p in fileio.c. */ | 171 file-symlink-p in fileio.c. */ |
172 do | 172 do |
173 { | 173 { |
174 bufsize *= 2; | 174 bufsize *= 2; |
175 lfinfo = (char *) xrealloc (lfinfo, bufsize); | 175 lfinfo = (Intbyte *) xrealloc (lfinfo, bufsize); |
176 len = readlink (lfname, lfinfo, bufsize); | 176 len = qxe_readlink (lfname, lfinfo, bufsize); |
177 } | 177 } |
178 while (len >= bufsize); | 178 while (len >= bufsize); |
179 | 179 |
180 /* If nonexistent lock file, all is well; otherwise, got strange error. */ | 180 /* If nonexistent lock file, all is well; otherwise, got strange error. */ |
181 if (len == -1) | 181 if (len == -1) |
195 local_owner = 1; | 195 local_owner = 1; |
196 } | 196 } |
197 | 197 |
198 /* Parse USER@HOST.PID. If can't parse, return -1. */ | 198 /* Parse USER@HOST.PID. If can't parse, return -1. */ |
199 /* The USER is everything before the first @. */ | 199 /* The USER is everything before the first @. */ |
200 at = strchr (lfinfo, '@'); | 200 at = qxestrchr (lfinfo, '@'); |
201 dot = strrchr (lfinfo, '.'); | 201 dot = qxestrrchr (lfinfo, '.'); |
202 if (!at || !dot) { | 202 if (!at || !dot) { |
203 xfree (lfinfo); | 203 xfree (lfinfo); |
204 return -1; | 204 return -1; |
205 } | 205 } |
206 len = at - lfinfo; | 206 len = at - lfinfo; |
207 owner->user = (char *) xmalloc (len + 1); | 207 owner->user = (Intbyte *) xmalloc (len + 1); |
208 strncpy (owner->user, lfinfo, len); | 208 qxestrncpy (owner->user, lfinfo, len); |
209 owner->user[len] = 0; | 209 owner->user[len] = 0; |
210 | 210 |
211 /* The PID is everything after the last `.'. */ | 211 /* The PID is everything after the last `.'. */ |
212 owner->pid = atoi (dot + 1); | 212 owner->pid = atoi ((CIntbyte *) dot + 1); |
213 | 213 |
214 /* The host is everything in between. */ | 214 /* The host is everything in between. */ |
215 len = dot - at - 1; | 215 len = dot - at - 1; |
216 owner->host = (char *) xmalloc (len + 1); | 216 owner->host = (Intbyte *) xmalloc (len + 1); |
217 strncpy (owner->host, at + 1, len); | 217 qxestrncpy (owner->host, at + 1, len); |
218 owner->host[len] = 0; | 218 owner->host[len] = 0; |
219 | 219 |
220 /* We're done looking at the link info. */ | 220 /* We're done looking at the link info. */ |
221 xfree (lfinfo); | 221 xfree (lfinfo); |
222 | 222 |
223 /* On current host? */ | 223 /* On current host? */ |
224 if (STRINGP (Fsystem_name ()) | 224 if (STRINGP (Fsystem_name ()) |
225 && strcmp (owner->host, (char *) XSTRING_DATA (Fsystem_name ())) == 0) | 225 && qxestrcmp (owner->host, XSTRING_DATA (Fsystem_name ())) == 0) |
226 { | 226 { |
227 if (owner->pid == getpid ()) | 227 if (owner->pid == qxe_getpid ()) |
228 ret = 2; /* We own it. */ | 228 ret = 2; /* We own it. */ |
229 else if (owner->pid > 0 | 229 else if (owner->pid > 0 |
230 && (kill (owner->pid, 0) >= 0 || errno == EPERM)) | 230 && (kill (owner->pid, 0) >= 0 || errno == EPERM)) |
231 ret = 1; /* An existing process on this machine owns it. */ | 231 ret = 1; /* An existing process on this machine owns it. */ |
232 /* The owner process is dead or has a strange pid (<=0), so try to | 232 /* The owner process is dead or has a strange pid (<=0), so try to |
233 zap the lockfile. */ | 233 zap the lockfile. */ |
234 else if (unlink (lfname) < 0) | 234 else if (qxe_unlink (lfname) < 0) |
235 ret = -1; | 235 ret = -1; |
236 else | 236 else |
237 ret = 0; | 237 ret = 0; |
238 } | 238 } |
239 else | 239 else |
255 Return positive if some other process owns the lock, and info about | 255 Return positive if some other process owns the lock, and info about |
256 that process in CLASHER. | 256 that process in CLASHER. |
257 Return -1 if cannot lock for any other reason. */ | 257 Return -1 if cannot lock for any other reason. */ |
258 | 258 |
259 static int | 259 static int |
260 lock_if_free (lock_info_type *clasher, char *lfname) | 260 lock_if_free (lock_info_type *clasher, Intbyte *lfname) |
261 { | 261 { |
262 /* Does not GC. */ | 262 /* Does not GC. */ |
263 if (lock_file_1 (lfname, 0) == 0) | 263 if (lock_file_1 ((Intbyte *) lfname, 0) == 0) |
264 { | 264 { |
265 int locker; | 265 int locker; |
266 | 266 |
267 if (errno != EEXIST) | 267 if (errno != EEXIST) |
268 return -1; | 268 return -1; |
307 you protect things right. */ | 307 you protect things right. */ |
308 /* Somebody updated the code in this function and removed the previous | 308 /* Somebody updated the code in this function and removed the previous |
309 comment. -slb */ | 309 comment. -slb */ |
310 | 310 |
311 register Lisp_Object attack, orig_fn; | 311 register Lisp_Object attack, orig_fn; |
312 register char *lfname, *locker; | 312 register Intbyte *lfname, *locker; |
313 lock_info_type lock_info; | 313 lock_info_type lock_info; |
314 struct gcpro gcpro1, gcpro2, gcpro3; | 314 struct gcpro gcpro1, gcpro2, gcpro3; |
315 Lisp_Object old_current_buffer; | 315 Lisp_Object old_current_buffer; |
316 Lisp_Object subject_buf; | 316 Lisp_Object subject_buf; |
317 | 317 |
344 /* Return now if we have locked it, or if lock creation failed | 344 /* Return now if we have locked it, or if lock creation failed |
345 or current buffer is killed. */ | 345 or current buffer is killed. */ |
346 goto done; | 346 goto done; |
347 | 347 |
348 /* Else consider breaking the lock */ | 348 /* Else consider breaking the lock */ |
349 locker = (char *) alloca (strlen (lock_info.user) + strlen (lock_info.host) | 349 locker = (Intbyte *) alloca (qxestrlen (lock_info.user) |
350 + LOCK_PID_MAX + 9); | 350 + qxestrlen (lock_info.host) |
351 sprintf (locker, "%s@%s (pid %d)", lock_info.user, lock_info.host, | 351 + LOCK_PID_MAX + 9); |
352 lock_info.pid); | 352 qxesprintf (locker, "%s@%s (pid %d)", lock_info.user, lock_info.host, |
353 lock_info.pid); | |
353 FREE_LOCK_INFO (lock_info); | 354 FREE_LOCK_INFO (lock_info); |
354 | 355 |
355 attack = call2_in_buffer (BUFFERP (subject_buf) ? XBUFFER (subject_buf) : | 356 attack = call2_in_buffer (BUFFERP (subject_buf) ? XBUFFER (subject_buf) : |
356 current_buffer, Qask_user_about_lock , fn, | 357 current_buffer, Qask_user_about_lock , fn, |
357 build_string (locker)); | 358 build_intstring (locker)); |
358 if (!NILP (attack) && current_buffer == XBUFFER (old_current_buffer)) | 359 if (!NILP (attack) && current_buffer == XBUFFER (old_current_buffer)) |
359 /* User says take the lock */ | 360 /* User says take the lock */ |
360 { | 361 { |
361 lock_file_1 (lfname, 1); | 362 lock_file_1 (lfname, 1); |
362 goto done; | 363 goto done; |
368 | 369 |
369 void | 370 void |
370 unlock_file (Lisp_Object fn) | 371 unlock_file (Lisp_Object fn) |
371 { | 372 { |
372 /* This can GC */ | 373 /* This can GC */ |
373 register char *lfname; | 374 register Intbyte *lfname; |
374 struct gcpro gcpro1; | 375 struct gcpro gcpro1; |
375 | 376 |
376 GCPRO1 (fn); | 377 GCPRO1 (fn); |
377 | 378 |
378 fn = Fexpand_file_name (fn, Qnil); | 379 fn = Fexpand_file_name (fn, Qnil); |
379 | 380 |
380 MAKE_LOCK_NAME (lfname, fn); | 381 MAKE_LOCK_NAME (lfname, fn); |
381 | 382 |
382 if (current_lock_owner (0, lfname) == 2) | 383 if (current_lock_owner (0, lfname) == 2) |
383 unlink (lfname); | 384 qxe_unlink (lfname); |
384 | 385 |
385 UNGCPRO; | 386 UNGCPRO; |
386 } | 387 } |
387 | 388 |
388 void | 389 void |
451 t if it is locked by you, else a string of the name of the locker. | 452 t if it is locked by you, else a string of the name of the locker. |
452 */ | 453 */ |
453 (filename)) | 454 (filename)) |
454 { | 455 { |
455 Lisp_Object ret; | 456 Lisp_Object ret; |
456 register char *lfname; | 457 register Intbyte *lfname; |
457 int owner; | 458 int owner; |
458 lock_info_type locker; | 459 lock_info_type locker; |
459 struct gcpro gcpro1; | 460 struct gcpro gcpro1; |
460 | 461 |
461 GCPRO1 (filename); | 462 GCPRO1 (filename); |
468 if (owner <= 0) | 469 if (owner <= 0) |
469 ret = Qnil; | 470 ret = Qnil; |
470 else if (owner == 2) | 471 else if (owner == 2) |
471 ret = Qt; | 472 ret = Qt; |
472 else | 473 else |
473 ret = build_string (locker.user); | 474 ret = build_intstring (locker.user); |
474 | 475 |
475 if (owner > 0) | 476 if (owner > 0) |
476 FREE_LOCK_INFO (locker); | 477 FREE_LOCK_INFO (locker); |
477 | 478 |
478 UNGCPRO; | 479 UNGCPRO; |