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