Coverage Report

Created: 2026-07-16 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/common/sysutils.c
Line
Count
Source
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 <limits.h>
44
#include <sys/types.h>
45
#include <unistd.h>
46
#include <errno.h>
47
#ifdef HAVE_STAT
48
# include <sys/stat.h>
49
#endif
50
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
51
# include <asm/sysinfo.h>
52
# include <asm/unistd.h>
53
#endif
54
#include <time.h>
55
#ifdef HAVE_SETRLIMIT
56
# include <sys/time.h>
57
# include <sys/resource.h>
58
#endif
59
#ifdef HAVE_PWD_H
60
# include <pwd.h>
61
# include <grp.h>
62
#endif /*HAVE_PWD_H*/
63
#ifdef HAVE_W32_SYSTEM
64
# if WINVER < 0x0500
65
#   define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
66
# endif
67
# ifdef HAVE_WINSOCK2_H
68
#  include <winsock2.h>
69
# endif
70
# include <windows.h>
71
#else /*!HAVE_W32_SYSTEM*/
72
# include <sys/socket.h>
73
# include <sys/un.h>
74
#endif
75
#ifdef HAVE_INOTIFY_INIT
76
# include <sys/inotify.h>
77
#endif /*HAVE_INOTIFY_INIT*/
78
#ifdef HAVE_NPTH
79
# include <npth.h>
80
#endif
81
#include <fcntl.h>
82
#include <dirent.h>
83
84
#include <assuan.h>
85
86
#include "util.h"
87
#include "i18n.h"
88
89
#include "sysutils.h"
90
91
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
92
93
94
/* The object used with our opendir functions.  We need to define our
95
 * own so that we can properly handle Unicode on Windows.  */
96
struct gnupg_dir_s
97
{
98
#ifdef HAVE_W32_SYSTEM
99
  _WDIR *dir;                    /* The system's DIR pointer.  */
100
#else
101
  DIR *dir;                      /* The system's DIR pointer.  */
102
#endif
103
  struct gnupg_dirent_s dirent;  /* The current dirent.  */
104
  size_t namesize;  /* If not 0 the allocated size of dirent.d_name.  */
105
  char name[256];   /* Only used if NAMESIZE is 0.  */
106
};
107
108
109
/* Flag to tell whether special file names are enabled.  See gpg.c for
110
 * an explanation of these file names.  */
111
static int allow_special_filenames;
112
113
#ifdef HAVE_W32_SYSTEM
114
/* State of gnupg_inhibit_set_foregound_window.  */
115
static int inhibit_set_foregound_window;
116
/* Disable the use of _open_osfhandle.  */
117
static int no_translate_sys2libc_fd;
118
#endif
119
120
121
static GPGRT_INLINE gpg_error_t
122
my_error_from_syserror (void)
123
0
{
124
0
  return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
125
0
}
126
127
static GPGRT_INLINE gpg_error_t
128
my_error (int e)
129
0
{
130
0
  return gpg_err_make (default_errsource, (e));
131
0
}
132
133
134
135
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
136
#warning using trap_unaligned
137
static int
138
setsysinfo(unsigned long op, void *buffer, unsigned long size,
139
         int *start, void *arg, unsigned long flag)
140
{
141
    return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
142
}
143
144
void
145
trap_unaligned(void)
146
{
147
    unsigned int buf[2];
148
149
    buf[0] = SSIN_UACPROC;
150
    buf[1] = UAC_SIGBUS | UAC_NOPRINT;
151
    setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
152
}
153
#else
154
void
155
trap_unaligned(void)
156
0
{  /* dummy */
157
0
}
158
#endif
159
160
161
int
162
disable_core_dumps (void)
163
0
{
164
#ifdef HAVE_DOSISH_SYSTEM
165
    return 0;
166
#else
167
0
# ifdef HAVE_SETRLIMIT
168
0
    struct rlimit limit;
169
170
    /* We only set the current limit unless we were not able to
171
       retrieve the old value. */
172
0
    if (getrlimit (RLIMIT_CORE, &limit))
173
0
      limit.rlim_max = 0;
174
0
    limit.rlim_cur = 0;
175
0
    if( !setrlimit (RLIMIT_CORE, &limit) )
176
0
  return 0;
177
0
    if( errno != EINVAL && errno != ENOSYS )
178
0
  log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
179
0
#endif
180
0
    return 1;
181
0
#endif
182
0
}
183
184
int
185
enable_core_dumps (void)
186
0
{
187
#ifdef HAVE_DOSISH_SYSTEM
188
    return 0;
189
#else
190
0
# ifdef HAVE_SETRLIMIT
191
0
    struct rlimit limit;
192
193
0
    if (getrlimit (RLIMIT_CORE, &limit))
194
0
      return 1;
195
0
    limit.rlim_cur = limit.rlim_max;
196
0
    setrlimit (RLIMIT_CORE, &limit);
197
0
    return 1; /* We always return true because this function is
198
                 merely a debugging aid. */
199
0
# endif
200
0
    return 1;
201
0
#endif
202
0
}
203
204
#ifdef HAVE_W32_SYSTEM
205
static int
206
any8bitchar (const char *string)
207
{
208
  if (string)
209
    for ( ; *string; string++)
210
      if ((*string & 0x80))
211
        return 1;
212
  return 0;
213
}
214
#endif /*HAVE_W32_SYSTEM*/
215
216
217
/* Helper for gnupg_w32_set_errno.  */
218
#ifdef HAVE_W32_SYSTEM
219
#if GPGRT_VERSION_NUMBER < 0x013e00  /* gpgrt < 1.62 */
220
static int
221
map_w32_to_errno (DWORD w32_err)
222
{
223
  switch (w32_err)
224
    {
225
    case 0:
226
      return 0;
227
228
    case ERROR_FILE_NOT_FOUND:
229
      return ENOENT;
230
231
    case ERROR_PATH_NOT_FOUND:
232
      return ENOENT;
233
234
    case ERROR_ACCESS_DENIED:
235
      return EPERM;  /* ReactOS uses EACCES ("Permission denied") and
236
                      * is likely right because they used an
237
                      * undocumented function to associate the error
238
                      * codes.  However we have always used EPERM
239
                      * ("Operation not permitted", e.g. function is
240
                      * required to be called by root) and we better
241
                      * stick to that to avoid surprising bugs. */
242
243
    case ERROR_INVALID_HANDLE:
244
      return EBADF;
245
246
    case ERROR_INVALID_BLOCK:
247
      return ENOMEM;
248
249
    case ERROR_NOT_ENOUGH_MEMORY:
250
      return ENOMEM;
251
252
    case ERROR_NO_DATA:
253
      return EPIPE;
254
255
    case ERROR_ALREADY_EXISTS:
256
      return EEXIST;
257
258
    case ERROR_FILE_INVALID:
259
      return EIO;
260
261
      /* This mapping has been taken from reactOS.  */
262
    case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
263
    case ERROR_ARENA_TRASHED: return ENOMEM;
264
    case ERROR_BAD_ENVIRONMENT: return E2BIG;
265
    case ERROR_BAD_FORMAT: return ENOEXEC;
266
    case ERROR_INVALID_DRIVE: return ENOENT;
267
    case ERROR_CURRENT_DIRECTORY: return EACCES;
268
    case ERROR_NOT_SAME_DEVICE: return EXDEV;
269
    case ERROR_NO_MORE_FILES: return ENOENT;
270
    case ERROR_WRITE_PROTECT: return EACCES;
271
    case ERROR_BAD_UNIT: return EACCES;
272
    case ERROR_NOT_READY: return EACCES;
273
    case ERROR_BAD_COMMAND: return EACCES;
274
    case ERROR_CRC: return EACCES;
275
    case ERROR_BAD_LENGTH: return EACCES;
276
    case ERROR_SEEK: return EACCES;
277
    case ERROR_NOT_DOS_DISK: return EACCES;
278
    case ERROR_SECTOR_NOT_FOUND: return EACCES;
279
    case ERROR_OUT_OF_PAPER: return EACCES;
280
    case ERROR_WRITE_FAULT: return EACCES;
281
    case ERROR_READ_FAULT: return EACCES;
282
    case ERROR_GEN_FAILURE: return EACCES;
283
    case ERROR_SHARING_VIOLATION: return EACCES;
284
    case ERROR_LOCK_VIOLATION: return EACCES;
285
    case ERROR_WRONG_DISK: return EACCES;
286
    case ERROR_SHARING_BUFFER_EXCEEDED: return EACCES;
287
    case ERROR_BAD_NETPATH: return ENOENT;
288
    case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
289
    case ERROR_BAD_NET_NAME: return ENOENT;
290
    case ERROR_FILE_EXISTS: return EEXIST;
291
    case ERROR_CANNOT_MAKE: return EACCES;
292
    case ERROR_FAIL_I24: return EACCES;
293
    case ERROR_NO_PROC_SLOTS: return EAGAIN;
294
    case ERROR_DRIVE_LOCKED: return EACCES;
295
    case ERROR_BROKEN_PIPE: return EPIPE;
296
    case ERROR_DISK_FULL: return ENOSPC;
297
    case ERROR_INVALID_TARGET_HANDLE: return EBADF;
298
    case ERROR_WAIT_NO_CHILDREN: return ECHILD;
299
    case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
300
    case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
301
    case ERROR_SEEK_ON_DEVICE: return EACCES;
302
    case ERROR_DIR_NOT_EMPTY: return ENOTEMPTY;
303
    case ERROR_NOT_LOCKED: return EACCES;
304
    case ERROR_BAD_PATHNAME: return ENOENT;
305
    case ERROR_MAX_THRDS_REACHED: return EAGAIN;
306
    case ERROR_LOCK_FAILED: return EACCES;
307
    case ERROR_INVALID_STARTING_CODESEG: return ENOEXEC;
308
    case ERROR_INVALID_STACKSEG: return ENOEXEC;
309
    case ERROR_INVALID_MODULETYPE: return ENOEXEC;
310
    case ERROR_INVALID_EXE_SIGNATURE: return ENOEXEC;
311
    case ERROR_EXE_MARKED_INVALID: return ENOEXEC;
312
    case ERROR_BAD_EXE_FORMAT: return ENOEXEC;
313
    case ERROR_ITERATED_DATA_EXCEEDS_64k: return ENOEXEC;
314
    case ERROR_INVALID_MINALLOCSIZE: return ENOEXEC;
315
    case ERROR_DYNLINK_FROM_INVALID_RING: return ENOEXEC;
316
    case ERROR_IOPL_NOT_ENABLED: return ENOEXEC;
317
    case ERROR_INVALID_SEGDPL: return ENOEXEC;
318
    case ERROR_AUTODATASEG_EXCEEDS_64k: return ENOEXEC;
319
    case ERROR_RING2SEG_MUST_BE_MOVABLE: return ENOEXEC;
320
    case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: return ENOEXEC;
321
    case ERROR_INFLOOP_IN_RELOC_CHAIN: return ENOEXEC;
322
    case ERROR_FILENAME_EXCED_RANGE: return ENOENT;
323
    case ERROR_NESTING_NOT_ALLOWED: return EAGAIN;
324
    case ERROR_NOT_ENOUGH_QUOTA: return ENOMEM;
325
326
    default:
327
      return EIO;
328
    }
329
}
330
#endif
331
#endif /*HAVE_W32_SYSTEM*/
332
333
334
/* Set ERRNO from the Windows error.  EC may be -1 to use the last
335
 * error.  Returns the Windows error code.  */
