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*/
475 /* Entirely disable all locking. This function should be called
476 before any locking is done. It may be called right at startup of
477 the process as it only sets a global value. */
479 dotlock_disable (void)
485 #ifdef HAVE_POSIX_SYSTEM
487 maybe_deadlock (dotlock_t h)
492 LOCK_all_lockfiles ();
493 for (r=all_lockfiles; r; r = r->next)
495 if ( r != h && r->locked )
501 UNLOCK_all_lockfiles ();
504 #endif /*HAVE_POSIX_SYSTEM*/
507 /* Read the lock file and return the pid, returns -1 on error. True
508 will be stored in the integer at address SAME_NODE if the lock file
509 has been created on the same node. */
510 #ifdef HAVE_POSIX_SYSTEM
512 read_lockfile (dotlock_t h, int *same_node )
514 char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
515 names are usually shorter. */
523 expected_len = 10 + 1 + h->nodename_len + 1;
524 if ( expected_len >= sizeof buffer_space)
526 buffer = xtrymalloc (expected_len);
531 buffer = buffer_space;
533 if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
536 my_info_2 ("error opening lockfile '%s': %s\n",
537 h->lockname, strerror(errno) );
538 if (buffer != buffer_space)
540 my_set_errno (e); /* Need to return ERRNO here. */
548 res = read (fd, p, expected_len - nread);
549 if (res == -1 && errno == EINTR)
554 my_info_1 ("error reading lockfile '%s'\n", h->lockname );
556 if (buffer != buffer_space)
564 while (res && nread != expected_len);
569 my_info_1 ("invalid size of lockfile '%s'\n", h->lockname);
570 if (buffer != buffer_space)
572 my_set_errno (EINVAL);
576 if (buffer[10] != '\n'
577 || (buffer[10] = 0, pid = atoi (buffer)) == -1
580 my_error_2 ("invalid pid %d in lockfile '%s'\n", pid, h->lockname);
581 if (buffer != buffer_space)
583 my_set_errno (EINVAL);
587 if (nread == expected_len
588 && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
589 && buffer[11+h->nodename_len] == '\n')
592 if (buffer != buffer_space)
596 #endif /*HAVE_POSIX_SYSTEM */
599 /* Check whether the file system which stores TNAME supports
600 hardlinks. Instead of using the non-portable statsfs call which
601 differs between various Unix versions, we do a runtime test.
602 Returns: 0 supports hardlinks; 1 no hardlink support, -1 unknown
604 #ifdef HAVE_POSIX_SYSTEM
606 use_hardlinks_p (const char *tname)
613 if (stat (tname, &sb))
615 nlink = (unsigned int)sb.st_nlink;
617 lname = xtrymalloc (strlen (tname) + 1 + 1);
620 strcpy (lname, tname);
623 /* We ignore the return value of link() because it is unreliable. */
624 (void) link (tname, lname);
626 if (stat (tname, &sb))
627 res = -1; /* Ooops. */
628 else if (sb.st_nlink == nlink + 1)
629 res = 0; /* Yeah, hardlinks are supported. */
631 res = 1; /* No hardlink support. */
637 #endif /*HAVE_POSIX_SYSTEM */
641 #ifdef HAVE_POSIX_SYSTEM
642 /* Locking core for Unix. It used a temporary file and the link
643 system call to make locking an atomic operation. */
645 dotlock_create_unix (dotlock_t h, const char *file_to_lock)
649 const char *nodename;
652 struct utsname utsbuf;
655 snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );
657 /* Create a temporary file. */
658 if ( uname ( &utsbuf ) )
659 nodename = "unknown";
661 nodename = utsbuf.nodename;
663 if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
670 dirpartlen = dirpart - file_to_lock;
671 dirpart = file_to_lock;
674 LOCK_all_lockfiles ();
675 h->next = all_lockfiles;
678 tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10 + 1;
679 h->tname = xtrymalloc (tnamelen + 1);
682 all_lockfiles = h->next;
683 UNLOCK_all_lockfiles ();
687 h->nodename_len = strlen (nodename);
689 snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
690 h->nodename_off = strlen (h->tname);
691 snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
692 "%s.%d", nodename, (int)getpid ());
697 fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
698 S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
700 while (fd == -1 && errno == EINTR);
704 int saveerrno = errno;
705 all_lockfiles = h->next;
706 UNLOCK_all_lockfiles ();
707 my_error_2 (_("failed to create temporary file '%s': %s\n"),
708 h->tname, strerror (errno));
711 my_set_errno (saveerrno);
714 if ( write (fd, pidstr, 11 ) != 11 )
716 if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) )
718 if ( write (fd, "\n", 1 ) != 1 )
722 if ( errno == EINTR )
728 /* Check whether we support hard links. */
729 switch (use_hardlinks_p (h->tname))
739 int saveerrno = errno;
740 my_error_2 ("can't check whether hardlinks are supported for '%s': %s\n"
741 , h->tname, strerror (saveerrno));
742 my_set_errno (saveerrno);
747 h->lockname = xtrymalloc (strlen (file_to_lock) + 6 );
750 int saveerrno = errno;
751 all_lockfiles = h->next;
752 UNLOCK_all_lockfiles ();
756 my_set_errno (saveerrno);
759 strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
760 UNLOCK_all_lockfiles ();
762 my_debug_1 ("locking for '%s' done via O_EXCL\n", h->lockname);
768 int saveerrno = errno;
769 all_lockfiles = h->next;
770 UNLOCK_all_lockfiles ();
771 my_error_2 (_("error writing to '%s': %s\n"), h->tname, strerror (errno));
777 my_set_errno (saveerrno);
781 #endif /*HAVE_POSIX_SYSTEM*/
784 #ifdef HAVE_DOSISH_SYSTEM
785 /* Locking core for Windows. This version does not need a temporary
786 file but uses the plain lock file along with record locking. We
787 create this file here so that we later only need to do the file
788 locking. For error reporting it is useful to keep the name of the
789 file in the handle. */
791 dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
793 LOCK_all_lockfiles ();
794 h->next = all_lockfiles;
797 h->lockname = xtrymalloc ( strlen (file_to_lock) + 6 );
800 all_lockfiles = h->next;
801 UNLOCK_all_lockfiles ();
805 strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
807 /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
808 along with FILE_SHARE_DELETE but that does not work due to a race
809 condition: Despite the OPEN_ALWAYS flag CreateFile may return an
810 error and we can't reliable create/open the lock file unless we
811 would wait here until it works - however there are other valid
812 reasons why a lock file can't be created and thus the process
813 would not stop as expected but spin until Windows crashes. Our
814 solution is to keep the lock file open; that does not harm. */
816 #ifdef HAVE_W32CE_SYSTEM
817 wchar_t *wname = utf8_to_wchar (h->lockname);
820 h->lockhd = CreateFile (wname,
821 GENERIC_READ|GENERIC_WRITE,
822 FILE_SHARE_READ|FILE_SHARE_WRITE,
823 NULL, OPEN_ALWAYS, 0, NULL);
825 h->lockhd = INVALID_HANDLE_VALUE;
828 h->lockhd = CreateFile (h->lockname,
829 GENERIC_READ|GENERIC_WRITE,
830 FILE_SHARE_READ|FILE_SHARE_WRITE,
831 NULL, OPEN_ALWAYS, 0, NULL);
834 if (h->lockhd == INVALID_HANDLE_VALUE)
836 int saveerrno = map_w32_to_errno (GetLastError ());
837 all_lockfiles = h->next;
838 UNLOCK_all_lockfiles ();
839 my_error_2 (_("can't create '%s': %s\n"), h->lockname, w32_strerror (-1));
842 my_set_errno (saveerrno);
847 #endif /*HAVE_DOSISH_SYSTEM*/
850 /* Create a lockfile for a file name FILE_TO_LOCK and returns an
851 object of type dotlock_t which may be used later to actually acquire
852 the lock. A cleanup routine gets installed to cleanup left over
853 locks or other files used internally by the lock mechanism.
855 Calling this function with NULL does only install the atexit
856 handler and may thus be used to assure that the cleanup is called
857 after all other atexit handlers.
859 This function creates a lock file in the same directory as
860 FILE_TO_LOCK using that name and a suffix of ".lock". Note that on
861 POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
866 The function returns an new handle which needs to be released using
867 destroy_dotlock but gets also released at the termination of the
868 process. On error NULL is returned.
872 dotlock_create (const char *file_to_lock, unsigned int flags)
874 static int initialized;
879 atexit (dotlock_remove_lockfiles);
884 return NULL; /* Only initialization was requested. */
888 my_set_errno (EINVAL);
892 h = xtrycalloc (1, sizeof *h);
900 LOCK_all_lockfiles ();
901 h->next = all_lockfiles;
903 UNLOCK_all_lockfiles ();
907 #ifdef HAVE_DOSISH_SYSTEM
908 return dotlock_create_w32 (h, file_to_lock);
909 #else /*!HAVE_DOSISH_SYSTEM */
910 return dotlock_create_unix (h, file_to_lock);
911 #endif /*!HAVE_DOSISH_SYSTEM*/
916 /* Convenience function to store a file descriptor (or any any other
917 integer value) in the context of handle H. */
919 dotlock_set_fd (dotlock_t h, int fd)
924 /* Convenience function to retrieve a file descriptor (or any any other
925 integer value) stored in the context of handle H. */
927 dotlock_get_fd (dotlock_t h)
934 #ifdef HAVE_POSIX_SYSTEM
935 /* Unix specific code of destroy_dotlock. */
937 dotlock_destroy_unix (dotlock_t h)
939 if (h->locked && h->lockname)
940 unlink (h->lockname);
941 if (h->tname && !h->use_o_excl)
945 #endif /*HAVE_POSIX_SYSTEM*/
948 #ifdef HAVE_DOSISH_SYSTEM
949 /* Windows specific code of destroy_dotlock. */
951 dotlock_destroy_w32 (dotlock_t h)
957 memset (&ovl, 0, sizeof ovl);
958 UnlockFileEx (h->lockhd, 0, 1, 0, &ovl);
960 CloseHandle (h->lockhd);
962 #endif /*HAVE_DOSISH_SYSTEM*/
965 /* Destroy the lock handle H and release the lock. */
967 dotlock_destroy (dotlock_t h)
969 dotlock_t hprev, htmp;
974 /* First remove the handle from our global list of all locks. */
975 LOCK_all_lockfiles ();
976 for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
980 hprev->next = htmp->next;
982 all_lockfiles = htmp->next;
986 UNLOCK_all_lockfiles ();
988 /* Then destroy the lock. */
991 #ifdef HAVE_DOSISH_SYSTEM
992 dotlock_destroy_w32 (h);
993 #else /* !HAVE_DOSISH_SYSTEM */
994 dotlock_destroy_unix (h);
995 #endif /* HAVE_DOSISH_SYSTEM */
1003 #ifdef HAVE_POSIX_SYSTEM
1004 /* Unix specific code of make_dotlock. Returns 0 on success and -1 on
1007 dotlock_take_unix (dotlock_t h, long timeout)
1014 const char *maybe_dead="";
1021 /* No hardlink support - use open(O_EXCL). */
1027 fd = open (h->lockname, O_WRONLY|O_CREAT|O_EXCL,
1028 S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
1030 while (fd == -1 && errno == EINTR);
1032 if (fd == -1 && errno == EEXIST)
1033 ; /* Lock held by another process. */
1037 my_error_2 ("lock not made: open(O_EXCL) of '%s' failed: %s\n",
1038 h->lockname, strerror (saveerrno));
1039 my_set_errno (saveerrno);
1046 snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid());
1047 if (write (fd, pidstr, 11 ) == 11
1048 && write (fd, h->tname + h->nodename_off,h->nodename_len)
1050 && write (fd, "\n", 1) == 1
1058 my_error_2 ("lock not made: writing to '%s' failed: %s\n",
1059 h->lockname, strerror (errno));
1061 unlink (h->lockname);
1062 my_set_errno (saveerrno);
1066 else /* Standard method: Use hardlinks. */
1070 /* We ignore the return value of link() because it is unreliable. */
1071 (void) link (h->tname, h->lockname);
1073 if (stat (h->tname, &sb))
1076 my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
1078 /* In theory this might be a severe error: It is possible
1079 that link succeeded but stat failed due to changed
1080 permissions. We can't do anything about it, though. */
1081 my_set_errno (saveerrno);
1085 if (sb.st_nlink == 2)
1088 return 0; /* Okay. */
1092 /* Check for stale lock files. */
1093 if ( (pid = read_lockfile (h, &same_node)) == -1 )
1095 if ( errno != ENOENT )
1098 my_info_0 ("cannot read lockfile\n");
1099 my_set_errno (saveerrno);
1102 my_info_0 ("lockfile disappeared\n");
1105 else if ( pid == getpid() && same_node )
1107 my_info_0 ("Oops: lock already held by us\n");
1109 return 0; /* okay */
1111 else if ( same_node && kill (pid, 0) && errno == ESRCH )
1113 /* Note: It is unlikley that we get a race here unless a pid is
1114 reused too fast or a new process with the same pid as the one
1115 of the stale file tries to lock right at the same time as we. */
1116 my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
1117 unlink (h->lockname);
1123 ownerchanged = (pid != lastpid);
1129 /* Wait until lock has been released. We use increasing retry
1130 intervals of 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s
1131 but reset it if the lock owner meanwhile changed. */
1132 if (!wtime || ownerchanged)
1134 else if (wtime < 800)
1136 else if (wtime == 800)
1138 else if (wtime < 8000)
1143 if (wtime > timeout)
1149 if (sumtime >= 1500)
1152 my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
1153 pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
1157 tv.tv_sec = wtime / 1000;
1158 tv.tv_usec = (wtime % 1000) * 1000;
1159 select (0, NULL, NULL, NULL, &tv);
1163 my_set_errno (EACCES);
1166 #endif /*HAVE_POSIX_SYSTEM*/
1169 #ifdef HAVE_DOSISH_SYSTEM
1170 /* Windows specific code of make_dotlock. Returns 0 on success and -1 on
1173 dotlock_take_w32 (dotlock_t h, long timeout)
1180 /* Lock one byte at offset 0. The offset is given by OVL. */
1181 memset (&ovl, 0, sizeof ovl);
1182 if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
1183 | LOCKFILE_FAIL_IMMEDIATELY), 0, 1, 0, &ovl))
1186 return 0; /* okay */
1189 w32err = GetLastError ();
1190 if (w32err != ERROR_LOCK_VIOLATION)
1192 my_error_2 (_("lock '%s' not made: %s\n"),
1193 h->lockname, w32_strerror (w32err));
1194 my_set_errno (map_w32_to_errno (w32err));
1200 /* Wait until lock has been released. We use retry intervals of
1201 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s. */
1204 else if (wtime < 800)
1206 else if (wtime == 800)
1208 else if (wtime < 8000)
1213 if (wtime > timeout)
1219 my_info_1 (_("waiting for lock %s...\n"), h->lockname);
1225 my_set_errno (EACCES);
1228 #endif /*HAVE_DOSISH_SYSTEM*/
1231 /* Take a lock on H. A value of 0 for TIMEOUT returns immediately if
1232 the lock can't be taked, -1 waits forever (hopefully not), other
1233 values wait for TIMEOUT milliseconds. Returns: 0 on success */
1235 dotlock_take (dotlock_t h, long timeout)
1240 return 0; /* Locks are completely disabled. Return success. */
1244 my_debug_1 ("Oops, '%s' is already locked\n", h->lockname);
1248 #ifdef HAVE_DOSISH_SYSTEM
1249 ret = dotlock_take_w32 (h, timeout);
1250 #else /*!HAVE_DOSISH_SYSTEM*/
1251 ret = dotlock_take_unix (h, timeout);
1252 #endif /*!HAVE_DOSISH_SYSTEM*/
1259 #ifdef HAVE_POSIX_SYSTEM
1260 /* Unix specific code of release_dotlock. */
1262 dotlock_release_unix (dotlock_t h)
1267 pid = read_lockfile (h, &same_node);
1271 my_error_0 ("release_dotlock: lockfile error\n");
1272 my_set_errno (saveerrno);
1275 if ( pid != getpid() || !same_node )
1277 my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
1278 my_set_errno (EACCES);
1282 if ( unlink( h->lockname ) )
1285 my_error_1 ("release_dotlock: error removing lockfile '%s'\n",
1287 my_set_errno (saveerrno);
1290 /* Fixme: As an extra check we could check whether the link count is
1294 #endif /*HAVE_POSIX_SYSTEM */
1297 #ifdef HAVE_DOSISH_SYSTEM
1298 /* Windows specific code of release_dotlock. */
1300 dotlock_release_w32 (dotlock_t h)
1304 memset (&ovl, 0, sizeof ovl);
1305 if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
1307 int saveerrno = map_w32_to_errno (GetLastError ());
1308 my_error_2 ("release_dotlock: error removing lockfile '%s': %s\n",
1309 h->lockname, w32_strerror (-1));
1310 my_set_errno (saveerrno);
1316 #endif /*HAVE_DOSISH_SYSTEM */
1319 /* Release a lock. Returns 0 on success. */
1321 dotlock_release (dotlock_t h)
1325 /* To avoid atexit race conditions we first check whether there are
1326 any locks left. It might happen that another atexit handler
1327 tries to release the lock while the atexit handler of this module
1328 already ran and thus H is undefined. */
1329 LOCK_all_lockfiles ();
1330 ret = !all_lockfiles;
1331 UNLOCK_all_lockfiles ();
1340 my_debug_1 ("Oops, '%s' is not locked\n", h->lockname);
1344 #ifdef HAVE_DOSISH_SYSTEM
1345 ret = dotlock_release_w32 (h);
1347 ret = dotlock_release_unix (h);
1357 /* Remove all lockfiles. This is called by the atexit handler
1358 installed by this module but may also be called by other
1359 termination handlers. */
1361 dotlock_remove_lockfiles (void)
1365 /* First set the lockfiles list to NULL so that for example
1366 dotlock_release is aware that this function is currently
1368 LOCK_all_lockfiles ();
1370 all_lockfiles = NULL;
1371 UNLOCK_all_lockfiles ();
1376 dotlock_destroy (h);