g10: Fix card-edit/fetch to use keyserver_fetch.
[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
169   /* Create a temporary file. */
170   if ( uname ( &utsbuf ) )
171     nodename = "unknown";
172   else
173     nodename = utsbuf.nodename;
174
175 #ifdef __riscos__
176   {
177     char *iter = (char *) nodename;
178     for (; iter[0]; iter++)
179       if (iter[0] == '.')
180         iter[0] = '/';
181   }
182 #endif /* __riscos__ */
183
184   if ( !(dirpart = strrchr (file_to_lock, DIRSEP_C)) )
185     {
186       dirpart = EXTSEP_S;
187       dirpartlen = 1;
188     }
189   else
190     {
191       dirpartlen = dirpart - file_to_lock;
192       dirpart = file_to_lock;
193     }
194
195 #ifdef _REENTRANT
196     /* fixme: aquire mutex on all_lockfiles */
197 #endif
198   h->next = all_lockfiles;
199   all_lockfiles = h;
200
201   tnamelen = dirpartlen + 6 + 30 + strlen(nodename) + 10;
202   h->tname = jnlib_malloc (tnamelen + 1);
203   if (!h->tname)
204     {
205       all_lockfiles = h->next;
206       jnlib_free (h);
207       return NULL;
208     }
209   h->nodename_len = strlen (nodename);
210
211 #ifndef __riscos__
212   snprintf (h->tname, tnamelen, "%.*s/.#lk%p.", dirpartlen, dirpart, h );
213   h->nodename_off = strlen (h->tname);
214   snprintf (h->tname+h->nodename_off, tnamelen - h->nodename_off,
215            "%s.%d", nodename, (int)getpid ());
216 #else /* __riscos__ */
217   snprintf (h->tname, tnamelen, "%.*s.lk%p/", dirpartlen, dirpart, h );
218   h->nodename_off = strlen (h->tname);
219   snprintf (h->tname+h->nodename_off, tnamelen - h->modename_off,
220             "%s/%d", nodename, (int)getpid () );
221 #endif /* __riscos__ */
222
223   do
224     {
225       errno = 0;
226       fd = open (h->tname, O_WRONLY|O_CREAT|O_EXCL,
227                  S_IRUSR|S_IRGRP|S_IROTH|S_IWUSR );
228     }
229   while (fd == -1 && errno == EINTR);
230
231   if ( fd == -1 )
232     {
233       all_lockfiles = h->next;
234       log_error (_("failed to create temporary file `%s': %s\n"),
235                   h->tname, strerror(errno));
236       jnlib_free (h->tname);
237       jnlib_free (h);
238       return NULL;
239     }
240   if ( write (fd, pidstr, 11 ) != 11 )
241     goto write_failed;
242   if ( write (fd, nodename, strlen (nodename) ) != strlen (nodename) )
243     goto write_failed;
244   if ( write (fd, "\n", 1 ) != 1 )
245     goto write_failed;
246   if ( close (fd) )
247     {
248       if ( errno == EINTR )
249         fd = -1;
250       goto write_failed;
251     }
252   fd = -1;
253
254 # ifdef _REENTRANT
255   /* release mutex */
256 # endif
257   h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
258   if (!h->lockname)
259     {
260       all_lockfiles = h->next;
261       unlink (h->tname);
262       jnlib_free (h->tname);
263       jnlib_free (h);
264       return NULL;
265     }
266   strcpy (stpcpy (h->lockname, file_to_lock), EXTSEP_S "lock");
267   return h;
268
269  write_failed:
270   all_lockfiles = h->next;
271 # ifdef _REENTRANT
272   /* fixme: release mutex */
273 # endif
274   log_error ( _("error writing to `%s': %s\n"), h->tname, strerror(errno) );
275   if (fd != -1)
276     close (fd);
277   unlink (h->tname);
278   jnlib_free (h->tname);
279   jnlib_free (h);
280   return NULL;
281
282 #else /* HAVE_DOSISH_SYSTEM */
283
284   /* The Windows version does not need a temporary file but uses the
285      plain lock file along with record locking.  We create this file
286      here so that we later do only need to do the file locking.  For
287      error reporting it is useful to keep the name of the file in the
288      handle.  */
289   h->next = all_lockfiles;
290   all_lockfiles = h;
291
292   h->lockname = jnlib_malloc ( strlen (file_to_lock) + 6 );
293   if (!h->lockname)
294     {
295       all_lockfiles = h->next;
296       jnlib_free (h);
297       return NULL;
298     }
299   strcpy (stpcpy(h->lockname, file_to_lock), EXTSEP_S "lock");
300
301   /* If would be nice if we would use the FILE_FLAG_DELETE_ON_CLOSE
302      along with FILE_SHARE_DELETE but that does not work due to a race
303      condition: Despite the OPEN_ALWAYS flag CreateFile may return an
304      error and we can't reliable create/open the lock file unless we
305      would wait here until it works - however there are other valid
306      reasons why a lock file can't be created and thus the process
307      would not stop as expected but spin til until Windows crashes.
308      Our solution is to keep the lock file open; that does not
309      harm. */
310   h->lockhd = CreateFile (h->lockname,
311                           GENERIC_READ|GENERIC_WRITE,
312                           FILE_SHARE_READ|FILE_SHARE_WRITE,
313                           NULL, OPEN_ALWAYS, 0, NULL);
314   if (h->lockhd == INVALID_HANDLE_VALUE)
315     {
316       log_error (_("can't create `%s': %s\n"), h->lockname, w32_strerror (-1));
317       all_lockfiles = h->next;
318       jnlib_free (h->lockname);
319       jnlib_free (h);
320       return NULL;
321     }
322   return h;
323
324 #endif /* HAVE_DOSISH_SYSTEM */
325 }
326
327
328 /* Destroy the local handle H and release the lock. */
329 void
330 destroy_dotlock ( DOTLOCK h )
331 {
332   DOTLOCK hprev, htmp;
333
334   if ( !h )
335     return;
336
337   /* First remove the handle from our global list of all locks. */
338   for (hprev=NULL, htmp=all_lockfiles; htmp; hprev=htmp, htmp=htmp->next)
339     if (htmp == h)
340       {
341         if (hprev)
342           hprev->next = htmp->next;
343         else
344           all_lockfiles = htmp->next;
345         h->next = NULL;
346         break;
347       }
348
349   /* Then destroy the lock. */
350   if (!h->disable)
351     {
352 #ifdef HAVE_DOSISH_SYSTEM
353       if (h->locked)
354         {
355           UnlockFile (h->lockhd, 0, 0, 1, 0);
356         }
357       CloseHandle (h->lockhd);
358 #else /* !HAVE_DOSISH_SYSTEM */
359       if (h->locked && h->lockname)
360         unlink (h->lockname);
361       if (h->tname)
362         unlink (h->tname);
363       jnlib_free (h->tname);
364 #endif /* HAVE_DOSISH_SYSTEM */
365       jnlib_free (h->lockname);
366     }
367   jnlib_free(h);
368 }
369
370
371 #ifndef HAVE_DOSISH_SYSTEM
372 static int
373 maybe_deadlock( DOTLOCK h )
374 {
375   DOTLOCK r;
376
377   for ( r=all_lockfiles; r; r = r->next )
378     {
379       if ( r != h && r->locked )
380         return 1;
381     }
382   return 0;
383 }
384 #endif /*!HAVE_DOSISH_SYSTEM*/
385
386
387
388 /* Do a lock on H. A TIMEOUT of 0 returns immediately, -1 waits
389    forever (hopefully not), other values are reserved (should then be
390    timeouts in milliseconds).  Returns: 0 on success  */
391 int
392 make_dotlock ( DOTLOCK h, long timeout )
393 {
394   int backoff = 0;
395 #ifndef HAVE_DOSISH_SYSTEM
396   int  pid;
397   const char *maybe_dead="";
398   int same_node;
399 #endif /*!HAVE_DOSISH_SYSTEM*/
400
401   if ( h->disable )
402     return 0; /* Locks are completely disabled.  Return success. */
403
404   if ( h->locked )
405     {
406 #ifndef __riscos__
407       log_debug ("Oops, `%s' is already locked\n", h->lockname);
408 #endif /* !__riscos__ */
409       return 0;
410     }
411
412   for (;;)
413     {
414 #ifndef HAVE_DOSISH_SYSTEM
415 # ifndef __riscos__
416       if ( !link(h->tname, h->lockname) )
417         {
418           /* fixme: better use stat to check the link count */
419           h->locked = 1;
420           return 0; /* okay */
421         }
422       if ( errno != EEXIST )
423         {
424           log_error ( "lock not made: link() failed: %s\n", strerror(errno) );
425           return -1;
426         }
427 # else /* __riscos__ */
428       if ( !renamefile(h->tname, h->lockname) )
429         {
430           h->locked = 1;
431           return 0; /* okay */
432         }
433       if ( errno != EEXIST )
434         {
435           log_error( "lock not made: rename() failed: %s\n", strerror(errno) );
436           return -1;
437         }
438 # endif /* __riscos__ */
439
440       if ( (pid = read_lockfile (h, &same_node)) == -1 )
441         {
442           if ( errno != ENOENT )
443             {
444               log_info ("cannot read lockfile\n");
445               return -1;
446             }
447           log_info( "lockfile disappeared\n");
448           continue;
449         }
450       else if ( pid == getpid() && same_node )
451         {
452           log_info( "Oops: lock already held by us\n");
453           h->locked = 1;
454           return 0; /* okay */
455         }
456       else if ( same_node && kill (pid, 0) && errno == ESRCH )
457         {
458 # ifndef __riscos__
459           log_info (_("removing stale lockfile (created by %d)\n"), pid );
460           unlink (h->lockname);
461           continue;
462 # else /* __riscos__ */
463           /* Under RISCOS we are *pretty* sure that the other task
464              is dead and therefore we remove the stale lock file. */
465           maybe_dead = _(" - probably dead - removing lock");
466           unlink(h->lockname);
467 # endif /* __riscos__ */
468         }
469
470       if ( timeout == -1 )
471         {
472           /* Wait until lock has been released. */
473           struct timeval tv;
474
475           log_info (_("waiting for lock (held by %d%s) %s...\n"),
476                     pid, maybe_dead, maybe_deadlock(h)? _("(deadlock?) "):"");
477
478
479           /* We can't use sleep, cause signals may be blocked. */
480           tv.tv_sec = 1 + backoff;
481           tv.tv_usec = 0;
482           select(0, NULL, NULL, NULL, &tv);
483           if ( backoff < 10 )
484             backoff++ ;
485         }
486       else
487         return -1;
488 #else /*HAVE_DOSISH_SYSTEM*/
489       int w32err;
490
491       if (LockFile (h->lockhd, 0, 0, 1, 0))
492         {
493           h->locked = 1;
494           return 0; /* okay */
495         }
496       w32err = GetLastError ();
497       if (w32err != ERROR_LOCK_VIOLATION)
498         {
499           log_error (_("lock `%s' not made: %s\n"),
500                      h->lockname, w32_strerror (w32err));
501           return -1;
502         }
503
504       if ( timeout == -1 )
505         {
506           /* Wait until lock has been released. */
507           log_info (_("waiting for lock %s...\n"), h->lockname);
508           Sleep ((1 + backoff)*1000);
509           if ( backoff < 10 )
510             backoff++ ;
511         }
512       else
513         return -1;
514 #endif /*HAVE_DOSISH_SYSTEM*/
515     }
516   /*NOTREACHED*/
517 }
518
519
520 /* Release a lock.  Returns 0 on success.  */
521 int
522 release_dotlock( DOTLOCK h )
523 {
524 #ifndef HAVE_DOSISH_SYSTEM
525   int pid, same_node;
526 #endif
527
528   /* To avoid atexit race conditions we first check whether there are
529      any locks left.  It might happen that another atexit handler
530      tries to release the lock while the atexit handler of this module
531      already ran and thus H is undefined.  */
532   if (!all_lockfiles)
533     return 0;
534
535   if ( h->disable )
536     return 0;
537
538   if ( !h->locked )
539     {
540       log_debug("Oops, `%s' is not locked\n", h->lockname);
541       return 0;
542     }
543
544 #ifdef HAVE_DOSISH_SYSTEM
545   if (!UnlockFile (h->lockhd, 0, 0, 1, 0))
546     {
547       log_error ("release_dotlock: error removing lockfile `%s': %s\n",
548                  h->lockname, w32_strerror (-1));
549       return -1;
550     }
551 #else
552
553   pid = read_lockfile (h, &same_node);
554   if ( pid == -1 )
555     {
556       log_error( "release_dotlock: lockfile error\n");
557       return -1;
558     }
559   if ( pid != getpid() || !same_node )
560     {
561       log_error( "release_dotlock: not our lock (pid=%d)\n", pid);
562       return -1;
563     }
564
565 #ifndef __riscos__
566   if ( unlink( h->lockname ) )
567     {
568       log_error ("release_dotlock: error removing lockfile `%s'\n",
569                  h->lockname);
570       return -1;
571     }
572   /* Fixme: As an extra check we could check whether the link count is
573      now really at 1. */
574 #else /* __riscos__ */
575   if ( renamefile (h->lockname, h->tname) )
576     {
577       log_error ("release_dotlock: error renaming lockfile `%s' to `%s'\n",
578                  h->lockname, h->tname);
579       return -1;
580     }
581 #endif /* __riscos__ */
582
583 #endif /* !HAVE_DOSISH_SYSTEM */
584   h->locked = 0;
585   return 0;
586 }
587
588
589 /* Read the lock file and return the pid, returns -1 on error.  True
590    will be stored in the integer at address SAME_NODE if the lock file
591    has been created on the same node. */
592 #ifndef HAVE_DOSISH_SYSTEM
593 static int
594 read_lockfile (DOTLOCK h, int *same_node )
595 {
596   char buffer_space[10+1+70+1]; /* 70 is just an estimated value; node
597                                    name are usually shorter. */
598   int fd;
599   int pid = -1;
600   char *buffer, *p;
601   size_t expected_len;
602   int res, nread;
603
604   *same_node = 0;
605   expected_len = 10 + 1 + h->nodename_len + 1;
606   if ( expected_len >= sizeof buffer_space)
607     {
608       buffer = jnlib_malloc (expected_len);
609       if (!buffer)
610         return -1;
611     }
612   else
613     buffer = buffer_space;
614
615   if ( (fd = open (h->lockname, O_RDONLY)) == -1 )
616     {
617       int e = errno;
618       log_info ("error opening lockfile `%s': %s\n",
619                 h->lockname, strerror(errno) );
620       if (buffer != buffer_space)
621         jnlib_free (buffer);
622       errno = e; /* Need to return ERRNO here. */
623       return -1;
624     }
625
626   p = buffer;
627   nread = 0;
628   do
629     {
630       res = read (fd, p, expected_len - nread);
631       if (res == -1 && errno == EINTR)
632         continue;
633       if (res < 0)
634         {
635           log_info ("error reading lockfile `%s'", h->lockname );
636           close (fd);
637           if (buffer != buffer_space)
638             jnlib_free (buffer);
639           errno = 0; /* Do not return an inappropriate ERRNO. */
640           return -1;
641         }
642       p += res;
643       nread += res;
644     }
645   while (res && nread != expected_len);
646   close(fd);
647
648   if (nread < 11)
649     {
650       log_info ("invalid size of lockfile `%s'", h->lockname );
651       if (buffer != buffer_space)
652         jnlib_free (buffer);
653       errno = 0; /* Better don't return an inappropriate ERRNO. */
654       return -1;
655     }
656
657   if (buffer[10] != '\n'
658       || (buffer[10] = 0, pid = atoi (buffer)) == -1
659 #ifndef __riscos__
660       || !pid
661 #else /* __riscos__ */
662       || (!pid && riscos_getpid())
663 #endif /* __riscos__ */
664       )
665     {
666       log_error ("invalid pid %d in lockfile `%s'", pid, h->lockname );
667       if (buffer != buffer_space)
668         jnlib_free (buffer);
669       errno = 0;
670       return -1;
671     }
672
673   if (nread == expected_len
674       && !memcmp (h->tname+h->nodename_off, buffer+11, h->nodename_len)
675       && buffer[11+h->nodename_len] == '\n')
676     *same_node = 1;
677
678   if (buffer != buffer_space)
679     jnlib_free (buffer);
680   return pid;
681 }
682 #endif /* !HAVE_DOSISH_SYSTEM */
683
684
685 /* Remove all lockfiles.  This is usually called by the atexit handler
686    installed by this module but may also be called by other
687    termination handlers.  */
688 void
689 dotlock_remove_lockfiles()
690 {
691   DOTLOCK h, h2;
692
693   h = all_lockfiles;
694   all_lockfiles = NULL;
695
696   while ( h )
697     {
698       h2 = h->next;
699       destroy_dotlock (h);
700       h = h2;
701     }
702 }
703