336
#ifdef HAVE_W32_SYSTEM
337
int
338
gnupg_w32_set_errno (int ec)
339
{
340
#if GPGRT_VERSION_NUMBER >= 0x013e00  /* gpgrt >= 1.62 */
341
  return gpgrt_w32_set_errno (ec);
342
#else
343
  if (ec == -1)
344
    ec = GetLastError ();
345
  _set_errno (map_w32_to_errno (ec));
346
  return ec;
347
#endif
348
}
349
#endif /*HAVE_W32_SYSTEM*/
350
351
352
353
/* Allow the use of special "-&nnn" style file names.  */
354
void
355
enable_special_filenames (void)
356
0
{
357
0
  allow_special_filenames = 1;
358
0
}
359
360
361
/* Disable the use use of _open_osfhandle on Windows.  */
362
void
363
disable_translate_sys2libc_fd (void)
364
0
{
365
#ifdef HAVE_W32_SYSTEM
366
  no_translate_sys2libc_fd = 1;
367
#endif
368
0
}
369
370
371
/* Return a string which is used as a kind of process ID.  */
372
const byte *
373
get_session_marker (size_t *rlen)
374
40.6k
{
375
40.6k
  static byte marker[SIZEOF_UNSIGNED_LONG*2];
376
40.6k
  static int initialized;
377
378
40.6k
  if (!initialized)
379
4
    {
380
4
      gcry_create_nonce (marker, sizeof marker);
381
4
      initialized = 1;
382
4
    }
383
40.6k
  *rlen = sizeof (marker);
384
40.6k
  return marker;
385
40.6k
}
386
387
/* Return a random number in an unsigned int. */
388
unsigned int
389
get_uint_nonce (void)
390
0
{
391
0
  unsigned int value;
392
393
0
  gcry_create_nonce (&value, sizeof value);
394
0
  return value;
395
0
}
396
397
398
399
#if 0 /* not yet needed - Note that this will require inclusion of
400
         cmacros.am in Makefile.am */
