Coverage Report

Created: 2026-01-10 07:04

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