Add --reload command to gpgconf.
[gnupg.git] / jnlib / dotlock.c
1 /* dotlock.c - dotfile locking
2  * Copyright (C) 1998, 2000, 2001, 2003, 2004, 
3  *               2005, 2006, 2008 Free Software Foundation, Inc.
4  *
5  * This file is part of JNLIB.
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 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #ifdef  HAVE_DOSISH_SYSTEM
29 # define WIN32_LEAN_AND_MEAN
30 # include <windows.h>
31 #else
32 # include <sys/utsname.h>
33 #endif
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <signal.h>
39
40 #include "libjnlib-config.h"
41 #include "stringhelp.h"
42 #include "dotlock.h"
43
44 #if !defined(DIRSEP_C) && !defined(EXTSEP_C) \
45     && !defined(DIRSEP_S) && !defined(EXTSEP_S)
46 #ifdef HAVE_DOSISH_SYSTEM
47 #define DIRSEP_C '\\'
48 #define EXTSEP_C '.'
49 #define DIRSEP_S "\\"
50 #define EXTSEP_S "."
51 #else
52 #define DIRSEP_C '/'
53 #define EXTSEP_C '.'
54 #define DIRSEP_S "/"
55 #define EXTSEP_S "."
56 #endif
57 #endif
58
59
60 /* The object describing a lock.  */
61 struct dotlock_handle 
62 {
63   struct dotlock_handle *next;
64   char *lockname;      /* Name of the actual lockfile.          */
65   int locked;          /* Lock status.                          */
66   int disable;         /* If true, locking is disabled.         */
67
68 #ifdef HAVE_DOSISH_SYSTEM
69   HANDLE lockhd;       /* The W32 handle of the lock file.      */
70 #else
71   char *tname;         /* Name of the lockfile template.        */
72   size_t nodename_off; /* Offset in TNAME of the nodename part. */
73   size_t nodename_len; /* Length of the nodename part.          */
74 #endif /* HAVE_DOSISH_SYSTEM */
75 };
76
77
78 /* A list of of all lock handles. */
79 static volatile DOTLOCK all_lockfiles;
80
81 /* If this has the value true all locking is disabled.  */
82 static int never_lock;
83
84
85 /* Local protototypes.  */
86 #ifndef HAVE_DOSISH_SYSTEM
87 static int read_lockfile (DOTLOCK h, int *same_node);
88 #endif /*!HAVE_DOSISH_SYSTEM*/
89
90
91
92 \f
93 /* Entirely disable all locking.  This function should be called
94    before any locking is done.  It may be called right at startup of
95    the process as it only sets a global value.  */
96 void
97 disable_dotlock(void)
98 {
99   never_lock = 1;
100 }
101
102
103
104 /* Create a lockfile for a file name FILE_TO_LOCK and returns an
105    object of type DOTLOCK which may be used later to actually acquire
106    the lock.  A cleanup routine gets installed to cleanup left over
107    locks or other files used internally by the lock mechanism.
108
109    Calling this function with NULL does only install the atexit
110    handler and may thus be used to assure that the cleanup is called
111    after all other atexit handlers.
112   
113    This function creates a lock file in the same directory as
114    FILE_TO_LOCK using that name and a suffix of ".lock".  Note that on
115    POSIX systems a temporary file ".#lk.<hostname>.pid[.threadid] is
116    used.
117
118    The function returns an new handle which needs to be released using
119    destroy_dotlock but gets also released at the termination of the
120    process.  On error NULL is returned.
121  */
122 DOTLOCK
123 create_dotlock (const char *file_to_lock)
124 {
125   static int initialized;
126   DOTLOCK h;
127 #ifndef  HAVE_DOSISH_SYSTEM
128   int  fd = -1;
129   char pidstr[16];
130   const char *nodename;
131   const char *dirpart;
132   int dirpartlen;
133   struct utsname utsbuf;
134   size_t tnamelen;
135 #endif
136
137   if ( !initialized )
138     {
139       atexit (dotlock_remove_lockfiles);
140       initialized = 1;
141     }
142
143   if ( !file_to_lock )
144     return NULL;  /* Only initialization was requested.  */
145
146   h = jnlib_calloc (1, sizeof *h);
147   if (!h)
148     return NULL;
149
150   if (never_lock)
151     {
152       h->disable = 1;
153 #ifdef _REENTRANT
154       /* fixme: aquire mutex on all_lockfiles */
155 #endif
156       h->next = all_lockfiles;
157       all_lockfiles = h;
158       return h;
159     }
160
161 #ifndef HAVE_DOSISH_SYSTEM
162   /*
163      This is the POSIX version which uses a temporary file and the
164      link system call to make locking an atomic operation.
165    */
166
167   snprintf (pidstr, sizeof pidstr, "%10d\n", (int)getpid() );
168   /* fixme: add the hostname to the second line (FQDN or IP addr?) */
169
170   /* Create a temporary file. */
171   if ( uname ( &utsbuf ) )
172     nodename = "unknown";
173   else
174     nodename = utsbuf.nodename;
175   
176 #ifdef __riscos__
177   {
178     char *iter = (char *) nodename;
179     for (; iter[0]; iter++)
180       if (iter[0] == '.')
181         iter[0] = '/';
182   }
183 #endif /* __riscos__ */
184
185   if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
186     {
187       dirpart = EXTSEP_S;
188       dirpartlen = 1;
189     }
190   else
191     {
192       dirpartlen = dirpart - file_to_lock;
193       dirpart = file_to_lock;
194     }
195
196 #ifdef _REENTRANT
197     /* fixme: aquire mutex on all_lockfiles */
198 #endif
199   h->next = all_lockfiles;
200   all_lockfiles = h;
201
202   tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10;
203   h->tname = jnlib_malloc (tnamelen + 1);
204   if (!h->tname)
205     {
206       all_lockfiles = h->next;
207       jnlib_free (h);
208       return NULL;
209     }
210   h->nodename_len = strlen (nodename);
211
212 #ifndef __riscos__
213   snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
214   h->nodename_off = strlen (h->tname);
215   snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
216            "%s.%d", nodename, (int)getpid ());
217 #else /* __riscos__ */
218   snprintf (h->tname, tnamelen, "%.*s.lk%p/", dirpartlen, dirpart, h );
219   h->nodename_off = strlen (h->tname);
220   snprintf (h->tname+h->nodename_off, tnamelen - h->modename_off,
221             "%s/%d", nodename, (int)getpid () );
222 #endif /* __riscos__ */
223
224   do 
225     {
226       errno = 0;
227       fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
228                  S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
229     } 
230   while (fd == -1 && errno == EINTR);
231
232   if ( fd == -1 ) 
233     {
234       all_lockfiles = h->next;
235       log_error (_("failed to create temporary file `%s': %s\n"),
236                   h->tname, strerror(errno));
237       jnlib_free (h->tname);
238       jnlib_free (h);
239       return NULL;
240     }
241   if ( write (fd, pidstr, 11 ) != 11 )
242     goto write_failed;
243   if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) )
244     goto write_failed;
245   if ( write (fd, "\n", 1 ) != 1 )
246     goto write_failed;
247   if ( close (fd) )
248     goto write_failed;
249
250 # ifdef _REENTRANT
251   /* release mutex */
252 # endif
253   h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
254   if (!h->lockname)
255     {
256       all_lockfiles = h->next;
257       unlink (h->tname);
258       jnlib_free (h->tname);
259       jnlib_free (h);
260       return NULL;
261     }
262   strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
263   return h;
264
265  write_failed:
266   all_lockfiles = h->next;
267 # ifdef _REENTRANT
268   /* fixme: release mutex */
269 # endif
270   log_error ( _("error writing to `%s': %s\n"), h->tname, strerror(errno) );
271   close (fd);
272   unlink (h->tname);
273   jnlib_free (h->tname);
274   jnlib_free (h);
275   return NULL;
276
277 #else /* HAVE_DOSISH_SYSTEM */
278
279   /* The Windows version does not need a temporary file but uses the
280      plain lock file along with record locking.  We create this file
281      here so that we later do only need to do the file locking.  For
282      error reporting it is useful to keep the name of the file in the
283      handle.  */
284   h->next = all_lockfiles;
285   all_lockfiles = h;
286
287   h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
288   if (!h->lockname)
289     {
290       all_lockfiles = h->next;
291       jnlib_free (h);
292       return NULL;
293     }
294   strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
295
296   /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
297      along with FILE_SHARE_DELETE but that does not work due to a race
298      condition: Despite the OPEN_ALWAYS flag CreateFile may return an
299      error and we can't reliable create/open the lock file unless we
300      would wait here until it works - however there are other valid
301      reasons why a lock file can't be created and thus the process
302      would not stop as expected but spin til until Windows crashes.
303      Our solution is to keep the lock file open; that does not
304      harm. */ 
305   h->lockhd = CreateFile (h->lockname,
306                           GENERIC_READ|GENERIC_WRITE,
307                           FILE_SHARE_READ|FILE_SHARE_WRITE,
308                           NULL, OPEN_ALWAYS, 0, NULL);
309   if (h->lockhd == INVALID_HANDLE_VALUE)
310     {
311       log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
312       all_lockfiles = h->next;
313       jnlib_free (h->lockname);
314       jnlib_free (h);
315       return NULL;
316     }
317   return h;
318
319 #endif /* HAVE_DOSISH_SYSTEM */
320 }
321
322
323 /* Destroy the local handle H and release the lock. */
324 void
325 destroy_dotlock ( DOTLOCK h )
326 {
327   DOTLOCK hprev, htmp;
328
329   if ( !h )
330     return;
331
332   /* First remove the handle from our global list of all locks. */
333   for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
334     if (htmp == h)
335       {
336         if (hprev)
337           hprev->next = htmp->next;
338         else
339           all_lockfiles = htmp->next;
340         h->next = NULL;
341         break;
342       }
343   
344   /* Then destroy the lock. */
345   if (!h->disable)
346     {
347 #ifdef HAVE_DOSISH_SYSTEM
348       if (h->locked)
349         {
350           UnlockFile (h->lockhd, 0, 0, 1, 0);
351         }
352       CloseHandle (h->lockhd);
353 #else /* !HAVE_DOSISH_SYSTEM */
354       if (h->locked && h->lockname)
355         unlink (h->lockname);
356       if (h->tname)
357         unlink (h->tname);
358       jnlib_free (h->tname);
359 #endif /* HAVE_DOSISH_SYSTEM */
360       jnlib_free (h->lockname);
361     }
362   jnlib_free(h);
363 }
364
365
366 #ifndef HAVE_DOSISH_SYSTEM
367 static int
368 maybe_deadlock( DOTLOCK h )
369 {
370   DOTLOCK r;
371
372   for ( r=all_lockfiles; r; r = r->next )
373     {
374       if ( r != h && r->locked )
375         return 1;
376     }
377   return 0;
378 }
379 #endif /*!HAVE_DOSISH_SYSTEM*/
380
381
382
383 /* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits
384    forever (hopefully not), other values are reserved (should then be
385    timeouts in milliseconds).  Returns: 0 on success  */
386 int
387 make_dotlock ( DOTLOCK h, long timeout )
388 {
389   int backoff = 0;
390 #ifndef HAVE_DOSISH_SYSTEM
391   int  pid;
392   const char *maybe_dead="";
393   int same_node;
394 #endif /*!HAVE_DOSISH_SYSTEM*/
395
396   if ( h->disable )
397     return 0; /* Locks are completely disabled.  Return success. */
398
399   if ( h->locked ) 
400     {
401 #ifndef __riscos__
402       log_debug ("Oops, `%s' is already locked\n", h->lockname);
403 #endif /* !__riscos__ */
404       return 0;
405     }
406
407   for (;;)
408     {
409 #ifndef HAVE_DOSISH_SYSTEM
410 # ifndef __riscos__
411       if ( !link(h->tname, h->lockname) )
412         {
413           /* fixme: better use stat to check the link count */
414           h->locked = 1;
415           return 0; /* okay */
416         }
417       if ( errno != EEXIST )
418         {
419           log_error ( "lock not made: link() failed: %s\n", strerror(errno) );
420           return -1;
421         }
422 # else /* __riscos__ */
423       if ( !renamefile(h->tname, h->lockname) ) 
424         {
425           h->locked = 1;
426           return 0; /* okay */
427         }
428       if ( errno != EEXIST ) 
429         {
430           log_error( "lock not made: rename() failed: %s\n", strerror(errno) );
431           return -1;
432         }
433 # endif /* __riscos__ */
434
435       if ( (pid = read_lockfile (h, &same_node)) == -1 ) 
436         {
437           if ( errno != ENOENT )
438             {
439               log_info ("cannot read lockfile\n");
440               return -1;
441             }
442           log_info( "lockfile disappeared\n");
443           continue;
444         }
445       else if ( pid == getpid() && same_node )
446         {
447           log_info( "Oops: lock already held by us\n");
448           h->locked = 1;
449           return 0; /* okay */
450         }
451       else if ( same_node && kill (pid, 0) && errno == ESRCH )
452         {
453 # ifndef __riscos__
454           log_info (_("removing stale lockfile (created by %d)\n"), pid );
455           unlink (h->lockname);
456           continue;
457 # else /* __riscos__ */
458           /* Under RISCOS we are *pretty* sure that the other task
459              is dead and therefore we remove the stale lock file. */
460           maybe_dead = _(" - probably dead - removing lock");
461           unlink(h->lockname);
462 # endif /* __riscos__ */
463         }
464
465       if ( timeout == -1 ) 
466         {
467           /* Wait until lock has been released. */
468           struct timeval tv;
469           
470           log_info (_("waiting for lock (held by %d%s) %s...\n"),
471                     pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
472
473
474           /* We can't use sleep, cause signals may be blocked. */
475           tv.tv_sec = 1 + backoff;
476           tv.tv_usec = 0;
477           select(0, NULL, NULL, NULL, &tv);
478           if ( backoff < 10 )
479             backoff++ ;
480         }
481       else
482         return -1;
483 #else /*HAVE_DOSISH_SYSTEM*/
484       int w32err;
485
486       if (LockFile (h->lockhd, 0, 0, 1, 0))
487         {
488           h->locked = 1;
489           return 0; /* okay */
490         }
491       w32err = GetLastError ();
492       if (w32err != ERROR_LOCK_VIOLATION)
493         {
494           log_error (_("lock `%s' not made: %s\n"),
495                      h->lockname, w32_strerror (w32err));
496           return -1;
497         }
498
499       if ( timeout == -1 ) 
500         {
501           /* Wait until lock has been released. */
502           log_info (_("waiting for lock %s...\n"), h->lockname);
503           Sleep ((1 + backoff)*1000);
504           if ( backoff < 10 )
505             backoff++ ;
506         }
507       else
508         return -1;
509 #endif /*HAVE_DOSISH_SYSTEM*/
510     }
511   /*NOTREACHED*/
512 }
513
514
515 /* Release a lock.  Returns 0 on success.  */
516 int
517 release_dotlock( DOTLOCK h )
518 {
519 #ifndef HAVE_DOSISH_SYSTEM
520   int pid, same_node;
521 #endif
522
523   /* To avoid atexit race conditions we first check whether there are
524      any locks left.  It might happen that another atexit handler
525      tries to release the lock while the atexit handler of this module
526      already ran and thus H is undefined.  */
527   if (!all_lockfiles)
528     return 0;
529
530   if ( h->disable )
531     return 0;
532
533   if ( !h->locked )
534     {
535       log_debug("Oops, `%s' is not locked\n", h->lockname);
536       return 0;
537     }
538
539 #ifdef HAVE_DOSISH_SYSTEM
540   if (!UnlockFile (h->lockhd, 0, 0, 1, 0))
541     {
542       log_error ("release_dotlock: error removing lockfile `%s': %s\n",
543                  h->lockname, w32_strerror (-1));
544       return -1;
545     }
546 #else
547
548   pid = read_lockfile (h, &same_node);
549   if ( pid == -1 ) 
550     {
551       log_error( "release_dotlock: lockfile error\n");
552       return -1;
553     }
554   if ( pid != getpid() || !same_node )
555     {
556       log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
557       return -1;
558     }
559
560 #ifndef __riscos__
561   if ( unlink( h->lockname ) )
562     {
563       log_error ("release_dotlock: error removing lockfile `%s'\n",
564                  h->lockname);
565       return -1;
566     }
567   /* Fixme: As an extra check we could check whether the link count is
568      now really at 1. */
569 #else /* __riscos__ */
570   if ( renamefile (h->lockname, h->tname) ) 
571     {
572       log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n",
573                  h->lockname, h->tname);
574       return -1;
575     }
576 #endif /* __riscos__ */
577
578 #endif /* !HAVE_DOSISH_SYSTEM */
579   h->locked = 0;
580   return 0;
581 }
582
583
584 /* Read the lock file and return the pid, returns -1 on error.  True
585    will be stored in the integer at address SAME_NODE if the lock file
586    has been created on the same node. */
587 #ifndef HAVE_DOSISH_SYSTEM
588 static int
589 read_lockfile (DOTLOCK h, int *same_node )
590 {
591   char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
592                                    name are usually shorter. */
593   int fd;
594   int pid = -1;
595   char *buffer, *p;
596   size_t expected_len;
597   int res, nread;
598   
599   *same_node = 0;
600   expected_len = 10 + 1 + h->nodename_len + 1;
601   if ( expected_len >= sizeof buffer_space)
602     buffer = jnlib_xmalloc (expected_len);
603   else
604     buffer = buffer_space;
605
606   if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
607     {
608       int e = errno;
609       log_info ("error opening lockfile `%s': %s\n",
610                 h->lockname, strerror(errno) );
611       if (buffer != buffer_space)
612         jnlib_free (buffer);
613       errno = e; /* Need to return ERRNO here. */
614       return -1;
615     }
616
617   p = buffer;
618   nread = 0;
619   do
620     {
621       res = read (fd, p, expected_len - nread);
622       if (res == -1 && errno == EINTR)
623         continue;
624       if (res < 0)
625         {
626           log_info ("error reading lockfile `%s'", h->lockname );
627           close (fd); 
628           if (buffer != buffer_space)
629             jnlib_free (buffer);
630           errno = 0; /* Do not return an inappropriate ERRNO. */
631           return -1;
632         }
633       p += res;
634       nread += res;
635     }
636   while (res && nread != expected_len);
637   close(fd);
638
639   if (nread < 11)
640     {
641       log_info ("invalid size of lockfile `%s'", h->lockname );
642       if (buffer != buffer_space)
643         jnlib_free (buffer);
644       errno = 0; /* Better don't return an inappropriate ERRNO. */
645       return -1;
646     }
647
648   if (buffer[10] != '\n'
649       || (buffer[10] = 0, pid = atoi (buffer)) == -1
650 #ifndef __riscos__
651       || !pid 
652 #else /* __riscos__ */
653       || (!pid && riscos_getpid())
654 #endif /* __riscos__ */
655       )
656     {
657       log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname );
658       if (buffer != buffer_space)
659         jnlib_free (buffer);
660       errno = 0;
661       return -1;
662     }
663
664   if (nread == expected_len
665       && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len) 
666       && buffer[11+h->nodename_len] == '\n')
667     *same_node = 1;
668
669   if (buffer != buffer_space)
670     jnlib_free (buffer);
671   return pid;
672 }
673 #endif /* !HAVE_DOSISH_SYSTEM */
674
675
676 /* Remove all lockfiles.  This is usually called by the atexit handler
677    installed by this module but may also be called by other
678    termination handlers.  */
679 void
680 dotlock_remove_lockfiles()
681 {
682   DOTLOCK h, h2;
683   
684   h = all_lockfiles;
685   all_lockfiles = NULL;
686     
687   while ( h )
688     {
689       h2 = h->next;
690       destroy_dotlock (h);
691       h = h2;
692     }
693 }
694