401
int
402
check_permissions(const char *path,int extension,int checkonly)
403
{
404
#if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
405
  char *tmppath;
406
  struct stat statbuf;
407
  int ret=1;
408
  int isdir=0;
409
410
  if(opt.no_perm_warn)
411
    return 0;
412
413
  if(extension && path[0]!=DIRSEP_C)
414
    {
415
      if(strchr(path,DIRSEP_C))
416
  tmppath=make_filename(path,NULL);
417
      else
418
  tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
419
    }
420
  else
421
    tmppath=m_strdup(path);
422
423
  /* It's okay if the file doesn't exist */
424
  if(stat(tmppath,&statbuf)!=0)
425
    {
426
      ret=0;
427
      goto end;
428
    }
429
430
  isdir=S_ISDIR(statbuf.st_mode);
431
432
  /* Per-user files must be owned by the user.  Extensions must be
433
     owned by the user or root. */
434
  if((!extension && statbuf.st_uid != getuid()) ||
435
     (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
436
    {
437
      if(!checkonly)
438
  log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
439
     isdir?"directory":extension?"extension":"file",path);
440
      goto end;
441
    }
442
443
  /* This works for both directories and files - basically, we don't
444
     care what the owner permissions are, so long as the group and
445
     other permissions are 0 for per-user files, and non-writable for
446
     extensions. */
447
  if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
448
     (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
449
    {
450
      char *dir;
451
452
      /* However, if the directory the directory/file is in is owned
453
         by the user and is 700, then this is not a problem.
454
         Theoretically, we could walk this test up to the root
455
         directory /, but for the sake of sanity, I'm stopping at one
456
         level down. */
457
458
      dir= make_dirname (tmppath);
459
      if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
460
   S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
461
  {
462
    xfree (dir);
463
    ret=0;
464
    goto end;
465
  }
466
467
      m_free(dir);
468
469
      if(!checkonly)
470
  log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
471
     isdir?"directory":extension?"extension":"file",path);
472
      goto end;
473
    }
474
475
  ret=0;
476
477
 end:
478
  m_free(tmppath);
479
480
  return ret;
481
482
#endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
483
484
  return 0;
485
}
486
#endif
487
488
489
/* Wrapper around the usual sleep function.  This one won't wake up
490
   before the sleep time has really elapsed.  When build with Pth it
491
   merely calls pth_sleep and thus suspends only the current
492
   thread. */
493
void
494
gnupg_sleep (unsigned int seconds)
495
0
{
496
0
#ifdef USE_NPTH
497
0
  npth_sleep (seconds);
498
#else
499
  /* Fixme:  make sure that a sleep won't wake up to early.  */
500
# ifdef HAVE_W32_SYSTEM
501
  Sleep (seconds*1000);
502
# else
503
  sleep (seconds);
504
# endif
505
#endif
506
0
}
507
508
509
/* Wrapper around the platforms usleep function.  This one won't wake
510
 * up before the sleep time has really elapsed.  When build with nPth
511
 * it merely calls npth_usleep and thus suspends only the current
512
 * thread. */
513
void
514
gnupg_usleep (unsigned int usecs)
515
0
{
516
0
#if defined(USE_NPTH)
517
518
0
  npth_usleep (usecs);
519
520
#elif defined(HAVE_W32_SYSTEM)
521
522
  Sleep ((usecs + 999) / 1000);
523
524
#elif defined(HAVE_NANOSLEEP)
525
526
  if (usecs)
527
    {
528
      struct timespec req;
529
      struct timespec rem;
530
531
      req.tv_sec  = usecs / 1000000;
532
      req.tv_nsec = (usecs % 1000000) * 1000;
533
      while (nanosleep (&req, &rem) < 0 && errno == EINTR)
534
          req = rem;
535
    }
536
537
#else /*Standard Unix*/
538
539
  if (usecs)
540
    {
541
      struct timeval tv;
542
543
      tv.tv_sec  = usecs / 1000000;
544
      tv.tv_usec = usecs % 1000000;
545
      select (0, NULL, NULL, NULL, &tv);
546
    }
547
548
#endif
549
0
}
550
551
552
/* This function is a NOP for POSIX systems but required under Windows
553
   as the file handles as returned by OS calls (like CreateFile) are
554
   different from the libc file descriptors (like open). This function
555
   translates system file handles to libc file handles.  FOR_WRITE
556
   gives the direction of the handle.  */
557
#if defined(HAVE_W32_SYSTEM)
558
static int
559
translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
560
{
561
  int x;
562
563
  if (fd == GNUPG_INVALID_FD)
564
    return -1;
565
566
  /* Note that _open_osfhandle is currently defined to take and return
567
     a long.  */
568
  x = _open_osfhandle ((intptr_t)fd, for_write ? 1 : 0);
569
  if (x == -1)
570
    log_error ("failed to translate osfhandle %p\n", (void *) fd);
571
  return x;
572
}
573
#endif /*!HAVE_W32_SYSTEM */
574
575
576
/* This is the same as translate_sys2libc_fd but takes an integer
577
   which is assumed to be such an system handle.   */
578
int
579
translate_sys2libc_fd_int (int fd, int for_write)
580
0
{
581
#ifdef HAVE_W32_SYSTEM
582
  if (fd <= 2 || no_translate_sys2libc_fd)
583
    return fd;  /* Do not do this for stdin, stdout, and stderr.  */
584
585
  return translate_sys2libc_fd ((void*)(intptr_t)fd, for_write);
586
#else
587
0
  (void)for_write;
588
0
  return fd;
589
0
#endif
590
0
}
591
592
593
/*
594
 * Parse the string representation of a file reference (file handle on
595
 * Windows or file descriptor on POSIX) in FDSTR.  The string
596
 * representation may be either of following:
597
598
 *  (1) 0, 1, or 2 which means stdin, stdout, and stderr, respectively.
599
 *  (2) Integer representation (by %d of printf).
600
 *  (3) Hex representation which starts as "0x".
601
 *
602
 * Then, fill R_SYSHD, according to the value of a file reference.
603
 *
604
 */
605
gpg_error_t
606
gnupg_parse_fdstr (const char *fdstr, es_syshd_t *r_syshd)
607
0
{
608
0
  int fd = -1;
609
#ifdef HAVE_W32_SYSTEM
610
  gnupg_fd_t hd;
611
  char *endptr;
612
  int base;
613
614
  if (!strcmp (fdstr, "0"))
615
    fd = 0;
616
  else if (!strcmp (fdstr, "1"))
617
    fd = 1;
618
  else if (!strcmp (fdstr, "2"))
619
    fd = 2;
620
621
  if (fd >= 0)
622
    {
623
      r_syshd->type = ES_SYSHD_FD;
624
      r_syshd->u.fd = fd;
625
      return 0;
626
    }
627
628
  if (!strncmp (fdstr, "0x", 2))
629
    {
630
      base = 16;
631
      fdstr += 2;
632
    }
633
  else
634
    base = 10;
635
636
  gpg_err_set_errno (0);
637
#ifdef _WIN64
638
  hd = (gnupg_fd_t)strtoll (fdstr, &endptr, base);
639
#else
640
  hd = (gnupg_fd_t)strtol (fdstr, &endptr, base);
641
#endif
642
  if (errno != 0 || endptr == fdstr || *endptr != '\0')
643
    return gpg_error (GPG_ERR_INV_ARG);
644
645
  r_syshd->type = ES_SYSHD_HANDLE;
646
  r_syshd->u.handle = hd;
647
  return 0;
648
#else
649
0
  fd = atoi (fdstr);
650
0
  r_syshd->type = ES_SYSHD_FD;
651
0
  r_syshd->u.fd = fd;
652
0
  return 0;
653
0
#endif
654
0
}
655
656
657
/* Check whether FNAME has the form "-&nnnn", where N is a non-zero
658
 * number.  Returns this number or -1 if it is not the case.  If the
659
 * caller wants to use the file descriptor for writing FOR_WRITE shall
660
 * be set to 1.  If NOTRANSLATE is set the Windows specific mapping is
661
 * not done. */
662
int
663
check_special_filename (const char *fname, int for_write, int notranslate)
664
0
{
665
0
  if (allow_special_filenames
666
0
      && fname && *fname == '-' && fname[1] == '&')
667
0
    {
668
0
      int i;
669
670
0
      fname += 2;
671
0
      for (i=0; digitp (fname+i); i++ )
672
0
        ;
673
0
      if (!fname[i])
674
0
        {
675
0
          if (notranslate)
676
0
            return atoi (fname);
677
0
          else
678
0
            {
679
0
              es_syshd_t syshd;
680
681
0
              if (gnupg_parse_fdstr (fname,  &syshd))
682
0
                return -1;
683
684
#ifdef HAVE_W32_SYSTEM
685
              if (syshd.type == ES_SYSHD_FD)
686
                return syshd.u.fd;
687
              else
688
                return translate_sys2libc_fd ((gnupg_fd_t)syshd.u.handle, for_write);
689
#else
690
0
              (void)for_write;
691
0
              return syshd.u.fd;
692
0
#endif
693
0
            }
694
0
        }
695
0
    }
696
0
  return -1;
697
0
}
698
699
700
/* Check whether FNAME has the form "-&nnnn", where N is a number
701
 * representing a file.  Returns GNUPG_INVALID_FD if it is not the
702
 * case.  Returns a file descriptor on POSIX, a system handle on
703
 * Windows.  */
704
gnupg_fd_t
705
gnupg_check_special_filename (const char *fname)
706
354k
{
707
354k
  if (allow_special_filenames
708
0
      && fname && *fname == '-' && fname[1] == '&')
709
0
    {
710
0
      int i;
711
712
0
      fname += 2;
713
0
      for (i=0; digitp (fname+i); i++ )
714
0
        ;
715
0
      if (!fname[i])
716
0
        {
717
0
          es_syshd_t syshd;
718
719
0
          if (gnupg_parse_fdstr (fname,  &syshd))
720
0
            return GNUPG_INVALID_FD;
721
722
#ifdef HAVE_W32_SYSTEM
723
          if (syshd.type == ES_SYSHD_FD)
724
            {
725
              if (syshd.u.fd == 0)
726
                return GetStdHandle (STD_INPUT_HANDLE);
727
              else if (syshd.u.fd == 1)
728
                return GetStdHandle (STD_OUTPUT_HANDLE);
729
              else if (syshd.u.fd == 2)
730
                return GetStdHandle (STD_ERROR_HANDLE);
731
            }
732
          else
733
            return syshd.u.handle;
734
#else
735
0
          return syshd.u.fd;
736
0
#endif
737
0
        }
738
0
    }
739
354k
  return GNUPG_INVALID_FD;
740
354k
}
741
742
/* Replacement for tmpfile().  This is required because the tmpfile
743
   function of Windows' runtime library is broken, insecure, ignores
744
   TMPDIR and so on.  In addition we create a file with an inheritable
745
   handle.  */
746
FILE *
747
gnupg_tmpfile (void)
748
0
{
749
#ifdef HAVE_W32_SYSTEM
750
  int attempts, n;
751
  char buffer[MAX_PATH+7+12+1];
752
  char *name, *p;
753
  HANDLE file;
754
  int pid = GetCurrentProcessId ();
755
  unsigned int value = 0;
756
  int i;
757
  SECURITY_ATTRIBUTES sec_attr;
758
759
  memset (&sec_attr, 0, sizeof sec_attr );
760
  sec_attr.nLength = sizeof sec_attr;
761
  sec_attr.bInheritHandle = TRUE;
762
763
  n = GetTempPath (MAX_PATH+1, buffer);
764
  if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
765
    {
766
      gpg_err_set_errno (ENOENT);
767
      return NULL;
768
    }
769
  p = buffer + strlen (buffer);
770
  p = stpcpy (p, "_gnupg");
771
  /* We try to create the directory but don't care about an error as
772
     it may already exist and the CreateFile would throw an error
773
     anyway.  */
774
  CreateDirectory (buffer, NULL);
775
  *p++ = '\\';
776
  name = p;
777
  for (attempts=0; attempts < 10; attempts++)
778
    {
779
      p = name;
780
      value += (GetTickCount () ^ ((pid<<16) & 0xffff0000));
781
      for (i=0; i < 8; i++)
782
  *p++ = tohex (((value >> (7 - i)*4) & 0x0f));
783
      strcpy (p, ".tmp");
784
      file = CreateFile (buffer,
785
                         GENERIC_READ | GENERIC_WRITE,
786
                         0,
787
                         &sec_attr,
788
                         CREATE_NEW,
789
                         FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
790
                         NULL);
791
      if (file != INVALID_HANDLE_VALUE)
792
        {
793
          FILE *fp;
794
          int fd = _open_osfhandle ((intptr_t)file, 0);
795
          if (fd == -1)
796
            {
797
              CloseHandle (file);
798
              return NULL;
799
            }
800
          fp = fdopen (fd, "w+b");
801
          if (!fp)
802
            {
803
              int save = errno;
804
              close (fd);
805
              gpg_err_set_errno (save);
806
              return NULL;
807
            }
808
          return fp;
809
        }
810
      Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
811
    }
812
  gpg_err_set_errno (ENOENT);
813
  return NULL;
814
815
#else /*!HAVE_W32_SYSTEM*/
816
817
0
  return tmpfile ();
818
819
0
#endif /*!HAVE_W32_SYSTEM*/
820
0
}
821
822
823
/* Make sure that the standard file descriptors are opened. Obviously
824
   some folks close them before an exec and the next file we open will
825
   get one of them assigned and thus any output (i.e. diagnostics) end
826
   up in that file (e.g. the trustdb).  Not actually a gpg problem as
827
   this will happen with almost all utilities when called in a wrong
828
   way.  However we try to minimize the damage here and raise
829
   awareness of the problem.
830
831
   Must be called before we open any files! */
832
void
833
gnupg_reopen_std (const char *pgmname)
834
0
{
835
0
#ifdef F_GETFD
836
0
  int did_stdin = 0;
837
0
  int did_stdout = 0;
838
0
  int did_stderr = 0;
839
0
  FILE *complain;
840
841
0
  if (fcntl (STDIN_FILENO, F_GETFD) == -1 && errno ==EBADF)
842
0
    {
843
0
      if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
844
0
  did_stdin = 1;
845
0
      else
846
0
  did_stdin = 2;
847
0
    }
848
849
0
  if (fcntl (STDOUT_FILENO, F_GETFD) == -1 && errno == EBADF)
850
0
    {
851
0
      if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
852
0
  did_stdout = 1;
853
0
      else
854
0
  did_stdout = 2;
855
0
    }
856
857
0
  if (fcntl (STDERR_FILENO, F_GETFD)==-1 && errno==EBADF)
858
0
    {
859
0
      if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
860
0
  did_stderr = 1;
861
0
      else
862
0
  did_stderr = 2;
863
0
    }
864
865
  /* It's hard to log this sort of thing since the filehandle we would
866
     complain to may be closed... */
867
0
  if (!did_stderr)
868
0
    complain = stderr;
869
0
  else if (!did_stdout)
870
0
    complain = stdout;
871
0
  else
872
0
    complain = NULL;
873
874
0
  if (complain)
875
0
    {
876
0
      if (did_stdin == 1)
877
0
  fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
878
0
      if (did_stdout == 1)
879
0
  fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
880
0
      if (did_stderr == 1)
881
0
  fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
882
883
0
      if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
884
0
  fprintf(complain,"%s: fatal: unable to reopen standard input,"
885
0
    " output, or error\n", pgmname);
886
0
    }
887
888
0
  if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
889
0
    exit (3);
890
#else /* !F_GETFD */
891
  (void)pgmname;
892
#endif
893
0
}
894
895
896
/* Inhibit calls to AllowSetForegroundWindow on Windows.  Calling this
897
 * with YES set to true calls to gnupg_allow_set_foregound_window are
898
 * shunted.  */
899
void
900
gnupg_inhibit_set_foregound_window (int yes)
901
0
{
902
#ifdef HAVE_W32_SYSTEM
903
  inhibit_set_foregound_window = yes;
904
#else
905
0
  (void)yes;
906
0
#endif
907
0
}
908
909
910
/* Hack required for Windows.  */
911
void
912
gnupg_allow_set_foregound_window (pid_t pid)
913
0
{
914
0
  if (!pid)
915
0
    log_info ("%s called with invalid pid %lu\n",
916
0
              "gnupg_allow_set_foregound_window", (unsigned long)pid);
917
#if defined(HAVE_W32_SYSTEM)
918
  else if (inhibit_set_foregound_window)
919
    ;
920
  else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
921
    {
922
      char *flags = getenv ("GNUPG_EXEC_DEBUG_FLAGS");
923
      if (flags && (atoi (flags) & 2))
924
        log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
925
                  (unsigned long)pid, w32_strerror (-1));
926
    }
927
#endif
928
0
}
929
930
931
/* Helper for gnupg_rename and gnupg_remove.  */
932
#ifdef HAVE_W32_SYSTEM
933
static int
934
w32_wait_when_sharing_violation (int wtime, const char *fname)
935
{                               /* in milliseconds */
936
  int ec = GetLastError ();
937
938
  if (ec != ERROR_SHARING_VIOLATION)
939
    {
940
      gnupg_w32_set_errno (ec);
941
      return 0;
942
    }
943
944
  /* Another process has the file open.  We do not use a
945
   * lock for read but instead we wait until the other
946
   * process has closed the file.  This may take long but
947
   * that would also be the case with a dotlock approach for
948
   * read and write.  Note that we don't need this on Unix
949
   * due to the inode concept.
950
   *
951
   * So let's wait until the file_op has worked.  The retry
952
   * intervals are 50, 100, 200, 400, 800, 50ms, ...  */
953
  if (!wtime || wtime >= 800)
954
    wtime = 50;
955
  else
956
    wtime *= 2;
957
958
  if (wtime >= 800)
959
    log_info (_("waiting for file '%s' to become accessible ...\n"),
960
              fname);
961
962
  gnupg_usleep ((unsigned int)wtime*1000);
963
  return wtime;  /* Note: WTIME is always > 0 */
964
}
965
#endif /*HAVE_W32_SYSTEM*/
966
967
968
/* The Windows version to remove a file.  If WAIT_FOR_ACCESS is
969
 * non-zero the functions waits until a sharing violation has been
970
 * solved.  A value of -1 waits indefinitely, a positive value gives
971
 * the number of milliseconds to wait at max.  */
