ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Urlader/urlader.c
(Generate patch)

Comparing Urlader/urlader.c (file contents):
Revision 1.6 by root, Fri Dec 30 12:21:28 2011 UTC vs.
Revision 1.7 by root, Fri Dec 30 14:51:45 2011 UTC

46 #define u_fsync(handle) FlushFileBuffers (handle) 46 #define u_fsync(handle) FlushFileBuffers (handle)
47 #define u_sync() 47 #define u_sync()
48 48
49 #define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) 49 #define u_lockfile(path) CreateFile (path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)
50 #define u_cloexec(handle) 50 #define u_cloexec(handle)
51 // acquire shared in addition to excl, then unlock excl
52 #define u_lock_write_to_read(wait) u_lock (U_LOCK_READ, 1); u_lock (U_UNLOCK, 1);
53 51
54#else 52#else
55 53
56 #define _GNU_SOURCE 1 54 #define _GNU_SOURCE 1
57 #define _BSD_SOURCE 1 55 #define _BSD_SOURCE 1
58 // the above increases our chances of getting MAP_ANONYMOUS 56 // the above increases our chances of getting MAP_ANONYMOUS
59 57
60 #include <sys/mman.h> 58 #include <sys/mman.h>
61 #include <sys/types.h> 59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <unistd.h>
62 #include <pwd.h> 62 #include <pwd.h>
63 63
64 #if defined (MAP_ANON) && !defined (MAP_ANONYMOUS) 64 #if defined (MAP_ANON) && !defined (MAP_ANONYMOUS)
65 #define MAP_ANONYMOUS MAP_ANON 65 #define MAP_ANONYMOUS MAP_ANON
66 #endif 66 #endif
89 #define u_fsync(handle) 89 #define u_fsync(handle)
90 #define u_sync() sync () 90 #define u_sync() sync ()
91 91
92 #define u_lockfile(path) open (path, O_RDWR | O_CREAT, 0666) 92 #define u_lockfile(path) open (path, O_RDWR | O_CREAT, 0666)
93 #define u_cloexec(handle) fcntl (handle, F_SETFD, FD_CLOEXEC) 93 #define u_cloexec(handle) fcntl (handle, F_SETFD, FD_CLOEXEC)
94 #define u_lock_write_to_read(wait) u_lock (U_LOCK_READ, 1);
95 94
96#endif 95#endif
97 96
98#define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1]) 97#define u_16(ptr) (((ptr)[0] << 8) | (ptr)[1])
99#define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3]) 98#define u_32(ptr) (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3])
216 if (!u_mkdir (tmppath)) 215 if (!u_mkdir (tmppath))
217 return; 216 return;
218 } 217 }
219} 218}
220 219
221enum 220static u_handle
221u_lock (const char *path, int excl, int dowait)
222{ 222{
223 U_UNLOCK, 223 u_handle h;
224 U_LOCK_READ,
225 U_LOCK_WRITE
226};
227 224
228static int 225 h = u_lockfile (path);
229u_lock (int mode, int dowait) 226 if (!u_valid (h))
230{ 227 return h;
231#ifdef _WIN32 228
232 if (mode == U_UNLOCK) 229 u_cloexec (h);
233 return !UnlockFile (lock_handle, 0, 0, 1, 0); 230
234 else 231 for (;;)
235 { 232 {
233 int success;
234
235 // acquire the lock
236#ifdef _WIN32
236 OVERLAPPED ov = { 0 }; 237 OVERLAPPED ov = { 0 };
237 238
238 return !LockFileEx (lock_handle, 239 success = LockFileEx (h,
239 0
240 | (mode == U_LOCK_WRITE ? LOCKFILE_EXCLUSIVE_LOCK : 0) 240 (excl ? LOCKFILE_EXCLUSIVE_LOCK : 0)
241 | (dowait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), 241 | (dowait ? 0 : LOCKFILE_FAIL_IMMEDIATELY),
242 0, 242 0,
243 1, 0, 243 1, 0,
244 &ov); 244 &ov);
245 }
246#else 245#else
247 static short mode2lck [] = { F_UNLCK, F_RDLCK, F_WRLCK };
248 struct flock lck; 246 struct flock lck = { 0 };
249 lck.l_type = mode2lck [mode]; 247
248 lck.l_type = excl ? F_WRLCK : F_RDLCK;
250 lck.l_whence = SEEK_SET; 249 lck.l_whence = SEEK_SET;
251 lck.l_start = 0;
252 lck.l_len = 1; 250 lck.l_len = 1;
253 251
254 return fcntl (lock_handle, dowait ? F_SETLKW : F_SETLK, &lck); 252 success = !fcntl (h, dowait ? F_SETLKW : F_SETLK, &lck);
255#endif 253#endif
254
255 if (!success)
256 break;
257
258 // we have the lock, now verify that the lockfile still exists
259
260#ifdef _WIN32
261 // apparently, we have to open the file to get its info :(
262 BY_HANDLE_FILE_INFORMATION s1, s2;
263 u_handle h2 = u_lockfile (path);
264 if (!u_valid (h))
265 break;
266
267 success = GetFileInformationByHandle (h, &s1)
268 && GetFileInformationByHandle (h2, &s2);
269
270 u_close (h2);
271
272 if (!success)
273 break;
274
275 success = s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber
276 && s1.nFileIndexHigh == s2.nFileIndexHigh
277 && s1.nFileIndexLow == s2.nFileIndexLow;
278#else
279 struct stat s1, s2;
280
281 if (fstat (h, &s1) || stat (path, &s2))
282 break;
283
284 success = s1.st_dev == s2.st_dev
285 && s1.st_ino == s2.st_ino;
286#endif
287
288 if (success)
289 return h; // lock successfully acquired
290
291 // files differ, close and retry - should be very rare
292 u_close (h);
293 }
294
295 // failure
296 u_close (h);
297 return u_invalid_handle;
256} 298}
257 299
258static void 300static void
259systemv (const char *const argv[]) 301systemv (const char *const argv[])
260{ 302{
463 strcpy (execdir, exe_dir); 505 strcpy (execdir, exe_dir);
464 u_append (execdir, "i-"); 506 u_append (execdir, "i-");
465 strcat (execdir, exe_ver); 507 strcat (execdir, exe_ver);
466 508
467 strcat (strcpy (tmppath, execdir), ".lck"); 509 strcat (strcpy (tmppath, execdir), ".lck");
468 lock_handle = u_lockfile (tmppath); 510 lock_handle = u_lock (tmppath, 0, 1);
469 if (!lock_handle) 511 if (!lock_handle)
470 fatal ("unable to create lock file"); 512 fatal ("unable to lock application instance");
471
472 u_cloexec (lock_handle);
473
474 // all users that uee an instance acquire a shared lock
475 // acquiring an exclusive lock is enough to delete the dir
476 // deleeting the lockfile is another topic altogether
477 u_lock (U_LOCK_READ, 1);
478 513
479 if (access (execdir, F_OK)) 514 if (access (execdir, F_OK))
480 { 515 {
481 // does not exist yet, so unpack and move 516 // does not exist yet, so unpack and move
482 tmpdir (exe_dir); 517 tmpdir (exe_dir);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines