1 /* dotlock.c - dotfile locking
2 * Copyright (C) 1998, 2000, 2001, 2003, 2004,
3 * 2005, 2006, 2008, 2010, 2011 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify it
8 * under the terms of either
10 * - the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at
12 * your option) any later version.
16 * - the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
20 * or both in parallel, as here.
22 * GnuPG is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
27 * You should have received a copies of the GNU General Public License
28 * and the GNU Lesser General Public License along with this program;
29 * if not, see <https://www.gnu.org/licenses/>.
31 * ALTERNATIVELY, this file may be distributed under the terms of the
32 * following license, in which case the provisions of this license are
33 * required INSTEAD OF the GNU Lesser General License or the GNU
34 * General Public License. If you wish to allow use of your version of
35 * this file only under the terms of the GNU Lesser General License or
36 * the GNU General Public License, and not to allow others to use your
37 * version of this file under the terms of the following license,
38 * indicate your decision by deleting this paragraph and the license
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
45 * 1. Redistributions of source code must retain the above copyright
46 * notice, and the entire permission notice in its entirety,
47 * including the disclaimer of warranties.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote
52 * products derived from this software without specific prior
55 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
56 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
57 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
58 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
59 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
60 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
61 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
63 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
65 * OF THE POSSIBILITY OF SUCH DAMAGE.
72 This module implements advisory file locking in a portable way.
73 Due to the problems with POSIX fcntl locking a separate lock file
74 is used. It would be possible to use fcntl locking on this lock
75 file and thus avoid the weird auto unlock bug of POSIX while still
76 having an unproved better performance of fcntl locking. However
77 there are still problems left, thus we resort to use a hardlink
78 which has the well defined property that a link call will fail if
79 the target file already exists.
81 Given that hardlinks are also available on NTFS file systems since
82 Windows XP; it will be possible to enhance this module to use
83 hardlinks even on Windows and thus allow Windows and Posix clients
84 to use locking on the same directory. This is not yet implemented;
85 instead we use a lockfile on Windows along with W32 style file
88 On FAT file systems hardlinks are not supported. Thus this method
89 does not work. Our solution is to use a O_EXCL locking instead.
90 Querying the type of the file system is not easy to do in a
91 portable way (e.g. Linux has a statfs, BSDs have a the same call
92 but using different structures and constants). What we do instead
93 is to check at runtime whether link(2) works for a specific lock
100 At program initialization time, the module should be explicitly
103 dotlock_create (NULL, 0);
105 This installs an atexit handler and may also initialize mutex etc.
106 It is optional for non-threaded applications. Only the first call
107 has an effect. This needs to be done before any extra threads are
110 To create a lock file (which prepares it but does not take the
115 h = dotlock_create (fname, 0);
117 error ("error creating lock file: %s\n", strerror (errno));
119 It is important to handle the error. For example on a read-only
120 file system a lock can't be created (but is usually not needed).
121 FNAME is the file you want to lock; the actual lockfile is that
122 name with the suffix ".lock" appended. On success a handle to be
123 used with the other functions is returned or NULL on error. Note
124 that the handle shall only be used by one thread at a time. This
125 function creates a unique file temporary file (".#lk*") in the same
126 directory as FNAME and returns a handle for further operations.
127 The module keeps track of theses unique files so that they will be
128 unlinked using the atexit handler. If you don't need the lock file
129 anymore, you may also explicitly remove it with a call to:
133 To actually lock the file, you use:
135 if (dotlock_take (h, -1))
136 error ("error taking lock: %s\n", strerror (errno));
138 This function will wait until the lock is acquired. If an
139 unexpected error occurs if will return non-zero and set ERRNO. If
140 you pass (0) instead of (-1) the function does not wait in case the
141 file is already locked but returns -1 and sets ERRNO to EACCES.
142 Any other positive value for the second parameter is considered a
143 timeout valuie in milliseconds.
145 To release the lock you call:
147 if (dotlock_release (h))
148 error ("error releasing lock: %s\n", strerror (errno));
150 or, if the lock file is not anymore needed, you may just call
151 dotlock_destroy. However dotlock_release does some extra checks
152 before releasing the lock and prints diagnostics to help detecting
155 If you want to explicitly destroy all lock files you may call
157 dotlock_remove_lockfiles ();
159 which is the core of the installed atexit handler. In case your
160 application wants to disable locking completely it may call
164 before any locks are created.
166 There are two convenience functions to store an integer (e.g. a
167 file descriptor) value with the handle:
169 void dotlock_set_fd (dotlock_t h, int fd);
170 int dotlock_get_fd (dotlock_t h);
172 If nothing has been stored dotlock_get_fd returns -1.
179 This module was originally developed for GnuPG but later changed to
180 allow its use without any GnuPG dependency. If you want to use it
181 with you application you may simply use it and it should figure out
182 most things automagically.
184 You may use the common config.h file to pass macros, but take care
185 to pass -DHAVE_CONFIG_H to the compiler. Macros used by this
188 DOTLOCK_USE_PTHREAD - Define if POSIX threads are in use.
190 DOTLOCK_GLIB_LOGGING - Define this to use Glib logging functions.
192 DOTLOCK_EXT_SYM_PREFIX - Prefix all external symbols with the
193 string to which this macro evaluates.
195 GNUPG_MAJOR_VERSION - Defined when used by GnuPG.
197 HAVE_DOSISH_SYSTEM - Defined for Windows etc. Will be
198 automatically defined if a the target is
201 HAVE_POSIX_SYSTEM - Internally defined to !HAVE_DOSISH_SYSTEM.
203 HAVE_SIGNAL_H - Should be defined on Posix systems. If config.h
204 is not used defaults to defined.
206 DIRSEP_C - Separation character for file name parts.
207 Usually not redefined.
209 EXTSEP_S - Separation string for file name suffixes.
210 Usually not redefined.
212 HAVE_W32CE_SYSTEM - Currently only used by GnuPG.
214 Note that there is a test program t-dotlock which has compile
215 instructions at its end. At least for SMBFS and CIFS it is
216 important that 64 bit versions of stat are used; most programming
217 environments do this these days, just in case you want to compile
218 it on the command line, remember to pass -D_FILE_OFFSET_BITS=64
224 On Windows this module is not yet thread-safe.
231 - Hardlinks are supported under Windows with NTFS since XP/Server2003.
232 - In Linux 2.6.33 both SMBFS and CIFS seem to support hardlinks.
233 - NFS supports hard links. But there are solvable problems.
234 - FAT does not support links
236 On the file locking API:
237 - CIFS on Linux 2.6.33 supports several locking methods.
238 SMBFS seems not to support locking. No closer checks done.
239 - NFS supports Posix locks. flock is emulated in the server.
240 However there are a couple of problems; see below.
241 - FAT does not support locks.
242 - An advantage of fcntl locking is that R/W locks can be
243 implemented which is not easy with a straight lock file.
246 - Does not work reliable on NFS
247 - Should work on CIFS and SMBFS but how can we delete lockfiles?
250 - Locks vanish if the server crashes and reboots.
251 - Client crashes keep the lock in the server until the client
253 - Communication problems may return unreliable error codes. The
254 MUA Postfix's workaround is to compare the link count after
255 seeing an error for link. However that gives a race. If using a
256 unique file to link to a lockfile and using stat to check the
257 link count instead of looking at the error return of link(2) is
259 - O_EXCL seems to have a race and may re-create a file anyway.
267 /* Some quick replacements for stuff we usually expect to be defined
268 in config.h. Define HAVE_POSIX_SYSTEM for better readability. */
269 #if !defined (HAVE_DOSISH_SYSTEM) && defined(_WIN32)
270 # define HAVE_DOSISH_SYSTEM 1
272 #if !defined (HAVE_DOSISH_SYSTEM) && !defined (HAVE_POSIX_SYSTEM)
273 # define HAVE_POSIX_SYSTEM 1
276 /* With no config.h assume that we have sitgnal.h. */
277 #if !defined (HAVE_CONFIG_H) && defined (HAVE_POSIX_SYSTEM)
278 # define HAVE_SIGNAL_H 1
281 /* Standard headers. */
289 #ifdef HAVE_DOSISH_SYSTEM
290 # define WIN32_LEAN_AND_MEAN /* We only need the OS core stuff. */
291 # include <windows.h>
293 # include <sys/types.h>
294 # include <sys/stat.h>
295 # include <sys/utsname.h>
297 #include <sys/types.h>
298 #include <sys/time.h>
299 #include <sys/stat.h>
304 #ifdef DOTLOCK_USE_PTHREAD
305 # include <pthread.h>
308 #ifdef DOTLOCK_GLIB_LOGGING
312 #ifdef GNUPG_MAJOR_VERSION
314 # include "common-defs.h"
315 # include "stringhelp.h" /* For stpcpy and w32_strerror. */
317 #ifdef HAVE_W32CE_SYSTEM
318 # include "utf8conv.h" /* WindowsCE requires filename conversion. */
324 /* Define constants for file name construction. */
325 #if !defined(DIRSEP_C) && !defined(EXTSEP_S)
326 # ifdef HAVE_DOSISH_SYSTEM
327 # define DIRSEP_C '\\'
328 # define EXTSEP_S "."
330 # define DIRSEP_C '/'
331 # define EXTSEP_S "."
335 /* In GnuPG we use wrappers around the malloc fucntions. If they are
336 not defined we assume that this code is used outside of GnuPG and
337 fall back to the regular malloc functions. */
339 # define xtrymalloc(a) malloc ((a))
340 # define xtrycalloc(a,b) calloc ((a), (b))
341 # define xfree(a) free ((a))
344 /* Wrapper to set ERRNO (required for W32CE). */
345 #ifdef GPG_ERROR_VERSION
346 # define my_set_errno(e) gpg_err_set_errno ((e))
348 # define my_set_errno(e) do { errno = (e); } while (0)
351 /* Gettext macro replacement. */
356 #ifdef GNUPG_MAJOR_VERSION
357 # define my_info_0(a) log_info ((a))
358 # define my_info_1(a,b) log_info ((a), (b))
359 # define my_info_2(a,b,c) log_info ((a), (b), (c))
360 # define my_info_3(a,b,c,d) log_info ((a), (b), (c), (d))
361 # define my_error_0(a) log_error ((a))
362 # define my_error_1(a,b) log_error ((a), (b))
363 # define my_error_2(a,b,c) log_error ((a), (b), (c))
364 # define my_debug_1(a,b) log_debug ((a), (b))
365 # define my_fatal_0(a) log_fatal ((a))
366 #elif defined (DOTLOCK_GLIB_LOGGING)
367 # define my_info_0(a) g_message ((a))
368 # define my_info_1(a,b) g_message ((a), (b))
369 # define my_info_2(a,b,c) g_message ((a), (b), (c))
370 # define my_info_3(a,b,c,d) g_message ((a), (b), (c), (d))
371 # define my_error_0(a) g_warning ((a))
372 # define my_error_1(a,b) g_warning ((a), (b))
373 # define my_error_2(a,b,c) g_warning ((a), (b), (c))
374 # define my_debug_1(a,b) g_debug ((a), (b))
375 # define my_fatal_0(a) g_error ((a))
377 # define my_info_0(a) fprintf (stderr, (a))
378 # define my_info_1(a,b) fprintf (stderr, (a), (b))
379 # define my_info_2(a,b,c) fprintf (stderr, (a), (b), (c))
380 # define my_info_3(a,b,c,d) fprintf (stderr, (a), (b), (c), (d))
381 # define my_error_0(a) fprintf (stderr, (a))
382 # define my_error_1(a,b) fprintf (stderr, (a), (b))
383 # define my_error_2(a,b,c) fprintf (stderr, (a), (b), (c))
384 # define my_debug_1(a,b) fprintf (stderr, (a), (b))
385 # define my_fatal_0(a) do { fprintf (stderr,(a)); fflush (stderr); \
386 abort (); } while (0)
393 /* The object describing a lock. */
394 struct dotlock_handle
396 struct dotlock_handle *next;
397 char *lockname; /* Name of the actual lockfile. */
398 unsigned int locked:1; /* Lock status. */
399 unsigned int disable:1; /* If true, locking is disabled. */
400 unsigned int use_o_excl:1; /* Use open (O_EXCL) for locking. */
402 int extra_fd; /* A place for the caller to store an FD. */
404 #ifdef HAVE_DOSISH_SYSTEM
405 HANDLE lockhd; /* The W32 handle of the lock file. */
406 #else /*!HAVE_DOSISH_SYSTEM */
407 char *tname; /* Name of the lockfile template. */
408 size_t nodename_off; /* Offset in TNAME of the nodename part. */
409 size_t nodename_len; /* Length of the nodename part. */
410 #endif /*!HAVE_DOSISH_SYSTEM */
414 /* A list of of all lock handles. The volatile attribute might help
415 if used in an atexit handler. Note that [UN]LOCK_all_lockfiles
416 must not change ERRNO. */
417 static volatile dotlock_t all_lockfiles;
418 #ifdef DOTLOCK_USE_PTHREAD
419 static pthread_mutex_t all_lockfiles_mutex = PTHREAD_MUTEX_INITIALIZER;
420 # define LOCK_all_lockfiles() do { \
421 if (pthread_mutex_lock (&all_lockfiles_mutex)) \
422 my_fatal_0 ("locking all_lockfiles_mutex failed\n"); \
424 # define UNLOCK_all_lockfiles() do { \
425 if (pthread_mutex_unlock (&all_lockfiles_mutex)) \
426 my_fatal_0 ("unlocking all_lockfiles_mutex failed\n"); \
428 #else /*!DOTLOCK_USE_PTHREAD*/
429 # define LOCK_all_lockfiles() do { } while (0)
430 # define UNLOCK_all_lockfiles() do { } while (0)
431 #endif /*!DOTLOCK_USE_PTHREAD*/
433 /* If this has the value true all locking is disabled. */
434 static int never_lock;
439 #ifdef HAVE_DOSISH_SYSTEM
441 map_w32_to_errno (DWORD w32_err)
448 case ERROR_FILE_NOT_FOUND:
451 case ERROR_PATH_NOT_FOUND:
454 case ERROR_ACCESS_DENIED:
457 case ERROR_INVALID_HANDLE:
458 case ERROR_INVALID_BLOCK:
461 case ERROR_NOT_ENOUGH_MEMORY:
465 case ERROR_BROKEN_PIPE:
472 #endif /*HAVE_DOSISH_SYSTEM*/
474 #define DLOG(h, m, ...) do{ \
475 dotlock_t DLOG_h = (h); \
476 int DLOG_se = errno; \
478 log_debug("dotlock %p %s " m, (DLOG_h), \
479 !(DLOG_h) ? "(none)" : \
480 !(DLOG_h)->lockname ? "(null)" : \
481 (DLOG_h)->lockname, \
487 /* Entirely disable all locking. This function should be called
488 before any locking is done. It may be called right at startup of
489 the process as it only sets a global value. */
491 dotlock_disable (void)
493 DLOG(0, "dotlock_disable\n");
498 #ifdef HAVE_POSIX_SYSTEM
500 maybe_deadlock (dotlock_t h)
505 DLOG(h, "maybe_deadlock\n");
507 LOCK_all_lockfiles ();
508 for (r=all_lockfiles; r; r = r->next)
510 if ( r != h && r->locked )
516 UNLOCK_all_lockfiles ();
519 #endif /*HAVE_POSIX_SYSTEM*/
522 /* Read the lock file and return the pid, returns -1 on error. True
523 will be stored in the integer at address SAME_NODE if the lock file
524 has been created on the same node. */
525 #ifdef HAVE_POSIX_SYSTEM
527 read_lockfile (dotlock_t h, int *same_node )
529 char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
530 names are usually shorter. */
537 DLOG(h, "read_lockfile()\n");
540 expected_len = 10 + 1 + h->nodename_len + 1;
541 if ( expected_len >= sizeof buffer_space)
543 buffer = xtrymalloc (expected_len);
548 buffer = buffer_space;
550 if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
553 my_info_2 ("error opening lockfile '%s': %s\n",
554 h->lockname, strerror(errno) );
555 if (buffer != buffer_space)
557 my_set_errno (e); /* Need to return ERRNO here. */
565 res = read (fd, p, expected_len - nread);
566 if (res == -1 && errno == EINTR)
571 my_info_1 ("error reading lockfile '%s'\n", h->lockname );
573 if (buffer != buffer_space)
581 while (res && nread != expected_len);
586 my_info_1 ("invalid size of lockfile '%s'\n", h->lockname);
587 if (buffer != buffer_space)
589 my_set_errno (EINVAL);
593 if (buffer[10] != '\n'
594 || (buffer[10] = 0, pid = atoi (buffer)) == -1
597 my_error_2 ("invalid pid %d in lockfile '%s'\n", pid, h->lockname);
598 if (buffer != buffer_space)
600 my_set_errno (EINVAL);
604 if (nread == expected_len
605 && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
606 && buffer[11+h->nodename_len] == '\n')
609 if (buffer != buffer_space)
611 DLOG(h, "read_lockfile(%d) = %ld\n", *same_node, (long)pid);
614 #endif /*HAVE_POSIX_SYSTEM */
617 /* Check whether the file system which stores TNAME supports
618 hardlinks. Instead of using the non-portable statsfs call which
619 differs between various Unix versions, we do a runtime test.
620 Returns: 0 supports hardlinks; 1 no hardlink support, -1 unknown
622 #ifdef HAVE_POSIX_SYSTEM
624 use_hardlinks_p (const char *tname)
631 DLOG(0, "use_hardlinks_p(%s)\n", tname);
633 if (stat (tname, &sb))
635 nlink = (unsigned int)sb.st_nlink;
637 lname = xtrymalloc (strlen (tname) + 1 + 1);
640 strcpy (lname, tname);
643 /* We ignore the return value of link() because it is unreliable. */
644 (void) link (tname, lname);
646 if (stat (tname, &sb))
647 res = -1; /* Ooops. */
648 else if (sb.st_nlink == nlink + 1)
649 res = 0; /* Yeah, hardlinks are supported. */
651 res = 1; /* No hardlink support. */
656 DLOG(0, "use_hardlinks_p(%s) = %d\n", tname, res);
659 #endif /*HAVE_POSIX_SYSTEM */
663 #ifdef HAVE_POSIX_SYSTEM
664 /* Locking core for Unix. It used a temporary file and the link
665 system call to make locking an atomic operation. */
667 dotlock_create_unix (dotlock_t h, const char *file_to_lock)
671 const char *nodename;
674 struct utsname utsbuf;
677 DLOG(h, "dotlock_create_unix(%s)...\n", file_to_lock);
679 snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );
681 /* Create a temporary file. */
682 if ( uname ( &utsbuf ) )
683 nodename = "unknown";
685 nodename = utsbuf.nodename;
687 if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
694 dirpartlen = dirpart - file_to_lock;
695 dirpart = file_to_lock;
698 LOCK_all_lockfiles ();
699 h->next = all_lockfiles;
702 tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10 + 1;
703 h->tname = xtrymalloc (tnamelen + 1);
706 all_lockfiles = h->next;
707 UNLOCK_all_lockfiles ();
709 DLOG(h, "dotlock_create_unix()=0 (!xtrymalloc)\n");
712 h->nodename_len = strlen (nodename);
714 snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
715 h->nodename_off = strlen (h->tname);
716 snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
717 "%s.%d", nodename, (int)getpid ());
719 DLOG(h, "dotlock_create_unix() open...\n");
723 fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
724 S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
726 while (fd == -1 && errno == EINTR);
727 DLOG(h, "dotlock_create_unix() open=%d...\n", fd);
731 int saveerrno = errno;
732 all_lockfiles = h->next;
733 UNLOCK_all_lockfiles ();
734 my_error_2 (_("failed to create temporary file '%s': %s\n"),
735 h->tname, strerror (errno));
738 my_set_errno (saveerrno);
739 DLOG(h, "dotlock_create_unix()=0 (fd=-1) E=%d\n",errno);
742 if ( write (fd, pidstr, 11 ) != 11 )
744 if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) )
746 if ( write (fd, "\n", 1 ) != 1 )
750 if ( errno == EINTR )
756 /* Check whether we support hard links. */
757 switch (use_hardlinks_p (h->tname))
767 int saveerrno = errno;
768 my_error_2 ("can't check whether hardlinks are supported for '%s': %s\n"
769 , h->tname, strerror (saveerrno));
770 my_set_errno (saveerrno);
775 h->lockname = xtrymalloc (strlen (file_to_lock) + 6 );
778 int saveerrno = errno;
779 all_lockfiles = h->next;
780 UNLOCK_all_lockfiles ();
784 my_set_errno (saveerrno);
785 DLOG(h, "dotlock_create_unix()=0 (!lockname) E=%d\n",errno);
788 strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
789 UNLOCK_all_lockfiles ();
791 my_debug_1 ("locking for '%s' done via O_EXCL\n", h->lockname);
793 DLOG(h, "dotlock_create_unix()=%p\n", h);
798 int saveerrno = errno;
799 all_lockfiles = h->next;
800 UNLOCK_all_lockfiles ();
801 my_error_2 (_("error writing to '%s': %s\n"), h->tname, strerror (errno));
807 my_set_errno (saveerrno);
809 DLOG(h, "dotlock_create_unix()=0 (write_failed) E=%d\n",errno);
812 #endif /*HAVE_POSIX_SYSTEM*/
815 #ifdef HAVE_DOSISH_SYSTEM
816 /* Locking core for Windows. This version does not need a temporary
817 file but uses the plain lock file along with record locking. We
818 create this file here so that we later only need to do the file
819 locking. For error reporting it is useful to keep the name of the
820 file in the handle. */
822 dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
824 LOCK_all_lockfiles ();
825 h->next = all_lockfiles;
828 h->lockname = xtrymalloc ( strlen (file_to_lock) + 6 );
831 all_lockfiles = h->next;
832 UNLOCK_all_lockfiles ();
836 strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
838 /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
839 along with FILE_SHARE_DELETE but that does not work due to a race
840 condition: Despite the OPEN_ALWAYS flag CreateFile may return an
841 error and we can't reliable create/open the lock file unless we
842 would wait here until it works - however there are other valid
843 reasons why a lock file can't be created and thus the process
844 would not stop as expected but spin until Windows crashes. Our
845 solution is to keep the lock file open; that does not harm. */
847 #ifdef HAVE_W32CE_SYSTEM
848 wchar_t *wname = utf8_to_wchar (h->lockname);
851 h->lockhd = CreateFile (wname,
852 GENERIC_READ|GENERIC_WRITE,
853 FILE_SHARE_READ|FILE_SHARE_WRITE,
854 NULL, OPEN_ALWAYS, 0, NULL);
856 h->lockhd = INVALID_HANDLE_VALUE;
859 h->lockhd = CreateFile (h->lockname,
860 GENERIC_READ|GENERIC_WRITE,
861 FILE_SHARE_READ|FILE_SHARE_WRITE,
862 NULL, OPEN_ALWAYS, 0, NULL);
865 if (h->lockhd == INVALID_HANDLE_VALUE)
867 int saveerrno = map_w32_to_errno (GetLastError ());
868 all_lockfiles = h->next;
869 UNLOCK_all_lockfiles ();
870 my_error_2 (_("can't create '%s': %s\n"), h->lockname, w32_strerror (-1));
873 my_set_errno (saveerrno);
878 #endif /*HAVE_DOSISH_SYSTEM*/
881 /* Create a lockfile for a file name FILE_TO_LOCK and returns an
882 object of type dotlock_t which may be used later to actually acquire
883 the lock. A cleanup routine gets installed to cleanup left over
884 locks or other files used internally by the lock mechanism.
886 Calling this function with NULL does only install the atexit
887 handler and may thus be used to assure that the cleanup is called
888 after all other atexit handlers.
890 This function creates a lock file in the same directory as
891 FILE_TO_LOCK using that name and a suffix of ".lock". Note that on
892 POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
897 The function returns an new handle which needs to be released using
898 destroy_dotlock but gets also released at the termination of the
899 process. On error NULL is returned.
903 dotlock_create (const char *file_to_lock, unsigned int flags)
905 static int initialized;
910 atexit (dotlock_remove_lockfiles);
915 return NULL; /* Only initialization was requested. */
919 my_set_errno (EINVAL);
923 h = xtrycalloc (1, sizeof *h);
931 LOCK_all_lockfiles ();
932 h->next = all_lockfiles;
934 UNLOCK_all_lockfiles ();
938 #ifdef HAVE_DOSISH_SYSTEM
939 return dotlock_create_w32 (h, file_to_lock);
940 #else /*!HAVE_DOSISH_SYSTEM */
941 return dotlock_create_unix (h, file_to_lock);
942 #endif /*!HAVE_DOSISH_SYSTEM*/
947 /* Convenience function to store a file descriptor (or any any other
948 integer value) in the context of handle H. */
950 dotlock_set_fd (dotlock_t h, int fd)
955 /* Convenience function to retrieve a file descriptor (or any any other
956 integer value) stored in the context of handle H. */
958 dotlock_get_fd (dotlock_t h)
965 #ifdef HAVE_POSIX_SYSTEM
966 /* Unix specific code of destroy_dotlock. */
968 dotlock_destroy_unix (dotlock_t h)
970 DLOG(h, "dotlock_destroy_unix() locked=%d lockname=%s tname=%s\n",
972 h->lockname ? h->lockname : "(null)",
973 h->tname ? h->tname : "(null)");
974 if (h->locked && h->lockname)
975 unlink (h->lockname);
976 if (h->tname && !h->use_o_excl)
980 #endif /*HAVE_POSIX_SYSTEM*/
983 #ifdef HAVE_DOSISH_SYSTEM
984 /* Windows specific code of destroy_dotlock. */
986 dotlock_destroy_w32 (dotlock_t h)
992 memset (&ovl, 0, sizeof ovl);
993 UnlockFileEx (h->lockhd, 0, 1, 0, &ovl);
995 CloseHandle (h->lockhd);
997 #endif /*HAVE_DOSISH_SYSTEM*/
1000 /* Destroy the lock handle H and release the lock. */
1002 dotlock_destroy (dotlock_t h)
1004 dotlock_t hprev, htmp;
1006 DLOG(h, "dotlock_destroy()\n");
1010 /* First remove the handle from our global list of all locks. */
1011 LOCK_all_lockfiles ();
1012 for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
1016 hprev->next = htmp->next;
1018 all_lockfiles = htmp->next;
1022 UNLOCK_all_lockfiles ();
1024 /* Then destroy the lock. */
1027 #ifdef HAVE_DOSISH_SYSTEM
1028 dotlock_destroy_w32 (h);
1029 #else /* !HAVE_DOSISH_SYSTEM */
1030 dotlock_destroy_unix (h);
1031 #endif /* HAVE_DOSISH_SYSTEM */
1032 xfree (h->lockname);
1039 #ifdef HAVE_POSIX_SYSTEM
1040 /* Unix specific code of make_dotlock. Returns 0 on success and -1 on
1043 dotlock_take_unix (dotlock_t h, long timeout)
1050 const char *maybe_dead="";
1054 DLOG(h, "dotlock_create_unix(timeout=%ld) ...\n", timeout);
1059 /* No hardlink support - use open(O_EXCL). */
1062 DLOG(h, "dotlock_take_unix() open...\n");
1066 fd = open (h->lockname, O_WRONLY|O_CREAT|O_EXCL,
1067 S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
1069 while (fd == -1 && errno == EINTR);
1070 DLOG(h, "dotlock_take_unix() open=%d E=%d...\n",fd,errno);
1072 if (fd == -1 && errno == EEXIST)
1073 ; /* Lock held by another process. */
1077 my_error_2 ("lock not made: open(O_EXCL) of '%s' failed: %s\n",
1078 h->lockname, strerror (saveerrno));
1079 my_set_errno (saveerrno);
1080 DLOG(h, "dotlock_take_unix()=-1 (fd=-1) E=%d\n",errno);
1087 snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid());
1088 if (write (fd, pidstr, 11 ) == 11
1089 && write (fd, h->tname + h->nodename_off,h->nodename_len)
1091 && write (fd, "\n", 1) == 1
1095 DLOG(h, "dotlock_take_unix()=0 (write)\n");
1100 my_error_2 ("lock not made: writing to '%s' failed: %s\n",
1101 h->lockname, strerror (errno));
1103 unlink (h->lockname);
1104 my_set_errno (saveerrno);
1105 DLOG(h, "dotlock_take_unix()=-1 (write) E=%d\n",errno);
1109 else /* Standard method: Use hardlinks. */
1113 /* We ignore the return value of link() because it is unreliable. */
1114 (void) link (h->tname, h->lockname);
1116 if (stat (h->tname, &sb))
1119 my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
1121 /* In theory this might be a severe error: It is possible
1122 that link succeeded but stat failed due to changed
1123 permissions. We can't do anything about it, though. */
1124 my_set_errno (saveerrno);
1125 DLOG(h, "dotlock_take_unix()=-1 (stat) E=%d\n",errno);
1129 if (sb.st_nlink == 2)
1132 DLOG(h, "dotlock_take_unix()=0 (nlink)\n");
1133 return 0; /* Okay. */
1137 /* Check for stale lock files. */
1138 if ( (pid = read_lockfile (h, &same_node)) == -1 )
1140 if ( errno != ENOENT )
1143 my_info_0 ("cannot read lockfile\n");
1144 my_set_errno (saveerrno);
1145 DLOG(h, "dotlock_take_unix()=-1 (read) E=%d\n",errno);
1148 my_info_0 ("lockfile disappeared\n");
1151 else if ( pid == getpid() && same_node )
1153 my_info_0 ("Oops: lock already held by us\n");
1155 DLOG(h, "dotlock_take_unix()=0 (oops)\n");
1156 return 0; /* okay */
1158 else if ( same_node && kill (pid, 0) && errno == ESRCH )
1160 /* Note: It is unlikley that we get a race here unless a pid is
1161 reused too fast or a new process with the same pid as the one
1162 of the stale file tries to lock right at the same time as we. */
1163 my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
1164 unlink (h->lockname);
1165 DLOG(h, "dotlock_take_unix() again...\n");
1171 ownerchanged = (pid != lastpid);
1177 /* Wait until lock has been released. We use increasing retry
1178 intervals of 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s
1179 but reset it if the lock owner meanwhile changed. */
1180 if (!wtime || ownerchanged)
1182 else if (wtime < 800)
1184 else if (wtime == 800)
1186 else if (wtime < 8000)
1191 if (wtime > timeout)
1197 if (sumtime >= 1500)
1200 my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
1201 pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
1205 tv.tv_sec = wtime / 1000;
1206 tv.tv_usec = (wtime % 1000) * 1000;
1207 select (0, NULL, NULL, NULL, &tv);
1211 my_set_errno (EACCES);
1212 DLOG(h, "dotlock_take_unix()=-1 (EACCES) E=%d\n",errno);
1215 #endif /*HAVE_POSIX_SYSTEM*/
1218 #ifdef HAVE_DOSISH_SYSTEM
1219 /* Windows specific code of make_dotlock. Returns 0 on success and -1 on
1222 dotlock_take_w32 (dotlock_t h, long timeout)
1229 /* Lock one byte at offset 0. The offset is given by OVL. */
1230 memset (&ovl, 0, sizeof ovl);
1231 if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
1232 | LOCKFILE_FAIL_IMMEDIATELY), 0, 1, 0, &ovl))
1235 return 0; /* okay */
1238 w32err = GetLastError ();
1239 if (w32err != ERROR_LOCK_VIOLATION)
1241 my_error_2 (_("lock '%s' not made: %s\n"),
1242 h->lockname, w32_strerror (w32err));
1243 my_set_errno (map_w32_to_errno (w32err));
1249 /* Wait until lock has been released. We use retry intervals of
1250 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s. */
1253 else if (wtime < 800)
1255 else if (wtime == 800)
1257 else if (wtime < 8000)
1262 if (wtime > timeout)
1268 my_info_1 (_("waiting for lock %s...\n"), h->lockname);
1274 my_set_errno (EACCES);
1277 #endif /*HAVE_DOSISH_SYSTEM*/
1280 /* Take a lock on H. A value of 0 for TIMEOUT returns immediately if
1281 the lock can't be taked, -1 waits forever (hopefully not), other
1282 values wait for TIMEOUT milliseconds. Returns: 0 on success */
1284 dotlock_take (dotlock_t h, long timeout)
1289 return 0; /* Locks are completely disabled. Return success. */
1293 my_debug_1 ("Oops, '%s' is already locked\n", h->lockname);
1297 #ifdef HAVE_DOSISH_SYSTEM
1298 ret = dotlock_take_w32 (h, timeout);
1299 #else /*!HAVE_DOSISH_SYSTEM*/
1300 ret = dotlock_take_unix (h, timeout);
1301 #endif /*!HAVE_DOSISH_SYSTEM*/
1308 #ifdef HAVE_POSIX_SYSTEM
1309 /* Unix specific code of release_dotlock. */
1311 dotlock_release_unix (dotlock_t h)
1316 DLOG(h, "dotlock_release_unix...\n");
1318 pid = read_lockfile (h, &same_node);
1322 my_error_0 ("release_dotlock: lockfile error\n");
1323 my_set_errno (saveerrno);
1324 DLOG(h, "dotlock_release_unix()=-1 (read) E=%d\n",errno);
1327 if ( pid != getpid() || !same_node )
1329 my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
1330 my_set_errno (EACCES);
1331 DLOG(h, "dotlock_release_unix()=-1 (not ours) E=%d\n",errno);
1335 if ( unlink( h->lockname ) )
1338 my_error_1 ("release_dotlock: error removing lockfile '%s'\n",
1340 my_set_errno (saveerrno);
1341 DLOG(h, "dotlock_release_unix()=-1 (unlink) E=%d\n",errno);
1344 /* Fixme: As an extra check we could check whether the link count is
1346 DLOG(h, "dotlock_release_unix()=0\n");
1349 #endif /*HAVE_POSIX_SYSTEM */
1352 #ifdef HAVE_DOSISH_SYSTEM
1353 /* Windows specific code of release_dotlock. */
1355 dotlock_release_w32 (dotlock_t h)
1359 memset (&ovl, 0, sizeof ovl);
1360 if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
1362 int saveerrno = map_w32_to_errno (GetLastError ());
1363 my_error_2 ("release_dotlock: error removing lockfile '%s': %s\n",
1364 h->lockname, w32_strerror (-1));
1365 my_set_errno (saveerrno);
1371 #endif /*HAVE_DOSISH_SYSTEM */
1374 /* Release a lock. Returns 0 on success. */
1376 dotlock_release (dotlock_t h)
1379 DLOG(h, "dotlock_release\n");
1381 /* To avoid atexit race conditions we first check whether there are
1382 any locks left. It might happen that another atexit handler
1383 tries to release the lock while the atexit handler of this module
1384 already ran and thus H is undefined. */
1385 LOCK_all_lockfiles ();
1386 ret = !all_lockfiles;
1387 UNLOCK_all_lockfiles ();
1396 my_debug_1 ("Oops, '%s' is not locked\n", h->lockname);
1400 #ifdef HAVE_DOSISH_SYSTEM
1401 ret = dotlock_release_w32 (h);
1403 ret = dotlock_release_unix (h);
1413 /* Remove all lockfiles. This is called by the atexit handler
1414 installed by this module but may also be called by other
1415 termination handlers. */
1417 dotlock_remove_lockfiles (void)
1420 DLOG(0, "dotlock_remove_lockfiles\n");
1422 /* First set the lockfiles list to NULL so that for example
1423 dotlock_release is aware that this function is currently
1426 LOCK_all_lockfiles ();
1428 all_lockfiles = NULL;
1429 UNLOCK_all_lockfiles ();
1434 dotlock_destroy (h);