972
#ifdef HAVE_W32_SYSTEM
973
static int
974
w32_remove (const char *fname, int wait_for_access)
975
{
976
  wchar_t *wfname;
977
  int wtime = 0;
978
  int totalwtime = 0;
979
980
  wfname = utf8_to_wchar (fname);
981
  if (!wfname)
982
    return -1; /* Error - ERRNO has already been set.  */
983
984
 again:
985
  if (DeleteFileW (wfname))
986
    {
987
      xfree (wfname);
988
      return 0; /* Success.  */
989
    }
990
  if (!wait_for_access
991
      || (wait_for_access > 0 && totalwtime > wait_for_access))
992
    gnupg_w32_set_errno (-1);
993
  else if ((wtime = w32_wait_when_sharing_violation (wtime, fname)))
994
    {
995
      totalwtime += wtime;
996
      goto again;
997
    }
998
999
  xfree (wfname);
1000
  return -1;
1001
}
1002
#endif /* HAVE_W32_SYSTEM */
1003
1004
/* This is a remove function which allows - on Windows - to wait until
1005
 * a sharing violation has been solved.  WAIT_FOR_ACCESS may eitehr be
1006
 * -1 to wait indefinitely or the number of milliseconds to wait
1007
 * before giving up.  */
1008
int
1009
gnupg_remove_ext (const char *fname, int wait_for_access)
1010
181
{
1011
#ifdef HAVE_W32_SYSTEM
1012
  return w32_remove (fname, wait_for_access);
1013
#else /* Unix */
1014
181
  (void)wait_for_access;
1015
  /* It is common to use /dev/null for testing.  We better don't
1016
   * remove that file.  */
1017
181
  if (fname && !strcmp (fname, "/dev/null"))
1018
0
    return 0;
1019
181
  else
1020
181
    return remove (fname);
1021
181
#endif
1022
181
}
1023
1024
int
1025
gnupg_remove (const char *fname)
1026
181
{
1027
181
  return gnupg_remove_ext (fname, 0);
1028
181
}
1029
1030
1031
/* Helper for gnupg_rename_file.  */
1032
#ifdef HAVE_W32_SYSTEM
1033
static int
1034
w32_rename (const char *oldname, const char *newname)
1035
{
1036
  if (any8bitchar (oldname) || any8bitchar (newname))
1037
    {
1038
      wchar_t *woldname, *wnewname;
1039
      int ret;
1040
1041
      woldname = utf8_to_wchar (oldname);
1042
      if (!woldname)
1043
        return -1;
1044
      wnewname = utf8_to_wchar (newname);
1045
      if (!wnewname)
1046
        {
1047
          xfree (wnewname);
1048
          return -1;
1049
        }
1050
      ret = _wrename (woldname, wnewname);
1051
      xfree (wnewname);
1052
      xfree (woldname);
1053
      return ret;
1054
    }
1055
  else
1056
    return rename (oldname, newname);
1057
}
1058
#endif /*HAVE_W32_SYSTEM*/
1059
1060
1061
/* Wrapper for rename(2) to handle Windows peculiarities.  If
1062
 * BLOCK_SIGNALS is not NULL and points to a variable set to true, all
1063
 * signals will be blocked by calling gnupg_block_all_signals; the
1064
 * caller needs to call gnupg_unblock_all_signals if that variable is
1065
 * still set to true on return. */
