Add prefix macro for dotlock functions.
[gnupg.git] / common / dotlock.c
1 /* dotlock.c - dotfile locking
2  * Copyright (C) 1998, 2000, 2001, 2003, 2004,
3  *               2005, 2006, 2008, 2010, 2011 Free Software Foundation, Inc.
4  *
5  * This file is part of JNLIB, which is a subsystem of GnuPG.
6  *
7  * JNLIB is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * JNLIB is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22    Overview:
23    =========
24
25    This module implements advisory file locking in a portable way.
26    Due to the problems with POSIX fcntl locking a separate lock file
27    is used.  It would be possible to use fcntl locking on this lock
28    file and thus avoid the weird auto unlock bug of POSIX while still
29    having an unproved better performance of fcntl locking.  However
30    there are still problems left, thus we resort to use a hardlink
31    which has the well defined property that a link call will fail if
32    the target file already exists.
33
34    Given that hardlinks are also available on NTFS file systems since
35    Windows XP; it will be possible to enhance this module to use
36    hardlinks even on Windows and thus allow Windows and Posix clients
37    to use locking on the same directory.  This is not yet implemented;
38    instead we use a lockfile on Windows along with W32 style file
39    locking.
40
41    On FAT file systems hardlinks are not supported.  Thus this method
42    does not work.  Our solution is to use a O_EXCL locking instead.
43    Querying the type of the file system is not easy to do in a
44    portable way (e.g. Linux has a statfs, BSDs have a the same call
45    but using different structures and constants).  What we do instead
46    is to check at runtime whether link(2) works for a specific lock
47    file.
48
49
50    How to use:
51    ===========
52
53    At program initialization time, the module should be explicitly
54    initialized:
55
56       dotlock_create (NULL, 0);
57
58    This installs an atexit handler and may also initialize mutex etc.
59    It is optional for non-threaded applications.  Only the first call
60    has an effect.  This needs to be done before any extra threads are
61    started.
62
63    To create a lock file (which  prepares it but does not take the
64    lock) you do:
65
66      dotlock_t h
67
68      h = dotlock_create (fname, 0);
69      if (!h)
70        error ("error creating lock file: %s\n", strerror (errno));
71
72    It is important to handle the error.  For example on a read-only
73    file system a lock can't be created (but is usually not needed).
74    FNAME is the file you want to lock; the actual lockfile is that
75    name with the suffix ".lock" appended.  On success a handle to be
76    used with the other functions is returned or NULL on error.  Note
77    that the handle shall only be used by one thread at a time.  This
78    function creates a unique file temporary file (".#lk*") in the same
79    directory as FNAME and returns a handle for further operations.
80    The module keeps track of theses unique files so that they will be
81    unlinked using the atexit handler.  If you don't need the lock file
82    anymore, you may also explicitly remove it with a call to:
83
84      dotlock_destroy (h);
85
86    To actually lock the file, you use:
87
88      if (dotlock_take (h, -1))
89        error ("error taking lock: %s\n", strerror (errno));
90
91    This function will wait until the lock is acquired.  If an
92    unexpected error occurs if will return non-zero and set ERRNO.  If
93    you pass (0) instead of (-1) the function does not wait in case the
94    file is already locked but returns -1 and sets ERRNO to EACCES.
95    Any other positive value for the second parameter is considered a
96    timeout valuie in milliseconds.
97
98    To release the lock you call:
99
100      if (dotlock_release (h))
101        error ("error releasing lock: %s\n", strerror (errno));
102
103    or, if the lock file is not anymore needed, you may just call
104    dotlock_destroy.  However dotlock_release does some extra checks
105    before releasing the lock and prints diagnostics to help detecting
106    bugs.
107
108    If you want to explicitly destroy all lock files you may call
109
110      dotlock_remove_lockfiles ();
111
112    which is the core of the installed atexit handler.  In case your
113    application wants to disable locking completely it may call
114
115      disable_locking ()
116
117    before any locks are created.
118
119    There are two convenience functions to store an integer (e.g. a
120    file descriptor) value with the handle:
121
122      void dotlock_set_fd (dotlock_t h, int fd);
123      int  dotlock_get_fd (dotlock_t h);
124
125    If nothing has been stored dotlock_get_fd returns -1.
126
127
128
129    How to build:
130    =============
131
132    This module was originally developed for GnuPG but later changed to
133    allow its use without any GnuPG dependency.  If you want to use it
134    with you application you may simply use it and it should figure out
135    most things automagically.
136
137    You may use the common config.h file to pass macros, but take care
138    to pass -DHAVE_CONFIG_H to the compiler.  Macros used by this
139    module are:
140
141      DOTLOCK_USE_PTHREAD  - Define if POSIX threads are in use.
142
143      DOTLOCK_GLIB_LOGGING - Define this to use Glib logging functions.
144
145      DOTLOCK_EXT_SYM_PREFIX - Prefix all external symbols with the
146                               string to which this macro evaluates.
147
148      GNUPG_MAJOR_VERSION - Defined when used by GnuPG.
149
150      HAVE_DOSISH_SYSTEM  - Defined for Windows etc.  Will be
151                            automatically defined if a the target is
152                            Windows.
153
154      HAVE_POSIX_SYSTEM   - Internally defined to !HAVE_DOSISH_SYSTEM.
155
156      HAVE_SIGNAL_H       - Should be defined on Posix systems.  If config.h
157                            is not used defaults to defined.
158
159      DIRSEP_C            - Separation character for file name parts.
160                            Usually not redefined.
161
162      EXTSEP_S            - Separation string for file name suffixes.
163                            Usually not redefined.
164
165      HAVE_W32CE_SYSTEM   - Currently only used by GnuPG.
166
167    Note that there is a test program t-dotlock which has compile
168    instructions at its end.  At least for SMBFS and CIFS it is
169    important that 64 bit versions of stat are used; most programming
170    environments do this these days, just in case you want to compile
171    it on the command line, remember to pass -D_FILE_OFFSET_BITS=64
172
173
174    Bugs:
175    =====
176
177    On Windows this module is not yet thread-safe.
178
179
180    Miscellaneous notes:
181    ====================
182
183    On hardlinks:
184    - Hardlinks are supported under Windows with NTFS since XP/Server2003.
185    - In Linux 2.6.33 both SMBFS and CIFS seem to support hardlinks.
186    - NFS supports hard links.  But there are solvable problems.
187    - FAT does not support links
188
189    On the file locking API:
190    - CIFS on Linux 2.6.33 supports several locking methods.
191      SMBFS seems not to support locking.  No closer checks done.
192    - NFS supports Posix locks.  flock is emulated in the server.
193      However there are a couple of problems; see below.
194    - FAT does not support locks.
195    - An advantage of fcntl locking is that R/W locks can be
196      implemented which is not easy with a straight lock file.
197
198    On O_EXCL:
199    - Does not work reliable on NFS
200    - Should work on CIFS and SMBFS but how can we delete lockfiles?
201
202    On NFS problems:
203    - Locks vanish if the server crashes and reboots.
204    - Client crashes keep the lock in the server until the client
205      re-connects.
206    - Communication problems may return unreliable error codes.  The
207      MUA Postfix's workaround is to compare the link count after
208      seeing an error for link.  However that gives a race.  If using a
209      unique file to link to a lockfile and using stat to check the
210      link count instead of looking at the error return of link(2) is
211      the best solution.
212    - O_EXCL seems to have a race and may re-create a file anyway.
213
214 */
215
216 #ifdef HAVE_CONFIG_H
217 # include <config.h>
218 #endif
219
220 /* Some quick replacements for stuff we usually expect to be defined
221    in config.h.  Define HAVE_POSIX_SYSTEM for better readability. */
222 #if !defined (HAVE_DOSISH_SYSTEM) && defined(_WIN32)
223 # define HAVE_DOSISH_SYSTEM 1
224 #endif
225 #if !defined (HAVE_DOSISH_SYSTEM) && !defined (HAVE_POSIX_SYSTEM)
226 # define HAVE_POSIX_SYSTEM 1
227 #endif
228
229 /* With no config.h assume that we have sitgnal.h.  */
230 #if !defined (HAVE_CONFIG_H) && defined (HAVE_POSIX_SYSTEM)
231 # define HAVE_SIGNAL_H 1
232 #endif
233
234 /* Standard headers.  */
235 #include <stdlib.h>
236 #include <stdio.h>
237 #include <string.h>
238 #include <errno.h>
239 #include <ctype.h>
240 #include <errno.h>
241 #include <unistd.h>
242 #ifdef  HAVE_DOSISH_SYSTEM
243 # define WIN32_LEAN_AND_MEAN  /* We only need the OS core stuff.  */
244 # include <windows.h>
245 #else
246 # include <sys/types.h>
247 # include <sys/stat.h>
248 # include <sys/utsname.h>
249 #endif
250 #include <sys/types.h>
251 #include <sys/time.h>
252 #include <sys/stat.h>
253 #include <fcntl.h>
254 #ifdef HAVE_SIGNAL_H
255 # include <signal.h>
256 #endif
257 #ifdef DOTLOCK_USE_PTHREAD
258 # include <pthread.h>
259 #endif
260
261 #ifdef DOTLOCK_GLIB_LOGGING
262 # include <glib.h>
263 #endif
264
265 #ifdef GNUPG_MAJOR_VERSION
266 # include "libjnlib-config.h"
267 #endif
268 #ifdef HAVE_W32CE_SYSTEM
269 # include "utf8conv.h"  /* WindowsCE requires filename conversion.  */
270 #endif
271
272 #include "dotlock.h"
273
274
275 /* Define constants for file name construction.  */
276 #if !defined(DIRSEP_C) && !defined(EXTSEP_S)
277 # ifdef HAVE_DOSISH_SYSTEM
278 #  define DIRSEP_C '\\'
279 #  define EXTSEP_S "."
280 #else
281 #  define DIRSEP_C '/'
282 #  define EXTSEP_S "."
283 # endif
284 #endif
285
286 /* In GnuPG we use wrappers around the malloc fucntions.  If they are
287    not defined we assume that this code is used outside of GnuPG and
288    fall back to the regular malloc functions.  */
289 #ifndef jnlib_malloc
290 # define jnlib_malloc(a)     malloc ((a))
291 # define jnlib_calloc(a,b)   calloc ((a), (b))
292 # define jnlib_free(a)       free ((a))
293 #endif
294
295 /* Wrapper to set ERRNO.  */
296 #ifndef jnlib_set_errno
297 # ifdef HAVE_W32CE_SYSTEM
298 #  define jnlib_set_errno(e)  gpg_err_set_errno ((e))
299 # else
300 #  define jnlib_set_errno(e)  do { errno = (e); } while (0)
301 # endif
302 #endif
303
304 /* Gettext macro replacement.  */
305 #ifndef _
306 # define _(a) (a)
307 #endif
308
309 #ifdef GNUPG_MAJOR_VERSION
310 # define my_info_0(a)       log_info ((a))
311 # define my_info_1(a,b)     log_info ((a), (b))
312 # define my_info_2(a,b,c)   log_info ((a), (b), (c))
313 # define my_info_3(a,b,c,d) log_info ((a), (b), (c), (d))
314 # define my_error_0(a)      log_error ((a))
315 # define my_error_1(a,b)    log_error ((a), (b))
316 # define my_error_2(a,b,c)  log_error ((a), (b), (c))
317 # define my_debug_1(a,b)    log_debug ((a), (b))
318 # define my_fatal_0(a)      log_fatal ((a))
319 #elif defined (DOTLOCK_GLIB_LOGGING)
320 # define my_info_0(a)       g_message ((a))
321 # define my_info_1(a,b)     g_message ((a), (b))
322 # define my_info_2(a,b,c)   g_message ((a), (b), (c))
323 # define my_info_3(a,b,c,d) g_message ((a), (b), (c), (d))
324 # define my_error_0(a)      g_warning ((a))
325 # define my_error_1(a,b)    g_warning ((a), (b))
326 # define my_error_2(a,b,c)  g_warning ((a), (b), (c))
327 # define my_debug_1(a,b)    g_debug ((a), (b))
328 # define my_fatal_0(a)      g_error ((a))
329 #else
330 # define my_info_0(a)       fprintf (stderr, (a))
331 # define my_info_1(a,b)     fprintf (stderr, (a), (b))
332 # define my_info_2(a,b,c)   fprintf (stderr, (a), (b), (c))
333 # define my_info_3(a,b,c,d) fprintf (stderr, (a), (b), (c), (d))
334 # define my_error_0(a)      fprintf (stderr, (a))
335 # define my_error_1(a,b)    fprintf (stderr, (a), (b))
336 # define my_error_2(a,b,c)  fprintf (stderr, (a), (b), (c))
337 # define my_debug_1(a,b)    fprintf (stderr, (a), (b))
338 # define my_fatal_0(a)      do { fprintf (stderr,(a)); fflush (stderr); \
339                                  abort (); } while (0)
340 #endif
341
342
343
344
345 \f
346 /* The object describing a lock.  */
347 struct dotlock_handle
348 {
349   struct dotlock_handle *next;
350   char *lockname;            /* Name of the actual lockfile.          */
351   unsigned int locked:1;     /* Lock status.                          */
352   unsigned int disable:1;    /* If true, locking is disabled.         */
353   unsigned int use_o_excl:1; /* Use open (O_EXCL) for locking.        */
354
355   int extra_fd;              /* A place for the caller to store an FD.  */
356
357 #ifdef HAVE_DOSISH_SYSTEM
358   HANDLE lockhd;       /* The W32 handle of the lock file.      */
359 #else /*!HAVE_DOSISH_SYSTEM */
360   char *tname;         /* Name of the lockfile template.        */
361   size_t nodename_off; /* Offset in TNAME of the nodename part. */
362   size_t nodename_len; /* Length of the nodename part.          */
363 #endif /*!HAVE_DOSISH_SYSTEM */
364 };
365
366
367 /* A list of of all lock handles.  The volatile attribute might help
368    if used in an atexit handler.  */
369 static volatile dotlock_t all_lockfiles;
370 #ifdef DOTLOCK_USE_PTHREAD
371 static pthread_mutex_t all_lockfiles_mutex = PTHREAD_MUTEX_INITIALIZER;
372 # define LOCK_all_lockfiles() do {                               \
373         if (pthread_mutex_lock (&all_lockfiles_mutex))           \
374           my_fatal_0 ("locking all_lockfiles_mutex failed\n");   \
375       } while (0)
376 # define UNLOCK_all_lockfiles() do {                             \
377         if (pthread_mutex_unlock (&all_lockfiles_mutex))         \
378           my_fatal_0 ("unlocking all_lockfiles_mutex failed\n"); \
379       } while (0)
380 #else  /*!DOTLOCK_USE_PTHREAD*/
381 # define LOCK_all_lockfiles()   do { } while (0)
382 # define UNLOCK_all_lockfiles() do { } while (0)
383 #endif /*!DOTLOCK_USE_PTHREAD*/
384
385 /* If this has the value true all locking is disabled.  */
386 static int never_lock;
387
388
389
390
391 \f
392 /* Entirely disable all locking.  This function should be called
393    before any locking is done.  It may be called right at startup of
394    the process as it only sets a global value.  */
395 void
396 dotlock_disable (void)
397 {
398   never_lock = 1;
399 }
400
401
402 #ifdef HAVE_POSIX_SYSTEM
403 static int
404 maybe_deadlock (dotlock_t h)
405 {
406   dotlock_t r;
407   int res = 0;
408
409   LOCK_all_lockfiles ();
410   for (r=all_lockfiles; r; r = r->next)
411     {
412       if ( r != h && r->locked )
413         {
414           res = 1;
415           break;
416         }
417     }
418   UNLOCK_all_lockfiles ();
419   return res;
420 }
421 #endif /*HAVE_POSIX_SYSTEM*/
422
423
424 /* Read the lock file and return the pid, returns -1 on error.  True
425    will be stored in the integer at address SAME_NODE if the lock file
426    has been created on the same node. */
427 #ifdef HAVE_POSIX_SYSTEM
428 static int
429 read_lockfile (dotlock_t h, int *same_node )
430 {
431   char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
432                                    names are usually shorter. */
433   int fd;
434   int pid = -1;
435   char *buffer, *p;
436   size_t expected_len;
437   int res, nread;
438
439   *same_node = 0;
440   expected_len = 10 + 1 + h->nodename_len + 1;
441   if ( expected_len >= sizeof buffer_space)
442     {
443       buffer = jnlib_malloc (expected_len);
444       if (!buffer)
445         return -1;
446     }
447   else
448     buffer = buffer_space;
449
450   if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
451     {
452       int e = errno;
453       my_info_2 ("error opening lockfile `%s': %s\n",
454                  h->lockname, strerror(errno) );
455       if (buffer != buffer_space)
456         jnlib_free (buffer);
457       jnlib_set_errno (e); /* Need to return ERRNO here. */
458       return -1;
459     }
460
461   p = buffer;
462   nread = 0;
463   do
464     {
465       res = read (fd, p, expected_len - nread);
466       if (res == -1 && errno == EINTR)
467         continue;
468       if (res < 0)
469         {
470           my_info_1 ("error reading lockfile `%s'\n", h->lockname );
471           close (fd);
472           if (buffer != buffer_space)
473             jnlib_free (buffer);
474           jnlib_set_errno (0); /* Do not return an inappropriate ERRNO. */
475           return -1;
476         }
477       p += res;
478       nread += res;
479     }
480   while (res && nread != expected_len);
481   close(fd);
482
483   if (nread < 11)
484     {
485       my_info_1 ("invalid size of lockfile `%s'\n", h->lockname);
486       if (buffer != buffer_space)
487         jnlib_free (buffer);
488       jnlib_set_errno (0); /* Better don't return an inappropriate ERRNO. */
489       return -1;
490     }
491
492   if (buffer[10] != '\n'
493       || (buffer[10] = 0, pid = atoi (buffer)) == -1
494       || !pid )
495     {
496       my_error_2 ("invalid pid %d in lockfile `%s'\n", pid, h->lockname);
497       if (buffer != buffer_space)
498         jnlib_free (buffer);
499       jnlib_set_errno (0);
500       return -1;
501     }
502
503   if (nread == expected_len
504       && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
505       && buffer[11+h->nodename_len] == '\n')
506     *same_node = 1;
507
508   if (buffer != buffer_space)
509     jnlib_free (buffer);
510   return pid;
511 }
512 #endif /*HAVE_POSIX_SYSTEM */
513
514
515 /* Check whether the file system which stores TNAME supports
516    hardlinks.  Instead of using the non-portable statsfs call which
517    differs between various Unix versions, we do a runtime test.
518    Returns: 0 supports hardlinks; 1 no hardlink support, -1 unknown
519    (test error).  */
520 #ifdef HAVE_POSIX_SYSTEM
521 static int
522 use_hardlinks_p (const char *tname)
523 {
524   char *lname;
525   struct stat sb;
526   unsigned int nlink;
527   int res;
528
529   if (stat (tname, &sb))
530     return -1;
531   nlink = (unsigned int)sb.st_nlink;
532
533   lname = jnlib_malloc (strlen (tname) + 1 + 1);
534   if (!lname)
535     return -1;
536   strcpy (lname, tname);
537   strcat (lname, "x");
538
539   link (tname, lname);
540
541   if (stat (tname, &sb))
542     res = -1;  /* Ooops.  */
543   else if (sb.st_nlink == nlink + 1)
544     res = 0;   /* Yeah, hardlinks are supported.  */
545   else
546     res = 1;   /* No hardlink support.  */
547
548   unlink (lname);
549   jnlib_free (lname);
550   return res;
551 }
552 #endif /*HAVE_POSIX_SYSTEM */
553
554
555 \f
556 #ifdef  HAVE_POSIX_SYSTEM
557 /* Locking core for Unix.  It used a temporary file and the link
558    system call to make locking an atomic operation. */
559 static dotlock_t
560 dotlock_create_unix (dotlock_t h, const char *file_to_lock)
561 {
562   int  fd = -1;
563   char pidstr[16];
564   const char *nodename;
565   const char *dirpart;
566   int dirpartlen;
567   struct utsname utsbuf;
568   size_t tnamelen;
569
570   snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );
571
572   /* Create a temporary file. */
573   if ( uname ( &utsbuf ) )
574     nodename = "unknown";
575   else
576     nodename = utsbuf.nodename;
577
578   if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
579     {
580       dirpart = EXTSEP_S;
581       dirpartlen = 1;
582     }
583   else
584     {
585       dirpartlen = dirpart - file_to_lock;
586       dirpart = file_to_lock;
587     }
588
589   LOCK_all_lockfiles ();
590   h->next = all_lockfiles;
591   all_lockfiles = h;
592
593   tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10 + 1;
594   h->tname = jnlib_malloc (tnamelen + 1);
595   if (!h->tname)
596     {
597       all_lockfiles = h->next;
598       UNLOCK_all_lockfiles ();
599       jnlib_free (h);
600       return NULL;
601     }
602   h->nodename_len = strlen (nodename);
603
604   snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
605   h->nodename_off = strlen (h->tname);
606   snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
607            "%s.%d", nodename, (int)getpid ());
608
609   do
610     {
611       jnlib_set_errno (0);
612       fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
613                  S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
614     }
615   while (fd == -1 && errno == EINTR);
616
617   if ( fd == -1 )
618     {
619       all_lockfiles = h->next;
620       UNLOCK_all_lockfiles ();
621       my_error_2 (_("failed to create temporary file `%s': %s\n"),
622                   h->tname, strerror(errno));
623       jnlib_free (h->tname);
624       jnlib_free (h);
625       return NULL;
626     }
627   if ( write (fd, pidstr, 11 ) != 11 )
628     goto write_failed;
629   if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) )
630     goto write_failed;
631   if ( write (fd, "\n", 1 ) != 1 )
632     goto write_failed;
633   if ( close (fd) )
634     goto write_failed;
635
636   /* Check whether we support hard links.  */
637   switch (use_hardlinks_p (h->tname))
638     {
639     case 0: /* Yes.  */
640       break;
641     case 1: /* No.  */
642       unlink (h->tname);
643       h->use_o_excl = 1;
644       break;
645     default:
646       my_error_2 ("can't check whether hardlinks are supported for `%s': %s\n",
647                   h->tname, strerror(errno));
648       goto write_failed;
649     }
650
651   h->lockname = jnlib_malloc (strlen (file_to_lock) + 6 );
652   if (!h->lockname)
653     {
654       all_lockfiles = h->next;
655       UNLOCK_all_lockfiles ();
656       unlink (h->tname);
657       jnlib_free (h->tname);
658       jnlib_free (h);
659       return NULL;
660     }
661   strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
662   UNLOCK_all_lockfiles ();
663   if (h->use_o_excl)
664     my_debug_1 ("locking for `%s' done via O_EXCL\n", h->lockname);
665
666   return h;
667
668  write_failed:
669   all_lockfiles = h->next;
670   UNLOCK_all_lockfiles ();
671   my_error_2 (_("error writing to `%s': %s\n"), h->tname, strerror (errno));
672   close (fd);
673   unlink (h->tname);
674   jnlib_free (h->tname);
675   jnlib_free (h);
676   return NULL;
677 }
678 #endif /*HAVE_POSIX_SYSTEM*/
679
680
681 #ifdef HAVE_DOSISH_SYSTEM
682 /* Locking core for Windows.  This version does not need a temporary
683    file but uses the plain lock file along with record locking.  We
684    create this file here so that we later only need to do the file
685    locking.  For error reporting it is useful to keep the name of the
686    file in the handle.  */
687 static dotlock_t
688 dotlock_create_w32 (dotlock_t h, const char *file_to_lock)
689 {
690   LOCK_all_lockfiles ();
691   h->next = all_lockfiles;
692   all_lockfiles = h;
693
694   h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
695   if (!h->lockname)
696     {
697       all_lockfiles = h->next;
698       UNLOCK_all_lockfiles ();
699       jnlib_free (h);
700       return NULL;
701     }
702   strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
703
704   /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
705      along with FILE_SHARE_DELETE but that does not work due to a race
706      condition: Despite the OPEN_ALWAYS flag CreateFile may return an
707      error and we can't reliable create/open the lock file unless we
708      would wait here until it works - however there are other valid
709      reasons why a lock file can't be created and thus the process
710      would not stop as expected but spin until Windows crashes.  Our
711      solution is to keep the lock file open; that does not harm. */
712   {
713 #ifdef HAVE_W32CE_SYSTEM
714     wchar_t *wname = utf8_to_wchar (h->lockname);
715
716     if (wname)
717       h->lockhd = CreateFile (wname,
718                               GENERIC_READ|GENERIC_WRITE,
719                               FILE_SHARE_READ|FILE_SHARE_WRITE,
720                               NULL, OPEN_ALWAYS, 0, NULL);
721     else
722       h->lockhd = INVALID_HANDLE_VALUE;
723     jnlib_free (wname);
724 #else
725     h->lockhd = CreateFile (h->lockname,
726                             GENERIC_READ|GENERIC_WRITE,
727                             FILE_SHARE_READ|FILE_SHARE_WRITE,
728                             NULL, OPEN_ALWAYS, 0, NULL);
729 #endif
730   }
731   if (h->lockhd == INVALID_HANDLE_VALUE)
732     {
733       all_lockfiles = h->next;
734       UNLOCK_all_lockfiles ();
735       my_error_2 (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
736       jnlib_free (h->lockname);
737       jnlib_free (h);
738       return NULL;
739     }
740   return h;
741 }
742 #endif /*HAVE_DOSISH_SYSTEM*/
743
744
745 /* Create a lockfile for a file name FILE_TO_LOCK and returns an
746    object of type dotlock_t which may be used later to actually acquire
747    the lock.  A cleanup routine gets installed to cleanup left over
748    locks or other files used internally by the lock mechanism.
749
750    Calling this function with NULL does only install the atexit
751    handler and may thus be used to assure that the cleanup is called
752    after all other atexit handlers.
753
754    This function creates a lock file in the same directory as
755    FILE_TO_LOCK using that name and a suffix of ".lock".  Note that on
756    POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
757    used.
758
759    FLAGS must be 0.
760
761    The function returns an new handle which needs to be released using
762    destroy_dotlock but gets also released at the termination of the
763    process.  On error NULL is returned.
764  */
765
766 dotlock_t
767 dotlock_create (const char *file_to_lock, unsigned int flags)
768 {
769   static int initialized;
770   dotlock_t h;
771
772   if ( !initialized )
773     {
774       atexit (dotlock_remove_lockfiles);
775       initialized = 1;
776     }
777
778   if ( !file_to_lock )
779     return NULL;  /* Only initialization was requested.  */
780
781   if (flags)
782     {
783       jnlib_set_errno (EINVAL);
784       return NULL;
785     }
786
787   h = jnlib_calloc (1, sizeof *h);
788   if (!h)
789     return NULL;
790   h->extra_fd = -1;
791
792   if (never_lock)
793     {
794       h->disable = 1;
795       LOCK_all_lockfiles ();
796       h->next = all_lockfiles;
797       all_lockfiles = h;
798       UNLOCK_all_lockfiles ();
799       return h;
800     }
801
802 #ifdef HAVE_DOSISH_SYSTEM
803   return dotlock_create_w32 (h, file_to_lock);
804 #else /*!HAVE_DOSISH_SYSTEM */
805   return dotlock_create_unix (h, file_to_lock);
806 #endif /*!HAVE_DOSISH_SYSTEM*/
807 }
808
809
810 \f
811 /* Convenience function to store a file descriptor (or any any other
812    integer value) in the context of handle H.  */
813 void
814 dotlock_set_fd (dotlock_t h, int fd)
815 {
816   h->extra_fd = fd;
817 }
818
819 /* Convenience function to retrieve a file descriptor (or any any other
820    integer value) stored in the context of handle H.  */
821 int
822 dotlock_get_fd (dotlock_t h)
823 {
824   return h->extra_fd;
825 }
826
827
828 \f
829 #ifdef HAVE_POSIX_SYSTEM
830 /* Unix specific code of destroy_dotlock.  */
831 static void
832 dotlock_destroy_unix (dotlock_t h)
833 {
834   if (h->locked && h->lockname)
835     unlink (h->lockname);
836   if (h->tname && !h->use_o_excl)
837     unlink (h->tname);
838   jnlib_free (h->tname);
839 }
840 #endif /*HAVE_POSIX_SYSTEM*/
841
842
843 #ifdef HAVE_DOSISH_SYSTEM
844 /* Windows specific code of destroy_dotlock.  */
845 static void
846 dotlock_destroy_w32 (dotlock_t h)
847 {
848   if (h->locked)
849     {
850       OVERLAPPED ovl;
851
852       memset (&ovl, 0, sizeof ovl);
853       UnlockFileEx (h->lockhd, 0, 1, 0, &ovl);
854     }
855   CloseHandle (h->lockhd);
856 }
857 #endif /*HAVE_DOSISH_SYSTEM*/
858
859
860 /* Destroy the locck handle H and release the lock.  */
861 void
862 dotlock_destroy (dotlock_t h)
863 {
864   dotlock_t hprev, htmp;
865
866   if ( !h )
867     return;
868
869   /* First remove the handle from our global list of all locks. */
870   LOCK_all_lockfiles ();
871   for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
872     if (htmp == h)
873       {
874         if (hprev)
875           hprev->next = htmp->next;
876         else
877           all_lockfiles = htmp->next;
878         h->next = NULL;
879         break;
880       }
881   UNLOCK_all_lockfiles ();
882
883   /* Then destroy the lock. */
884   if (!h->disable)
885     {
886 #ifdef HAVE_DOSISH_SYSTEM
887       dotlock_destroy_w32 (h);
888 #else /* !HAVE_DOSISH_SYSTEM */
889       dotlock_destroy_unix (h);
890 #endif /* HAVE_DOSISH_SYSTEM */
891       jnlib_free (h->lockname);
892     }
893   jnlib_free(h);
894 }
895
896
897 \f
898 #ifdef HAVE_POSIX_SYSTEM
899 /* Unix specific code of make_dotlock.  Returns 0 on success and -1 on
900    error.  */
901 static int
902 dotlock_take_unix (dotlock_t h, long timeout)
903 {
904   int wtime = 0;
905   int sumtime = 0;
906   int pid;
907   int lastpid = -1;
908   int ownerchanged;
909   const char *maybe_dead="";
910   int same_node;
911
912  again:
913   if (h->use_o_excl)
914     {
915       /* No hardlink support - use open(O_EXCL).  */
916       int fd;
917
918       do
919         {
920           jnlib_set_errno (0);
921           fd = open (h->lockname, O_WRONLY|O_CREAT|O_EXCL,
922                      S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
923         }
924       while (fd == -1 && errno == EINTR);
925
926       if (fd == -1 && errno == EEXIST)
927         ; /* Lock held by another process.  */
928       else if (fd == -1)
929         {
930           my_error_2 ("lock not made: open(O_EXCL) of `%s' failed: %s\n",
931                       h->lockname, strerror (errno));
932           return -1;
933         }
934       else
935         {
936           char pidstr[16];
937
938           snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid());
939           if (write (fd, pidstr, 11 ) == 11
940               && write (fd, h->tname + h->nodename_off,h->nodename_len)
941               == h->nodename_len
942               && write (fd, "\n", 1) == 1
943               && !close (fd))
944             {
945               h->locked = 1;
946               return 0;
947             }
948           /* Write error.  */
949           my_error_2 ("lock not made: writing to `%s' failed: %s\n",
950                       h->lockname, strerror (errno));
951           close (fd);
952           unlink (h->lockname);
953           return -1;
954         }
955     }
956   else /* Standard method:  Use hardlinks.  */
957     {
958       struct stat sb;
959
960       link (h->tname, h->lockname);
961
962       if (stat (h->tname, &sb))
963         {
964           my_error_1 ("lock not made: Oops: stat of tmp file failed: %s\n",
965                       strerror (errno));
966           /* In theory this might be a severe error: It is possible
967              that link succeeded but stat failed due to changed
968              permissions.  We can't do anything about it, though.  */
969           return -1;
970         }
971
972       if (sb.st_nlink == 2)
973         {
974           h->locked = 1;
975           return 0; /* Okay.  */
976         }
977     }
978
979   /* Check for stale lock files.  */
980   if ( (pid = read_lockfile (h, &same_node)) == -1 )
981     {
982       if ( errno != ENOENT )
983         {
984           my_info_0 ("cannot read lockfile\n");
985           return -1;
986         }
987       my_info_0 ("lockfile disappeared\n");
988       goto again;
989     }
990   else if ( pid == getpid() && same_node )
991     {
992       my_info_0 ("Oops: lock already held by us\n");
993       h->locked = 1;
994       return 0; /* okay */
995     }
996   else if ( same_node && kill (pid, 0) && errno == ESRCH )
997     {
998       /* Note: It is unlikley that we get a race here unless a pid is
999          reused too fast or a new process with the same pid as the one
1000          of the stale file tries to lock right at the same time as we.  */
1001       my_info_1 (_("removing stale lockfile (created by %d)\n"), pid);
1002       unlink (h->lockname);
1003       goto again;
1004     }
1005
1006   if (lastpid == -1)
1007     lastpid = pid;
1008   ownerchanged = (pid != lastpid);
1009
1010   if (timeout)
1011     {
1012       struct timeval tv;
1013
1014       /* Wait until lock has been released.  We use increasing retry
1015          intervals of 50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s
1016          but reset it if the lock owner meanwhile changed.  */
1017       if (!wtime || ownerchanged)
1018         wtime = 50;
1019       else if (wtime < 800)
1020         wtime *= 2;
1021       else if (wtime == 800)
1022         wtime = 2000;
1023       else if (wtime < 8000)
1024         wtime *= 2;
1025
1026       if (timeout > 0)
1027         {
1028           if (wtime > timeout)
1029             wtime = timeout;
1030           timeout -= wtime;
1031         }
1032
1033       sumtime += wtime;
1034       if (sumtime >= 1500)
1035         {
1036           sumtime = 0;
1037           my_info_3 (_("waiting for lock (held by %d%s) %s...\n"),
1038                      pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
1039         }
1040
1041
1042       tv.tv_sec = wtime / 1000;
1043       tv.tv_usec = (wtime % 1000) * 1000;
1044       select (0, NULL, NULL, NULL, &tv);
1045       goto again;
1046     }
1047
1048   jnlib_set_errno (EACCES);
1049   return -1;
1050 }
1051 #endif /*HAVE_POSIX_SYSTEM*/
1052
1053
1054 #ifdef HAVE_DOSISH_SYSTEM
1055 /* Windows specific code of make_dotlock.  Returns 0 on success and -1 on
1056    error.  */
1057 static int
1058 dotlock_take_w32 (dotlock_t h, long timeout)
1059 {
1060   int wtime = 0;
1061   int w32err;
1062   OVERLAPPED ovl;
1063
1064  again:
1065   /* Lock one byte at offset 0.  The offset is given by OVL.  */
1066   memset (&ovl, 0, sizeof ovl);
1067   if (LockFileEx (h->lockhd, (LOCKFILE_EXCLUSIVE_LOCK
1068                               | LOCKFILE_FAIL_IMMEDIATELY), 0, 1, 0, &ovl))
1069     {
1070       h->locked = 1;
1071       return 0; /* okay */
1072     }
1073
1074   w32err = GetLastError ();
1075   if (w32err != ERROR_LOCK_VIOLATION)
1076     {
1077       my_error_2 (_("lock `%s' not made: %s\n"),
1078                   h->lockname, w32_strerror (w32err));
1079       return -1;
1080     }
1081
1082   if (timeout)
1083     {
1084       /* Wait until lock has been released.  We use retry intervals of
1085          50ms, 100ms, 200ms, 400ms, 800ms, 2s, 4s and 8s.  */
1086       if (!wtime)
1087         wtime = 50;
1088       else if (wtime < 800)
1089         wtime *= 2;
1090       else if (wtime == 800)
1091         wtime = 2000;
1092       else if (wtime < 8000)
1093         wtime *= 2;
1094
1095       if (timeout > 0)
1096         {
1097           if (wtime > timeout)
1098             wtime = timeout;
1099           timeout -= wtime;
1100         }
1101
1102       if (wtime >= 800)
1103         my_info_1 (_("waiting for lock %s...\n"), h->lockname);
1104
1105       Sleep (wtime);
1106       goto again;
1107     }
1108
1109   return -1;
1110 }
1111 #endif /*HAVE_DOSISH_SYSTEM*/
1112
1113
1114 /* Take a lock on H.  A value of 0 for TIMEOUT returns immediately if
1115    the lock can't be taked, -1 waits forever (hopefully not), other
1116    values wait for TIMEOUT milliseconds.  Returns: 0 on success  */
1117 int
1118 dotlock_take (dotlock_t h, long timeout)
1119 {
1120   int ret;
1121
1122   if ( h->disable )
1123     return 0; /* Locks are completely disabled.  Return success. */
1124
1125   if ( h->locked )
1126     {
1127       my_debug_1 ("Oops, `%s' is already locked\n", h->lockname);
1128       return 0;
1129     }
1130
1131 #ifdef HAVE_DOSISH_SYSTEM
1132   ret = dotlock_take_w32 (h, timeout);
1133 #else /*!HAVE_DOSISH_SYSTEM*/
1134   ret = dotlock_take_unix (h, timeout);
1135 #endif /*!HAVE_DOSISH_SYSTEM*/
1136
1137   return ret;
1138 }
1139
1140
1141 \f
1142 #ifdef HAVE_POSIX_SYSTEM
1143 /* Unix specific code of release_dotlock.  */
1144 static int
1145 dotlock_release_unix (dotlock_t h)
1146 {
1147   int pid, same_node;
1148
1149   pid = read_lockfile (h, &same_node);
1150   if ( pid == -1 )
1151     {
1152       my_error_0 ("release_dotlock: lockfile error\n");
1153       return -1;
1154     }
1155   if ( pid != getpid() || !same_node )
1156     {
1157       my_error_1 ("release_dotlock: not our lock (pid=%d)\n", pid);
1158       return -1;
1159     }
1160
1161   if ( unlink( h->lockname ) )
1162     {
1163       my_error_1 ("release_dotlock: error removing lockfile `%s'\n",
1164                   h->lockname);
1165       return -1;
1166     }
1167   /* Fixme: As an extra check we could check whether the link count is
1168      now really at 1. */
1169   return 0;
1170 }
1171 #endif /*HAVE_POSIX_SYSTEM */
1172
1173
1174 #ifdef HAVE_DOSISH_SYSTEM
1175 /* Windows specific code of release_dotlock.  */
1176 static int
1177 dotlock_release_w32 (dotlock_t h)
1178 {
1179   OVERLAPPED ovl;
1180
1181   memset (&ovl, 0, sizeof ovl);
1182   if (!UnlockFileEx (h->lockhd, 0, 1, 0, &ovl))
1183     {
1184       my_error_2 ("release_dotlock: error removing lockfile `%s': %s\n",
1185                   h->lockname, w32_strerror (-1));
1186       return -1;
1187     }
1188
1189   return 0;
1190 }
1191 #endif /*HAVE_DOSISH_SYSTEM */
1192
1193
1194 /* Release a lock.  Returns 0 on success.  */
1195 int
1196 dotlock_release (dotlock_t h)
1197 {
1198   int ret;
1199
1200   /* To avoid atexit race conditions we first check whether there are
1201      any locks left.  It might happen that another atexit handler
1202      tries to release the lock while the atexit handler of this module
1203      already ran and thus H is undefined.  */
1204   LOCK_all_lockfiles ();
1205   ret = !all_lockfiles;
1206   UNLOCK_all_lockfiles ();
1207   if (ret)
1208     return 0;
1209
1210   if ( h->disable )
1211     return 0;
1212
1213   if ( !h->locked )
1214     {
1215       my_debug_1 ("Oops, `%s' is not locked\n", h->lockname);
1216       return 0;
1217     }
1218
1219 #ifdef HAVE_DOSISH_SYSTEM
1220   ret = dotlock_release_w32 (h);
1221 #else
1222   ret = dotlock_release_unix (h);
1223 #endif
1224
1225   if (!ret)
1226     h->locked = 0;
1227   return ret;
1228 }
1229
1230
1231 \f
1232 /* Remove all lockfiles.  This is called by the atexit handler
1233    installed by this module but may also be called by other
1234    termination handlers.  */
1235 void
1236 dotlock_remove_lockfiles (void)
1237 {
1238   dotlock_t h, h2;
1239
1240   /* First set the lockfiles list to NULL so that for example
1241      dotlock_release is ware that this fucntion is currently
1242      running.  */
1243   LOCK_all_lockfiles ();
1244   h = all_lockfiles;
1245   all_lockfiles = NULL;
1246   UNLOCK_all_lockfiles ();
1247
1248   while ( h )
1249     {
1250       h2 = h->next;
1251       dotlock_destroy (h);
1252       h = h2;
1253     }
1254 }