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