1066
gpg_error_t
1067
gnupg_rename_file (const char *oldname, const char *newname, int *block_signals)
1068
4.85k
{
1069
4.85k
  gpg_error_t err = 0;
1070
1071
4.85k
  if (block_signals && *block_signals)
1072
2.42k
    gnupg_block_all_signals ();
1073
1074
#ifdef HAVE_DOSISH_SYSTEM
1075
  {
1076
    int wtime = 0;
1077
1078
    w32_remove (newname, -1);
1079
  again:
1080
    if (w32_rename (oldname, newname))
1081
      {
1082
        if ((wtime = w32_wait_when_sharing_violation (wtime, oldname)))
1083
          goto again;
1084
        err = my_error_from_syserror ();
1085
      }
1086
  }
1087
#else /* Unix */
1088
4.85k
  {
1089
#ifdef __riscos__
1090
    gnupg_remove (newname);
1091
#endif
1092
4.85k
    if (rename (oldname, newname) )
1093
0
      err = my_error_from_syserror ();
1094
4.85k
  }
1095
4.85k
#endif /* Unix */
1096
1097
4.85k
  if (block_signals && *block_signals && err)
1098
0
    {
1099
0
      gnupg_unblock_all_signals ();
1100
0
      *block_signals = 0;
1101
0
    }
1102
1103
4.85k
  if (err)
1104
4.85k
    log_error (_("renaming '%s' to '%s' failed: %s\n"),
1105
0
               oldname, newname, gpg_strerror (err));
1106
4.85k
  return err;
1107
4.85k
}
1108
1109
1110
#ifndef HAVE_W32_SYSTEM
1111
static mode_t
1112
modestr_to_mode (const char *modestr, mode_t oldmode)
1113
0
{
1114
0
  static struct {
1115
0
    char letter;
1116
0
    mode_t value;
1117
0
  } table[] = { { '-', 0 },
1118
0
                { 'r', S_IRUSR }, { 'w', S_IWUSR }, { 'x', S_IXUSR },
1119
0
                { 'r', S_IRGRP }, { 'w', S_IWGRP }, { 'x', S_IXGRP },
1120
0
                { 'r', S_IROTH }, { 'w', S_IWOTH }, { 'x', S_IXOTH } };
1121
0
  int idx;
1122
0
  mode_t mode = 0;
1123
1124
  /* For now we only support a string as used by ls(1) and no octal
1125
   * numbers.  The first character must be a dash.  */
1126
0
  for (idx=0; idx < 10 && *modestr; idx++, modestr++)
1127
0
    {
1128
0
      if (*modestr == table[idx].letter)
1129
0
        mode |= table[idx].value;
1130
0
      else if (*modestr == '.')
1131
0
        {
1132
0
          if (!idx)
1133
0
            ;  /* Skip the dummy.  */
1134
0
          else if ((oldmode & table[idx].value))
1135
0
            mode |= (oldmode & table[idx].value);
1136
0
          else
1137
0
            mode &= ~(oldmode & table[idx].value);
1138
0
        }
1139
0
      else if (*modestr != '-')
1140
0
        break;
1141
0
    }
1142
1143
1144
0
  return mode;
1145
0
}
1146
#endif
1147
1148
1149
/* A wrapper around mkdir which takes a string for the mode argument.
1150
   This makes it easier to handle the mode argument which is not
1151
   defined on all systems.  The format of the modestring is
1152
1153
      "-rwxrwxrwx"
1154
1155
   '-' is a don't care or not set.  'r', 'w', 'x' are read allowed,
1156
   write allowed, execution allowed with the first group for the user,
1157
   the second for the group and the third for all others.  If the
1158
   string is shorter than above the missing mode characters are meant
1159
   to be not set.  */
1160
int
1161
gnupg_mkdir (const char *name, const char *modestr)
1162
0
{
1163
  /* Note that gpgrt_mkdir also sets ERRNO in addition to returning an
1164
   * gpg-error style error code.  */
1165
0
  return gpgrt_mkdir (name, modestr);
1166
0
}
1167
1168
1169
/* A simple wrapper around chdir.  NAME is expected to be utf8
1170
 * encoded.  */
1171
int
1172
gnupg_chdir (const char *name)
1173
0
{
1174
  /* Note that gpgrt_chdir also sets ERRNO in addition to returning an
1175
   * gpg-error style error code.  */
1176
0
  return gpgrt_chdir (name);
1177
0
}
1178
1179
1180
/* A wrapper around rmdir.  NAME is expected to be utf8 encoded.  */
1181
int
1182
gnupg_rmdir (const char *name)
1183
0
{
1184
#ifdef HAVE_W32_SYSTEM
1185
  int rc;
1186
  wchar_t *wfname;
1187
1188
  wfname = utf8_to_wchar (name);
1189
  if (!wfname)
1190
    rc = 0;
1191
  else
1192
    {
1193
      rc = RemoveDirectoryW (wfname);
1194
      if (!rc)
1195
        gnupg_w32_set_errno (-1);
1196
      xfree (wfname);
1197
    }
1198
  if (!rc)
1199
    return -1;
1200
  return 0;
1201
#else
1202
0
  return rmdir (name);
1203
0
#endif
1204
0
}
1205
1206
1207
/* A wrapper around chmod which takes a string for the mode argument.
1208
   This makes it easier to handle the mode argument which is not
1209
   defined on all systems.  The format of the modestring is the same
1210
   as for gnupg_mkdir with extra feature that a '.' keeps the original
1211
   mode bit.  */
1212
int
1213
gnupg_chmod (const char *name, const char *modestr)
1214
0
{
1215
#ifdef HAVE_W32_SYSTEM
1216
  (void)name;
1217
  (void)modestr;
1218
  return 0;
1219
#else
1220
0
  mode_t oldmode;
1221
0
  if (strchr (modestr, '.'))
1222
0
    {
1223
      /* Get the old mode so that a '.' can copy that bit.  */
1224
0
      struct stat st;
1225
1226
0
      if (stat (name, &st))
1227
0
        return -1;
1228
0
      oldmode = st.st_mode;
1229
0
    }
1230
0
  else
1231
0
    oldmode = 0;
1232
0
  return chmod (name, modestr_to_mode (modestr, oldmode));
1233
0
#endif
1234
0
}
1235
1236
1237
/* Our version of mkdtemp.  The API is identical to POSIX.1-2008
1238
   version.  We do not use a system provided mkdtemp because we have a
1239
   good RNG instantly available and this way we don't have diverging
1240
   versions.  */
1241
char *
1242
gnupg_mkdtemp (char *tmpl)
1243
0
{
1244
  /* A lower bound on the number of temporary files to attempt to
1245
     generate.  The maximum total number of temporary file names that
1246
     can exist for a given template is 62**6 (5*36**3 for Windows).
1247
     It should never be necessary to try all these combinations.
1248
     Instead if a reasonable number of names is tried (we define
1249
     reasonable as 62**3 or 5*36**3) fail to give the system
1250
     administrator the chance to remove the problems.  */
1251
#ifdef HAVE_W32_SYSTEM
1252
  static const char letters[] =
1253
    "abcdefghijklmnopqrstuvwxyz0123456789";
1254
# define NUMBER_OF_LETTERS 36
1255
# define ATTEMPTS_MIN (5 * 36 * 36 * 36)
1256
#else
1257
0
  static const char letters[] =
1258
0
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
1259
0
# define NUMBER_OF_LETTERS 62
1260
0
# define ATTEMPTS_MIN (62 * 62 * 62)
1261
0
#endif
1262
0
  int len;
1263
0
  char *XXXXXX;
1264
0
  uint64_t value;
1265
0
  unsigned int count;
1266
0
  int save_errno = errno;
1267
  /* The number of times to attempt to generate a temporary file.  To
1268
     conform to POSIX, this must be no smaller than TMP_MAX.  */
1269
#if ATTEMPTS_MIN < TMP_MAX
1270
  unsigned int attempts = TMP_MAX;
1271
#else
1272
0
  unsigned int attempts = ATTEMPTS_MIN;
1273
0
#endif
1274
1275
0
  len = strlen (tmpl);
1276
0
  if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
1277
0
    {
1278
0
      gpg_err_set_errno (EINVAL);
1279
0
      return NULL;
1280
0
    }
1281
1282
  /* This is where the Xs start.  */
1283
0
  XXXXXX = &tmpl[len - 6];
1284
1285
  /* Get a random start value.  */
1286
0
  gcry_create_nonce (&value, sizeof value);
1287
1288
  /* Loop until a directory was created.  */
1289
0
  for (count = 0; count < attempts; value += 7777, ++count)
1290
0
    {
1291
0
      uint64_t v = value;
1292
1293
      /* Fill in the random bits.  */
1294
0
      XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
1295
0
      v /= NUMBER_OF_LETTERS;
1296
0
      XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
1297
0
      v /= NUMBER_OF_LETTERS;
1298
0
      XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
1299
0
      v /= NUMBER_OF_LETTERS;
1300
0
      XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
1301
0
      v /= NUMBER_OF_LETTERS;
1302
0
      XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
1303
0
      v /= NUMBER_OF_LETTERS;
1304
0
      XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
1305
1306
0
      if (!gnupg_mkdir (tmpl, "-rwx"))
1307
0
        {
1308
0
          gpg_err_set_errno (save_errno);
1309
0
          return tmpl;
1310
0
        }
1311
0
      if (errno != EEXIST)
1312
0
  return NULL;
1313
0
    }
1314
1315
  /* We got out of the loop because we ran out of combinations to try.  */
1316
0
  gpg_err_set_errno (EEXIST);
1317
0
  return NULL;
1318
0
}
1319
1320
1321
int
1322
gnupg_setenv (const char *name, const char *value, int overwrite)
1323
0
{
1324
#ifdef HAVE_W32_SYSTEM
1325
  /*  Windows maintains (at least) two sets of environment variables.
1326
      One set can be accessed by GetEnvironmentVariable and
1327
      SetEnvironmentVariable.  This set is inherited by the children.
1328
      The other set is maintained in the C runtime, and is accessed
1329
      using getenv and putenv.  We try to keep them in sync by
1330
      modifying both sets.  */
1331
  {
1332
    int exists;
1333
    char tmpbuf[10];
1334
    exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf);
1335
1336
    if ((! exists || overwrite) && !SetEnvironmentVariable (name, value))
1337
      {
1338
        gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
1339
        return -1;
1340
      }
1341
  }
