LCOV - code coverage report
Current view: top level - common - sysutils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 131 227 57.7 %
Date: 2016-11-29 15:00:56 Functions: 19 26 73.1 %

          Line data    Source code
       1             : /* sysutils.c -  system helpers
       2             :  * Copyright (C) 1991-2001, 2003-2004,
       3             :  *               2006-2008  Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013-2014 Werner Koch
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * This file is free software; you can redistribute it and/or modify
       9             :  * it under the terms of either
      10             :  *
      11             :  *   - the GNU Lesser General Public License as published by the Free
      12             :  *     Software Foundation; either version 3 of the License, or (at
      13             :  *     your option) any later version.
      14             :  *
      15             :  * or
      16             :  *
      17             :  *   - the GNU General Public License as published by the Free
      18             :  *     Software Foundation; either version 2 of the License, or (at
      19             :  *     your option) any later version.
      20             :  *
      21             :  * or both in parallel, as here.
      22             :  *
      23             :  * This file is distributed in the hope that it will be useful,
      24             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      25             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      26             :  * GNU General Public License for more details.
      27             :  *
      28             :  * You should have received a copy of the GNU General Public License
      29             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      30             :  */
      31             : 
      32             : #include <config.h>
      33             : 
      34             : #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth.  */
      35             : # undef HAVE_NPTH
      36             : # undef USE_NPTH
      37             : #endif
      38             : 
      39             : #include <stdio.h>
      40             : #include <stdlib.h>
      41             : #include <stdint.h>
      42             : #include <string.h>
      43             : #include <unistd.h>
      44             : #include <errno.h>
      45             : #ifdef HAVE_STAT
      46             : # include <sys/stat.h>
      47             : #endif
      48             : #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
      49             : # include <asm/sysinfo.h>
      50             : # include <asm/unistd.h>
      51             : #endif
      52             : #include <time.h>
      53             : #ifdef HAVE_SETRLIMIT
      54             : # include <sys/time.h>
      55             : # include <sys/resource.h>
      56             : #endif
      57             : #ifdef HAVE_W32_SYSTEM
      58             : # if WINVER < 0x0500
      59             : #   define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
      60             : # endif
      61             : # ifdef HAVE_WINSOCK2_H
      62             : #  include <winsock2.h>
      63             : # endif
      64             : # include <windows.h>
      65             : #else /*!HAVE_W32_SYSTEM*/
      66             : # include <sys/socket.h>
      67             : # include <sys/un.h>
      68             : #endif
      69             : #ifdef HAVE_INOTIFY_INIT
      70             : # include <sys/inotify.h>
      71             : #endif /*HAVE_INOTIFY_INIT*/
      72             : #ifdef HAVE_NPTH
      73             : # include <npth.h>
      74             : #endif
      75             : #include <fcntl.h>
      76             : 
      77             : #include <assuan.h>
      78             : 
      79             : #include "util.h"
      80             : #include "i18n.h"
      81             : 
      82             : #include "sysutils.h"
      83             : 
      84             : #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
      85             : 
      86             : 
      87             : static GPGRT_INLINE gpg_error_t
      88           0 : my_error_from_syserror (void)
      89             : {
      90           0 :   return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
      91             : }
      92             : 
      93             : static GPGRT_INLINE gpg_error_t
      94           0 : my_error (int e)
      95             : {
      96           0 :   return gpg_err_make (default_errsource, (e));
      97             : }
      98             : 
      99             : 
     100             : 
     101             : #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
     102             : #warning using trap_unaligned
     103             : static int
     104             : setsysinfo(unsigned long op, void *buffer, unsigned long size,
     105             :                      int *start, void *arg, unsigned long flag)
     106             : {
     107             :     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
     108             : }
     109             : 
     110             : void
     111             : trap_unaligned(void)
     112             : {
     113             :     unsigned int buf[2];
     114             : 
     115             :     buf[0] = SSIN_UACPROC;
     116             :     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
     117             :     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
     118             : }
     119             : #else
     120             : void
     121        1227 : trap_unaligned(void)
     122             : {  /* dummy */
     123        1227 : }
     124             : #endif
     125             : 
     126             : 
     127             : int
     128        1280 : disable_core_dumps (void)
     129             : {
     130             : #ifdef HAVE_DOSISH_SYSTEM
     131             :     return 0;
     132             : #else
     133             : # ifdef HAVE_SETRLIMIT
     134             :     struct rlimit limit;
     135             : 
     136             :     /* We only set the current limit unless we were not able to
     137             :        retrieve the old value. */
     138        1280 :     if (getrlimit (RLIMIT_CORE, &limit))
     139           0 :       limit.rlim_max = 0;
     140        1280 :     limit.rlim_cur = 0;
     141        1280 :     if( !setrlimit (RLIMIT_CORE, &limit) )
     142        1280 :         return 0;
     143           0 :     if( errno != EINVAL && errno != ENOSYS )
     144           0 :         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
     145             : #endif
     146           0 :     return 1;
     147             : #endif
     148             : }
     149             : 
     150             : int
     151           0 : enable_core_dumps (void)
     152             : {
     153             : #ifdef HAVE_DOSISH_SYSTEM
     154             :     return 0;
     155             : #else
     156             : # ifdef HAVE_SETRLIMIT
     157             :     struct rlimit limit;
     158             : 
     159           0 :     if (getrlimit (RLIMIT_CORE, &limit))
     160           0 :       return 1;
     161           0 :     limit.rlim_cur = limit.rlim_max;
     162           0 :     setrlimit (RLIMIT_CORE, &limit);
     163           0 :     return 1; /* We always return true because this function is
     164             :                  merely a debugging aid. */
     165             : # endif
     166             :     return 1;
     167             : #endif
     168             : }
     169             : 
     170             : 
     171             : 
     172             : /* Return a string which is used as a kind of process ID.  */
     173             : const byte *
     174          34 : get_session_marker (size_t *rlen)
     175             : {
     176             :   static byte marker[SIZEOF_UNSIGNED_LONG*2];
     177             :   static int initialized;
     178             : 
     179          34 :   if (!initialized)
     180             :     {
     181          16 :       gcry_create_nonce (marker, sizeof marker);
     182          16 :       initialized = 1;
     183             :     }
     184          34 :   *rlen = sizeof (marker);
     185          34 :   return marker;
     186             : }
     187             : 
     188             : /* Return a random number in an unsigned int. */
     189             : unsigned int
     190           0 : get_uint_nonce (void)
     191             : {
     192             :   unsigned int value;
     193             : 
     194           0 :   gcry_create_nonce (&value, sizeof value);
     195           0 :   return value;
     196             : }
     197             : 
     198             : 
     199             : 
     200             : #if 0 /* not yet needed - Note that this will require inclusion of
     201             :          cmacros.am in Makefile.am */
     202             : int
     203             : check_permissions(const char *path,int extension,int checkonly)
     204             : {
     205             : #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
     206             :   char *tmppath;
     207             :   struct stat statbuf;
     208             :   int ret=1;
     209             :   int isdir=0;
     210             : 
     211             :   if(opt.no_perm_warn)
     212             :     return 0;
     213             : 
     214             :   if(extension && path[0]!=DIRSEP_C)
     215             :     {
     216             :       if(strchr(path,DIRSEP_C))
     217             :         tmppath=make_filename(path,NULL);
     218             :       else
     219             :         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
     220             :     }
     221             :   else
     222             :     tmppath=m_strdup(path);
     223             : 
     224             :   /* It's okay if the file doesn't exist */
     225             :   if(stat(tmppath,&statbuf)!=0)
     226             :     {
     227             :       ret=0;
     228             :       goto end;
     229             :     }
     230             : 
     231             :   isdir=S_ISDIR(statbuf.st_mode);
     232             : 
     233             :   /* Per-user files must be owned by the user.  Extensions must be
     234             :      owned by the user or root. */
     235             :   if((!extension && statbuf.st_uid != getuid()) ||
     236             :      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
     237             :     {
     238             :       if(!checkonly)
     239             :         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
     240             :                  isdir?"directory":extension?"extension":"file",path);
     241             :       goto end;
     242             :     }
     243             : 
     244             :   /* This works for both directories and files - basically, we don't
     245             :      care what the owner permissions are, so long as the group and
     246             :      other permissions are 0 for per-user files, and non-writable for
     247             :      extensions. */
     248             :   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
     249             :      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
     250             :     {
     251             :       char *dir;
     252             : 
     253             :       /* However, if the directory the directory/file is in is owned
     254             :          by the user and is 700, then this is not a problem.
     255             :          Theoretically, we could walk this test up to the root
     256             :          directory /, but for the sake of sanity, I'm stopping at one
     257             :          level down. */
     258             : 
     259             :       dir= make_dirname (tmppath);
     260             :       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
     261             :          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
     262             :         {
     263             :           xfree (dir);
     264             :           ret=0;
     265             :           goto end;
     266             :         }
     267             : 
     268             :       m_free(dir);
     269             : 
     270             :       if(!checkonly)
     271             :         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
     272             :                  isdir?"directory":extension?"extension":"file",path);
     273             :       goto end;
     274             :     }
     275             : 
     276             :   ret=0;
     277             : 
     278             :  end:
     279             :   m_free(tmppath);
     280             : 
     281             :   return ret;
     282             : 
     283             : #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
     284             : 
     285             :   return 0;
     286             : }
     287             : #endif
     288             : 
     289             : 
     290             : /* Wrapper around the usual sleep function.  This one won't wake up
     291             :    before the sleep time has really elapsed.  When build with Pth it
     292             :    merely calls pth_sleep and thus suspends only the current
     293             :    thread. */
     294             : void
     295          50 : gnupg_sleep (unsigned int seconds)
     296             : {
     297             : #ifdef USE_NPTH
     298           0 :   npth_sleep (seconds);
     299             : #else
     300             :   /* Fixme:  make sure that a sleep won't wake up to early.  */
     301             : # ifdef HAVE_W32_SYSTEM
     302             :   Sleep (seconds*1000);
     303             : # else
     304          50 :   sleep (seconds);
     305             : # endif
     306             : #endif
     307          50 : }
     308             : 
     309             : 
     310             : /* Wrapper around the platforms usleep function.  This one won't wake
     311             :  * up before the sleep time has really elapsed.  When build with nPth
     312             :  * it merely calls npth_usleep and thus suspends only the current
     313             :  * thread. */
     314             : void
     315           0 : gnupg_usleep (unsigned int usecs)
     316             : {
     317             : #if defined(USE_NPTH)
     318             : 
     319           0 :   npth_usleep (usecs);
     320             : 
     321             : #elif defined(HAVE_W32_SYSTEM)
     322             : 
     323             :   Sleep ((usecs + 999) / 1000);
     324             : 
     325             : #elif defined(HAVE_NANOSLEEP)
     326             : 
     327           0 :   if (usecs)
     328             :     {
     329             :       struct timespec req;
     330             :       struct timespec rem;
     331             : 
     332           0 :       req.tv_sec = 0;
     333           0 :       req.tv_nsec = usecs * 1000;
     334             : 
     335           0 :       while (nanosleep (&req, &rem) < 0 && errno == EINTR)
     336           0 :         req = rem;
     337             :     }
     338             : 
     339             : #else /*Standard Unix*/
     340             : 
     341             :   if (usecs)
     342             :     {
     343             :       struct timeval tv;
     344             : 
     345             :       tv.tv_sec  = usecs / 1000000;
     346             :       tv.tv_usec = usecs % 1000000;
     347             :       select (0, NULL, NULL, NULL, &tv);
     348             :     }
     349             : 
     350             : #endif
     351           0 : }
     352             : 
     353             : 
     354             : /* This function is a NOP for POSIX systems but required under Windows
     355             :    as the file handles as returned by OS calls (like CreateFile) are
     356             :    different from the libc file descriptors (like open). This function
     357             :    translates system file handles to libc file handles.  FOR_WRITE
     358             :    gives the direction of the handle.  */
     359             : int
     360           0 : translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
     361             : {
     362             : #if defined(HAVE_W32CE_SYSTEM)
     363             :   (void)for_write;
     364             :   return (int) fd;
     365             : #elif defined(HAVE_W32_SYSTEM)
     366             :   int x;
     367             : 
     368             :   if (fd == GNUPG_INVALID_FD)
     369             :     return -1;
     370             : 
     371             :   /* Note that _open_osfhandle is currently defined to take and return
     372             :      a long.  */
     373             :   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
     374             :   if (x == -1)
     375             :     log_error ("failed to translate osfhandle %p\n", (void *) fd);
     376             :   return x;
     377             : #else /*!HAVE_W32_SYSTEM */
     378             :   (void)for_write;
     379           0 :   return fd;
     380             : #endif
     381             : }
     382             : 
     383             : /* This is the same as translate_sys2libc_fd but takes an integer
     384             :    which is assumed to be such an system handle.  On WindowsCE the
     385             :    passed FD is a rendezvous ID and the function finishes the pipe
     386             :    creation. */
     387             : int
     388         193 : translate_sys2libc_fd_int (int fd, int for_write)
     389             : {
     390             : #if HAVE_W32CE_SYSTEM
     391             :   fd = (int) _assuan_w32ce_finish_pipe (fd, for_write);
     392             :   return translate_sys2libc_fd ((void*)fd, for_write);
     393             : #elif HAVE_W32_SYSTEM
     394             :   if (fd <= 2)
     395             :     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
     396             : 
     397             :   return translate_sys2libc_fd ((void*)fd, for_write);
     398             : #else
     399             :   (void)for_write;
     400         193 :   return fd;
     401             : #endif
     402             : }
     403             : 
     404             : 
     405             : 
     406             : /* Replacement for tmpfile().  This is required because the tmpfile
     407             :    function of Windows' runtime library is broken, insecure, ignores
     408             :    TMPDIR and so on.  In addition we create a file with an inheritable
     409             :    handle.  */
     410             : FILE *
     411          10 : gnupg_tmpfile (void)
     412             : {
     413             : #ifdef HAVE_W32_SYSTEM
     414             :   int attempts, n;
     415             : #ifdef HAVE_W32CE_SYSTEM
     416             :   wchar_t buffer[MAX_PATH+7+12+1];
     417             : # define mystrlen(a) wcslen (a)
     418             :   wchar_t *name, *p;
     419             : #else
     420             :   char buffer[MAX_PATH+7+12+1];
     421             : # define mystrlen(a) strlen (a)
     422             :   char *name, *p;
     423             : #endif
     424             :   HANDLE file;
     425             :   int pid = GetCurrentProcessId ();
     426             :   unsigned int value;
     427             :   int i;
     428             :   SECURITY_ATTRIBUTES sec_attr;
     429             : 
     430             :   memset (&sec_attr, 0, sizeof sec_attr );
     431             :   sec_attr.nLength = sizeof sec_attr;
     432             :   sec_attr.bInheritHandle = TRUE;
     433             : 
     434             :   n = GetTempPath (MAX_PATH+1, buffer);
     435             :   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
     436             :     {
     437             :       gpg_err_set_errno (ENOENT);
     438             :       return NULL;
     439             :     }
     440             :   p = buffer + mystrlen (buffer);
     441             : #ifdef HAVE_W32CE_SYSTEM
     442             :   wcscpy (p, L"_gnupg");
     443             :   p += 7;
     444             : #else
     445             :   p = stpcpy (p, "_gnupg");
     446             : #endif
     447             :   /* We try to create the directory but don't care about an error as
     448             :      it may already exist and the CreateFile would throw an error
     449             :      anyway.  */
     450             :   CreateDirectory (buffer, NULL);
     451             :   *p++ = '\\';
     452             :   name = p;
     453             :   for (attempts=0; attempts < 10; attempts++)
     454             :     {
     455             :       p = name;
     456             :       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
     457             :       for (i=0; i < 8; i++)
     458             :         {
     459             :           *p++ = tohex (((value >> 28) & 0x0f));
     460             :           value <<= 4;
     461             :         }
     462             : #ifdef HAVE_W32CE_SYSTEM
     463             :       wcscpy (p, L".tmp");
     464             : #else
     465             :       strcpy (p, ".tmp");
     466             : #endif
     467             :       file = CreateFile (buffer,
     468             :                          GENERIC_READ | GENERIC_WRITE,
     469             :                          0,
     470             :                          &sec_attr,
     471             :                          CREATE_NEW,
     472             :                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
     473             :                          NULL);
     474             :       if (file != INVALID_HANDLE_VALUE)
     475             :         {
     476             :           FILE *fp;
     477             : #ifdef HAVE_W32CE_SYSTEM
     478             :           int fd = (int)file;
     479             :           fp = _wfdopen (fd, L"w+b");
     480             : #else
     481             :           int fd = _open_osfhandle ((long)file, 0);
     482             :           if (fd == -1)
     483             :             {
     484             :               CloseHandle (file);
     485             :               return NULL;
     486             :             }
     487             :           fp = fdopen (fd, "w+b");
     488             : #endif
     489             :           if (!fp)
     490             :             {
     491             :               int save = errno;
     492             :               close (fd);
     493             :               gpg_err_set_errno (save);
     494             :               return NULL;
     495             :             }
     496             :           return fp;
     497             :         }
     498             :       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
     499             :     }
     500             :   gpg_err_set_errno (ENOENT);
     501             :   return NULL;
     502             : #undef mystrlen
     503             : #else /*!HAVE_W32_SYSTEM*/
     504          10 :   return tmpfile ();
     505             : #endif /*!HAVE_W32_SYSTEM*/
     506             : }
     507             : 
     508             : 
     509             : /* Make sure that the standard file descriptors are opened. Obviously
     510             :    some folks close them before an exec and the next file we open will
     511             :    get one of them assigned and thus any output (i.e. diagnostics) end
     512             :    up in that file (e.g. the trustdb).  Not actually a gpg problem as
     513             :    this will happen with almost all utilities when called in a wrong
     514             :    way.  However we try to minimize the damage here and raise
     515             :    awareness of the problem.
     516             : 
     517             :    Must be called before we open any files! */
     518             : void
     519        1388 : gnupg_reopen_std (const char *pgmname)
     520             : {
     521             : #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
     522             :   struct stat statbuf;
     523        1388 :   int did_stdin = 0;
     524        1388 :   int did_stdout = 0;
     525        1388 :   int did_stderr = 0;
     526             :   FILE *complain;
     527             : 
     528        1388 :   if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
     529             :     {
     530           0 :       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
     531           0 :         did_stdin = 1;
     532             :       else
     533           0 :         did_stdin = 2;
     534             :     }
     535             : 
     536        1388 :   if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
     537             :     {
     538           0 :       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
     539           0 :         did_stdout = 1;
     540             :       else
     541           0 :         did_stdout = 2;
     542             :     }
     543             : 
     544        1388 :   if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
     545             :     {
     546           0 :       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
     547           0 :         did_stderr = 1;
     548             :       else
     549           0 :         did_stderr = 2;
     550             :     }
     551             : 
     552             :   /* It's hard to log this sort of thing since the filehandle we would
     553             :      complain to may be closed... */
     554        1388 :   if (!did_stderr)
     555        1388 :     complain = stderr;
     556           0 :   else if (!did_stdout)
     557           0 :     complain = stdout;
     558             :   else
     559           0 :     complain = NULL;
     560             : 
     561        1388 :   if (complain)
     562             :     {
     563        1388 :       if (did_stdin == 1)
     564           0 :         fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
     565        1388 :       if (did_stdout == 1)
     566           0 :         fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
     567        1388 :       if (did_stderr == 1)
     568           0 :         fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
     569             : 
     570        1388 :       if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
     571           0 :         fprintf(complain,"%s: fatal: unable to reopen standard input,"
     572             :                 " output, or error\n", pgmname);
     573             :     }
     574             : 
     575        1388 :   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
     576           0 :     exit (3);
     577             : #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
     578             :   (void)pgmname;
     579             : #endif
     580        1388 : }
     581             : 
     582             : 
     583             : /* Hack required for Windows.  */
     584             : void
     585           5 : gnupg_allow_set_foregound_window (pid_t pid)
     586             : {
     587           5 :   if (!pid)
     588           1 :     log_info ("%s called with invalid pid %lu\n",
     589             :               "gnupg_allow_set_foregound_window", (unsigned long)pid);
     590             : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
     591             :   else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
     592             :     log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
     593             :                (unsigned long)pid, w32_strerror (-1));
     594             : #endif
     595           5 : }
     596             : 
     597             : int
     598         200 : gnupg_remove (const char *fname)
     599             : {
     600             : #ifdef HAVE_W32CE_SYSTEM
     601             :   int rc;
     602             :   wchar_t *wfname;
     603             : 
     604             :   wfname = utf8_to_wchar (fname);
     605             :   if (!wfname)
     606             :     rc = 0;
     607             :   else
     608             :     {
     609             :       rc = DeleteFile (wfname);
     610             :       xfree (wfname);
     611             :     }
     612             :   if (!rc)
     613             :     return -1; /* ERRNO is automagically provided by gpg-error.h.  */
     614             :   return 0;
     615             : #else
     616         200 :   return remove (fname);
     617             : #endif
     618             : }
     619             : 
     620             : 
     621             : /* Wrapper for rename(2) to handle Windows peculiarities.  If
     622             :  * BLOCK_SIGNALS is not NULL and points to a variable set to true, all
     623             :  * signals will be blocked by calling gnupg_block_all_signals; the
     624             :  * caller needs to call gnupg_unblock_all_signals if that variable is
     625             :  * still set to true on return. */
     626             : gpg_error_t
     627         334 : gnupg_rename_file (const char *oldname, const char *newname, int *block_signals)
     628             : {
     629         334 :   gpg_error_t err = 0;
     630             : 
     631         334 :   if (block_signals && *block_signals)
     632         167 :     gnupg_block_all_signals ();
     633             : 
     634             : #ifdef HAVE_DOSISH_SYSTEM
     635             :   {
     636             :     int wtime = 0;
     637             : 
     638             :     gnupg_remove (newname);
     639             :   again:
     640             :     if (rename (oldname, newname))
     641             :       {
     642             :         if (GetLastError () == ERROR_SHARING_VIOLATION)
     643             :           {
     644             :             /* Another process has the file open.  We do not use a
     645             :              * lock for read but instead we wait until the other
     646             :              * process has closed the file.  This may take long but
     647             :              * that would also be the case with a dotlock approach for
     648             :              * read and write.  Note that we don't need this on Unix
     649             :              * due to the inode concept.
     650             :              *
     651             :              * So let's wait until the rename has worked.  The retry
     652             :              * intervals are 50, 100, 200, 400, 800, 50ms, ...  */
     653             :             if (!wtime || wtime >= 800)
     654             :               wtime = 50;
     655             :             else
     656             :               wtime *= 2;
     657             : 
     658             :             if (wtime >= 800)
     659             :               log_info (_("waiting for file '%s' to become accessible ...\n"),
     660             :                         oldname);
     661             : 
     662             :             Sleep (wtime);
     663             :             goto again;
     664             :           }
     665             :         err = my_error_from_syserror ();
     666             :       }
     667             :   }
     668             : #else /* Unix */
     669             :   {
     670             : #ifdef __riscos__
     671             :     gnupg_remove (newname);
     672             : #endif
     673         334 :     if (rename (oldname, newname) )
     674           0 :       err = my_error_from_syserror ();
     675             :   }
     676             : #endif /* Unix */
     677             : 
     678         334 :   if (block_signals && *block_signals && err)
     679             :     {
     680           0 :       gnupg_unblock_all_signals ();
     681           0 :       *block_signals = 0;
     682             :     }
     683             : 
     684         334 :   if (err)
     685           0 :     log_error (_("renaming '%s' to '%s' failed: %s\n"),
     686             :                oldname, newname, gpg_strerror (err));
     687         334 :   return err;
     688             : }
     689             : 
     690             : 
     691             : #ifndef HAVE_W32_SYSTEM
     692             : static mode_t
     693        1242 : modestr_to_mode (const char *modestr)
     694             : {
     695        1242 :   mode_t mode = 0;
     696             : 
     697        1242 :   if (modestr && *modestr)
     698             :     {
     699        1241 :       modestr++;
     700        1241 :       if (*modestr && *modestr++ == 'r')
     701        1241 :         mode |= S_IRUSR;
     702        1241 :       if (*modestr && *modestr++ == 'w')
     703        1241 :         mode |= S_IWUSR;
     704        1241 :       if (*modestr && *modestr++ == 'x')
     705        1241 :         mode |= S_IXUSR;
     706        1241 :       if (*modestr && *modestr++ == 'r')
     707           0 :         mode |= S_IRGRP;
     708        1241 :       if (*modestr && *modestr++ == 'w')
     709           0 :         mode |= S_IWGRP;
     710        1241 :       if (*modestr && *modestr++ == 'x')
     711           0 :         mode |= S_IXGRP;
     712        1241 :       if (*modestr && *modestr++ == 'r')
     713           0 :         mode |= S_IROTH;
     714        1241 :       if (*modestr && *modestr++ == 'w')
     715           0 :         mode |= S_IWOTH;
     716        1241 :       if (*modestr && *modestr++ == 'x')
     717           0 :         mode |= S_IXOTH;
     718             :     }
     719             : 
     720        1242 :   return mode;
     721             : }
     722             : #endif
     723             : 
     724             : 
     725             : /* A wrapper around mkdir which takes a string for the mode argument.
     726             :    This makes it easier to handle the mode argument which is not
     727             :    defined on all systems.  The format of the modestring is
     728             : 
     729             :       "-rwxrwxrwx"
     730             : 
     731             :    '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
     732             :    write allowed, execution allowed with the first group for the user,
     733             :    the second for the group and the third for all others.  If the
     734             :    string is shorter than above the missing mode characters are meant
     735             :    to be not set.  */
     736             : int
     737         992 : gnupg_mkdir (const char *name, const char *modestr)
     738             : {
     739             : #ifdef HAVE_W32CE_SYSTEM
     740             :   wchar_t *wname;
     741             :   (void)modestr;
     742             : 
     743             :   wname = utf8_to_wchar (name);
     744             :   if (!wname)
     745             :     return -1;
     746             :   if (!CreateDirectoryW (wname, NULL))
     747             :     {
     748             :       xfree (wname);
     749             :       return -1;  /* ERRNO is automagically provided by gpg-error.h.  */
     750             :     }
     751             :   xfree (wname);
     752             :   return 0;
     753             : #elif MKDIR_TAKES_ONE_ARG
     754             :   (void)modestr;
     755             :   /* Note: In the case of W32 we better use CreateDirectory and try to
     756             :      set appropriate permissions.  However using mkdir is easier
     757             :      because this sets ERRNO.  */
     758             :   return mkdir (name);
     759             : #else
     760         992 :   return mkdir (name, modestr_to_mode (modestr));
     761             : #endif
     762             : }
     763             : 
     764             : 
     765             : /* A wrapper around chmod which takes a string for the mode argument.
     766             :    This makes it easier to handle the mode argument which is not
     767             :    defined on all systems.  The format of the modestring is the same
     768             :    as for gnupg_mkdir.  */
     769             : int
     770         250 : gnupg_chmod (const char *name, const char *modestr)
     771             : {
     772             : #ifdef HAVE_W32_SYSTEM
     773             :   (void)name;
     774             :   (void)modestr;
     775             :   return 0;
     776             : #else
     777         250 :   return chmod (name, modestr_to_mode (modestr));
     778             : #endif
     779             : }
     780             : 
     781             : 
     782             : /* Our version of mkdtemp.  The API is identical to POSIX.1-2008
     783             :    version.  We do not use a system provided mkdtemp because we have a
     784             :    good RNG instantly available and this way we don't have diverging
     785             :    versions.  */
     786             : char *
     787         863 : gnupg_mkdtemp (char *tmpl)
     788             : {
     789             :   /* A lower bound on the number of temporary files to attempt to
     790             :      generate.  The maximum total number of temporary file names that
     791             :      can exist for a given template is 62**6 (5*36**3 for Windows).
     792             :      It should never be necessary to try all these combinations.
     793             :      Instead if a reasonable number of names is tried (we define
     794             :      reasonable as 62**3 or 5*36**3) fail to give the system
     795             :      administrator the chance to remove the problems.  */
     796             : #ifdef HAVE_W32_SYSTEM
     797             :   static const char letters[] =
     798             :     "abcdefghijklmnopqrstuvwxyz0123456789";
     799             : # define NUMBER_OF_LETTERS 36
     800             : # define ATTEMPTS_MIN (5 * 36 * 36 * 36)
     801             : #else
     802             :   static const char letters[] =
     803             :     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     804             : # define NUMBER_OF_LETTERS 62
     805             : # define ATTEMPTS_MIN (62 * 62 * 62)
     806             : #endif
     807             :   int len;
     808             :   char *XXXXXX;
     809             :   uint64_t value;
     810             :   unsigned int count;
     811         863 :   int save_errno = errno;
     812             :   /* The number of times to attempt to generate a temporary file.  To
     813             :      conform to POSIX, this must be no smaller than TMP_MAX.  */
     814             : #if ATTEMPTS_MIN < TMP_MAX
     815             :   unsigned int attempts = TMP_MAX;
     816             : #else
     817         863 :   unsigned int attempts = ATTEMPTS_MIN;
     818             : #endif
     819             : 
     820         863 :   len = strlen (tmpl);
     821         863 :   if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
     822             :     {
     823           0 :       gpg_err_set_errno (EINVAL);
     824           0 :       return NULL;
     825             :     }
     826             : 
     827             :   /* This is where the Xs start.  */
     828         863 :   XXXXXX = &tmpl[len - 6];
     829             : 
     830             :   /* Get a random start value.  */
     831         863 :   gcry_create_nonce (&value, sizeof value);
     832             : 
     833             :   /* Loop until a directory was created.  */
     834         863 :   for (count = 0; count < attempts; value += 7777, ++count)
     835             :     {
     836         863 :       uint64_t v = value;
     837             : 
     838             :       /* Fill in the random bits.  */
     839         863 :       XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
     840         863 :       v /= NUMBER_OF_LETTERS;
     841         863 :       XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
     842         863 :       v /= NUMBER_OF_LETTERS;
     843         863 :       XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
     844         863 :       v /= NUMBER_OF_LETTERS;
     845         863 :       XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
     846         863 :       v /= NUMBER_OF_LETTERS;
     847         863 :       XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
     848         863 :       v /= NUMBER_OF_LETTERS;
     849         863 :       XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
     850             : 
     851         863 :       if (!gnupg_mkdir (tmpl, "-rwx"))
     852             :         {
     853         863 :           gpg_err_set_errno (save_errno);
     854         863 :           return tmpl;
     855             :         }
     856           0 :       if (errno != EEXIST)
     857           0 :         return NULL;
     858             :     }
     859             : 
     860             :   /* We got out of the loop because we ran out of combinations to try.  */
     861           0 :   gpg_err_set_errno (EEXIST);
     862           0 :   return NULL;
     863             : }
     864             : 
     865             : 
     866             : int
     867         106 : gnupg_setenv (const char *name, const char *value, int overwrite)
     868             : {
     869             : #ifdef HAVE_W32CE_SYSTEM
     870             :   (void)name;
     871             :   (void)value;
     872             :   (void)overwrite;
     873             :   return 0;
     874             : #else /*!W32CE*/
     875             : # ifdef HAVE_W32_SYSTEM
     876             :   /*  Windows maintains (at least) two sets of environment variables.
     877             :       One set can be accessed by GetEnvironmentVariable and
     878             :       SetEnvironmentVariable.  This set is inherited by the children.
     879             :       The other set is maintained in the C runtime, and is accessed
     880             :       using getenv and putenv.  We try to keep them in sync by
     881             :       modifying both sets.  */
     882             :   {
     883             :     int exists;
     884             :     char tmpbuf[10];
     885             :     exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf);
     886             : 
     887             :     if ((! exists || overwrite) && !SetEnvironmentVariable (name, value))
     888             :       {
     889             :         gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
     890             :         return -1;
     891             :       }
     892             :   }
     893             : # endif /*W32*/
     894             : 
     895             : # ifdef HAVE_SETENV
     896         106 :   return setenv (name, value, overwrite);
     897             : # else /*!HAVE_SETENV*/
     898             :   if (! getenv (name) || overwrite)
     899             :     {
     900             :       char *buf;
     901             : 
     902             :       (void)overwrite;
     903             :       if (!name || !value)
     904             :         {
     905             :           gpg_err_set_errno (EINVAL);
     906             :           return -1;
     907             :         }
     908             :       buf = strconcat (name, "=", value, NULL);
     909             :       if (!buf)
     910             :         return -1;
     911             : # if __GNUC__
     912             : #  warning no setenv - using putenv but leaking memory.
     913             : # endif
     914             :       return putenv (buf);
     915             :     }
     916             :   return 0;
     917             : # endif /*!HAVE_SETENV*/
     918             : #endif /*!W32CE*/
     919             : }
     920             : 
     921             : 
     922             : int
     923         100 : gnupg_unsetenv (const char *name)
     924             : {
     925             : #ifdef HAVE_W32CE_SYSTEM
     926             :   (void)name;
     927             :   return 0;
     928             : #else /*!W32CE*/
     929             : # ifdef HAVE_W32_SYSTEM
     930             :   /*  Windows maintains (at least) two sets of environment variables.
     931             :       One set can be accessed by GetEnvironmentVariable and
     932             :       SetEnvironmentVariable.  This set is inherited by the children.
     933             :       The other set is maintained in the C runtime, and is accessed
     934             :       using getenv and putenv.  We try to keep them in sync by
     935             :       modifying both sets.  */
     936             :   if (!SetEnvironmentVariable (name, NULL))
     937             :     {
     938             :       gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
     939             :       return -1;
     940             :     }
     941             : # endif /*W32*/
     942             : 
     943             : # ifdef HAVE_UNSETENV
     944         100 :   return unsetenv (name);
     945             : # else /*!HAVE_UNSETENV*/
     946             :   {
     947             :     char *buf;
     948             : 
     949             :     if (!name)
     950             :       {
     951             :         gpg_err_set_errno (EINVAL);
     952             :         return -1;
     953             :       }
     954             :     buf = xtrystrdup (name);
     955             :     if (!buf)
     956             :       return -1;
     957             : #  if __GNUC__
     958             : #   warning no unsetenv - trying putenv but leaking memory.
     959             : #  endif
     960             :     return putenv (buf);
     961             :   }
     962             : # endif /*!HAVE_UNSETENV*/
     963             : #endif /*!W32CE*/
     964             : }
     965             : 
     966             : 
     967             : /* Return the current working directory as a malloced string.  Return
     968             :    NULL and sets ERRNo on error.  */
     969             : char *
     970         133 : gnupg_getcwd (void)
     971             : {
     972             :   char *buffer;
     973         133 :   size_t size = 100;
     974             : 
     975             :   for (;;)
     976             :     {
     977         133 :       buffer = xtrymalloc (size+1);
     978         133 :       if (!buffer)
     979           0 :         return NULL;
     980             : #ifdef HAVE_W32CE_SYSTEM
     981             :       strcpy (buffer, "/");  /* Always "/".  */
     982             :       return buffer;
     983             : #else
     984         133 :       if (getcwd (buffer, size) == buffer)
     985         133 :         return buffer;
     986           0 :       xfree (buffer);
     987           0 :       if (errno != ERANGE)
     988           0 :         return NULL;
     989           0 :       size *= 2;
     990             : #endif
     991           0 :     }
     992             : }
     993             : 
     994             : 
     995             : 
     996             : #ifdef HAVE_W32CE_SYSTEM
     997             : /* There is a isatty function declaration in cegcc but it does not
     998             :    make sense, thus we redefine it.  */
     999             : int
    1000             : _gnupg_isatty (int fd)
    1001             : {
    1002             :   (void)fd;
    1003             :   return 0;
    1004             : }
    1005             : #endif
    1006             : 
    1007             : 
    1008             : #ifdef HAVE_W32CE_SYSTEM
    1009             : /* Replacement for getenv which takes care of the our use of getenv.
    1010             :    The code is not thread safe but we expect it to work in all cases
    1011             :    because it is called for the first time early enough.  */
    1012             : char *
    1013             : _gnupg_getenv (const char *name)
    1014             : {
    1015             :   static int initialized;
    1016             :   static char *assuan_debug;
    1017             : 
    1018             :   if (!initialized)
    1019             :     {
    1020             :       assuan_debug = read_w32_registry_string (NULL,
    1021             :                                                "\\Software\\GNU\\libassuan",
    1022             :                                                "debug");
    1023             :       initialized = 1;
    1024             :     }
    1025             : 
    1026             :   if (!strcmp (name, "ASSUAN_DEBUG"))
    1027             :     return assuan_debug;
    1028             :   else
    1029             :     return NULL;
    1030             : }
    1031             : 
    1032             : #endif /*HAVE_W32CE_SYSTEM*/
    1033             : 
    1034             : 
    1035             : #ifdef HAVE_W32_SYSTEM
    1036             : /* Return the user's security identifier from the current process.  */
    1037             : PSID
    1038             : w32_get_user_sid (void)
    1039             : {
    1040             :   int okay = 0;
    1041             :   HANDLE proc = NULL;
    1042             :   HANDLE token = NULL;
    1043             :   TOKEN_USER *user = NULL;
    1044             :   PSID sid = NULL;
    1045             :   DWORD tokenlen, sidlen;
    1046             : 
    1047             :   proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
    1048             :   if (!proc)
    1049             :     goto leave;
    1050             : 
    1051             :   if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
    1052             :     goto leave;
    1053             : 
    1054             :   if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
    1055             :       && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    1056             :     goto leave;
    1057             : 
    1058             :   user = xtrymalloc (tokenlen);
    1059             :   if (!user)
    1060             :     goto leave;
    1061             : 
    1062             :   if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
    1063             :     goto leave;
    1064             :   if (!IsValidSid (user->User.Sid))
    1065             :     goto leave;
    1066             :   sidlen = GetLengthSid (user->User.Sid);
    1067             :   sid = xtrymalloc (sidlen);
    1068             :   if (!sid)
    1069             :     goto leave;
    1070             :   if (!CopySid (sidlen, sid, user->User.Sid))
    1071             :     goto leave;
    1072             :   okay = 1;
    1073             : 
    1074             :  leave:
    1075             :   xfree (user);
    1076             :   if (token)
    1077             :     CloseHandle (token);
    1078             :   if (proc)
    1079             :     CloseHandle (proc);
    1080             : 
    1081             :   if (!okay)
    1082             :     {
    1083             :       xfree (sid);
    1084             :       sid = NULL;
    1085             :     }
    1086             :   return sid;
    1087             : }
    1088             : #endif /*HAVE_W32_SYSTEM*/
    1089             : 
    1090             : 
    1091             : 
    1092             : /* Support for inotify under Linux.  */
    1093             : 
    1094             : /* Store a new inotify file handle for SOCKET_NAME at R_FD or return
    1095             :  * an error code. */
    1096             : gpg_error_t
    1097          50 : gnupg_inotify_watch_socket (int *r_fd, const char *socket_name)
    1098             : {
    1099             : #if HAVE_INOTIFY_INIT
    1100             :   gpg_error_t err;
    1101             :   char *fname;
    1102             :   int fd;
    1103             :   char *p;
    1104             : 
    1105          50 :   *r_fd = -1;
    1106             : 
    1107          50 :   if (!socket_name)
    1108           0 :     return my_error (GPG_ERR_INV_VALUE);
    1109             : 
    1110          50 :   fname = xtrystrdup (socket_name);
    1111          50 :   if (!fname)
    1112           0 :     return my_error_from_syserror ();
    1113             : 
    1114          50 :   fd = inotify_init ();
    1115          50 :   if (fd == -1)
    1116             :     {
    1117           0 :       err = my_error_from_syserror ();
    1118           0 :       xfree (fname);
    1119           0 :       return err;
    1120             :     }
    1121             : 
    1122             :   /* We need to watch the directory for the file because there won't
    1123             :    * be an IN_DELETE_SELF for a socket file.  To handle a removal of
    1124             :    * the directory we also watch the directory itself. */
    1125          50 :   p = strrchr (fname, '/');
    1126          50 :   if (p)
    1127          50 :     *p = 0;
    1128          50 :   if (inotify_add_watch (fd, fname,
    1129             :                          (IN_DELETE|IN_DELETE_SELF|IN_EXCL_UNLINK)) == -1)
    1130             :     {
    1131           0 :       err = my_error_from_syserror ();
    1132           0 :       close (fd);
    1133           0 :       xfree (fname);
    1134           0 :       return err;
    1135             :     }
    1136             : 
    1137          50 :   xfree (fname);
    1138             : 
    1139          50 :   *r_fd = fd;
    1140          50 :   return 0;
    1141             : #else /*!HAVE_INOTIFY_INIT*/
    1142             : 
    1143             :   (void)socket_name;
    1144             :   *r_fd = -1;
    1145             :   return my_error (GPG_ERR_NOT_SUPPORTED);
    1146             : 
    1147             : #endif /*!HAVE_INOTIFY_INIT*/
    1148             : }
    1149             : 
    1150             : 
    1151             : /* Read an inotify event and return true if it matches NAME or if it
    1152             :  * sees an IN_DELETE_SELF event for the directory of NAME.  */
    1153             : int
    1154          78 : gnupg_inotify_has_name (int fd, const char *name)
    1155             : {
    1156             : #if USE_NPTH && HAVE_INOTIFY_INIT
    1157             : #define BUFSIZE_FOR_INOTIFY (sizeof (struct inotify_event) + 255 + 1)
    1158             :   union {
    1159             :     struct inotify_event ev;
    1160             :     char _buf[sizeof (struct inotify_event) + 255 + 1];
    1161             :   } buf;
    1162             :   struct inotify_event *evp;
    1163             :   int n;
    1164             : 
    1165          78 :   n = npth_read (fd, &buf, sizeof buf);
    1166             :   /* log_debug ("notify read: n=%d\n", n); */
    1167          78 :   evp = &buf.ev;
    1168         244 :   while (n >= sizeof (struct inotify_event))
    1169             :     {
    1170             :       /* log_debug ("             mask=%x len=%u name=(%s)\n", */
    1171             :       /*        evp->mask, (unsigned int)evp->len, evp->len? evp->name:""); */
    1172          92 :       if ((evp->mask & IN_UNMOUNT))
    1173             :         {
    1174             :           /* log_debug ("             found (dir unmounted)\n"); */
    1175           0 :           return 3; /* Directory was unmounted.  */
    1176             :         }
    1177          92 :       if ((evp->mask & IN_DELETE_SELF))
    1178             :         {
    1179             :           /* log_debug ("             found (dir removed)\n"); */
    1180           0 :           return 2; /* Directory was removed.  */
    1181             :         }
    1182          92 :       if ((evp->mask & IN_DELETE))
    1183             :         {
    1184          92 :           if (evp->len >= strlen (name) && !strcmp (evp->name, name))
    1185             :             {
    1186             :               /* log_debug ("             found (file removed)\n"); */
    1187           4 :               return 1; /* File was removed.  */
    1188             :             }
    1189             :         }
    1190          88 :       n -= sizeof (*evp) + evp->len;
    1191          88 :       evp = (struct inotify_event *)(void *)
    1192          88 :         ((char *)evp + sizeof (*evp) + evp->len);
    1193             :     }
    1194             : 
    1195             : #else /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
    1196             : 
    1197             :   (void)fd;
    1198             :   (void)name;
    1199             : 
    1200             : #endif  /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
    1201             : 
    1202          74 :   return 0; /* Not found.  */
    1203             : }
    1204             : 
    1205             : 
    1206             : /* Return a malloc'ed string that is the path to the passed
    1207             :  * unix-domain socket (or return NULL if this is not a valid
    1208             :  * unix-domain socket).  We use a plain int here because it is only
    1209             :  * used on Linux.
    1210             :  *
    1211             :  * FIXME: This function needs to be moved to libassuan.  */
    1212             : #ifndef HAVE_W32_SYSTEM
    1213             : char *
    1214           0 : gnupg_get_socket_name (int fd)
    1215             : {
    1216             :   struct sockaddr_un un;
    1217           0 :   socklen_t len = sizeof(un);
    1218           0 :   char *name = NULL;
    1219             : 
    1220           0 :   if (getsockname (fd, (struct sockaddr*)&un, &len) != 0)
    1221           0 :     log_error ("could not getsockname(%d): %s\n", fd,
    1222             :                gpg_strerror (my_error_from_syserror ()));
    1223           0 :   else if (un.sun_family != AF_UNIX)
    1224           0 :     log_error ("file descriptor %d is not a unix-domain socket\n", fd);
    1225           0 :   else if (len <= offsetof (struct sockaddr_un, sun_path))
    1226           0 :     log_error ("socket name not present for file descriptor %d\n", fd);
    1227           0 :   else if (len > sizeof(un))
    1228           0 :     log_error ("socket name for file descriptor %d was truncated "
    1229             :                "(passed %zu bytes, wanted %u)\n", fd, sizeof(un), len);
    1230             :   else
    1231             :     {
    1232           0 :       size_t namelen = len - offsetof (struct sockaddr_un, sun_path);
    1233             : 
    1234             :       /* log_debug ("file descriptor %d has path %s (%zu octets)\n", fd, */
    1235             :       /*            un.sun_path, namelen); */
    1236           0 :       name = xtrymalloc (namelen + 1);
    1237           0 :       if (!name)
    1238           0 :         log_error ("failed to allocate memory for name of fd %d: %s\n",
    1239             :                    fd, gpg_strerror (my_error_from_syserror ()));
    1240             :       else
    1241             :         {
    1242           0 :           memcpy (name, un.sun_path, namelen);
    1243           0 :           name[namelen] = 0;
    1244             :         }
    1245             :     }
    1246             : 
    1247           0 :   return name;
    1248             : }
    1249             : #endif /*!HAVE_W32_SYSTEM*/

Generated by: LCOV version 1.11