LCOV - code coverage report
Current view: top level - kbx - keybox-util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 38 46 82.6 %
Date: 2016-09-12 13:01:59 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* keybox-util.c - Utility functions for Keybox
       2             :  *      Copyright (C) 2001 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <stdlib.h>
      22             : #include <stdio.h>
      23             : #include <string.h>
      24             : #ifdef  HAVE_DOSISH_SYSTEM
      25             : # define WIN32_LEAN_AND_MEAN  /* We only need the OS core stuff.  */
      26             : # include <windows.h>
      27             : #endif
      28             : 
      29             : #include "keybox-defs.h"
      30             : #include "utilproto.h"
      31             : 
      32             : 
      33             : static void *(*alloc_func)(size_t n) = malloc;
      34             : static void *(*realloc_func)(void *p, size_t n) = realloc;
      35             : static void (*free_func)(void*) = free;
      36             : 
      37             : 
      38             : 
      39             : void
      40           3 : keybox_set_malloc_hooks ( void *(*new_alloc_func)(size_t n),
      41             :                           void *(*new_realloc_func)(void *p, size_t n),
      42             :                           void (*new_free_func)(void*) )
      43             : {
      44           3 :   alloc_func        = new_alloc_func;
      45           3 :   realloc_func      = new_realloc_func;
      46           3 :   free_func         = new_free_func;
      47           3 : }
      48             : 
      49             : void *
      50      170393 : _keybox_malloc (size_t n)
      51             : {
      52      170393 :   return alloc_func (n);
      53             : }
      54             : 
      55             : void *
      56          48 : _keybox_realloc (void *a, size_t n)
      57             : {
      58          48 :   return realloc_func (a, n);
      59             : }
      60             : 
      61             : void *
      62       85255 : _keybox_calloc (size_t n, size_t m)
      63             : {
      64       85255 :   void *p = _keybox_malloc (n*m);
      65       85255 :   if (p)
      66       85255 :     memset (p, 0, n* m);
      67       85255 :   return p;
      68             : }
      69             : 
      70             : void
      71      495553 : _keybox_free (void *p)
      72             : {
      73      495553 :   if (p)
      74      165759 :     free_func (p);
      75      495553 : }
      76             : 
      77             : 
      78             : /* Store the two malloced temporary file names used for keybox updates
      79             :    of file FILENAME at R_BAKNAME and R_TMPNAME.  On error an error
      80             :    code is returned and NULL stored at R_BAKNAME and R_TMPNAME.  If
      81             :    FOR_KEYRING is true the returned names match those used by GnuPG's
      82             :    keyring code.  */
      83             : gpg_error_t
      84          73 : keybox_tmp_names (const char *filename, int for_keyring,
      85             :                   char **r_bakname, char **r_tmpname)
      86             : {
      87             :   gpg_error_t err;
      88             :   char *bak_name, *tmp_name;
      89             : 
      90          73 :   *r_bakname = NULL;
      91          73 :   *r_tmpname = NULL;
      92             : 
      93             : # ifdef USE_ONLY_8DOT3
      94             :   /* Here is another Windoze bug?:
      95             :    * you can't rename("pubring.kbx.tmp", "pubring.kbx");
      96             :    * but        rename("pubring.kbx.tmp", "pubring.aaa");
      97             :    * works.  So we replace ".kbx" by ".kb_" or ".k__".  Note that we
      98             :    * can't use ".bak" and ".tmp", because these suffixes are used by
      99             :    * gpg's keyrings and would lead to a sharing violation or data
     100             :    * corruption.  If the name does not end in ".kbx" we assume working
     101             :    * on a modern file system and append the suffix.  */
     102             :   {
     103             :     const char *ext   = for_keyring? EXTSEP_S GPGEXT_GPG : EXTSEP_S "kbx";
     104             :     const char *b_ext = for_keyring? EXTSEP_S "bak"      : EXTSEP_S "kb_";
     105             :     const char *t_ext = for_keyring? EXTSEP_S "tmp"      : EXTSEP_S "k__";
     106             :     int repl;
     107             : 
     108             :     if (strlen (ext) != 4 || strlen (b_ext) != 4)
     109             :       BUG ();
     110             :     repl = (strlen (filename) > 4
     111             :             && !strcmp (filename + strlen (filename) - 4, ext));
     112             :     bak_name = xtrymalloc (strlen (filename) + (repl?0:4) + 1);
     113             :     if (!bak_name)
     114             :       return gpg_error_from_syserror ();
     115             :     strcpy (bak_name, filename);
     116             :     strcpy (bak_name + strlen (filename) - (repl?4:0), b_ext);
     117             : 
     118             :     tmp_name = xtrymalloc (strlen (filename) + (repl?0:4) + 1);
     119             :     if (!tmp_name)
     120             :       {
     121             :         err = gpg_error_from_syserror ();
     122             :         xfree (bak_name);
     123             :         return err;
     124             :       }
     125             :     strcpy (tmp_name, filename);
     126             :     strcpy (tmp_name + strlen (filename) - (repl?4:0), t_ext);
     127             :   }
     128             : # else /* Posix file names */
     129             :   (void)for_keyring;
     130          73 :   bak_name = xtrymalloc (strlen (filename) + 2);
     131          73 :   if (!bak_name)
     132           0 :     return gpg_error_from_syserror ();
     133          73 :   strcpy (stpcpy (bak_name, filename), "~");
     134             : 
     135          73 :   tmp_name = xtrymalloc (strlen (filename) + 5);
     136          73 :   if (!tmp_name)
     137             :     {
     138           0 :       err = gpg_error_from_syserror ();
     139           0 :       xfree (bak_name);
     140           0 :       return err;
     141             :     }
     142          73 :   strcpy (stpcpy (tmp_name,filename), EXTSEP_S "tmp");
     143             : # endif /* Posix filename */
     144             : 
     145          73 :   *r_bakname = bak_name;
     146          73 :   *r_tmpname = tmp_name;
     147          73 :   return 0;
     148             : }
     149             : 
     150             : 
     151             : /* Wrapper for rename(2) to handle Windows peculiarities.  If
     152             :  * BLOCK_SIGNALS is not NULL and points to a variable set to true, all
     153             :  * signals will be blocked by calling gnupg_block_all_signals; the
     154             :  * caller needs to call gnupg_unblock_all_signals if that variable is
     155             :  * still set to true on return. */
     156             : gpg_error_t
     157         142 : keybox_file_rename (const char *oldname, const char *newname,
     158             :                     int *block_signals)
     159             : {
     160         142 :   gpg_error_t err = 0;
     161             : 
     162         142 :   if (block_signals && *block_signals)
     163          71 :     gnupg_block_all_signals ();
     164             : 
     165             : #ifdef HAVE_DOSISH_SYSTEM
     166             :   {
     167             :     int wtime = 0;
     168             : 
     169             :     gnupg_remove (newname);
     170             :   again:
     171             :     if (rename (oldname, newname))
     172             :       {
     173             :         if (GetLastError () == ERROR_SHARING_VIOLATION)
     174             :           {
     175             :             /* Another process has the file open.  We do not use a
     176             :              * lock for read but instead we wait until the other
     177             :              * process has closed the file.  This may take long but
     178             :              * that would also be the case with a dotlock approach for
     179             :              * read and write.  Note that we don't need this on Unix
     180             :              * due to the inode concept.
     181             :              *
     182             :              * So let's wait until the rename has worked.  The retry
     183             :              * intervals are 50, 100, 200, 400, 800, 50ms, ...  */
     184             :             if (!wtime || wtime >= 800)
     185             :               wtime = 50;
     186             :             else
     187             :               wtime *= 2;
     188             : 
     189             :             if (wtime >= 800)
     190             :               log_info ("waiting for file '%s' to become accessible ...\n",
     191             :                         oldname);
     192             : 
     193             :             Sleep (wtime);
     194             :             goto again;
     195             :           }
     196             :         err = gpg_error_from_syserror ();
     197             :       }
     198             :   }
     199             : #else /* Unix */
     200             :   {
     201             : #ifdef __riscos__
     202             :     gnupg_remove (newname);
     203             : #endif
     204         142 :     if (rename (oldname, newname) )
     205           0 :       err = gpg_error_from_syserror ();
     206             :   }
     207             : #endif /* Unix */
     208             : 
     209         142 :   if (block_signals && *block_signals && err)
     210             :     {
     211           0 :       gnupg_unblock_all_signals ();
     212           0 :       *block_signals = 0;
     213             :     }
     214             : 
     215         142 :   if (err)
     216           0 :     log_error ("renaming '%s' to '%s' failed: %s\n",
     217             :                oldname, newname, gpg_strerror (err));
     218         142 :   return err;
     219             : }

Generated by: LCOV version 1.11