1342
#endif /*W32*/
1343
1344
0
#ifdef HAVE_SETENV
1345
0
  return setenv (name, value, overwrite);
1346
#else /*!HAVE_SETENV*/
1347
  if (! getenv (name) || overwrite)
1348
#if defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
1349
    {
1350
      int e = _putenv_s (name, value);
1351
1352
      if (e)
1353
        {
1354
          gpg_err_set_errno (e);
1355
          return -1;
1356
        }
1357
      else
1358
        return 0;
1359
    }
1360
#else
1361
    {
1362
      char *buf;
1363
1364
      (void)overwrite;
1365
      if (!name || !value)
1366
        {
1367
          gpg_err_set_errno (EINVAL);
1368
          return -1;
1369
        }
1370
      buf = strconcat (name, "=", value, NULL);
1371
      if (!buf)
1372
        return -1;
1373
# if __GNUC__
1374
#  warning no setenv - using putenv but leaking memory.
1375
# endif
1376
      return putenv (buf);
1377
    }
1378
#endif /*!HAVE_W32_SYSTEM*/
1379
  return 0;
1380
#endif /*!HAVE_SETENV*/
1381
0
}
1382
1383
1384
int
1385
gnupg_unsetenv (const char *name)
1386
0
{
1387
#ifdef HAVE_W32_SYSTEM
1388
  /*  Windows maintains (at least) two sets of environment variables.
1389
      One set can be accessed by GetEnvironmentVariable and
1390
      SetEnvironmentVariable.  This set is inherited by the children.
1391
      The other set is maintained in the C runtime, and is accessed
1392
      using getenv and putenv.  We try to keep them in sync by
1393
      modifying both sets.  */
1394
  if (!SetEnvironmentVariable (name, NULL))
1395
    {
1396
      gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
1397
      return -1;
1398
    }
1399
#endif /*W32*/
1400
1401
0
#ifdef HAVE_UNSETENV
1402
0
  return unsetenv (name);
1403
#elif defined(HAVE_W32_SYSTEM) && defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
1404
  {
1405
    int e = _putenv_s (name, "");
1406
1407
    if (e)
1408
      {
1409
  gpg_err_set_errno (e);
1410
  return -1;
1411
      }
1412
    else
1413
      return 0;
1414
  }
1415
#else /*!HAVE_UNSETENV*/
1416
  {
1417
    char *buf;
1418
    int r;
1419
1420
    if (!name)
1421
      {
1422
        gpg_err_set_errno (EINVAL);
1423
        return -1;
1424
      }
1425
    buf = strconcat (name, "=", NULL);
1426
    if (!buf)
1427
      return -1;
1428
1429
    r = putenv (buf);
1430
# ifdef HAVE_W32_SYSTEM
1431
    /* For Microsoft implementation, we can free the memory in this
1432
       use case.  */
1433
    xfree (buf);
1434
# else
1435
#  if __GNUC__
1436
#   warning no unsetenv - trying putenv but leaking memory.
1437
#  endif
1438
# endif
1439
    return r;
1440
  }
1441
#endif /*!HAVE_UNSETENV*/
1442
0
}
1443
1444
1445
/* Return the current working directory as a malloced string.  Return
1446
   NULL and sets ERRNO on error.  */
1447
char *
1448
gnupg_getcwd (void)
1449
0
{
1450
0
  return gpgrt_getcwd ();
1451
0
}
1452
1453
1454
/* A simple wrapper around access.  NAME is expected to be utf8
1455
 * encoded.  This function returns an error code and sets ERRNO. */
1456
gpg_err_code_t
1457
gnupg_access (const char *name, int mode)
1458
11.7k
{
1459
11.7k
  return gpgrt_access (name, mode);
1460
11.7k
}
1461
1462
1463
/* A wrapper around stat to handle Unicode file names under Windows.  */
1464
#ifdef HAVE_STAT
1465
int
1466
gnupg_stat (const char *name, struct stat *statbuf)
1467
4
{
1468
# ifdef HAVE_W32_SYSTEM
1469
#  if __MINGW32_MAJOR_VERSION > 3
1470
    /* mingw.org's MinGW */
1471
#   define STRUCT_STAT _stat
1472
#  elif defined(_USE_32BIT_TIME_T)
1473
    /* MinGW64 for i686 */
1474
#   define STRUCT_STAT _stat32
1475
#  else
1476
    /* MinGW64 for x86_64 */
1477
#   define STRUCT_STAT _stat64i32
1478
#  endif
1479
  if (any8bitchar (name))
1480
    {
1481
      wchar_t *wname;
1482
      struct STRUCT_STAT st32;
1483
      int ret;
1484
1485
      wname = utf8_to_wchar (name);
1486
      if (!wname)
1487
        return -1;
1488
      ret = _wstat (wname, &st32);
1489
      xfree (wname);
1490
      if (!ret)
1491
        {
1492
          statbuf->st_dev   = st32.st_dev;
1493
          statbuf->st_ino   = st32.st_ino;
1494
          statbuf->st_mode  = st32.st_mode;
1495
          statbuf->st_nlink = st32.st_nlink;
1496
          statbuf->st_uid   = st32.st_uid;
1497
          statbuf->st_gid   = st32.st_gid;
1498
          statbuf->st_rdev  = st32.st_rdev;
1499
          statbuf->st_size  = st32.st_size;
1500
          statbuf->st_atime = st32.st_atime;
1501
          statbuf->st_mtime = st32.st_mtime;
1502
          statbuf->st_ctime = st32.st_ctime;
1503
        }
1504
      return ret;
1505
    }
1506
  else
1507
    return stat (name, statbuf);
1508
# else
1509
4
  return stat (name, statbuf);
1510
4
# endif
1511
4
}
1512
#endif /*HAVE_STAT*/
1513
1514
1515
/* A wrapper around open to handle Unicode file names under Windows.  */
1516
int
1517
gnupg_open (const char *name, int flags, unsigned int mode)
1518
4
{
1519
#ifdef HAVE_W32_SYSTEM
1520
  if (any8bitchar (name))
1521
    {
1522
      wchar_t *wname;
1523
      int ret;
1524
1525
      wname = utf8_to_wchar (name);
1526
      if (!wname)
1527
        return -1;
1528
      ret = _wopen (wname, flags, mode);
1529
      xfree (wname);
1530
      return ret;
1531
    }
1532
  else
1533
    return open (name, flags, mode);
1534
#else
1535
4
  return open (name, flags, mode);
1536
4
#endif
1537
4
}
1538
1539
1540
/* A wrapper around opendir to handle Unicode file names under
1541
 * Windows.  This assumes the mingw toolchain.  */
