LCOV - code coverage report
Current view: top level - common - sysutils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 134 239 56.1 %
Date: 2016-12-01 18:37:21 Functions: 20 28 71.4 %

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

Generated by: LCOV version 1.11