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