1542
gnupg_dir_t
1543
gnupg_opendir (const char *name)
1544
0
{
1545
#ifdef HAVE_W32_SYSTEM
1546
  _WDIR *dir;
1547
  wchar_t *wname;
1548
#else
1549
0
  DIR *dir;
1550
0
#endif
1551
0
  gnupg_dir_t gdir;
1552
1553
#ifdef HAVE_W32_SYSTEM
1554
  /* Note: See gpgtar-create for an alternative implementation which
1555
   * could be used here to avoid a mingw dependency.  */
1556
  wname = utf8_to_wchar (name);
1557
  if (!wname)
1558
    return NULL;
1559
  dir = _wopendir (wname);
1560
  xfree (wname);
1561
#else
1562
0
  dir = opendir (name);
1563
0
#endif
1564
1565
0
  if (!dir)
1566
0
    return NULL;
1567
1568
0
  gdir = xtrymalloc (sizeof *gdir);
1569
0
  if (!gdir)
1570
0
    {
1571
0
      int save_errno = errno;
1572
#ifdef HAVE_W32_SYSTEM
1573
      _wclosedir (dir);
1574
#else
1575
0
      closedir (dir);
1576
0
#endif
1577
0
      gpg_err_set_errno (save_errno);
1578
0
      return NULL;
1579
0
    }
1580
0
  gdir->dir = dir;
1581
0
  gdir->namesize = 0;
1582
0
  gdir->dirent.d_name = gdir->name;
1583
1584
0
  return gdir;
1585
0
}
1586
1587
1588
gnupg_dirent_t
1589
gnupg_readdir (gnupg_dir_t gdir)
1590
0
{
1591
#ifdef HAVE_W32_SYSTEM
1592
  char *namebuffer = NULL;
1593
  struct _wdirent *de;
1594
#else
1595
0
  struct dirent *de;
1596
0
#endif
1597
0
  size_t n;
1598
0
  gnupg_dirent_t gde;
1599
0
  const char *name;
1600
1601
0
  if (!gdir)
1602
0
    {
1603
0
      gpg_err_set_errno (EINVAL);
1604
0
      return 0;
1605
0
    }
1606
1607
#ifdef HAVE_W32_SYSTEM
1608
  de = _wreaddir (gdir->dir);
1609
  if (!de)
1610
    return NULL;
1611
  namebuffer = wchar_to_utf8 (de->d_name);
1612
  if (!namebuffer)
1613
    return NULL;
1614
  name = namebuffer;
1615
#else
1616
0
  de = readdir (gdir->dir);
1617
0
  if (!de)
1618
0
    return NULL;
1619
0
  name = de->d_name;
1620
0
#endif
1621
1622
0
  gde = &gdir->dirent;
1623
0
  n = strlen (name);
1624
0
  if (gdir->namesize)
1625
0
    {
1626
      /* Use allocated buffer.  */
1627
0
      if (n+1 >= gdir->namesize || !gde->d_name)
1628
0
        {
1629
0
          gdir->namesize = n + 256;
1630
0
          xfree (gde->d_name);
1631
0
          gde->d_name = xtrymalloc (gdir->namesize);
1632
0
          if (!gde->d_name)
1633
0
            return NULL;  /* ERRNO is already set.  */
1634
0
        }
1635
0
      strcpy (gde->d_name, name);
1636
0
    }
1637
0
  else if (n+1 >= sizeof (gdir->name))
1638
0
    {
1639
      /* Switch to allocated buffer.  */
1640
0
      gdir->namesize = n + 256;
1641
0
      gde->d_name = xtrymalloc (gdir->namesize);
1642
0
      if (!gde->d_name)
1643
0
        return NULL;  /* ERRNO is already set.  */
1644
0
      strcpy (gde->d_name, name);
1645
0
    }
1646
0
  else
1647
0
    {
1648
      /* Use static buffer.  */
1649
0
      gde->d_name = gdir->name;
1650
0
      strcpy (gde->d_name, name);
1651
0
    }
1652
1653
#ifdef HAVE_W32_SYSTEM
1654
  xfree (namebuffer);
1655
#endif
1656
1657
0
  return gde;
1658
0
}
1659
1660
1661
int
1662
gnupg_closedir (gnupg_dir_t gdir)
1663
0
{
1664
#ifdef HAVE_W32_SYSTEM
1665
  _WDIR *dir;
1666
#else
1667
0
  DIR *dir;
1668
0
#endif
1669
1670
0
  if (!gdir)
1671
0
    return 0;
1672
0
  dir = gdir->dir;
1673
0
  if (gdir->namesize)
1674
0
    xfree (gdir->dirent.d_name);
1675
0
  xfree (gdir);
1676
1677
#ifdef HAVE_W32_SYSTEM
1678
  return _wclosedir (dir);
1679
#else
1680
0
  return closedir (dir);
1681
0
#endif
1682
0
}
1683
1684
1685
/* Try to set an envvar.  Print only a notice on error.  */
1686
#ifndef HAVE_W32_SYSTEM
1687
static void
1688
try_set_envvar (const char *name, const char *value, int silent)
1689
0
{
1690
0
  if (gnupg_setenv (name, value, 1))
1691
0
    if (!silent)
1692
0
      log_info ("error setting envvar %s to '%s': %s\n", name, value,
1693
0
                gpg_strerror (my_error_from_syserror ()));
1694
0
}
1695
#endif /*!HAVE_W32_SYSTEM*/
1696
1697
1698
/* Switch to USER which is either a name or an UID.  This is a nop
1699
 * under Windows.  Note that in general it is only possible to switch
1700
 * to another user id if the process is running under root.  if silent
1701
 * is set no diagnostics are printed.  */
1702
gpg_error_t
1703
gnupg_chuid (const char *user, int silent)
1704
0
{
1705
#ifdef HAVE_W32_SYSTEM
1706
  (void)user;  /* Not implemented for Windows - ignore.  */
1707
  (void)silent;
1708
  return 0;
1709
1710
#elif HAVE_PWD_H /* A proper Unix  */
1711
  unsigned long ul;
1712
0
  struct passwd *pw;
1713
0
  struct stat st;
1714
0
  char *endp;
1715
0
  gpg_error_t err;
1716
1717
0
  gpg_err_set_errno (0);
1718
0
  ul = strtoul (user, &endp, 10);
1719
0
  if (errno || endp == user || *endp)
1720
0
    pw = getpwnam (user);  /* Not a number; assume USER is a name.  */
1721
0
  else
1722
0
    pw = getpwuid ((uid_t)ul);
1723
1724
0
  if (!pw)
1725
0
    {
1726
0
      if (!silent)
1727
0
        log_error ("user '%s' not found\n", user);
1728
0
      return my_error (GPG_ERR_NOT_FOUND);
1729
0
    }
1730
1731
  /* Try to set some envvars even if we are already that user.  */
1732
0
  if (!stat (pw->pw_dir, &st))
1733
0
    try_set_envvar ("HOME", pw->pw_dir, silent);
1734
1735
0
  try_set_envvar ("USER", pw->pw_name, silent);
1736
0
  try_set_envvar ("LOGNAME", pw->pw_name, silent);
1737
#ifdef _AIX
1738
  try_set_envvar ("LOGIN", pw->pw_name, silent);
1739
#endif
1740
1741
0
  if (getuid () == pw->pw_uid)
1742
0
    return 0;  /* We are already this user.  */
1743
1744
  /* If we need to switch set PATH to a standard value and make sure
1745
   * GNUPGHOME is not set. */
1746
0
  try_set_envvar ("PATH", "/usr/local/bin:/usr/bin:/bin", silent);
1747
0
  if (gnupg_unsetenv ("GNUPGHOME"))
1748
0
    if (!silent)
1749
0
      log_info ("error unsetting envvar %s: %s\n", "GNUPGHOME",
1750
0
                gpg_strerror (gpg_error_from_syserror ()));
1751
1752
0
  if (initgroups (pw->pw_name, pw->pw_gid))
1753
0
    {
1754
0
      err = my_error_from_syserror ();
1755
0
      if (!silent)
1756
0
        log_error ("error setting supplementary groups for '%s': %s\n",
1757
0
                   pw->pw_name, gpg_strerror (err));
1758
0
      return err;
1759
0
    }
1760
1761
0
  if (setuid (pw->pw_uid))
1762
0
    {
1763
0
      err = my_error_from_syserror ();
1764
0
      log_error ("error switching to user '%s': %s\n",
1765
0
                 pw->pw_name, gpg_strerror (err));
1766
0
      return err;
1767
0
    }
1768
1769
0
  return 0;
1770
1771
#else /*!HAVE_PWD_H */
1772
  if (!silent)
1773
    log_info ("system is missing passwd querying functions\n");
1774
  return my_error (GPG_ERR_NOT_IMPLEMENTED);
1775
#endif
1776
0
}
1777
1778
1779

1780
1781
1782
#ifdef HAVE_W32_SYSTEM
1783
/* Return the user's security identifier from the current process.  */
1784
PSID
1785
w32_get_user_sid (void)
1786
{
1787
  int okay = 0;
1788
  HANDLE proc = NULL;
1789
  HANDLE token = NULL;
1790
  TOKEN_USER *user = NULL;
1791
  PSID sid = NULL;
1792
  DWORD tokenlen, sidlen;
1793
1794
  proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
1795
  if (!proc)
1796
    goto leave;
1797
1798
  if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
1799
    goto leave;
1800
1801
  if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
1802
      && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1803
    goto leave;
1804
1805
  user = xtrymalloc (tokenlen);
1806
  if (!user)
1807
    goto leave;
1808
1809
  if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
1810
    goto leave;
1811
  if (!IsValidSid (user->User.Sid))
1812
    goto leave;
1813
  sidlen = GetLengthSid (user->User.Sid);
1814
  sid = xtrymalloc (sidlen);
1815
  if (!sid)
1816
    goto leave;
1817
  if (!CopySid (sidlen, sid, user->User.Sid))
1818
    goto leave;
1819
  okay = 1;
1820
1821
 leave:
1822
  xfree (user);
1823
  if (token)
1824
    CloseHandle (token);
1825
  if (proc)
1826
    CloseHandle (proc);
1827
1828
  if (!okay)
1829
    {
1830
      xfree (sid);
1831
      sid = NULL;
1832
    }
1833
  return sid;
1834
}
1835
#endif /*HAVE_W32_SYSTEM*/
1836
1837
1838

1839
/* Support for inotify under Linux.  */
1840
1841
/* Store a new inotify file handle for FNAME at R_FD or return an
1842
 * error code.  This file descriptor watch the removal of FNAME. */
1843
gpg_error_t
1844
gnupg_inotify_watch_delete_self (int *r_fd, const char *fname)
1845
0
{
1846
0
#if HAVE_INOTIFY_INIT
1847
0
  gpg_error_t err;
1848
0
  int fd;
1849
1850
0
  *r_fd = -1;
1851
1852
0
  if (!fname)
1853
0
    return my_error (GPG_ERR_INV_VALUE);
1854
1855
0
  fd = inotify_init ();
1856
0
  if (fd == -1)
1857
0
    return my_error_from_syserror ();
1858
1859
0
  if (inotify_add_watch (fd, fname, IN_DELETE_SELF) == -1)
1860
0
    {
1861
0
      err = my_error_from_syserror ();
1862
0
      close (fd);
1863
0
      return err;
1864
0
    }
1865
1866
0
  *r_fd = fd;
1867
0
  return 0;
1868
#else /*!HAVE_INOTIFY_INIT*/
1869
1870
  (void)fname;
1871
  *r_fd = -1;
1872
  return my_error (GPG_ERR_NOT_SUPPORTED);
1873
1874
#endif /*!HAVE_INOTIFY_INIT*/
1875
0
}
1876
1877
1878
/* Store a new inotify file handle for SOCKET_NAME at R_FD or return
1879
 * an error code. */
1880
gpg_error_t
1881
gnupg_inotify_watch_socket (int *r_fd, const char *socket_name)
1882
0
{
1883
0
#if HAVE_INOTIFY_INIT
1884
0
  gpg_error_t err;
1885
0
  char *fname;
1886
0
  int fd;
1887
0
  char *p;
1888
1889
0
  *r_fd = -1;
1890
1891
0
  if (!socket_name)
1892
0
    return my_error (GPG_ERR_INV_VALUE);
1893
1894
0
  fname = xtrystrdup (socket_name);
1895
0
  if (!fname)
1896
0
    return my_error_from_syserror ();
1897
1898
0
  fd = inotify_init ();
1899
0
  if (fd == -1)
1900
0
    {
1901
0
      err = my_error_from_syserror ();
1902
0
      xfree (fname);
1903
0
      return err;
1904
0
    }
1905
1906
  /* We need to watch the directory for the file because there won't
1907
   * be an IN_DELETE_SELF for a socket file.  To handle a removal of
1908
   * the directory we also watch the directory itself. */
1909
0
  p = strrchr (fname, '/');
1910
0
  if (p)
1911
0
    *p = 0;
1912
0
  if (inotify_add_watch (fd, fname,
1913
0
                         (IN_DELETE|IN_DELETE_SELF|IN_EXCL_UNLINK)) == -1)
1914
0
    {
1915
0
      err = my_error_from_syserror ();
1916
0
      close (fd);
1917
0
      xfree (fname);
1918
0
      return err;
1919
0
    }
1920
1921
0
  xfree (fname);
1922
1923
0
  *r_fd = fd;
1924
0
  return 0;
1925
#else /*!HAVE_INOTIFY_INIT*/
1926
1927
  (void)socket_name;
1928
  *r_fd = -1;
1929
  return my_error (GPG_ERR_NOT_SUPPORTED);
1930
1931
#endif /*!HAVE_INOTIFY_INIT*/
1932
0
}
1933
1934
1935
/* Read an inotify event and return true if it matches NAME or if it
1936
 * sees an IN_DELETE_SELF event for the directory of NAME.  */
1937
int
1938
gnupg_inotify_has_name (int fd, const char *name)
1939
0
{
1940
0
#if USE_NPTH && HAVE_INOTIFY_INIT
1941
0
#define BUFSIZE_FOR_INOTIFY (sizeof (struct inotify_event) + 255 + 1)
1942
0
  union {
1943
0
    struct inotify_event ev;
1944
0
    char _buf[sizeof (struct inotify_event) + 255 + 1];
1945
0
  } buf;
1946
0
  struct inotify_event *evp;
1947
0
  int n;
1948
1949
0
  n = npth_read (fd, &buf, sizeof buf);
1950
  /* log_debug ("notify read: n=%d\n", n); */
1951
0
  evp = &buf.ev;
1952
0
  while (n >= sizeof (struct inotify_event))
1953
0
    {
1954
      /* log_debug ("             mask=%x len=%u name=(%s)\n", */
1955
      /*        evp->mask, (unsigned int)evp->len, evp->len? evp->name:""); */
1956
0
      if ((evp->mask & IN_UNMOUNT))
1957
0
        {
1958
          /* log_debug ("             found (dir unmounted)\n"); */
1959
0
          return 3; /* Directory was unmounted.  */
1960
0
        }
1961
0
      if ((evp->mask & IN_DELETE_SELF))
1962
0
        {
1963
          /* log_debug ("             found (dir removed)\n"); */
1964
0
          return 2; /* Directory was removed.  */
1965
0
        }
1966
0
      if ((evp->mask & IN_DELETE))
1967
0
        {
1968
0
          if (evp->len >= strlen (name) && !strcmp (evp->name, name))
1969
0
            {
1970
              /* log_debug ("             found (file removed)\n"); */
1971
0
              return 1; /* File was removed.  */
1972
0
            }
1973
0
        }
1974
0
      n -= sizeof (*evp) + evp->len;
1975
0
      evp = (struct inotify_event *)(void *)
1976
0
        ((char *)evp + sizeof (*evp) + evp->len);
1977
0
    }
1978
1979
#else /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
1980
1981
  (void)fd;
1982
  (void)name;
1983
1984
#endif  /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
1985
1986
0
  return 0; /* Not found.  */
1987
0
}
1988
1989
1990
/* Return a malloc'ed string that is the path to the passed
1991
 * unix-domain socket (or return NULL if this is not a valid
1992
 * unix-domain socket).  We use a plain int here because it is only
1993
 * used on Linux.
1994
 *
1995
 * FIXME: This function needs to be moved to libassuan.  */
1996
#ifndef HAVE_W32_SYSTEM
1997
char *
1998
gnupg_get_socket_name (int fd)
1999
0
{
2000
0
  struct sockaddr_un un;
2001
0
  socklen_t len = sizeof(un);
2002
0
  char *name = NULL;
2003
2004
0
  if (getsockname (fd, (struct sockaddr*)&un, &len) != 0)
2005
0
    log_error ("could not getsockname(%d): %s\n", fd,
2006
0
               gpg_strerror (my_error_from_syserror ()));
2007
0
  else if (un.sun_family != AF_UNIX)
2008
0
    log_error ("file descriptor %d is not a unix-domain socket\n", fd);
2009
0
  else if (len <= offsetof (struct sockaddr_un, sun_path))
2010
0
    log_error ("socket name not present for file descriptor %d\n", fd);
2011
0
  else if (len > sizeof(un))
2012
0
    log_error ("socket name for file descriptor %d was truncated "
2013
0
               "(passed %zu bytes, wanted %u)\n", fd, sizeof(un), len);
2014
0
  else
2015
0
    {
2016
0
      size_t namelen = len - offsetof (struct sockaddr_un, sun_path);
2017
2018
      /* log_debug ("file descriptor %d has path %s (%zu octets)\n", fd, */
2019
      /*            un.sun_path, namelen); */
2020
0
      name = xtrymalloc (namelen + 1);
2021
0
      if (!name)
2022
0
        log_error ("failed to allocate memory for name of fd %d: %s\n",
2023
0
                   fd, gpg_strerror (my_error_from_syserror ()));
2024
0
      else
2025
0
        {
2026
0
          memcpy (name, un.sun_path, namelen);
2027
0
          name[namelen] = 0;
2028
0
        }
2029
0
    }
2030
2031
0
  return name;
2032
0
}
2033
#endif /*!HAVE_W32_SYSTEM*/
2034
2035
/* Check whether FD is valid.  */
2036
int
2037
gnupg_fd_valid (int fd)
2038
0
{
2039
0
  int d = dup (fd);
2040
0
  if (d < 0)
2041
0
    return 0;
2042
0
  close (d);
2043
0
  return 1;
2044
0
}
2045
2046
2047
/* Open a stream from FD (a file descriptor on POSIX, a system
2048
   handle on Windows), non-closed.  */
2049
estream_t
2050
open_stream_nc (gnupg_fd_t fd, const char *mode)
2051
0
{
2052
0
  es_syshd_t syshd;
2053
2054
#ifdef HAVE_W32_SYSTEM
2055
  syshd.type = ES_SYSHD_HANDLE;
2056
  syshd.u.handle = fd;
2057
#else
2058
0
  syshd.type = ES_SYSHD_FD;
2059
0
  syshd.u.fd = fd;
2060
0
#endif
2061
2062
0
  return es_sysopen_nc (&syshd, mode);
2063
0
}
2064
2065
2066
/* Debug helper to track down problems with logging under Windows.  */
2067
void
2068
output_debug_string (const char *format, ...)
2069
0
{
2070
#ifdef HAVE_W32_SYSTEM
2071
  char *buf;
2072
  va_list arg_ptr;
2073
2074
  va_start (arg_ptr, format);
2075
  buf = gpgrt_vbsprintf (format, arg_ptr);
2076
  va_end (arg_ptr);
2077
  if (buf)
2078
    OutputDebugStringA (buf);
2079
  else
2080
    OutputDebugStringA ("vbsprintf failed");
2081
  gpgrt_free (buf);
2082
#else
2083
0
  (void)format;
2084
0
#endif
2085
0
}