1 /* estream.c - Extended Stream I/O Library
2  * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011,
3  *               2014, 2015, 2016, 2017 g10 Code GmbH
4  *
5  * This file is part of Libestream.
6  *
7  * Libestream is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as
9  * published by the Free Software Foundation; either version 2.1 of
10  * the License, or (at your option) any later version.
11  *
12  * Libestream is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libestream; if not, see <https://www.gnu.org/licenses/>.
19  *
20  * ALTERNATIVELY, Libestream may be distributed under the terms of the
21  * following license, in which case the provisions of this license are
22  * required INSTEAD OF the GNU General Public License. If you wish to
23  * allow use of your version of this file only under the terms of the
24  * GNU General Public License, and not to allow others to use your
25  * version of this file under the terms of the following license,
26  * indicate your decision by deleting this paragraph and the license
27  * below.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  * 1. Redistributions of source code must retain the above copyright
33  *    notice, and the entire permission notice in its entirety,
34  *    including the disclaimer of warranties.
35  * 2. Redistributions in binary form must reproduce the above copyright
36  *    notice, this list of conditions and the following disclaimer in the
37  *    documentation and/or other materials provided with the distribution.
38  * 3. The name of the author may not be used to endorse or promote
39  *    products derived from this software without specific prior
40  *    written permission.
41  *
42  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
43  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
45  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
46  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
47  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52  * OF THE POSSIBILITY OF SUCH DAMAGE.
53  */
54 
55 #ifdef USE_ESTREAM_SUPPORT_H
56 # include <estream-support.h>
57 #endif
58 
59 #ifdef HAVE_CONFIG_H
60 # include <config.h>
61 #endif
62 
63 #if defined(_WIN32) && !defined(HAVE_W32_SYSTEM)
64 # define HAVE_W32_SYSTEM 1
65 # if defined(__MINGW32CE__) && !defined (HAVE_W32CE_SYSTEM)
66 #  define HAVE_W32CE_SYSTEM
67 # endif
68 #endif
69 
70 #ifdef HAVE_SYS_SELECT_H
71 # include <sys/select.h>
72 #endif
73 #ifdef HAVE_SYS_TIME_H
74 # include <sys/time.h>
75 #endif
76 #include <sys/types.h>
77 #include <sys/file.h>
78 #include <sys/stat.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <unistd.h>
83 #include <stdarg.h>
84 #include <fcntl.h>
85 #include <errno.h>
86 #include <stddef.h>
87 #ifdef HAVE_W32_SYSTEM
88 # ifdef HAVE_WINSOCK2_H
89 #  include <winsock2.h>
90 # endif
91 # include <windows.h>
92 #else
93 # ifdef HAVE_POLL_H
94 #  include <poll.h>
95 # endif
96 #endif
97 
98 /* Enable tracing.  The value is the module name to be printed.  */
99 /*#define ENABLE_TRACING "estream"*/
100 
101 #include "gpgrt-int.h"
102 #include "estream-printf.h"
103 #include "thread.h"
104 #include "lock.h"
105 
106 
107 #ifndef O_BINARY
108 # define O_BINARY 0
109 #endif
110 #ifndef HAVE_DOSISH_SYSTEM
111 # ifdef HAVE_W32_SYSTEM
112 #  define HAVE_DOSISH_SYSTEM 1
113 # endif
114 #endif
115 
116 
117 #ifdef HAVE_W32_SYSTEM
118 # ifndef  S_IRGRP
119 #  define S_IRGRP S_IRUSR
120 # endif
121 # ifndef  S_IROTH
122 #  define S_IROTH S_IRUSR
123 # endif
124 # ifndef  S_IWGRP
125 #  define S_IWGRP S_IWUSR
126 # endif
127 # ifndef  S_IWOTH
128 #  define S_IWOTH S_IWUSR
129 # endif
130 # ifndef  S_IXGRP
131 #  define S_IXGRP S_IXUSR
132 # endif
133 # ifndef  S_IXOTH
134 #  define S_IXOTH S_IXUSR
135 # endif
136 #endif
137 
138 #if !defined (EWOULDBLOCK) && defined (HAVE_W32_SYSTEM)
139 /* Compatibility with errno.h from mingw-2.0 */
140 # define EWOULDBLOCK 140
141 #endif
142 
143 #ifndef EAGAIN
144 # define EAGAIN  EWOULDBLOCK
145 #endif
146 
147 
148 #ifdef HAVE_W32CE_SYSTEM
149 # define _set_errno(a)  gpg_err_set_errno ((a))
150 /* Setmode is missing in cegcc but available since CE 5.0.  */
151 int _setmode (int handle, int mode);
152 # define setmode(a,b)   _setmode ((a),(b))
153 #else
154 # define _set_errno(a)  do { errno = (a); } while (0)
155 #endif
156 
157 #define IS_INVALID_FD(a)    ((a) == -1)
158 
159 /* Calculate array dimension.  */
160 #ifndef DIM
161 #define DIM(array) (sizeof (array) / sizeof (*array))
162 #endif
163 
164 /* A helper macro used to convert to a hex string.  */
165 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
166 
167 
168 /* Generally used types.  */
169 
170 typedef void *(*func_realloc_t) (void *mem, size_t size);
171 typedef void (*func_free_t) (void *mem);
172 
173 
174 
175 
176 /*
177  * A linked list to hold active stream objects.
178  * Protected by ESTREAM_LIST_LOCK.
179  */
180 struct estream_list_s
181 {
182   struct estream_list_s *next;
183   estream_t stream;  /* Entry is not used if NULL.  */
184 };
185 typedef struct estream_list_s *estream_list_t;
186 static estream_list_t estream_list;
187 
188 /*
189  * File descriptors registered for use as the standard file handles.
190  * Protected by ESTREAM_LIST_LOCK.
191  */
192 static int custom_std_fds[3];
193 static unsigned char custom_std_fds_valid[3];
194 
195 /*
196  * A lock object to protect ESTREAM LIST, CUSTOM_STD_FDS and
197  * CUSTOM_STD_FDS_VALID.  Used by lock_list() and unlock_list().
198  */
199 GPGRT_LOCK_DEFINE (estream_list_lock);
200 
201 
202 /*
203  * Error code replacements.
204  */
205 #ifndef EOPNOTSUPP
206 # define EOPNOTSUPP ENOSYS
207 #endif
208 
209 
210 /* Local prototypes.  */
211 static void fname_set_internal (estream_t stream, const char *fname, int quote);
212 
213 
214 
215 
216 /*
217  * Memory allocation wrappers used in this file.
218  */
219 static void *
mem_alloc(size_t n)220 mem_alloc (size_t n)
221 {
222   return _gpgrt_malloc (n);
223 }
224 
225 static void *
mem_realloc(void * p,size_t n)226 mem_realloc (void *p, size_t n)
227 {
228   return _gpgrt_realloc (p, n);
229 }
230 
231 static void
mem_free(void * p)232 mem_free (void *p)
233 {
234   if (p)
235     _gpgrt_free (p);
236 }
237 
238 
239 /*
240  * A Windows helper function to map a W32 API error code to a standard
241  * system error code.  That actually belong into sysutils but to allow
242  * standalone use of estream we keep it here.
243  */
244 #ifdef HAVE_W32_SYSTEM
245 static int
map_w32_to_errno(DWORD w32_err)246 map_w32_to_errno (DWORD w32_err)
247 {
248   switch (w32_err)
249     {
250     case 0:
251       return 0;
252 
253     case ERROR_FILE_NOT_FOUND:
254       return ENOENT;
255 
256     case ERROR_PATH_NOT_FOUND:
257       return ENOENT;
258 
259     case ERROR_ACCESS_DENIED:
260       return EPERM;  /* ReactOS uses EACCES ("Permission denied") and
261                       * is likely right because they used an
262                       * undocumented function to associate the error
263                       * codes.  However we have always used EPERM
264                       * ("Operation not permitted", e.g. function is
265                       * required to be called by root) and we better
266                       * stick to that to avoid surprising bugs. */
267 
268     case ERROR_INVALID_HANDLE:
269       return EBADF;
270 
271     case ERROR_INVALID_BLOCK:
272       return ENOMEM;
273 
274     case ERROR_NOT_ENOUGH_MEMORY:
275       return ENOMEM;
276 
277     case ERROR_NO_DATA:
278       return EPIPE;
279 
280     case ERROR_ALREADY_EXISTS:
281       return EEXIST;
282 
283       /* This mapping has been taken from reactOS.  */
284     case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
285     case ERROR_ARENA_TRASHED: return ENOMEM;
286     case ERROR_BAD_ENVIRONMENT: return E2BIG;
287     case ERROR_BAD_FORMAT: return ENOEXEC;
288     case ERROR_INVALID_DRIVE: return ENOENT;
289     case ERROR_CURRENT_DIRECTORY: return EACCES;
290     case ERROR_NOT_SAME_DEVICE: return EXDEV;
291     case ERROR_NO_MORE_FILES: return ENOENT;
292     case ERROR_WRITE_PROTECT: return EACCES;
293     case ERROR_BAD_UNIT: return EACCES;
294     case ERROR_NOT_READY: return EACCES;
295     case ERROR_BAD_COMMAND: return EACCES;
296     case ERROR_CRC: return EACCES;
297     case ERROR_BAD_LENGTH: return EACCES;
298     case ERROR_SEEK: return EACCES;
299     case ERROR_NOT_DOS_DISK: return EACCES;
300     case ERROR_SECTOR_NOT_FOUND: return EACCES;
301     case ERROR_OUT_OF_PAPER: return EACCES;
302     case ERROR_WRITE_FAULT: return EACCES;
303     case ERROR_READ_FAULT: return EACCES;
304     case ERROR_GEN_FAILURE: return EACCES;
305     case ERROR_SHARING_VIOLATION: return EACCES;
306     case ERROR_LOCK_VIOLATION: return EACCES;
307     case ERROR_WRONG_DISK: return EACCES;
308     case ERROR_SHARING_BUFFER_EXCEEDED: return EACCES;
309     case ERROR_BAD_NETPATH: return ENOENT;
310     case ERROR_NETWORK_ACCESS_DENIED: return EACCES;
311     case ERROR_BAD_NET_NAME: return ENOENT;
312     case ERROR_FILE_EXISTS: return EEXIST;
313     case ERROR_CANNOT_MAKE: return EACCES;
314     case ERROR_FAIL_I24: return EACCES;
315     case ERROR_NO_PROC_SLOTS: return EAGAIN;
316     case ERROR_DRIVE_LOCKED: return EACCES;
317     case ERROR_BROKEN_PIPE: return EPIPE;
318     case ERROR_DISK_FULL: return ENOSPC;
319     case ERROR_INVALID_TARGET_HANDLE: return EBADF;
320     case ERROR_WAIT_NO_CHILDREN: return ECHILD;
321     case ERROR_CHILD_NOT_COMPLETE: return ECHILD;
322     case ERROR_DIRECT_ACCESS_HANDLE: return EBADF;
323     case ERROR_SEEK_ON_DEVICE: return EACCES;
324     case ERROR_DIR_NOT_EMPTY: return ENOTEMPTY;
325     case ERROR_NOT_LOCKED: return EACCES;
326     case ERROR_BAD_PATHNAME: return ENOENT;
327     case ERROR_MAX_THRDS_REACHED: return EAGAIN;
328     case ERROR_LOCK_FAILED: return EACCES;
329     case ERROR_INVALID_STARTING_CODESEG: return ENOEXEC;
330     case ERROR_INVALID_STACKSEG: return ENOEXEC;
331     case ERROR_INVALID_MODULETYPE: return ENOEXEC;
332     case ERROR_INVALID_EXE_SIGNATURE: return ENOEXEC;
333     case ERROR_EXE_MARKED_INVALID: return ENOEXEC;
334     case ERROR_BAD_EXE_FORMAT: return ENOEXEC;
335     case ERROR_ITERATED_DATA_EXCEEDS_64k: return ENOEXEC;
336     case ERROR_INVALID_MINALLOCSIZE: return ENOEXEC;
337     case ERROR_DYNLINK_FROM_INVALID_RING: return ENOEXEC;
338     case ERROR_IOPL_NOT_ENABLED: return ENOEXEC;
339     case ERROR_INVALID_SEGDPL: return ENOEXEC;
340     case ERROR_AUTODATASEG_EXCEEDS_64k: return ENOEXEC;
341     case ERROR_RING2SEG_MUST_BE_MOVABLE: return ENOEXEC;
342     case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: return ENOEXEC;
343     case ERROR_INFLOOP_IN_RELOC_CHAIN: return ENOEXEC;
344     case ERROR_FILENAME_EXCED_RANGE: return ENOENT;
345     case ERROR_NESTING_NOT_ALLOWED: return EAGAIN;
346     case ERROR_NOT_ENOUGH_QUOTA: return ENOMEM;
347 
348     default:
349       return EIO;
350     }
351 }
352 
353 /* Wrapper to be used by other modules to set ERRNO from the Windows
354  * error.  EC may be -1 to get the last error.  */
355 void
_gpgrt_w32_set_errno(int ec)356 _gpgrt_w32_set_errno (int ec)
357 {
358   if (ec == -1)
359     ec = GetLastError ();
360   _set_errno (map_w32_to_errno (ec));
361 }
362 
363 
364 #endif /*HAVE_W32_SYSTEM*/
365 
366 /*
367  * Replacement for a missing memrchr.
368  */
369 #ifndef HAVE_MEMRCHR
370 static void *
memrchr(const void * buffer,int c,size_t n)371 memrchr (const void *buffer, int c, size_t n)
372 {
373   const unsigned char *p = buffer;
374 
375   for (p += n; n ; n--)
376     if (*--p == c)
377       return (void *)p;
378   return NULL;
379 }
380 #endif /*HAVE_MEMRCHR*/
381 
382 
383 
384 /*
385  * Wrappers to lock a stream or the list of streams.
386  */
387 #if 0
388 # define dbg_lock_0(f)        fprintf (stderr, "estream: " f);
389 # define dbg_lock_1(f, a)     fprintf (stderr, "estream: " f, (a));
390 # define dbg_lock_2(f, a, b)  fprintf (stderr, "estream: " f, (a), (b));
391 #else
392 # define dbg_lock_0(f)
393 # define dbg_lock_1(f, a)
394 # define dbg_lock_2(f, a, b)
395 #endif
396 
397 static int
init_stream_lock(estream_t _GPGRT__RESTRICT stream)398 init_stream_lock (estream_t _GPGRT__RESTRICT stream)
399 {
400   int rc;
401 
402   if (!stream->intern->samethread)
403     {
404       dbg_lock_1 ("enter init_stream_lock for %p\n", stream);
405       memset (&stream->intern->lock, 0 , sizeof stream->intern->lock);
406       rc = _gpgrt_lock_init (&stream->intern->lock);
407       dbg_lock_2 ("leave init_stream_lock for %p: rc=%d\n", stream, rc);
408     }
409   else
410     rc = 0;
411   return rc;
412 }
413 
414 
415 static void
destroy_stream_lock(estream_t _GPGRT__RESTRICT stream)416 destroy_stream_lock (estream_t _GPGRT__RESTRICT stream)
417 {
418   if (!stream->intern->samethread)
419     {
420       dbg_lock_1 ("enter destroy_stream_lock for %p\n", stream);
421       _gpgrt_lock_destroy (&stream->intern->lock);
422       dbg_lock_1 ("leave destroy_stream_lock for %p\n", stream);
423     }
424 }
425 
426 
427 static void
lock_stream(estream_t _GPGRT__RESTRICT stream)428 lock_stream (estream_t _GPGRT__RESTRICT stream)
429 {
430   if (!stream->intern->samethread)
431     {
432       dbg_lock_1 ("enter lock_stream for %p\n", stream);
433       _gpgrt_lock_lock (&stream->intern->lock);
434       dbg_lock_1 ("leave lock_stream for %p\n", stream);
435     }
436 }
437 
438 
439 static int
trylock_stream(estream_t _GPGRT__RESTRICT stream)440 trylock_stream (estream_t _GPGRT__RESTRICT stream)
441 {
442   int rc;
443 
444   if (!stream->intern->samethread)
445     {
446       dbg_lock_1 ("enter trylock_stream for %p\n", stream);
447       rc = _gpgrt_lock_trylock (&stream->intern->lock)? 0 : -1;
448       dbg_lock_2 ("leave trylock_stream for %p: rc=%d\n", stream, rc);
449     }
450   else
451     rc = 0;
452   return rc;
453 }
454 
455 
456 static void
unlock_stream(estream_t _GPGRT__RESTRICT stream)457 unlock_stream (estream_t _GPGRT__RESTRICT stream)
458 {
459   if (!stream->intern->samethread)
460     {
461       dbg_lock_1 ("enter unlock_stream for %p\n", stream);
462       _gpgrt_lock_unlock (&stream->intern->lock);
463       dbg_lock_1 ("leave unlock_stream for %p\n", stream);
464     }
465 }
466 
467 
468 static void
lock_list(void)469 lock_list (void)
470 {
471   dbg_lock_0 ("enter lock_list\n");
472   _gpgrt_lock_lock (&estream_list_lock);
473   dbg_lock_0 ("leave lock_list\n");
474 }
475 
476 
477 static void
unlock_list(void)478 unlock_list (void)
479 {
480   dbg_lock_0 ("enter unlock_list\n");
481   _gpgrt_lock_unlock (&estream_list_lock);
482   dbg_lock_0 ("leave unlock_list\n");
483 }
484 
485 
486 #undef dbg_lock_0
487 #undef dbg_lock_1
488 #undef dbg_lock_2
489 
490 
491 
492 /*
493  * Manipulation of the list of stream.
494  */
495 
496 /*
497  * Add STREAM to the list of registered stream objects.  If
498  * WITH_LOCKED_LIST is true it is assumed that the list of streams is
499  * already locked.  The implementation is straightforward: We first
500  * look for an unused entry in the list and use that; if none is
501  * available we put a new item at the head.  We drawback of the
502  * strategy never to shorten the list is that a one time allocation of
503  * many streams will lead to scanning unused entries later.  If that
504  * turns out to be a problem, we may either free some items from the
505  * list or append new entries at the end; or use a table.  Returns 0
506  * on success; on error or non-zero is returned and ERRNO set.
507  */
508 static int
do_list_add(estream_t stream,int with_locked_list)509 do_list_add (estream_t stream, int with_locked_list)
510 {
511   estream_list_t item;
512 
513   if (!with_locked_list)
514     lock_list ();
515 
516   for (item = estream_list; item && item->stream; item = item->next)
517     ;
518   if (!item)
519     {
520       item = mem_alloc (sizeof *item);
521       if (item)
522         {
523           item->next = estream_list;
524           estream_list = item;
525         }
526     }
527   if (item)
528     item->stream = stream;
529 
530   if (!with_locked_list)
531     unlock_list ();
532 
533   return item? 0 : -1;
534 }
535 
536 /*
537  * Remove STREAM from the list of registered stream objects.
538  */
539 static void
do_list_remove(estream_t stream,int with_locked_list)540 do_list_remove (estream_t stream, int with_locked_list)
541 {
542   estream_list_t item, item_prev = NULL;
543 
544   if (!with_locked_list)
545     lock_list ();
546 
547   for (item = estream_list; item; item = item->next)
548     if (item->stream == stream)
549       break;
550     else
551       item_prev = item;
552 
553   if (item)
554     {
555       if (item_prev)
556         item_prev->next = item->next;
557       else
558         estream_list = item->next;
559       mem_free (item);
560     }
561 
562   if (!with_locked_list)
563     unlock_list ();
564 }
565 
566 
567 
568 /*
569  * The atexit handler for the entire gpgrt.
570  */
571 static void
do_deinit(void)572 do_deinit (void)
573 {
574   /* Flush all streams. */
575   _gpgrt_fflush (NULL);
576 
577   /* We should release the estream_list.  However there is one
578      problem: That list is also used to search for the standard
579      estream file descriptors.  If we would remove the entire list,
580      any use of es_foo in another atexit function may re-create the
581      list and the streams with possible undesirable effects.  Given
582      that we don't close the stream either, it should not matter that
583      we keep the list and let the OS clean it up at process end.  */
584 
585   /* Reset the syscall clamp.  */
586   _gpgrt_set_syscall_clamp (NULL, NULL);
587 }
588 
589 
590 /*
591  * Initialization of the estream module.
592  */
593 int
_gpgrt_estream_init(void)594 _gpgrt_estream_init (void)
595 {
596   static int initialized;
597 
598   if (!initialized)
599     {
600       initialized = 1;
601       atexit (do_deinit);
602     }
603   return 0;
604 }
605 
606 
607 /*
608  * Implementation of memory based I/O.
609  */
610 
611 /* Cookie for memory objects.  */
612 typedef struct estream_cookie_mem
613 {
614   unsigned int modeflags;	/* Open flags.  */
615   unsigned char *memory;	/* Allocated data buffer.  */
616   size_t memory_size;		/* Allocated size of MEMORY.  */
617   size_t memory_limit;          /* Caller supplied maximum allowed
618                                    allocation size or 0 for no limit.  */
619   size_t offset;		/* Current offset in MEMORY.  */
620   size_t data_len;		/* Used length of data in MEMORY.  */
621   size_t block_size;		/* Block size.  */
622   struct {
623     unsigned int grow: 1;	/* MEMORY is allowed to grow.  */
624   } flags;
625   func_realloc_t func_realloc;
626   func_free_t func_free;
627 } *estream_cookie_mem_t;
628 
629 
630 /*
631  * Create function for memory objects.  DATA is either NULL or a user
632  * supplied buffer with the initial conetnt of the memory buffer.  If
633  * DATA is NULL, DATA_N and DATA_LEN need to be 0 as well.  If DATA is
634  * not NULL, DATA_N gives the allocated size of DATA and DATA_LEN the
635  * used length in DATA.  If this function succeeds DATA is now owned
636  * by this function.  If GROW is false FUNC_REALLOC is not
637  * required.
638  */
639 static int
func_mem_create(void * _GPGRT__RESTRICT * _GPGRT__RESTRICT cookie,unsigned char * _GPGRT__RESTRICT data,size_t data_n,size_t data_len,size_t block_size,unsigned int grow,func_realloc_t func_realloc,func_free_t func_free,unsigned int modeflags,size_t memory_limit)640 func_mem_create (void *_GPGRT__RESTRICT *_GPGRT__RESTRICT cookie,
641                  unsigned char *_GPGRT__RESTRICT data, size_t data_n,
642                  size_t data_len,
643                  size_t block_size, unsigned int grow,
644                  func_realloc_t func_realloc, func_free_t func_free,
645                  unsigned int modeflags,
646                  size_t memory_limit)
647 {
648   estream_cookie_mem_t mem_cookie;
649   int err;
650 
651   if (!data && (data_n || data_len))
652     {
653       _set_errno (EINVAL);
654       return -1;
655     }
656   if (grow && func_free && !func_realloc)
657     {
658       _set_errno (EINVAL);
659       return -1;
660     }
661 
662   /* Round a memory limit up to the next block length.  */
663   if (memory_limit && block_size)
664     {
665       memory_limit += block_size - 1;
666       memory_limit /= block_size;
667       memory_limit *= block_size;
668     }
669 
670   mem_cookie = mem_alloc (sizeof (*mem_cookie));
671   if (!mem_cookie)
672     err = -1;
673   else
674     {
675       mem_cookie->modeflags = modeflags;
676       mem_cookie->memory = data;
677       mem_cookie->memory_size = data_n;
678       mem_cookie->memory_limit = memory_limit;
679       mem_cookie->offset = 0;
680       mem_cookie->data_len = data_len;
681       mem_cookie->block_size = block_size;
682       mem_cookie->flags.grow = !!grow;
683       mem_cookie->func_realloc
684         = grow? (func_realloc ? func_realloc : mem_realloc) : NULL;
685       mem_cookie->func_free = func_free ? func_free : mem_free;
686       *cookie = mem_cookie;
687       err = 0;
688     }
689 
690   return err;
691 }
692 
693 
694 /*
695  * Read function for memory objects.
696  */
697 static gpgrt_ssize_t
func_mem_read(void * cookie,void * buffer,size_t size)698 func_mem_read (void *cookie, void *buffer, size_t size)
699 {
700   estream_cookie_mem_t mem_cookie = cookie;
701   gpgrt_ssize_t ret;
702 
703   if (!size)  /* Just the pending data check.  */
704     return (mem_cookie->data_len - mem_cookie->offset)? 0 : -1;
705 
706   if (size > mem_cookie->data_len - mem_cookie->offset)
707     size = mem_cookie->data_len - mem_cookie->offset;
708 
709   if (size)
710     {
711       memcpy (buffer, mem_cookie->memory + mem_cookie->offset, size);
712       mem_cookie->offset += size;
713     }
714 
715   ret = size;
716   return ret;
717 }
718 
719 
720 /*
721  * Write function for memory objects.
722  */
723 static gpgrt_ssize_t
func_mem_write(void * cookie,const void * buffer,size_t size)724 func_mem_write (void *cookie, const void *buffer, size_t size)
725 {
726   estream_cookie_mem_t mem_cookie = cookie;
727   gpgrt_ssize_t ret;
728   size_t nleft;
729 
730   if (!size)
731     return 0;  /* A flush is a NOP for memory objects.  */
732 
733   if (mem_cookie->modeflags & O_APPEND)
734     {
735       /* Append to data.  */
736       mem_cookie->offset = mem_cookie->data_len;
737     }
738 
739   gpgrt_assert (mem_cookie->memory_size >= mem_cookie->offset);
740   nleft = mem_cookie->memory_size - mem_cookie->offset;
741 
742   /* If we are not allowed to grow the buffer, limit the size to the
743      left space.  */
744   if (!mem_cookie->flags.grow && size > nleft)
745     size = nleft;
746 
747   /* Enlarge the memory buffer if needed.  */
748   if (size > nleft)
749     {
750       unsigned char *newbuf;
751       size_t newsize;
752 
753       if (!mem_cookie->memory_size)
754         newsize = size;  /* Not yet allocated.  */
755       else
756         newsize = mem_cookie->memory_size + (size - nleft);
757       if (newsize < mem_cookie->offset)
758         {
759           _set_errno (EINVAL);
760           return -1;
761         }
762 
763       /* Round up to the next block length.  BLOCK_SIZE should always
764          be set; we check anyway.  */
765       if (mem_cookie->block_size)
766         {
767           newsize += mem_cookie->block_size - 1;
768           if (newsize < mem_cookie->offset)
769             {
770               _set_errno (EINVAL);
771               return -1;
772             }
773           newsize /= mem_cookie->block_size;
774           newsize *= mem_cookie->block_size;
775         }
776 
777       /* Check for a total limit.  */
778       if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit)
779         {
780           _set_errno (ENOSPC);
781           return -1;
782         }
783 
784       gpgrt_assert (mem_cookie->func_realloc);
785       newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
786       if (!newbuf)
787         return -1;
788 
789       mem_cookie->memory = newbuf;
790       mem_cookie->memory_size = newsize;
791 
792       gpgrt_assert (mem_cookie->memory_size >= mem_cookie->offset);
793       nleft = mem_cookie->memory_size - mem_cookie->offset;
794 
795       gpgrt_assert (size <= nleft);
796     }
797 
798   memcpy (mem_cookie->memory + mem_cookie->offset, buffer, size);
799   if (mem_cookie->offset + size > mem_cookie->data_len)
800     mem_cookie->data_len = mem_cookie->offset + size;
801   mem_cookie->offset += size;
802 
803   ret = size;
804   return ret;
805 }
806 
807 
808 /*
809  * Seek function for memory objects.
810  */
811 static int
func_mem_seek(void * cookie,gpgrt_off_t * offset,int whence)812 func_mem_seek (void *cookie, gpgrt_off_t *offset, int whence)
813 {
814   estream_cookie_mem_t mem_cookie = cookie;
815   gpgrt_off_t pos_new;
816 
817   switch (whence)
818     {
819     case SEEK_SET:
820       pos_new = *offset;
821       break;
822 
823     case SEEK_CUR:
824       pos_new = mem_cookie->offset += *offset;
825       break;
826 
827     case SEEK_END:
828       pos_new = mem_cookie->data_len += *offset;
829       break;
830 
831     default:
832       _set_errno (EINVAL);
833       return -1;
834     }
835 
836   if (pos_new > mem_cookie->memory_size)
837     {
838       size_t newsize;
839       void *newbuf;
840 
841       if (!mem_cookie->flags.grow)
842 	{
843 	  _set_errno (ENOSPC);
844 	  return -1;
845         }
846 
847       newsize = pos_new + mem_cookie->block_size - 1;
848       if (newsize < pos_new)
849         {
850           _set_errno (EINVAL);
851           return -1;
852         }
853       newsize /= mem_cookie->block_size;
854       newsize *= mem_cookie->block_size;
855 
856       if (mem_cookie->memory_limit && newsize > mem_cookie->memory_limit)
857         {
858           _set_errno (ENOSPC);
859           return -1;
860         }
861 
862       gpgrt_assert (mem_cookie->func_realloc);
863       newbuf = mem_cookie->func_realloc (mem_cookie->memory, newsize);
864       if (!newbuf)
865         return -1;
866 
867       mem_cookie->memory = newbuf;
868       mem_cookie->memory_size = newsize;
869     }
870 
871   if (pos_new > mem_cookie->data_len)
872     {
873       /* Fill spare space with zeroes.  */
874       memset (mem_cookie->memory + mem_cookie->data_len,
875               0, pos_new - mem_cookie->data_len);
876       mem_cookie->data_len = pos_new;
877     }
878 
879   mem_cookie->offset = pos_new;
880   *offset = pos_new;
881 
882   return 0;
883 }
884 
885 
886 /*
887  * The IOCTL function for memory objects.
888  */
889 static int
func_mem_ioctl(void * cookie,int cmd,void * ptr,size_t * len)890 func_mem_ioctl (void *cookie, int cmd, void *ptr, size_t *len)
891 {
892   estream_cookie_mem_t mem_cookie = cookie;
893   int ret;
894 
895   if (cmd == COOKIE_IOCTL_SNATCH_BUFFER)
896     {
897       /* Return the internal buffer of the stream to the caller and
898          invalidate it for the stream.  */
899       *(void**)ptr = mem_cookie->memory;
900       *len = mem_cookie->data_len;
901       mem_cookie->memory = NULL;
902       mem_cookie->memory_size = 0;
903       mem_cookie->offset = 0;
904       ret = 0;
905     }
906   else if (cmd == COOKIE_IOCTL_TRUNCATE)
907     {
908       gpgrt_off_t length = *(gpgrt_off_t *)ptr;
909 
910       ret = func_mem_seek (cookie, &length, SEEK_SET);
911       if (ret != -1)
912         mem_cookie->data_len = mem_cookie->offset;
913     }
914   else
915     {
916       _set_errno (EINVAL);
917       ret = -1;
918     }
919 
920   return ret;
921 }
922 
923 
924 /*
925  * The destroy function for memory objects.
926  */
927 static int
func_mem_destroy(void * cookie)928 func_mem_destroy (void *cookie)
929 {
930   estream_cookie_mem_t mem_cookie = cookie;
931 
932   if (cookie)
933     {
934       mem_cookie->func_free (mem_cookie->memory);
935       mem_free (mem_cookie);
936     }
937   return 0;
938 }
939 
940 /*
941  * Access object for the memory functions.
942  */
943 static struct cookie_io_functions_s estream_functions_mem =
944   {
945     {
946       func_mem_read,
947       func_mem_write,
948       func_mem_seek,
949       func_mem_destroy,
950     },
951     func_mem_ioctl,
952   };
953 
954 
955 
956 /*
957  * Implementation of file descriptor based I/O.
958  */
959 
960 /* Cookie for fd objects.  */
961 typedef struct estream_cookie_fd
962 {
963   int fd;        /* The file descriptor we are using for actual output.  */
964   int no_close;  /* If set we won't close the file descriptor.  */
965   int nonblock;  /* Non-blocking mode is enabled.  */
966 } *estream_cookie_fd_t;
967 
968 
969 /*
970  * Create function for objects indentified by a libc file descriptor.
971  */
972 static int
func_fd_create(void ** cookie,int fd,unsigned int modeflags,int no_close)973 func_fd_create (void **cookie, int fd, unsigned int modeflags, int no_close)
974 {
975   estream_cookie_fd_t fd_cookie;
976   int err;
977 
978   trace (("enter: fd=%d mf=%x nc=%d", fd, modeflags, no_close));
979 
980   fd_cookie = mem_alloc (sizeof (*fd_cookie));
981   if (! fd_cookie)
982     err = -1;
983   else
984     {
985 #ifdef HAVE_DOSISH_SYSTEM
986       /* Make sure it is in binary mode if requested.  */
987       if ( (modeflags & O_BINARY) )
988         setmode (fd, O_BINARY);
989 #endif
990       fd_cookie->fd = fd;
991       fd_cookie->no_close = no_close;
992       fd_cookie->nonblock = !!(modeflags & O_NONBLOCK);
993       *cookie = fd_cookie;
994       err = 0;
995     }
996 
997   trace_errno (err, ("leave: cookie=%p err=%d", *cookie, err));
998   return err;
999 }
1000 
1001 
1002 /*
1003  * Read function for fd objects.
1004  */
1005 static gpgrt_ssize_t
func_fd_read(void * cookie,void * buffer,size_t size)1006 func_fd_read (void *cookie, void *buffer, size_t size)
1007 
1008 {
1009   estream_cookie_fd_t file_cookie = cookie;
1010   gpgrt_ssize_t bytes_read;
1011 
1012   trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size));
1013 
1014   if (!size)
1015     bytes_read = -1; /* We don't know whether anything is pending.  */
1016   else if (IS_INVALID_FD (file_cookie->fd))
1017     {
1018       _gpgrt_yield ();
1019       bytes_read = 0;
1020     }
1021   else
1022     {
1023       _gpgrt_pre_syscall ();
1024       do
1025         {
1026           bytes_read = read (file_cookie->fd, buffer, size);
1027         }
1028       while (bytes_read == -1 && errno == EINTR);
1029       _gpgrt_post_syscall ();
1030     }
1031 
1032   trace_errno (bytes_read == -1, ("leave: bytes_read=%d", (int)bytes_read));
1033   return bytes_read;
1034 }
1035 
1036 
1037 /*
1038  * Write function for fd objects.
1039  */
1040 static gpgrt_ssize_t
func_fd_write(void * cookie,const void * buffer,size_t size)1041 func_fd_write (void *cookie, const void *buffer, size_t size)
1042 {
1043   estream_cookie_fd_t file_cookie = cookie;
1044   gpgrt_ssize_t bytes_written;
1045 
1046   trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size));
1047 
1048   if (IS_INVALID_FD (file_cookie->fd))
1049     {
1050       _gpgrt_yield ();
1051       bytes_written = size; /* Yeah:  Success writing to the bit bucket.  */
1052     }
1053   else if (buffer)
1054     {
1055       _gpgrt_pre_syscall ();
1056       do
1057         {
1058           bytes_written = write (file_cookie->fd, buffer, size);
1059         }
1060       while (bytes_written == -1 && errno == EINTR);
1061       _gpgrt_post_syscall ();
1062     }
1063   else
1064     bytes_written = size; /* Note that for a flush SIZE should be 0.  */
1065 
1066   trace_errno (bytes_written == -1,
1067                ("leave: bytes_written=%d", (int)bytes_written));
1068   return bytes_written;
1069 }
1070 
1071 
1072 /*
1073  * Seek function for fd objects.
1074  */
1075 static int
func_fd_seek(void * cookie,gpgrt_off_t * offset,int whence)1076 func_fd_seek (void *cookie, gpgrt_off_t *offset, int whence)
1077 {
1078   estream_cookie_fd_t file_cookie = cookie;
1079   gpgrt_off_t offset_new;
1080   int err;
1081 
1082   if (IS_INVALID_FD (file_cookie->fd))
1083     {
1084       _set_errno (ESPIPE);
1085       err = -1;
1086     }
1087   else
1088     {
1089       _gpgrt_pre_syscall ();
1090       offset_new = lseek (file_cookie->fd, *offset, whence);
1091       _gpgrt_post_syscall ();
1092       if (offset_new == -1)
1093         err = -1;
1094       else
1095         {
1096           *offset = offset_new;
1097           err = 0;
1098         }
1099     }
1100 
1101   return err;
1102 }
1103 
1104 
1105 /*
1106  * The IOCTL function for fd objects.
1107  */
1108 static int
func_fd_ioctl(void * cookie,int cmd,void * ptr,size_t * len)1109 func_fd_ioctl (void *cookie, int cmd, void *ptr, size_t *len)
1110 {
1111   estream_cookie_fd_t fd_cookie = cookie;
1112   int ret;
1113 
1114   if (cmd == COOKIE_IOCTL_NONBLOCK && !len)
1115     {
1116       fd_cookie->nonblock = !!ptr;
1117       if (IS_INVALID_FD (fd_cookie->fd))
1118         {
1119           _set_errno (EINVAL);
1120           ret = -1;
1121         }
1122       else
1123         {
1124 #ifdef _WIN32
1125           _set_errno (EOPNOTSUPP); /* FIXME: Implement for Windows.  */
1126           ret = -1;
1127 #else
1128           _set_errno (0);
1129           ret = fcntl (fd_cookie->fd, F_GETFL, 0);
1130           if (ret == -1 && errno)
1131             ;
1132           else if (fd_cookie->nonblock)
1133             ret = fcntl (fd_cookie->fd, F_SETFL, (ret | O_NONBLOCK));
1134           else
1135             ret = fcntl (fd_cookie->fd, F_SETFL, (ret & ~O_NONBLOCK));
1136 #endif
1137         }
1138     }
1139   else
1140     {
1141       _set_errno (EINVAL);
1142       ret = -1;
1143     }
1144 
1145   return ret;
1146 }
1147 
1148 /*
1149  * The destroy function for fd objects.
1150  */
1151 static int
func_fd_destroy(void * cookie)1152 func_fd_destroy (void *cookie)
1153 {
1154   estream_cookie_fd_t fd_cookie = cookie;
1155   int err;
1156 
1157   trace (("enter: cookie=%p", cookie));
1158 
1159   if (fd_cookie)
1160     {
1161       if (IS_INVALID_FD (fd_cookie->fd))
1162         err = 0;
1163       else
1164         err = fd_cookie->no_close? 0 : close (fd_cookie->fd);
1165       mem_free (fd_cookie);
1166     }
1167   else
1168     err = 0;
1169 
1170   trace_errno (err,("leave: err=%d", err));
1171   return err;
1172 }
1173 
1174 
1175 /*
1176  * Access object for the fd functions.
1177  */
1178 static struct cookie_io_functions_s estream_functions_fd =
1179   {
1180     {
1181       func_fd_read,
1182       func_fd_write,
1183       func_fd_seek,
1184       func_fd_destroy,
1185     },
1186     func_fd_ioctl,
1187   };
1188 
1189 
1190 
1191 
1192 /*
1193  * Implementation of W32 handle based I/O.
1194  */
1195 #ifdef HAVE_W32_SYSTEM
1196 
1197 /* Cookie for fd objects.  */
1198 typedef struct estream_cookie_w32
1199 {
1200   HANDLE hd;     /* The handle we are using for actual output.  */
1201   int no_close;  /* If set we won't close the handle.  */
1202   int no_syscall_clamp; /* Do not use the syscall clamp. */
1203 } *estream_cookie_w32_t;
1204 
1205 
1206 /*
1207  * Create function for w32 handle objects.
1208  */
1209 static int
func_w32_create(void ** cookie,HANDLE hd,unsigned int modeflags,int no_close,int no_syscall_clamp)1210 func_w32_create (void **cookie, HANDLE hd,
1211                  unsigned int modeflags, int no_close, int no_syscall_clamp)
1212 {
1213   estream_cookie_w32_t w32_cookie;
1214   int err;
1215 
1216   trace (("enter: hd=%p mf=%x nc=%d nsc=%d",
1217           hd, modeflags, no_close, no_syscall_clamp));
1218   w32_cookie = mem_alloc (sizeof (*w32_cookie));
1219   if (!w32_cookie)
1220     err = -1;
1221   else
1222     {
1223       /* CR/LF translations are not supported when using the bare W32
1224          API.  If that is really required we need to implemented that
1225          in the upper layer.  */
1226       (void)modeflags;
1227 
1228       w32_cookie->hd = hd;
1229       w32_cookie->no_close = no_close;
1230       w32_cookie->no_syscall_clamp = no_syscall_clamp;
1231       *cookie = w32_cookie;
1232       err = 0;
1233     }
1234 
1235   trace_errno (err, ("leave: cookie=%p err=%d", *cookie, err));
1236   return err;
1237 }
1238 
1239 /*
1240  * Read function for W32 handle objects.
1241  *
1242  * Note that this function may also be used by the reader thread of
1243  * w32-stream.  In that case the NO_SYSCALL_CLAMP is set.
1244  */
1245 static gpgrt_ssize_t
func_w32_read(void * cookie,void * buffer,size_t size)1246 func_w32_read (void *cookie, void *buffer, size_t size)
1247 {
1248   estream_cookie_w32_t w32_cookie = cookie;
1249   gpgrt_ssize_t bytes_read;
1250 
1251   trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size));
1252 
1253   if (!size)
1254     bytes_read = -1; /* We don't know whether anything is pending.  */
1255   else if (w32_cookie->hd == INVALID_HANDLE_VALUE)
1256     {
1257       _gpgrt_yield ();
1258       bytes_read = 0;
1259     }
1260   else
1261     {
1262       if (!w32_cookie->no_syscall_clamp)
1263         _gpgrt_pre_syscall ();
1264       do
1265         {
1266           DWORD nread, ec;
1267 
1268           trace (("cookie=%p calling ReadFile", cookie));
1269           if (!ReadFile (w32_cookie->hd, buffer, size, &nread, NULL))
1270             {
1271               ec = GetLastError ();
1272               trace (("cookie=%p ReadFile failed: ec=%ld", cookie,ec));
1273               if (ec == ERROR_BROKEN_PIPE)
1274                 bytes_read = 0; /* Like our pth_read we handle this as EOF.  */
1275               else
1276                 {
1277                   _set_errno (map_w32_to_errno (ec));
1278                   bytes_read = -1;
1279                 }
1280             }
1281           else
1282             bytes_read = (int)nread;
1283         }
1284       while (bytes_read == -1 && errno == EINTR);
1285       if (!w32_cookie->no_syscall_clamp)
1286         _gpgrt_post_syscall ();
1287     }
1288 
1289   trace_errno (bytes_read==-1,("leave: bytes_read=%d", (int)bytes_read));
1290   return bytes_read;
1291 }
1292 
1293 
1294 /*
1295  * Write function for W32 handle objects.
1296  *
1297  * Note that this function may also be used by the writer thread of
1298  * w32-stream.  In that case the NO_SYSCALL_CLAMP is set.
1299  */
1300 static gpgrt_ssize_t
func_w32_write(void * cookie,const void * buffer,size_t size)1301 func_w32_write (void *cookie, const void *buffer, size_t size)
1302 {
1303   estream_cookie_w32_t w32_cookie = cookie;
1304   gpgrt_ssize_t bytes_written;
1305 
1306   trace (("enter: cookie=%p buffer=%p size=%d", cookie, buffer, (int)size));
1307 
1308   if (w32_cookie->hd == INVALID_HANDLE_VALUE)
1309     {
1310       _gpgrt_yield ();
1311       bytes_written = size; /* Yeah:  Success writing to the bit bucket.  */
1312     }
1313   else if (buffer)
1314     {
1315       if (!w32_cookie->no_syscall_clamp)
1316         _gpgrt_pre_syscall ();
1317       do
1318         {
1319           DWORD nwritten;
1320 
1321           trace (("cookie=%p calling WriteFile", cookie));
1322 	  if (!WriteFile (w32_cookie->hd, buffer, size, &nwritten, NULL))
1323 	    {
1324               DWORD ec = GetLastError ();
1325               trace (("cookie=%p WriteFile failed: ec=%ld", cookie, ec));
1326 	      _set_errno (map_w32_to_errno (ec));
1327 	      bytes_written = -1;
1328 	    }
1329 	  else
1330 	    bytes_written = (int)nwritten;
1331         }
1332       while (bytes_written == -1 && errno == EINTR);
1333       if (!w32_cookie->no_syscall_clamp)
1334         _gpgrt_post_syscall ();
1335     }
1336   else
1337     bytes_written = size; /* Note that for a flush SIZE should be 0.  */
1338 
1339   trace_errno (bytes_written==-1,
1340                ("leave: bytes_written=%d", (int)bytes_written));
1341   return bytes_written;
1342 }
1343 
1344 
1345 /*
1346  * Seek function for W32 handle objects.
1347  */
1348 static int
func_w32_seek(void * cookie,gpgrt_off_t * offset,int whence)1349 func_w32_seek (void *cookie, gpgrt_off_t *offset, int whence)
1350 {
1351   estream_cookie_w32_t w32_cookie = cookie;
1352   DWORD method;
1353   LARGE_INTEGER distance, newoff;
1354 
1355   if (w32_cookie->hd == INVALID_HANDLE_VALUE)
1356     {
1357       _set_errno (ESPIPE);
1358       return -1;
1359     }
1360 
1361   if (whence == SEEK_SET)
1362     {
1363       method = FILE_BEGIN;
1364       distance.QuadPart = (unsigned long long)(*offset);
1365     }
1366   else if (whence == SEEK_CUR)
1367     {
1368       method = FILE_CURRENT;
1369       distance.QuadPart = (long long)(*offset);
1370     }
1371   else if (whence == SEEK_END)
1372     {
1373       method = FILE_END;
1374       distance.QuadPart = (long long)(*offset);
1375     }
1376   else
1377     {
1378       _set_errno (EINVAL);
1379       return -1;
1380     }
1381 #ifdef HAVE_W32CE_SYSTEM
1382 # warning need to use SetFilePointer
1383 #else
1384   if (!w32_cookie->no_syscall_clamp)
1385     _gpgrt_pre_syscall ();
1386   if (!SetFilePointerEx (w32_cookie->hd, distance, &newoff, method))
1387     {
1388       _set_errno (map_w32_to_errno (GetLastError ()));
1389       _gpgrt_post_syscall ();
1390       return -1;
1391     }
1392   if (!w32_cookie->no_syscall_clamp)
1393     _gpgrt_post_syscall ();
1394 #endif
1395   /* Note that gpgrt_off_t is always 64 bit.  */
1396   *offset = (gpgrt_off_t)newoff.QuadPart;
1397   return 0;
1398 }
1399 
1400 
1401 /*
1402  * Destroy function for W32 handle objects.
1403  */
1404 static int
func_w32_destroy(void * cookie)1405 func_w32_destroy (void *cookie)
1406 {
1407   estream_cookie_w32_t w32_cookie = cookie;
1408   int err;
1409 
1410   trace (("enter: cookie=%p", cookie));
1411 
1412   if (w32_cookie)
1413     {
1414       if (w32_cookie->hd == INVALID_HANDLE_VALUE)
1415         err = 0;
1416       else if (w32_cookie->no_close)
1417         err = 0;
1418       else
1419         {
1420           trace (("cookie=%p closing handle %p", cookie, w32_cookie->hd));
1421           if (!CloseHandle (w32_cookie->hd))
1422             {
1423               DWORD ec = GetLastError ();
1424               trace (("cookie=%p CloseHandle failed: ec=%ld", cookie,ec));
1425 	      _set_errno (map_w32_to_errno (ec));
1426               err = -1;
1427             }
1428           else
1429             err = 0;
1430         }
1431       mem_free (w32_cookie);
1432     }
1433   else
1434     err = 0;
1435 
1436   trace_errno (err, ("leave: err=%d", err));
1437   return err;
1438 }
1439 
1440 
1441 /*
1442  * Access object for the W32 handle based objects.
1443  */
1444 static struct cookie_io_functions_s estream_functions_w32 =
1445   {
1446     {
1447       func_w32_read,
1448       func_w32_write,
1449       func_w32_seek,
1450       func_w32_destroy,
1451     },
1452     NULL,
1453   };
1454 #endif /*HAVE_W32_SYSTEM*/
1455 
1456 
1457 
1458 
1459 /*
1460  * Implementation of stdio based I/O.
1461  */
1462 
1463 /* Cookie for fp objects.  */
1464 typedef struct estream_cookie_fp
1465 {
1466   FILE *fp;      /* The file pointer we are using for actual output.  */
1467   int no_close;  /* If set we won't close the file pointer.  */
1468 } *estream_cookie_fp_t;
1469 
1470 
1471 /*
1472  * Create function for stdio based objects.
1473  */
1474 static int
func_fp_create(void ** cookie,FILE * fp,unsigned int modeflags,int no_close)1475 func_fp_create (void **cookie, FILE *fp,
1476                 unsigned int modeflags, int no_close)
1477 {
1478   estream_cookie_fp_t fp_cookie;
1479   int err;
1480 
1481   fp_cookie = mem_alloc (sizeof *fp_cookie);
1482   if (!fp_cookie)
1483     err = -1;
1484   else
1485     {
1486 #ifdef HAVE_DOSISH_SYSTEM
1487       /* Make sure it is in binary mode if requested.  */
1488       if ( (modeflags & O_BINARY) )
1489         setmode (fileno (fp), O_BINARY);
1490 #else
1491       (void)modeflags;
1492 #endif
1493       fp_cookie->fp = fp;
1494       fp_cookie->no_close = no_close;
1495       *cookie = fp_cookie;
1496       err = 0;
1497     }
1498 
1499   return err;
1500 }
1501 
1502 
1503 /*
1504  * Read function for stdio based objects.
1505  */
1506 static gpgrt_ssize_t
func_fp_read(void * cookie,void * buffer,size_t size)1507 func_fp_read (void *cookie, void *buffer, size_t size)
1508 
1509 {
1510   estream_cookie_fp_t file_cookie = cookie;
1511   gpgrt_ssize_t bytes_read;
1512 
1513   if (!size)
1514     return -1; /* We don't know whether anything is pending.  */
1515 
1516   if (file_cookie->fp)
1517     {
1518       _gpgrt_pre_syscall ();
1519       bytes_read = fread (buffer, 1, size, file_cookie->fp);
1520       _gpgrt_post_syscall ();
1521     }
1522   else
1523     bytes_read = 0;
1524   if (!bytes_read && ferror (file_cookie->fp))
1525     return -1;
1526   return bytes_read;
1527 }
1528 
1529 
1530 /*
1531  * Write function for stdio bases objects.
1532  */
1533 static gpgrt_ssize_t
func_fp_write(void * cookie,const void * buffer,size_t size)1534 func_fp_write (void *cookie, const void *buffer, size_t size)
1535 {
1536   estream_cookie_fp_t file_cookie = cookie;
1537   size_t bytes_written;
1538 
1539   if (file_cookie->fp)
1540     {
1541       _gpgrt_pre_syscall ();
1542       if (buffer)
1543         {
1544 #ifdef HAVE_W32_SYSTEM
1545           /* Using an fwrite to stdout connected to the console fails
1546              with the error "Not enough space" for an fwrite size of
1547              >= 52KB (tested on Windows XP SP2).  To solve this we
1548              always chunk the writes up into smaller blocks.  */
1549           bytes_written = 0;
1550           while (bytes_written < size)
1551             {
1552               size_t cnt = size - bytes_written;
1553 
1554               if (cnt > 32*1024)
1555                 cnt = 32*1024;
1556               if (fwrite ((const char*)buffer + bytes_written,
1557                           cnt, 1, file_cookie->fp) != 1)
1558                 break; /* Write error.  */
1559               bytes_written += cnt;
1560             }
1561 #else
1562           bytes_written = fwrite (buffer, 1, size, file_cookie->fp);
1563 #endif
1564         }
1565       else /* Only flush requested.  */
1566         bytes_written = size;
1567 
1568       fflush (file_cookie->fp);
1569       _gpgrt_post_syscall ();
1570     }
1571   else
1572     bytes_written = size; /* Successfully written to the bit bucket.  */
1573 
1574   if (bytes_written != size)
1575     return -1;
1576   return bytes_written;
1577 }
1578 
1579 
1580 /*
1581  * Seek function for stdio based objects.
1582  */
1583 static int
func_fp_seek(void * cookie,gpgrt_off_t * offset,int whence)1584 func_fp_seek (void *cookie, gpgrt_off_t *offset, int whence)
1585 {
1586   estream_cookie_fp_t file_cookie = cookie;
1587   long int offset_new;
1588 
1589   if (!file_cookie->fp)
1590     {
1591       _set_errno (ESPIPE);
1592       return -1;
1593     }
1594 
1595   _gpgrt_pre_syscall ();
1596   if ( fseek (file_cookie->fp, (long int)*offset, whence) )
1597     {
1598       /* fprintf (stderr, "\nfseek failed: errno=%d (%s)\n", */
1599       /*          errno,strerror (errno)); */
1600       _gpgrt_post_syscall ();
1601       return -1;
1602     }
1603 
1604   offset_new = ftell (file_cookie->fp);
1605   _gpgrt_post_syscall ();
1606   if (offset_new == -1)
1607     {
1608       /* fprintf (stderr, "\nftell failed: errno=%d (%s)\n",  */
1609       /*          errno,strerror (errno)); */
1610       return -1;
1611     }
1612   *offset = offset_new;
1613   return 0;
1614 }
1615 
1616 
1617 /*
1618  * Destroy function for stdio based objects.
1619  */
1620 static int
func_fp_destroy(void * cookie)1621 func_fp_destroy (void *cookie)
1622 {
1623   estream_cookie_fp_t fp_cookie = cookie;
1624   int err;
1625 
1626   if (fp_cookie)
1627     {
1628       if (fp_cookie->fp)
1629         {
1630           _gpgrt_pre_syscall ();
1631           fflush (fp_cookie->fp);
1632           _gpgrt_post_syscall ();
1633           err = fp_cookie->no_close? 0 : fclose (fp_cookie->fp);
1634         }
1635       else
1636         err = 0;
1637       mem_free (fp_cookie);
1638     }
1639   else
1640     err = 0;
1641 
1642   return err;
1643 }
1644 
1645 
1646 /*
1647  * Access object for stdio based objects.
1648  */
1649 static struct cookie_io_functions_s estream_functions_fp =
1650   {
1651     {
1652       func_fp_read,
1653       func_fp_write,
1654       func_fp_seek,
1655       func_fp_destroy,
1656     },
1657     NULL,
1658   };
1659 
1660 
1661 
1662 
1663 /*
1664  * Implementation of file name based I/O.
1665  *
1666  * Note that only a create function is required because the other
1667  * operations ares handled by file descriptor based I/O.
1668  */
1669 
1670 #ifdef HAVE_W32_SYSTEM
1671 static int
any8bitchar(const char * string)1672 any8bitchar (const char *string)
1673 {
1674   if (string)
1675     for ( ; *string; string++)
1676       if ((*string & 0x80))
1677         return 1;
1678   return 0;
1679 }
1680 #endif /*HAVE_W32_SYSTEM*/
1681 
1682 /* Create function for objects identified by a file name.  */
1683 static int
func_file_create(void ** cookie,int * filedes,const char * path,unsigned int modeflags,unsigned int cmode)1684 func_file_create (void **cookie, int *filedes,
1685                   const char *path, unsigned int modeflags, unsigned int cmode)
1686 {
1687   estream_cookie_fd_t file_cookie;
1688   int err;
1689   int fd;
1690 
1691   err = 0;
1692 
1693   file_cookie = mem_alloc (sizeof (*file_cookie));
1694   if (! file_cookie)
1695     {
1696       err = -1;
1697       goto out;
1698     }
1699 
1700 #ifdef HAVE_W32_SYSTEM
1701   if (any8bitchar (path))
1702     {
1703       wchar_t *wpath;
1704 
1705       wpath = _gpgrt_utf8_to_wchar (path);
1706       if (!wpath)
1707         fd = -1;
1708       else
1709         {
1710           fd = _wopen (wpath, modeflags, cmode);
1711           _gpgrt_free_wchar (wpath);
1712         }
1713     }
1714   else  /* Avoid unnecessary conversion.  */
1715     fd = open (path, modeflags, cmode);
1716 #else
1717   fd = open (path, modeflags, cmode);
1718 #endif
1719   if (fd == -1)
1720     {
1721       err = -1;
1722       goto out;
1723     }
1724 #ifdef HAVE_DOSISH_SYSTEM
1725   /* Make sure it is in binary mode if requested.  */
1726   if ( (modeflags & O_BINARY) )
1727     setmode (fd, O_BINARY);
1728 #endif
1729 
1730   file_cookie->fd = fd;
1731   file_cookie->no_close = 0;
1732   *cookie = file_cookie;
1733   *filedes = fd;
1734 
1735  out:
1736 
1737   if (err)
1738     mem_free (file_cookie);
1739 
1740   return err;
1741 }
1742 
1743 
1744 
1745 /* Flags used by parse_mode and friends.  */
1746 #define X_SAMETHREAD	(1 << 0)
1747 #define X_SYSOPEN	(1 << 1)
1748 #define X_POLLABLE	(1 << 2)
1749 
1750 /* Parse the mode flags of fopen et al.  In addition to the POSIX
1751  * defined mode flags keyword parameters are supported.  These are
1752  * key/value pairs delimited by comma and optional white spaces.
1753  * Keywords and values may not contain a comma or white space; unknown
1754  * keywords are skipped. Supported keywords are:
1755  *
1756  * mode=<string>
1757  *
1758  *    Creates a file and gives the new file read and write permissions
1759  *    for the user and read permission for the group.  The format of
1760  *    the string is the same as shown by the -l option of the ls(1)
1761  *    command.  However the first letter must be a dash and it is
1762  *    allowed to leave out trailing dashes.  If this keyword parameter
1763  *    is not given the default mode for creating files is "-rw-rw-r--"
1764  *    (664).  Note that the system still applies the current umask to
1765  *    the mode when creating a file.  Example:
1766  *
1767  *       "wb,mode=-rw-r--"
1768  *
1769  * samethread
1770  *
1771  *    Assumes that the object is only used by the creating thread and
1772  *    disables any internal locking.  This keyword is also found on
1773  *    IBM systems.
1774  *
1775  * nonblock
1776  *
1777  *    The object is opened in non-blocking mode.  This is the same as
1778  *    calling gpgrt_set_nonblock on the file.
1779  *
1780  * sysopen
1781  *
1782  *    The object is opened in sysmode.  On POSIX this is a NOP but
1783  *    under Windows the direct W32 API functions (HANDLE) are used
1784  *    instead of their libc counterparts (fd).
1785  *    FIXME: The functionality is not yet implemented.
1786  *
1787  * pollable
1788  *
1789  *    The object is opened in a way suitable for use with es_poll.  On
1790  *    POSIX this is a NOP but under Windows we create up to two
1791  *    threads, one for reading and one for writing, do any I/O there,
1792  *    and synchronize with them in order to support es_poll.
1793  *
1794  * Note: R_CMODE is optional because is only required by functions
1795  * which are able to creat a file.
1796  */
1797 static int
parse_mode(const char * modestr,unsigned int * modeflags,unsigned int * r_xmode,unsigned int * r_cmode)1798 parse_mode (const char *modestr,
1799             unsigned int *modeflags,
1800             unsigned int *r_xmode,
1801             unsigned int *r_cmode)
1802 {
1803   unsigned int omode, oflags, cmode;
1804   int got_cmode = 0;
1805 
1806   *r_xmode = 0;
1807 
1808   switch (*modestr)
1809     {
1810     case 'r':
1811       omode = O_RDONLY;
1812       oflags = 0;
1813       break;
1814     case 'w':
1815       omode = O_WRONLY;
1816       oflags = O_TRUNC | O_CREAT;
1817       break;
1818     case 'a':
1819       omode = O_WRONLY;
1820       oflags = O_APPEND | O_CREAT;
1821       break;
1822     default:
1823       _set_errno (EINVAL);
1824       return -1;
1825     }
1826   for (modestr++; *modestr; modestr++)
1827     {
1828       switch (*modestr)
1829         {
1830         case '+':
1831           omode = O_RDWR;
1832           break;
1833         case 'b':
1834           oflags |= O_BINARY;
1835           break;
1836         case 'x':
1837           oflags |= O_EXCL;
1838           break;
1839         case ',':
1840           goto keyvalue;
1841         default: /* Ignore unknown flags.  */
1842           break;
1843         }
1844     }
1845 
1846  keyvalue:
1847   /* Parse key/value pairs (similar to fopen on mainframes).  */
1848   for (cmode=0; *modestr == ','; modestr += strcspn (modestr, ","))
1849     {
1850       modestr++;
1851       modestr += strspn (modestr, " \t");
1852       if (!strncmp (modestr, "mode=", 5))
1853         {
1854           static struct {
1855             char letter;
1856             unsigned int value;
1857           } table[] = { { '-', 0 },
1858                         { 'r', S_IRUSR }, { 'w', S_IWUSR }, { 'x', S_IXUSR },
1859                         { 'r', S_IRGRP }, { 'w', S_IWGRP }, { 'x', S_IXGRP },
1860                         { 'r', S_IROTH }, { 'w', S_IWOTH }, { 'x', S_IXOTH }};
1861           int idx;
1862 
1863           got_cmode = 1;
1864           modestr += 5;
1865           /* For now we only support a string as used by ls(1) and no
1866              octal numbers.  The first character must be a dash.  */
1867           for (idx=0; idx < 10 && *modestr; idx++, modestr++)
1868             {
1869               if (*modestr == table[idx].letter)
1870                 cmode |= table[idx].value;
1871               else if (*modestr != '-')
1872                 break;
1873             }
1874           if (*modestr && !strchr (" \t,", *modestr))
1875             {
1876               _set_errno (EINVAL);
1877               return -1;
1878             }
1879         }
1880       else if (!strncmp (modestr, "samethread", 10))
1881         {
1882           modestr += 10;
1883           if (*modestr && !strchr (" \t,", *modestr))
1884             {
1885               _set_errno (EINVAL);
1886               return -1;
1887             }
1888           *r_xmode |= X_SAMETHREAD;
1889         }
1890       else if (!strncmp (modestr, "nonblock", 8))
1891         {
1892           modestr += 8;
1893           if (*modestr && !strchr (" \t,", *modestr))
1894             {
1895               _set_errno (EINVAL);
1896               return -1;
1897             }
1898           oflags |= O_NONBLOCK;
1899 #if HAVE_W32_SYSTEM
1900           /* Currently, nonblock implies pollable on Windows.  */
1901           *r_xmode |= X_POLLABLE;
1902 #endif
1903         }
1904       else if (!strncmp (modestr, "sysopen", 7))
1905         {
1906           modestr += 7;
1907           if (*modestr && !strchr (" \t,", *modestr))
1908             {
1909               _set_errno (EINVAL);
1910               return -1;
1911             }
1912           *r_xmode |= X_SYSOPEN;
1913         }
1914       else if (!strncmp (modestr, "pollable", 8))
1915         {
1916           modestr += 8;
1917           if (*modestr && !strchr (" \t,", *modestr))
1918             {
1919               _set_errno (EINVAL);
1920               return -1;
1921             }
1922           *r_xmode |= X_POLLABLE;
1923         }
1924     }
1925   if (!got_cmode)
1926     cmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
1927 
1928   *modeflags = (omode | oflags);
1929   if (r_cmode)
1930     *r_cmode = cmode;
1931   return 0;
1932 }
1933 
1934 
1935 
1936 /*
1937  * Low level stream functionality.
1938  */
1939 
1940 static int
fill_stream(estream_t stream)1941 fill_stream (estream_t stream)
1942 {
1943   size_t bytes_read = 0;
1944   int err;
1945 
1946   if (!stream->intern->func_read)
1947     {
1948       _set_errno (EOPNOTSUPP);
1949       err = -1;
1950     }
1951   else if (!stream->buffer_size)
1952     err = 0;
1953   else
1954     {
1955       gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
1956       gpgrt_ssize_t ret;
1957 
1958       ret = (*func_read) (stream->intern->cookie,
1959 			  stream->buffer, stream->buffer_size);
1960       if (ret == -1)
1961 	{
1962 	  bytes_read = 0;
1963 	  err = -1;
1964 #if EWOULDBLOCK != EAGAIN
1965           if (errno == EWOULDBLOCK)
1966             _set_errno (EAGAIN);
1967 #endif
1968 	}
1969       else
1970 	{
1971 	  bytes_read = ret;
1972 	  err = 0;
1973 	}
1974     }
1975 
1976   if (err)
1977     {
1978       if (errno != EAGAIN)
1979         {
1980           if (errno == EPIPE)
1981             stream->intern->indicators.hup = 1;
1982           stream->intern->indicators.err = 1;
1983         }
1984     }
1985   else if (!bytes_read)
1986     stream->intern->indicators.eof = 1;
1987 
1988   stream->intern->offset += stream->data_len;
1989   stream->data_len = bytes_read;
1990   stream->data_offset = 0;
1991 
1992   return err;
1993 }
1994 
1995 static int
flush_stream(estream_t stream)1996 flush_stream (estream_t stream)
1997 {
1998   gpgrt_cookie_write_function_t func_write = stream->intern->func_write;
1999   int err;
2000 
2001   gpgrt_assert (stream->flags.writing);
2002 
2003   if (stream->data_offset)
2004     {
2005       size_t bytes_written;
2006       size_t data_flushed;
2007       gpgrt_ssize_t ret;
2008 
2009       if (! func_write)
2010 	{
2011           _set_errno (EOPNOTSUPP);
2012           err = -1;
2013 	  goto out;
2014 	}
2015 
2016       /* Note: to prevent an endless loop caused by user-provided
2017 	 write-functions that pretend to have written more bytes than
2018 	 they were asked to write, we have to check for
2019 	 "(stream->data_offset - data_flushed) > 0" instead of
2020 	 "stream->data_offset - data_flushed".  */
2021 
2022       data_flushed = 0;
2023       err = 0;
2024 
2025       while ((((gpgrt_ssize_t) (stream->data_offset - data_flushed)) > 0)
2026              && !err)
2027 	{
2028 	  ret = (*func_write) (stream->intern->cookie,
2029 			       stream->buffer + data_flushed,
2030 			       stream->data_offset - data_flushed);
2031 	  if (ret == -1)
2032 	    {
2033 	      bytes_written = 0;
2034 	      err = -1;
2035 #if EWOULDBLOCK != EAGAIN
2036               if (errno == EWOULDBLOCK)
2037                 _set_errno (EAGAIN);
2038 #endif
2039 	    }
2040 	  else
2041 	    bytes_written = ret;
2042 
2043 	  data_flushed += bytes_written;
2044 	  if (err)
2045 	    break;
2046 	}
2047 
2048       stream->data_flushed += data_flushed;
2049       if (stream->data_offset == data_flushed)
2050 	{
2051 	  stream->intern->offset += stream->data_offset;
2052 	  stream->data_offset = 0;
2053 	  stream->data_flushed = 0;
2054 	}
2055     }
2056   else
2057     err = 0;
2058 
2059   /* Always propagate flush event in case gpgrt_fflush was called
2060    * explictly to do flush buffers in caller's cookie functions.  */
2061   (*func_write) (stream->intern->cookie, NULL, 0);
2062 
2063  out:
2064 
2065   if (err && errno != EAGAIN)
2066     {
2067       if (errno == EPIPE)
2068         stream->intern->indicators.hup = 1;
2069       stream->intern->indicators.err = 1;
2070     }
2071 
2072   return err;
2073 }
2074 
2075 
2076 /*
2077  * Discard buffered data for STREAM.
2078  */
2079 static void
es_empty(estream_t stream)2080 es_empty (estream_t stream)
2081 {
2082   gpgrt_assert (!stream->flags.writing);
2083   stream->data_len = 0;
2084   stream->data_offset = 0;
2085   stream->unread_data_len = 0;
2086 }
2087 
2088 
2089 /*
2090  * Initialize STREAM.
2091  */
2092 static void
init_stream_obj(estream_t stream,void * cookie,es_syshd_t * syshd,gpgrt_stream_backend_kind_t kind,struct cookie_io_functions_s functions,unsigned int modeflags,unsigned int xmode)2093 init_stream_obj (estream_t stream,
2094                  void *cookie, es_syshd_t *syshd,
2095                  gpgrt_stream_backend_kind_t kind,
2096                  struct cookie_io_functions_s functions,
2097                  unsigned int modeflags, unsigned int xmode)
2098 {
2099   stream->intern->kind = kind;
2100   stream->intern->cookie = cookie;
2101   stream->intern->opaque = NULL;
2102   stream->intern->offset = 0;
2103   stream->intern->func_read = functions.public.func_read;
2104   stream->intern->func_write = functions.public.func_write;
2105   stream->intern->func_seek = functions.public.func_seek;
2106   stream->intern->func_ioctl = functions.func_ioctl;
2107   stream->intern->func_close = functions.public.func_close;
2108   stream->intern->strategy = _IOFBF;
2109   stream->intern->syshd = *syshd;
2110   stream->intern->print_ntotal = 0;
2111   stream->intern->indicators.err = 0;
2112   stream->intern->indicators.eof = 0;
2113   stream->intern->indicators.hup = 0;
2114   stream->intern->is_stdstream = 0;
2115   stream->intern->stdstream_fd = 0;
2116   stream->intern->deallocate_buffer = 0;
2117   stream->intern->printable_fname = NULL;
2118   stream->intern->printable_fname_inuse = 0;
2119   stream->intern->samethread = !! (xmode & X_SAMETHREAD);
2120   stream->intern->onclose = NULL;
2121 
2122   stream->data_len = 0;
2123   stream->data_offset = 0;
2124   stream->data_flushed = 0;
2125   stream->unread_data_len = 0;
2126   /* Depending on the modeflags we set whether we start in writing or
2127      reading mode.  This is required in case we are working on a
2128      stream which is not seeekable (like stdout).  Without this
2129      pre-initialization we would do a seek at the first write call and
2130      as this will fail no output will be delivered. */
2131   if ((modeflags & O_WRONLY) || (modeflags & O_RDWR) )
2132     stream->flags.writing = 1;
2133   else
2134     stream->flags.writing = 0;
2135 }
2136 
2137 
2138 /*
2139  * Deinitialize the STREAM object.  This does _not_ free the memory,
2140  * destroys the lock, or closes the underlying descriptor.
2141  */
2142 static int
deinit_stream_obj(estream_t stream)2143 deinit_stream_obj (estream_t stream)
2144 {
2145   gpgrt_cookie_close_function_t func_close;
2146   int err, tmp_err;
2147 
2148   trace (("enter: stream %p", stream));
2149   func_close = stream->intern->func_close;
2150 
2151   err = 0;
2152   if (stream->flags.writing)
2153     {
2154       tmp_err = flush_stream (stream);
2155       if (!err)
2156         err = tmp_err;
2157     }
2158   if (func_close)
2159     {
2160       trace (("stream %p calling func_close", stream));
2161       tmp_err = func_close (stream->intern->cookie);
2162       if (!err)
2163         err = tmp_err;
2164     }
2165 
2166   mem_free (stream->intern->printable_fname);
2167   stream->intern->printable_fname = NULL;
2168   stream->intern->printable_fname_inuse = 0;
2169   while (stream->intern->onclose)
2170     {
2171       notify_list_t tmp = stream->intern->onclose->next;
2172       mem_free (stream->intern->onclose);
2173       stream->intern->onclose = tmp;
2174     }
2175 
2176   trace_errno (err, ("leave: stream %p err=%d", stream, err));
2177   return err;
2178 }
2179 
2180 
2181 /*
2182  * Create a new stream and initialize it.  On success the new stream
2183  * handle is tsored at R_STREAM.  On failure NULL is stored at
2184  * R_STREAM.
2185  */
2186 static int
create_stream(estream_t * r_stream,void * cookie,es_syshd_t * syshd,gpgrt_stream_backend_kind_t kind,struct cookie_io_functions_s functions,unsigned int modeflags,unsigned int xmode,int with_locked_list)2187 create_stream (estream_t *r_stream, void *cookie, es_syshd_t *syshd,
2188                gpgrt_stream_backend_kind_t kind,
2189                struct cookie_io_functions_s functions, unsigned int modeflags,
2190                unsigned int xmode, int with_locked_list)
2191 {
2192   estream_internal_t stream_internal_new;
2193   estream_t stream_new;
2194   int err;
2195 #if HAVE_W32_SYSTEM
2196   void *old_cookie = NULL;
2197 #endif
2198 
2199   stream_new = NULL;
2200   stream_internal_new = NULL;
2201 
2202 #if HAVE_W32_SYSTEM
2203   if ((xmode & X_POLLABLE) && kind != BACKEND_W32)
2204     {
2205       /* We require the W32 backend, because only that allows us to
2206        * write directly using the native W32 API and to disable the
2207        * system clamp.  Note that func_w32_create has already been
2208        * called with the flag to disable the system call clamp.  */
2209       _set_errno (EINVAL);
2210       err = -1;
2211       goto out;
2212     }
2213 #endif /*HAVE_W32_SYSTEM*/
2214 
2215   stream_new = mem_alloc (sizeof (*stream_new));
2216   if (! stream_new)
2217     {
2218       err = -1;
2219       goto out;
2220     }
2221 
2222   stream_internal_new = mem_alloc (sizeof (*stream_internal_new));
2223   if (! stream_internal_new)
2224     {
2225       err = -1;
2226       goto out;
2227     }
2228 
2229   stream_new->buffer = stream_internal_new->buffer;
2230   stream_new->buffer_size = sizeof (stream_internal_new->buffer);
2231   stream_new->unread_buffer = stream_internal_new->unread_buffer;
2232   stream_new->unread_buffer_size = sizeof (stream_internal_new->unread_buffer);
2233   stream_new->intern = stream_internal_new;
2234 
2235 #if HAVE_W32_SYSTEM
2236   if ((xmode & X_POLLABLE))
2237     {
2238       void *new_cookie;
2239 
2240       err = _gpgrt_w32_pollable_create (&new_cookie, modeflags,
2241                                         functions, cookie);
2242       if (err)
2243         goto out;
2244 
2245       modeflags &= ~O_NONBLOCK;
2246       old_cookie = cookie;
2247       cookie = new_cookie;
2248       kind = BACKEND_W32_POLLABLE;
2249       functions = _gpgrt_functions_w32_pollable;
2250     }
2251 #endif /*HAVE_W32_SYSTEM*/
2252 
2253   init_stream_obj (stream_new, cookie, syshd, kind, functions, modeflags,
2254                    xmode);
2255   init_stream_lock (stream_new);
2256 
2257   err = do_list_add (stream_new, with_locked_list);
2258   if (err)
2259     goto out;
2260 
2261   *r_stream = stream_new;
2262 
2263  out:
2264 
2265   if (err)
2266     {
2267       trace_errno (err, ("leave: err=%d", err));
2268       if (stream_new)
2269 	{
2270 	  deinit_stream_obj (stream_new);
2271           destroy_stream_lock (stream_new);
2272 	  mem_free (stream_new->intern);
2273 	  mem_free (stream_new);
2274 	}
2275     }
2276 #if HAVE_W32_SYSTEM
2277   else if (old_cookie)
2278     trace (("leave: success stream=%p cookie=%p,%p",
2279             *r_stream, old_cookie, cookie));
2280 #endif
2281   else
2282     trace (("leave: success stream=%p cookie=%p", *r_stream, cookie));
2283 
2284   return err;
2285 }
2286 
2287 
2288 /*
2289  * Deinitialize a stream object and destroy it.  With CANCEL_MODE set
2290  * try to cancel as much as possible (see _gpgrt_fcancel).
2291  */
2292 static int
do_close(estream_t stream,int cancel_mode,int with_locked_list)2293 do_close (estream_t stream, int cancel_mode, int with_locked_list)
2294 {
2295   int err;
2296 
2297   trace (("stream %p %s", stream, with_locked_list? "(with locked list)":""));
2298 
2299   if (stream)
2300     {
2301       do_list_remove (stream, with_locked_list);
2302       if (cancel_mode)
2303         {
2304           stream->flags.writing = 0;
2305           es_empty (stream);
2306         }
2307       while (stream->intern->onclose)
2308         {
2309           notify_list_t tmp = stream->intern->onclose->next;
2310 
2311           if (stream->intern->onclose->fnc)
2312             stream->intern->onclose->fnc (stream,
2313                                           stream->intern->onclose->fnc_value);
2314           mem_free (stream->intern->onclose);
2315           stream->intern->onclose = tmp;
2316         }
2317       err = deinit_stream_obj (stream);
2318       destroy_stream_lock (stream);
2319       if (stream->intern->deallocate_buffer)
2320         mem_free (stream->buffer);
2321       mem_free (stream->intern);
2322       mem_free (stream);
2323     }
2324   else
2325     err = 0;
2326 
2327   trace_errno (err, ("stream %p err=%d", stream, err));
2328   return err;
2329 }
2330 
2331 
2332 /*
2333  * The onclose worker function which is called with a locked
2334  * stream.
2335  */
2336 static int
do_onclose(estream_t stream,int mode,void (* fnc)(estream_t,void *),void * fnc_value)2337 do_onclose (estream_t stream, int mode,
2338             void (*fnc) (estream_t, void*), void *fnc_value)
2339 {
2340   notify_list_t item;
2341 
2342   if (!mode)
2343     {
2344       for (item = stream->intern->onclose; item; item = item->next)
2345         if (item->fnc && item->fnc == fnc && item->fnc_value == fnc_value)
2346           item->fnc = NULL; /* Disable this notification.  */
2347     }
2348   else
2349     {
2350       item = mem_alloc (sizeof *item);
2351       if (!item)
2352         return -1;
2353       item->fnc = fnc;
2354       item->fnc_value = fnc_value;
2355       item->next = stream->intern->onclose;
2356       stream->intern->onclose = item;
2357     }
2358   return 0;
2359 }
2360 
2361 
2362 /*
2363  * Try to read BYTES_TO_READ bytes from STREAM into BUFFER in
2364  * unbuffered-mode, storing the amount of bytes read at BYTES_READ.
2365  */
2366 static int
do_read_nbf(estream_t _GPGRT__RESTRICT stream,unsigned char * _GPGRT__RESTRICT buffer,size_t bytes_to_read,size_t * _GPGRT__RESTRICT bytes_read)2367 do_read_nbf (estream_t _GPGRT__RESTRICT stream,
2368 	     unsigned char *_GPGRT__RESTRICT buffer,
2369 	     size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read)
2370 {
2371   gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
2372   size_t data_read;
2373   gpgrt_ssize_t ret;
2374   int err;
2375 
2376   data_read = 0;
2377   err = 0;
2378 
2379   while (bytes_to_read - data_read)
2380     {
2381       ret = (*func_read) (stream->intern->cookie,
2382 			  buffer + data_read, bytes_to_read - data_read);
2383       if (ret == -1)
2384 	{
2385 	  err = -1;
2386 #if EWOULDBLOCK != EAGAIN
2387           if (errno == EWOULDBLOCK)
2388             _set_errno (EAGAIN);
2389 #endif
2390 	  break;
2391 	}
2392       else if (ret)
2393 	data_read += ret;
2394       else
2395 	break;
2396     }
2397 
2398   stream->intern->offset += data_read;
2399   *bytes_read = data_read;
2400 
2401   return err;
2402 }
2403 
2404 
2405 /*
2406  * Helper for check_pending.
2407  */
2408 static int
check_pending_nbf(estream_t _GPGRT__RESTRICT stream)2409 check_pending_nbf (estream_t _GPGRT__RESTRICT stream)
2410 {
2411   gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
2412   char buffer[1];
2413 
2414   if (!(*func_read) (stream->intern->cookie, buffer, 0))
2415     return 1; /* Pending bytes.  */
2416   return 0; /* No pending bytes or error.  */
2417 }
2418 
2419 
2420 /*
2421  * Try to read BYTES_TO_READ bytes from STREAM into BUFFER in
2422  * fully-buffered-mode, storing the amount of bytes read at
2423  * BYTES_READ.
2424  */
2425 static int
do_read_fbf(estream_t _GPGRT__RESTRICT stream,unsigned char * _GPGRT__RESTRICT buffer,size_t bytes_to_read,size_t * _GPGRT__RESTRICT bytes_read)2426 do_read_fbf (estream_t _GPGRT__RESTRICT stream,
2427 	     unsigned char *_GPGRT__RESTRICT buffer,
2428 	     size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read)
2429 {
2430   size_t data_available;
2431   size_t data_to_read;
2432   size_t data_read;
2433   int err;
2434 
2435   data_read = 0;
2436   err = 0;
2437 
2438   while ((bytes_to_read - data_read) && (! err))
2439     {
2440       if (stream->data_offset == stream->data_len)
2441 	{
2442 	  /* Nothing more to read in current container, try to
2443 	     fill container with new data.  */
2444 	  err = fill_stream (stream);
2445 	  if (! err)
2446 	    if (! stream->data_len)
2447 	      /* Filling did not result in any data read.  */
2448 	      break;
2449 	}
2450 
2451       if (! err)
2452 	{
2453 	  /* Filling resulted in some new data.  */
2454 
2455 	  data_to_read = bytes_to_read - data_read;
2456 	  data_available = stream->data_len - stream->data_offset;
2457 	  if (data_to_read > data_available)
2458 	    data_to_read = data_available;
2459 
2460 	  memcpy (buffer + data_read,
2461 		  stream->buffer + stream->data_offset, data_to_read);
2462 	  stream->data_offset += data_to_read;
2463 	  data_read += data_to_read;
2464 	}
2465     }
2466 
2467   *bytes_read = data_read;
2468 
2469   return err;
2470 }
2471 
2472 
2473 /*
2474  * Helper for check_pending.
2475  */
2476 static int
check_pending_fbf(estream_t _GPGRT__RESTRICT stream)2477 check_pending_fbf (estream_t _GPGRT__RESTRICT stream)
2478 {
2479   gpgrt_cookie_read_function_t func_read = stream->intern->func_read;
2480   char buffer[1];
2481 
2482   if (stream->data_offset == stream->data_len)
2483     {
2484       /* Nothing more to read in current container, check whether it
2485          would be possible to fill the container with new data.  */
2486       if (!(*func_read) (stream->intern->cookie, buffer, 0))
2487         return 1; /* Pending bytes.  */
2488     }
2489   else
2490     return 1;
2491   return 0;
2492 }
2493 
2494 
2495 /*
2496  * Try to read BYTES_TO_READ bytes from STREAM into BUFFER in
2497  * line-buffered-mode, storing the amount of bytes read at BYTES_READ.
2498  */
2499 static int
do_read_lbf(estream_t _GPGRT__RESTRICT stream,unsigned char * _GPGRT__RESTRICT buffer,size_t bytes_to_read,size_t * _GPGRT__RESTRICT bytes_read)2500 do_read_lbf (estream_t _GPGRT__RESTRICT stream,
2501 	     unsigned char *_GPGRT__RESTRICT buffer,
2502 	     size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read)
2503 {
2504   int err;
2505 
2506   err = do_read_fbf (stream, buffer, bytes_to_read, bytes_read);
2507 
2508   return err;
2509 }
2510 
2511 
2512 /*
2513  * Try to read BYTES_TO_READ bytes from STREAM into BUFFER, storing
2514  * the amount of bytes read at BYTES_READ.
2515  */
2516 static int
es_readn(estream_t _GPGRT__RESTRICT stream,void * _GPGRT__RESTRICT buffer_arg,size_t bytes_to_read,size_t * _GPGRT__RESTRICT bytes_read)2517 es_readn (estream_t _GPGRT__RESTRICT stream,
2518 	  void *_GPGRT__RESTRICT buffer_arg,
2519 	  size_t bytes_to_read, size_t *_GPGRT__RESTRICT bytes_read)
2520 {
2521   unsigned char *buffer = (unsigned char *)buffer_arg;
2522   size_t data_read_unread, data_read;
2523   int err;
2524 
2525   data_read_unread = 0;
2526   data_read = 0;
2527   err = 0;
2528 
2529   if (stream->flags.writing)
2530     {
2531       /* Switching to reading mode -> flush output.  */
2532       err = flush_stream (stream);
2533       if (err)
2534 	goto out;
2535       stream->flags.writing = 0;
2536     }
2537 
2538   /* Read unread data first.  */
2539   while ((bytes_to_read - data_read_unread) && stream->unread_data_len)
2540     {
2541       buffer[data_read_unread]
2542 	= stream->unread_buffer[stream->unread_data_len - 1];
2543       stream->unread_data_len--;
2544       data_read_unread++;
2545     }
2546 
2547   switch (stream->intern->strategy)
2548     {
2549     case _IONBF:
2550       err = do_read_nbf (stream,
2551 			 buffer + data_read_unread,
2552 			 bytes_to_read - data_read_unread, &data_read);
2553       break;
2554     case _IOLBF:
2555       err = do_read_lbf (stream,
2556 			 buffer + data_read_unread,
2557 			 bytes_to_read - data_read_unread, &data_read);
2558       break;
2559     case _IOFBF:
2560       err = do_read_fbf (stream,
2561 			 buffer + data_read_unread,
2562 			 bytes_to_read - data_read_unread, &data_read);
2563       break;
2564     }
2565 
2566  out:
2567 
2568   if (bytes_read)
2569     *bytes_read = data_read_unread + data_read;
2570 
2571   return err;
2572 }
2573 
2574 
2575 /*
2576  * Return true if at least one byte is pending for read.  This is a
2577  * best effort check and it it possible that bytes are still pending
2578  * even if false is returned.  If the stream is in writing mode it is
2579  * switched to read mode.
2580  */
2581 static int
check_pending(estream_t _GPGRT__RESTRICT stream)2582 check_pending (estream_t _GPGRT__RESTRICT stream)
2583 {
2584   if (stream->flags.writing)
2585     {
2586       /* Switching to reading mode -> flush output.  */
2587       if (flush_stream (stream))
2588 	return 0; /* Better return 0 on error.  */
2589       stream->flags.writing = 0;
2590     }
2591 
2592   /* Check unread data first.  */
2593   if (stream->unread_data_len)
2594     return 1;
2595 
2596   switch (stream->intern->strategy)
2597     {
2598     case _IONBF:
2599       return check_pending_nbf (stream);
2600     case _IOLBF:
2601     case _IOFBF:
2602       return check_pending_fbf (stream);
2603     }
2604 
2605   return 0;
2606 }
2607 
2608 
2609 /*
2610  * Try to unread DATA_N bytes from DATA into STREAM, storing the
2611  * amount of bytes successfully unread at BYTES_UNREAD.
2612  */
2613 static void
es_unreadn(estream_t _GPGRT__RESTRICT stream,const unsigned char * _GPGRT__RESTRICT data,size_t data_n,size_t * _GPGRT__RESTRICT bytes_unread)2614 es_unreadn (estream_t _GPGRT__RESTRICT stream,
2615 	    const unsigned char *_GPGRT__RESTRICT data, size_t data_n,
2616 	    size_t *_GPGRT__RESTRICT bytes_unread)
2617 {
2618   size_t space_left;
2619 
2620   space_left = stream->unread_buffer_size - stream->unread_data_len;
2621 
2622   if (data_n > space_left)
2623     data_n = space_left;
2624 
2625   if (! data_n)
2626     goto out;
2627 
2628   memcpy (stream->unread_buffer + stream->unread_data_len, data, data_n);
2629   stream->unread_data_len += data_n;
2630   stream->intern->indicators.eof = 0;
2631 
2632  out:
2633 
2634   if (bytes_unread)
2635     *bytes_unread = data_n;
2636 }
2637 
2638 
2639 /*
2640  * Seek in STREAM.
2641  */
2642 static int
es_seek(estream_t _GPGRT__RESTRICT stream,gpgrt_off_t offset,int whence,gpgrt_off_t * _GPGRT__RESTRICT offset_new)2643 es_seek (estream_t _GPGRT__RESTRICT stream, gpgrt_off_t offset, int whence,
2644 	 gpgrt_off_t *_GPGRT__RESTRICT offset_new)
2645 {
2646   gpgrt_cookie_seek_function_t func_seek = stream->intern->func_seek;
2647   int err, ret;
2648   gpgrt_off_t off;
2649 
2650   if (! func_seek)
2651     {
2652       _set_errno (EOPNOTSUPP);
2653       err = -1;
2654       goto out;
2655     }
2656 
2657   if (stream->flags.writing)
2658     {
2659       /* Flush data first in order to prevent flushing it to the wrong
2660 	 offset.  */
2661       err = flush_stream (stream);
2662       if (err)
2663 	goto out;
2664       stream->flags.writing = 0;
2665     }
2666 
2667   off = offset;
2668   if (whence == SEEK_CUR)
2669     {
2670       off = off - stream->data_len + stream->data_offset;
2671       off -= stream->unread_data_len;
2672     }
2673 
2674   ret = (*func_seek) (stream->intern->cookie, &off, whence);
2675   if (ret == -1)
2676     {
2677       err = -1;
2678 #if EWOULDBLOCK != EAGAIN
2679       if (errno == EWOULDBLOCK)
2680         _set_errno (EAGAIN);
2681 #endif
2682       goto out;
2683     }
2684 
2685   err = 0;
2686   es_empty (stream);
2687 
2688   if (offset_new)
2689     *offset_new = off;
2690 
2691   stream->intern->indicators.eof = 0;
2692   stream->intern->offset = off;
2693 
2694  out:
2695 
2696   if (err)
2697     {
2698       if (errno == EPIPE)
2699         stream->intern->indicators.hup = 1;
2700       stream->intern->indicators.err = 1;
2701     }
2702 
2703   return err;
2704 }
2705 
2706 
2707 /*
2708  * Write BYTES_TO_WRITE bytes from BUFFER into STREAM in
2709  * unbuffered-mode, storing the amount of bytes written at
2710  * BYTES_WRITTEN.
2711  */
2712 static int
es_write_nbf(estream_t _GPGRT__RESTRICT stream,const unsigned char * _GPGRT__RESTRICT buffer,size_t bytes_to_write,size_t * _GPGRT__RESTRICT bytes_written)2713 es_write_nbf (estream_t _GPGRT__RESTRICT stream,
2714 	      const unsigned char *_GPGRT__RESTRICT buffer,
2715 	      size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written)
2716 {
2717   gpgrt_cookie_write_function_t func_write = stream->intern->func_write;
2718   size_t data_written;
2719   gpgrt_ssize_t ret;
2720   int err;
2721 
2722   if (bytes_to_write && (! func_write))
2723     {
2724       _set_errno (EOPNOTSUPP);
2725       err = -1;
2726       goto out;
2727     }
2728 
2729   data_written = 0;
2730   err = 0;
2731 
2732   while (bytes_to_write - data_written)
2733     {
2734       ret = (*func_write) (stream->intern->cookie,
2735 			   buffer + data_written,
2736 			   bytes_to_write - data_written);
2737       if (ret == -1)
2738 	{
2739 	  err = -1;
2740 #if EWOULDBLOCK != EAGAIN
2741           if (errno == EWOULDBLOCK)
2742             _set_errno (EAGAIN);
2743 #endif
2744 	  break;
2745 	}
2746       else
2747 	data_written += ret;
2748     }
2749 
2750   stream->intern->offset += data_written;
2751   *bytes_written = data_written;
2752 
2753  out:
2754 
2755   return err;
2756 }
2757 
2758 
2759 /*
2760  * Write BYTES_TO_WRITE bytes from BUFFER into STREAM in
2761  * fully-buffered-mode, storing the amount of bytes written at
2762  * BYTES_WRITTEN.
2763  */
2764 static int
es_write_fbf(estream_t _GPGRT__RESTRICT stream,const unsigned char * _GPGRT__RESTRICT buffer,size_t bytes_to_write,size_t * _GPGRT__RESTRICT bytes_written)2765 es_write_fbf (estream_t _GPGRT__RESTRICT stream,
2766 	      const unsigned char *_GPGRT__RESTRICT buffer,
2767 	      size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written)
2768 {
2769   size_t space_available;
2770   size_t data_to_write;
2771   size_t data_written;
2772   int err;
2773 
2774   data_written = 0;
2775   err = 0;
2776 
2777   while ((bytes_to_write - data_written) && (! err))
2778     {
2779       if (stream->data_offset == stream->buffer_size)
2780 	/* Container full, flush buffer.  */
2781 	err = flush_stream (stream);
2782 
2783       if (! err)
2784 	{
2785 	  /* Flushing resulted in empty container.  */
2786 
2787 	  data_to_write = bytes_to_write - data_written;
2788 	  space_available = stream->buffer_size - stream->data_offset;
2789 	  if (data_to_write > space_available)
2790 	    data_to_write = space_available;
2791 
2792 	  memcpy (stream->buffer + stream->data_offset,
2793 		  buffer + data_written, data_to_write);
2794 	  stream->data_offset += data_to_write;
2795 	  data_written += data_to_write;
2796 	}
2797     }
2798 
2799   *bytes_written = data_written;
2800 
2801   return err;
2802 }
2803 
2804 
2805 /* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in
2806    line-buffered-mode, storing the amount of bytes written in
2807    *BYTES_WRITTEN.  */
2808 static int
es_write_lbf(estream_t _GPGRT__RESTRICT stream,const unsigned char * _GPGRT__RESTRICT buffer,size_t bytes_to_write,size_t * _GPGRT__RESTRICT bytes_written)2809 es_write_lbf (estream_t _GPGRT__RESTRICT stream,
2810 	      const unsigned char *_GPGRT__RESTRICT buffer,
2811 	      size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written)
2812 {
2813   size_t data_flushed = 0;
2814   size_t data_buffered = 0;
2815   unsigned char *nlp;
2816   int err = 0;
2817 
2818   nlp = memrchr (buffer, '\n', bytes_to_write);
2819   if (nlp)
2820     {
2821       /* Found a newline, directly write up to (including) this
2822 	 character.  */
2823       err = flush_stream (stream);
2824       if (!err)
2825 	err = es_write_nbf (stream, buffer, nlp - buffer + 1, &data_flushed);
2826     }
2827 
2828   if (!err)
2829     {
2830       /* Write remaining data fully buffered.  */
2831       err = es_write_fbf (stream, buffer + data_flushed,
2832 			  bytes_to_write - data_flushed, &data_buffered);
2833     }
2834 
2835   *bytes_written = data_flushed + data_buffered;
2836   return err;
2837 }
2838 
2839 
2840 /* Write BYTES_TO_WRITE bytes from BUFFER into STREAM in, storing the
2841    amount of bytes written in BYTES_WRITTEN.  */
2842 static int
es_writen(estream_t _GPGRT__RESTRICT stream,const void * _GPGRT__RESTRICT buffer,size_t bytes_to_write,size_t * _GPGRT__RESTRICT bytes_written)2843 es_writen (estream_t _GPGRT__RESTRICT stream,
2844 	   const void *_GPGRT__RESTRICT buffer,
2845 	   size_t bytes_to_write, size_t *_GPGRT__RESTRICT bytes_written)
2846 {
2847   size_t data_written;
2848   int err;
2849 
2850   data_written = 0;
2851   err = 0;
2852 
2853   if (!stream->flags.writing)
2854     {
2855       /* Switching to writing mode -> discard input data and seek to
2856 	 position at which reading has stopped.  We can do this only
2857 	 if a seek function has been registered. */
2858       if (stream->intern->func_seek)
2859         {
2860           err = es_seek (stream, 0, SEEK_CUR, NULL);
2861           if (err)
2862             {
2863               if (errno == ESPIPE)
2864                 err = 0;
2865               else
2866                 goto out;
2867             }
2868           stream->flags.writing = 1;
2869         }
2870     }
2871 
2872   switch (stream->intern->strategy)
2873     {
2874     case _IONBF:
2875       err = es_write_nbf (stream, buffer, bytes_to_write, &data_written);
2876       break;
2877 
2878     case _IOLBF:
2879       err = es_write_lbf (stream, buffer, bytes_to_write, &data_written);
2880       break;
2881 
2882     case _IOFBF:
2883       err = es_write_fbf (stream, buffer, bytes_to_write, &data_written);
2884       break;
2885     }
2886 
2887  out:
2888 
2889   if (bytes_written)
2890     *bytes_written = data_written;
2891 
2892   return err;
2893 }
2894 
2895 
2896 static int
peek_stream(estream_t _GPGRT__RESTRICT stream,unsigned char ** _GPGRT__RESTRICT data,size_t * _GPGRT__RESTRICT data_len)2897 peek_stream (estream_t _GPGRT__RESTRICT stream,
2898              unsigned char **_GPGRT__RESTRICT data,
2899              size_t *_GPGRT__RESTRICT data_len)
2900 {
2901   int err;
2902 
2903   if (stream->flags.writing)
2904     {
2905       /* Switching to reading mode -> flush output.  */
2906       err = flush_stream (stream);
2907       if (err)
2908 	goto out;
2909       stream->flags.writing = 0;
2910     }
2911 
2912   if (stream->data_offset == stream->data_len)
2913     {
2914       /* Refill container.  */
2915       err = fill_stream (stream);
2916       if (err)
2917 	goto out;
2918     }
2919 
2920   if (data)
2921     *data = stream->buffer + stream->data_offset;
2922   if (data_len)
2923     *data_len = stream->data_len - stream->data_offset;
2924   err = 0;
2925 
2926  out:
2927 
2928   return err;
2929 }
2930 
2931 
2932 /* Skip SIZE bytes of input data contained in buffer.  */
2933 static int
skip_stream(estream_t stream,size_t size)2934 skip_stream (estream_t stream, size_t size)
2935 {
2936   int err;
2937 
2938   if (stream->data_offset + size > stream->data_len)
2939     {
2940       _set_errno (EINVAL);
2941       err = -1;
2942     }
2943   else
2944     {
2945       stream->data_offset += size;
2946       err = 0;
2947     }
2948 
2949   return err;
2950 }
2951 
2952 
2953 static int
doreadline(estream_t _GPGRT__RESTRICT stream,size_t max_length,char * _GPGRT__RESTRICT * _GPGRT__RESTRICT line,size_t * _GPGRT__RESTRICT line_length)2954 doreadline (estream_t _GPGRT__RESTRICT stream, size_t max_length,
2955             char *_GPGRT__RESTRICT *_GPGRT__RESTRICT line,
2956             size_t *_GPGRT__RESTRICT line_length)
2957 {
2958   size_t line_size;
2959   estream_t line_stream;
2960   char *line_new;
2961   void *line_stream_cookie;
2962   char *newline;
2963   unsigned char *data;
2964   size_t data_len;
2965   int err;
2966   es_syshd_t syshd;
2967 
2968   line_new = NULL;
2969   line_stream = NULL;
2970   line_stream_cookie = NULL;
2971 
2972   err = func_mem_create (&line_stream_cookie, NULL, 0, 0,
2973                          BUFFER_BLOCK_SIZE, 1,
2974                          mem_realloc, mem_free,
2975                          O_RDWR,
2976                          0);
2977   if (err)
2978     goto out;
2979 
2980   memset (&syshd, 0, sizeof syshd);
2981   err = create_stream (&line_stream, line_stream_cookie,
2982                        &syshd, BACKEND_MEM,
2983                        estream_functions_mem, O_RDWR, 1, 0);
2984   if (err)
2985     goto out;
2986 
2987   {
2988     size_t space_left = max_length;
2989 
2990     line_size = 0;
2991     for (;;)
2992       {
2993         if (max_length && (space_left == 1))
2994           break;
2995 
2996         err = peek_stream (stream, &data, &data_len);
2997         if (err || (! data_len))
2998           break;
2999 
3000         if (data_len > (space_left - 1))
3001           data_len = space_left - 1;
3002 
3003         newline = memchr (data, '\n', data_len);
3004         if (newline)
3005           {
3006             data_len = (newline - (char *) data) + 1;
3007             err = _gpgrt_write (line_stream, data, data_len, NULL);
3008             if (! err)
3009               {
3010                 /* Not needed: space_left -= data_len */
3011                 line_size += data_len;
3012                 skip_stream (stream, data_len);
3013                 break; /* endless loop */
3014               }
3015           }
3016         else
3017           {
3018             err = _gpgrt_write (line_stream, data, data_len, NULL);
3019             if (! err)
3020               {
3021                 space_left -= data_len;
3022                 line_size += data_len;
3023                 skip_stream (stream, data_len);
3024               }
3025           }
3026         if (err)
3027           break;
3028       }
3029   }
3030   if (err)
3031     goto out;
3032 
3033   /* Complete line has been written to line_stream.  */
3034 
3035   if ((max_length > 1) && (! line_size))
3036     {
3037       stream->intern->indicators.eof = 1;
3038       goto out;
3039     }
3040 
3041   err = es_seek (line_stream, 0, SEEK_SET, NULL);
3042   if (err)
3043     goto out;
3044 
3045   if (! *line)
3046     {
3047       line_new = mem_alloc (line_size + 1);
3048       if (! line_new)
3049 	{
3050 	  err = -1;
3051 	  goto out;
3052 	}
3053     }
3054   else
3055     line_new = *line;
3056 
3057   err = _gpgrt_read (line_stream, line_new, line_size, NULL);
3058   if (err)
3059     goto out;
3060 
3061   line_new[line_size] = '\0';
3062 
3063   if (! *line)
3064     *line = line_new;
3065   if (line_length)
3066     *line_length = line_size;
3067 
3068  out:
3069 
3070   if (line_stream)
3071     do_close (line_stream, 0, 0);
3072   else if (line_stream_cookie)
3073     func_mem_destroy (line_stream_cookie);
3074 
3075   if (err)
3076     {
3077       if (! *line)
3078 	mem_free (line_new);
3079       stream->intern->indicators.err = 1;
3080     }
3081 
3082   return err;
3083 }
3084 
3085 
3086 /* Output function used by estream_format.  */
3087 static int
print_writer(void * outfncarg,const char * buf,size_t buflen)3088 print_writer (void *outfncarg, const char *buf, size_t buflen)
3089 {
3090   estream_t stream = outfncarg;
3091   size_t nwritten;
3092   int rc;
3093 
3094   nwritten = 0;
3095   rc = es_writen (stream, buf, buflen, &nwritten);
3096   stream->intern->print_ntotal += nwritten;
3097   return rc;
3098 }
3099 
3100 
3101 /* The core of our printf function.  This is called in locked state. */
3102 static int
do_print_stream(estream_t _GPGRT__RESTRICT stream,gpgrt_string_filter_t sf,void * sfvalue,const char * _GPGRT__RESTRICT format,va_list ap)3103 do_print_stream (estream_t _GPGRT__RESTRICT stream,
3104                  gpgrt_string_filter_t sf, void *sfvalue,
3105                  const char *_GPGRT__RESTRICT format, va_list ap)
3106 {
3107   int rc;
3108 
3109   stream->intern->print_ntotal = 0;
3110   rc = _gpgrt_estream_format (print_writer, stream, sf, sfvalue, format, ap);
3111   if (rc)
3112     return -1;
3113   return (int)stream->intern->print_ntotal;
3114 }
3115 
3116 
3117 static int
es_set_buffering(estream_t _GPGRT__RESTRICT stream,char * _GPGRT__RESTRICT buffer,int mode,size_t size)3118 es_set_buffering (estream_t _GPGRT__RESTRICT stream,
3119 		  char *_GPGRT__RESTRICT buffer, int mode, size_t size)
3120 {
3121   int err;
3122 
3123   /* Flush or empty buffer depending on mode.  */
3124   if (stream->flags.writing)
3125     {
3126       err = flush_stream (stream);
3127       if (err)
3128 	goto out;
3129     }
3130   else
3131     es_empty (stream);
3132 
3133   stream->intern->indicators.eof = 0;
3134 
3135   /* Free old buffer in case that was allocated by this function.  */
3136   if (stream->intern->deallocate_buffer)
3137     {
3138       stream->intern->deallocate_buffer = 0;
3139       mem_free (stream->buffer);
3140       stream->buffer = NULL;
3141     }
3142 
3143   if (mode == _IONBF)
3144     stream->buffer_size = 0;
3145   else
3146     {
3147       void *buffer_new;
3148 
3149       if (buffer)
3150 	buffer_new = buffer;
3151       else
3152 	{
3153           if (!size)
3154             size = BUFSIZ;
3155 	  buffer_new = mem_alloc (size);
3156 	  if (! buffer_new)
3157 	    {
3158 	      err = -1;
3159 	      goto out;
3160 	    }
3161 	}
3162 
3163       stream->buffer = buffer_new;
3164       stream->buffer_size = size;
3165       if (! buffer)
3166 	stream->intern->deallocate_buffer = 1;
3167     }
3168   stream->intern->strategy = mode;
3169   err = 0;
3170 
3171  out:
3172 
3173   return err;
3174 }
3175 
3176 
3177 static gpgrt_off_t
es_offset_calculate(estream_t stream)3178 es_offset_calculate (estream_t stream)
3179 {
3180   gpgrt_off_t offset;
3181 
3182   offset = stream->intern->offset + stream->data_offset;
3183   if (offset < stream->unread_data_len)
3184     /* Offset undefined.  */
3185     offset = 0;
3186   else
3187     offset -= stream->unread_data_len;
3188 
3189   return offset;
3190 }
3191 
3192 
3193 static void
es_opaque_ctrl(estream_t _GPGRT__RESTRICT stream,void * _GPGRT__RESTRICT opaque_new,void ** _GPGRT__RESTRICT opaque_old)3194 es_opaque_ctrl (estream_t _GPGRT__RESTRICT stream,
3195                 void *_GPGRT__RESTRICT opaque_new,
3196 		void **_GPGRT__RESTRICT opaque_old)
3197 {
3198   if (opaque_old)
3199     *opaque_old = stream->intern->opaque;
3200   if (opaque_new)
3201     stream->intern->opaque = opaque_new;
3202 }
3203 
3204 
3205 /* API.  */
3206 
3207 estream_t
_gpgrt_fopen(const char * _GPGRT__RESTRICT path,const char * _GPGRT__RESTRICT mode)3208 _gpgrt_fopen (const char *_GPGRT__RESTRICT path,
3209               const char *_GPGRT__RESTRICT mode)
3210 {
3211   unsigned int modeflags, cmode, xmode;
3212   int create_called;
3213   estream_t stream;
3214   void *cookie;
3215   int err;
3216   int fd;
3217   es_syshd_t syshd;
3218 
3219   stream = NULL;
3220   cookie = NULL;
3221   create_called = 0;
3222 
3223   err = parse_mode (mode, &modeflags, &xmode, &cmode);
3224   if (err)
3225     goto out;
3226 
3227   err = func_file_create (&cookie, &fd, path, modeflags, cmode);
3228   if (err)
3229     goto out;
3230 
3231   syshd.type = ES_SYSHD_FD;
3232   syshd.u.fd = fd;
3233   create_called = 1;
3234   err = create_stream (&stream, cookie, &syshd, BACKEND_FD,
3235                        estream_functions_fd, modeflags, xmode, 0);
3236   if (err)
3237     goto out;
3238 
3239   if (stream && path)
3240     fname_set_internal (stream, path, 1);
3241 
3242  out:
3243 
3244   if (err && create_called)
3245     (*estream_functions_fd.public.func_close) (cookie);
3246 
3247   return stream;
3248 }
3249 
3250 
3251 
3252 /* Create a new estream object in memory.  If DATA is not NULL this
3253    buffer will be used as the memory buffer; thus after this functions
3254    returns with the success the the memory at DATA belongs to the new
3255    estream.  The allocated length of DATA is given by DATA_LEN and its
3256    used length by DATA_N.  Usually this is malloced buffer; if a
3257    static buffer is provided, the caller must pass false for GROW and
3258    provide a dummy function for FUNC_FREE.  FUNC_FREE and FUNC_REALLOC
3259    allow the caller to provide custom functions for realloc and free
3260    to be used by the new estream object.  Note that the realloc
3261    function is also used for initial allocation.  If DATA is NULL a
3262    buffer is internally allocated; either using internal function or
3263    those provide by the caller.  It is an error to provide a realloc
3264    function but no free function.  Providing only a free function is
3265    allowed as long as GROW is false.  */
3266 estream_t
_gpgrt_mopen(void * _GPGRT__RESTRICT data,size_t data_n,size_t data_len,unsigned int grow,func_realloc_t func_realloc,func_free_t func_free,const char * _GPGRT__RESTRICT mode)3267 _gpgrt_mopen (void *_GPGRT__RESTRICT data, size_t data_n, size_t data_len,
3268               unsigned int grow,
3269               func_realloc_t func_realloc, func_free_t func_free,
3270               const char *_GPGRT__RESTRICT mode)
3271 {
3272   int create_called = 0;
3273   estream_t stream = NULL;
3274   void *cookie = NULL;
3275   unsigned int modeflags, xmode;
3276   int err;
3277   es_syshd_t syshd;
3278 
3279   err = parse_mode (mode, &modeflags, &xmode, NULL);
3280   if (err)
3281     goto out;
3282 
3283   err = func_mem_create (&cookie, data, data_n, data_len,
3284                          BUFFER_BLOCK_SIZE, grow,
3285                          func_realloc, func_free, modeflags, 0);
3286   if (err)
3287     goto out;
3288 
3289   memset (&syshd, 0, sizeof syshd);
3290   create_called = 1;
3291   err = create_stream (&stream, cookie, &syshd, BACKEND_MEM,
3292                        estream_functions_mem, modeflags, xmode, 0);
3293 
3294  out:
3295 
3296   if (err && create_called)
3297     (*estream_functions_mem.public.func_close) (cookie);
3298 
3299   return stream;
3300 }
3301 
3302 
3303 
3304 estream_t
_gpgrt_fopenmem(size_t memlimit,const char * _GPGRT__RESTRICT mode)3305 _gpgrt_fopenmem (size_t memlimit, const char *_GPGRT__RESTRICT mode)
3306 {
3307   unsigned int modeflags, xmode;
3308   estream_t stream = NULL;
3309   void *cookie = NULL;
3310   es_syshd_t syshd;
3311 
3312   /* Memory streams are always read/write.  We use MODE only to get
3313      the append flag.  */
3314   if (parse_mode (mode, &modeflags, &xmode, NULL))
3315     return NULL;
3316   modeflags |= O_RDWR;
3317 
3318   if (func_mem_create (&cookie, NULL, 0, 0,
3319                        BUFFER_BLOCK_SIZE, 1,
3320                        mem_realloc, mem_free, modeflags,
3321                        memlimit))
3322     return NULL;
3323 
3324   memset (&syshd, 0, sizeof syshd);
3325   if (create_stream (&stream, cookie, &syshd, BACKEND_MEM,
3326                      estream_functions_mem, modeflags, xmode, 0))
3327     (*estream_functions_mem.public.func_close) (cookie);
3328 
3329   return stream;
3330 }
3331 
3332 
3333 /* This is the same as es_fopenmem but intializes the memory with a
3334    copy of (DATA,DATALEN).  The stream is initially set to the
3335    beginning.  If MEMLIMIT is not 0 but shorter than DATALEN it
3336    DATALEN will be used as the value for MEMLIMIT.  */
3337 estream_t
_gpgrt_fopenmem_init(size_t memlimit,const char * _GPGRT__RESTRICT mode,const void * data,size_t datalen)3338 _gpgrt_fopenmem_init (size_t memlimit, const char *_GPGRT__RESTRICT mode,
3339                       const void *data, size_t datalen)
3340 {
3341   estream_t stream;
3342 
3343   if (memlimit && memlimit < datalen)
3344     memlimit = datalen;
3345 
3346   stream = _gpgrt_fopenmem (memlimit, mode);
3347   if (stream && data && datalen)
3348     {
3349       if (es_writen (stream, data, datalen, NULL))
3350         {
3351           int saveerrno = errno;
3352           _gpgrt_fclose (stream);
3353           stream = NULL;
3354           _set_errno (saveerrno);
3355         }
3356       else
3357         {
3358           es_seek (stream, 0L, SEEK_SET, NULL);
3359           stream->intern->indicators.eof = 0;
3360           stream->intern->indicators.err = 0;
3361         }
3362     }
3363   return stream;
3364 }
3365 
3366 
3367 
3368 estream_t
_gpgrt_fopencookie(void * _GPGRT__RESTRICT cookie,const char * _GPGRT__RESTRICT mode,gpgrt_cookie_io_functions_t functions)3369 _gpgrt_fopencookie (void *_GPGRT__RESTRICT cookie,
3370                     const char *_GPGRT__RESTRICT mode,
3371                     gpgrt_cookie_io_functions_t functions)
3372 {
3373   unsigned int modeflags, xmode;
3374   estream_t stream;
3375   int err;
3376   es_syshd_t syshd;
3377   struct cookie_io_functions_s io_functions = { functions, NULL };
3378 
3379   stream = NULL;
3380   modeflags = 0;
3381 
3382   err = parse_mode (mode, &modeflags, &xmode, NULL);
3383   if (err)
3384     goto out;
3385 
3386   memset (&syshd, 0, sizeof syshd);
3387   err = create_stream (&stream, cookie, &syshd, BACKEND_USER, io_functions,
3388                        modeflags, xmode, 0);
3389   if (err)
3390     goto out;
3391 
3392  out:
3393   return stream;
3394 }
3395 
3396 
3397 
3398 static estream_t
do_fdopen(int filedes,const char * mode,int no_close,int with_locked_list)3399 do_fdopen (int filedes, const char *mode, int no_close, int with_locked_list)
3400 {
3401   int create_called = 0;
3402   estream_t stream = NULL;
3403   void *cookie = NULL;
3404   unsigned int modeflags, xmode;
3405   int err;
3406   es_syshd_t syshd;
3407 
3408   err = parse_mode (mode, &modeflags, &xmode, NULL);
3409   if (err)
3410     goto out;
3411   if ((xmode & X_SYSOPEN))
3412     {
3413       /* Not allowed for fdopen.  */
3414       _set_errno (EINVAL);
3415       err = -1;
3416       goto out;
3417     }
3418 
3419   err = func_fd_create (&cookie, filedes, modeflags, no_close);
3420   if (err)
3421     goto out;
3422 
3423   syshd.type = ES_SYSHD_FD;
3424   syshd.u.fd = filedes;
3425   create_called = 1;
3426   err = create_stream (&stream, cookie, &syshd,
3427                        BACKEND_FD, estream_functions_fd,
3428                        modeflags, xmode, with_locked_list);
3429 
3430   if (!err && stream)
3431     {
3432       if ((modeflags & O_NONBLOCK))
3433         err = stream->intern->func_ioctl (cookie, COOKIE_IOCTL_NONBLOCK,
3434                                           "", NULL);
3435     }
3436 
3437  out:
3438   if (err && create_called)
3439     (*estream_functions_fd.public.func_close) (cookie);
3440 
3441   return stream;
3442 }
3443 
3444 estream_t
_gpgrt_fdopen(int filedes,const char * mode)3445 _gpgrt_fdopen (int filedes, const char *mode)
3446 {
3447   return do_fdopen (filedes, mode, 0, 0);
3448 }
3449 
3450 /* A variant of es_fdopen which does not close FILEDES at the end.  */
3451 estream_t
_gpgrt_fdopen_nc(int filedes,const char * mode)3452 _gpgrt_fdopen_nc (int filedes, const char *mode)
3453 {
3454   return do_fdopen (filedes, mode, 1, 0);
3455 }
3456 
3457 
3458 
3459 static estream_t
do_fpopen(FILE * fp,const char * mode,int no_close,int with_locked_list)3460 do_fpopen (FILE *fp, const char *mode, int no_close, int with_locked_list)
3461 {
3462   unsigned int modeflags, cmode, xmode;
3463   int create_called = 0;
3464   estream_t stream = NULL;
3465   void *cookie = NULL;
3466   int err;
3467   es_syshd_t syshd;
3468 
3469   err = parse_mode (mode, &modeflags, &xmode, &cmode);
3470   if (err)
3471     goto out;
3472   if ((xmode & X_SYSOPEN))
3473     {
3474       /* Not allowed for fpopen.  */
3475       _set_errno (EINVAL);
3476       err = -1;
3477       goto out;
3478     }
3479 
3480   if (fp)
3481     fflush (fp);
3482   err = func_fp_create (&cookie, fp, modeflags, no_close);
3483   if (err)
3484     goto out;
3485 
3486   syshd.type = ES_SYSHD_FD;
3487   syshd.u.fd = fp? fileno (fp): -1;
3488   create_called = 1;
3489   err = create_stream (&stream, cookie, &syshd,
3490                        BACKEND_FP, estream_functions_fp,
3491                        modeflags, xmode, with_locked_list);
3492 
3493  out:
3494   if (err && create_called)
3495     (*estream_functions_fp.public.func_close) (cookie);
3496 
3497   return stream;
3498 }
3499 
3500 
3501 /* Create an estream from the stdio stream FP.  This mechanism is
3502    useful in case the stdio streams have special properties and may
3503    not be mixed with fd based functions.  This is for example the case
3504    under Windows where the 3 standard streams are associated with the
3505    console whereas a duped and fd-opened stream of one of this stream
3506    won't be associated with the console.  As this messes things up it
3507    is easier to keep on using the standard I/O stream as a backend for
3508    estream. */
3509 estream_t
_gpgrt_fpopen(FILE * fp,const char * mode)3510 _gpgrt_fpopen (FILE *fp, const char *mode)
3511 {
3512   return do_fpopen (fp, mode, 0, 0);
3513 }
3514 
3515 
3516 /* Same as es_fpopen but does not close  FP at the end.  */
3517 estream_t
_gpgrt_fpopen_nc(FILE * fp,const char * mode)3518 _gpgrt_fpopen_nc (FILE *fp, const char *mode)
3519 {
3520   return do_fpopen (fp, mode, 1, 0);
3521 }
3522 
3523 
3524 
3525 #ifdef HAVE_W32_SYSTEM
3526 estream_t
do_w32open(HANDLE hd,const char * mode,int no_close,int with_locked_list)3527 do_w32open (HANDLE hd, const char *mode,
3528             int no_close, int with_locked_list)
3529 {
3530   unsigned int modeflags, cmode, xmode;
3531   int create_called = 0;
3532   estream_t stream = NULL;
3533   void *cookie = NULL;
3534   int err;
3535   es_syshd_t syshd;
3536 
3537   /* For obvious reasons we ignore sysmode here.  */
3538   err = parse_mode (mode, &modeflags, &xmode, &cmode);
3539   if (err)
3540     goto leave;
3541 
3542   /* If we are pollable we create the function cookie with syscall
3543    * clamp disabled.  This is because functions are called from
3544    * separatre reader and writer threads in w32-stream.  */
3545   err = func_w32_create (&cookie, hd, modeflags,
3546                          no_close, !!(xmode & X_POLLABLE));
3547   if (err)
3548     goto leave;
3549 
3550   syshd.type = ES_SYSHD_HANDLE;
3551   syshd.u.handle = hd;
3552   create_called = 1;
3553   err = create_stream (&stream, cookie, &syshd,
3554                        BACKEND_W32, estream_functions_w32,
3555                        modeflags, xmode, with_locked_list);
3556 
3557  leave:
3558   if (err && create_called)
3559     (*estream_functions_w32.public.func_close) (cookie);
3560 
3561   return stream;
3562 }
3563 #endif /*HAVE_W32_SYSTEM*/
3564 
3565 static estream_t
do_sysopen(es_syshd_t * syshd,const char * mode,int no_close)3566 do_sysopen (es_syshd_t *syshd, const char *mode, int no_close)
3567 {
3568   estream_t stream;
3569 
3570   switch (syshd->type)
3571     {
3572     case ES_SYSHD_FD:
3573     case ES_SYSHD_SOCK:
3574       stream = do_fdopen (syshd->u.fd, mode, no_close, 0);
3575       break;
3576 
3577 #ifdef HAVE_W32_SYSTEM
3578     case ES_SYSHD_HANDLE:
3579       stream = do_w32open (syshd->u.handle, mode, no_close, 0);
3580       break;
3581 #endif
3582 
3583     /* FIXME: Support RVIDs under Wince?  */
3584 
3585     default:
3586       _set_errno (EINVAL);
3587       stream = NULL;
3588     }
3589   return stream;
3590 }
3591 
3592 /* On POSIX systems this function is an alias for es_fdopen.  Under
3593    Windows it uses the bare W32 API and thus a HANDLE instead of a
3594    file descriptor.  */
3595 estream_t
_gpgrt_sysopen(es_syshd_t * syshd,const char * mode)3596 _gpgrt_sysopen (es_syshd_t *syshd, const char *mode)
3597 {
3598   return do_sysopen (syshd, mode, 0);
3599 }
3600 
3601 /* Same as es_sysopen but the handle/fd will not be closed by
3602    es_fclose.  */
3603 estream_t
_gpgrt_sysopen_nc(es_syshd_t * syshd,const char * mode)3604 _gpgrt_sysopen_nc (es_syshd_t *syshd, const char *mode)
3605 {
3606   return do_sysopen (syshd, mode, 1);
3607 }
3608 
3609 
3610 
3611 /* Set custom standard descriptors to be used for stdin, stdout and
3612    stderr.  This function needs to be called before any of the
3613    standard streams are accessed.  This internal version uses a double
3614    dash inside its name. */
3615 void
_gpgrt__set_std_fd(int no,int fd)3616 _gpgrt__set_std_fd (int no, int fd)
3617 {
3618   /* fprintf (stderr, "es_set_std_fd(%d, %d)\n", no, fd); */
3619   lock_list ();
3620   if (no >= 0 && no < 3 && !custom_std_fds_valid[no])
3621     {
3622       custom_std_fds[no] = fd;
3623       custom_std_fds_valid[no] = 1;
3624     }
3625   unlock_list ();
3626 }
3627 
3628 
3629 /* Return the stream used for stdin, stdout or stderr.
3630    This internal version uses a double dash inside its name. */
3631 estream_t
_gpgrt__get_std_stream(int fd)3632 _gpgrt__get_std_stream (int fd)
3633 {
3634   estream_list_t list_obj;
3635   estream_t stream = NULL;
3636 
3637   fd %= 3; /* We only allow 0, 1 or 2 but we don't want to return an error. */
3638 
3639   lock_list ();
3640 
3641   for (list_obj = estream_list; list_obj; list_obj = list_obj->next)
3642     if (list_obj->stream && list_obj->stream->intern->is_stdstream
3643         && list_obj->stream->intern->stdstream_fd == fd)
3644       {
3645 	stream = list_obj->stream;
3646 	break;
3647       }
3648   if (!stream)
3649     {
3650       /* Standard stream not yet created.  We first try to create them
3651          from registered file descriptors.  */
3652       if (!fd && custom_std_fds_valid[0])
3653         stream = do_fdopen (custom_std_fds[0], "r", 1, 1);
3654       else if (fd == 1 && custom_std_fds_valid[1])
3655         stream = do_fdopen (custom_std_fds[1], "a", 1, 1);
3656       else if (custom_std_fds_valid[2])
3657         stream = do_fdopen (custom_std_fds[2], "a", 1, 1);
3658 
3659       if (!stream)
3660         {
3661           /* Second try is to use the standard C streams.  */
3662           if (!fd)
3663             stream = do_fpopen (stdin, "r", 1, 1);
3664           else if (fd == 1)
3665             stream = do_fpopen (stdout, "a", 1, 1);
3666           else
3667             stream = do_fpopen (stderr, "a", 1, 1);
3668         }
3669 
3670       if (!stream)
3671         {
3672           /* Last try: Create a bit bucket.  */
3673           stream = do_fpopen (NULL, fd? "a":"r", 0, 1);
3674           if (!stream)
3675             {
3676               fprintf (stderr, "fatal: error creating a dummy estream"
3677                        " for %d: %s\n", fd, strerror (errno));
3678               _gpgrt_abort();
3679             }
3680         }
3681 
3682       stream->intern->is_stdstream = 1;
3683       stream->intern->stdstream_fd = fd;
3684       if (fd == 2)
3685         es_set_buffering (stream, NULL, _IOLBF, 0);
3686       fname_set_internal (stream,
3687                           fd == 0? "[stdin]" :
3688                           fd == 1? "[stdout]" : "[stderr]", 0);
3689     }
3690 
3691   unlock_list ();
3692   return stream;
3693 }
3694 
3695 /* Note: A "samethread" keyword given in "mode" is ignored and the
3696  * value used by STREAM is used instead.  Note that this function is
3697  * the reasons why some of the init and deinit code is split up into
3698  * several functions.  */
3699 estream_t
_gpgrt_freopen(const char * _GPGRT__RESTRICT path,const char * _GPGRT__RESTRICT mode,estream_t _GPGRT__RESTRICT stream)3700 _gpgrt_freopen (const char *_GPGRT__RESTRICT path,
3701                 const char *_GPGRT__RESTRICT mode,
3702                 estream_t _GPGRT__RESTRICT stream)
3703 {
3704   int err;
3705 
3706   if (path)
3707     {
3708       unsigned int modeflags, cmode, xmode, dummy;
3709       int create_called;
3710       void *cookie;
3711       int fd;
3712       es_syshd_t syshd;
3713 
3714       cookie = NULL;
3715       create_called = 0;
3716 
3717       xmode = stream->intern->samethread ? X_SAMETHREAD : 0;
3718 
3719       lock_stream (stream);
3720 
3721       deinit_stream_obj (stream);
3722 
3723       err = parse_mode (mode, &modeflags, &dummy, &cmode);
3724       if (err)
3725 	goto leave;
3726       (void)dummy;
3727 
3728       err = func_file_create (&cookie, &fd, path, modeflags, cmode);
3729       if (err)
3730 	goto leave;
3731 
3732       syshd.type = ES_SYSHD_FD;
3733       syshd.u.fd = fd;
3734       create_called = 1;
3735       init_stream_obj (stream, cookie, &syshd, BACKEND_FD,
3736                        estream_functions_fd, modeflags, xmode);
3737 
3738     leave:
3739 
3740       if (err)
3741 	{
3742 	  if (create_called)
3743 	    func_fd_destroy (cookie);
3744 
3745 	  do_close (stream, 0, 0);
3746 	  stream = NULL;
3747 	}
3748       else
3749         {
3750           if (path)
3751             fname_set_internal (stream, path, 1);
3752           unlock_stream (stream);
3753         }
3754     }
3755   else
3756     {
3757       /* FIXME?  We don't support re-opening at the moment.  */
3758       _set_errno (EINVAL);
3759       deinit_stream_obj (stream);
3760       do_close (stream, 0, 0);
3761       stream = NULL;
3762     }
3763 
3764   return stream;
3765 }
3766 
3767 
3768 int
_gpgrt_fclose(estream_t stream)3769 _gpgrt_fclose (estream_t stream)
3770 {
3771   int err;
3772 
3773   err = do_close (stream, 0, 0);
3774 
3775   return err;
3776 }
3777 
3778 
3779 /* gpgrt_fcancel does the same as gpgrt_fclose but tries to avoid
3780  * flushing out any data still held in internal buffers.  It may or
3781  * may not remove a new file created for that stream by the open
3782  * function.  */
3783 int
_gpgrt_fcancel(estream_t stream)3784 _gpgrt_fcancel (estream_t stream)
3785 {
3786   int err;
3787 
3788   err = do_close (stream, 1, 0);
3789 
3790   return err;
3791 }
3792 
3793 
3794 /* This is a special version of es_fclose which can be used with
3795    es_fopenmem to return the memory buffer.  This is feature is useful
3796    to write to a memory buffer using estream.  Note that the function
3797    does not close the stream if the stream does not support snatching
3798    the buffer.  On error NULL is stored at R_BUFFER.  Note that if no
3799    write operation has happened, NULL may also be stored at BUFFER on
3800    success.  The caller needs to release the returned memory using
3801    gpgrt_free.  */
3802 int
_gpgrt_fclose_snatch(estream_t stream,void ** r_buffer,size_t * r_buflen)3803 _gpgrt_fclose_snatch (estream_t stream, void **r_buffer, size_t *r_buflen)
3804 {
3805   int err;
3806 
3807   /* Note: There is no need to lock the stream in a close call.  The
3808      object will be destroyed after the close and thus any other
3809      contender for the lock would work on a closed stream.  */
3810 
3811   if (r_buffer)
3812     {
3813       cookie_ioctl_function_t func_ioctl = stream->intern->func_ioctl;
3814       size_t buflen;
3815 
3816       *r_buffer = NULL;
3817 
3818       if (!func_ioctl)
3819         {
3820           _set_errno (EOPNOTSUPP);
3821           err = -1;
3822           goto leave;
3823         }
3824 
3825       if (stream->flags.writing)
3826         {
3827           err = flush_stream (stream);
3828           if (err)
3829             goto leave;
3830           stream->flags.writing = 0;
3831         }
3832 
3833       err = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_SNATCH_BUFFER,
3834                         r_buffer, &buflen);
3835       if (err)
3836         goto leave;
3837       if (r_buflen)
3838         *r_buflen = buflen;
3839     }
3840 
3841   err = do_close (stream, 0, 0);
3842 
3843  leave:
3844   if (err && r_buffer)
3845     {
3846       mem_free (*r_buffer);
3847       *r_buffer = NULL;
3848     }
3849   return err;
3850 }
3851 
3852 
3853 /* Register or unregister a close notification function for STREAM.
3854    FNC is the function to call and FNC_VALUE the value passed as
3855    second argument.  To register the notification the value for MODE
3856    must be 1.  If mode is 0 the function tries to remove or disable an
3857    already registered notification; for this to work the value of FNC
3858    and FNC_VALUE must be the same as with the registration and
3859    FNC_VALUE must be a unique value.  No error will be returned if
3860    MODE is 0.
3861 
3862    FIXME: I think the next comment is not anymore correct:
3863    Unregister should only be used in the error case because it may not
3864    be able to remove memory internally allocated for the onclose
3865    handler.
3866 
3867    FIXME: Unregister is not thread safe.
3868 
3869    The notification will be called right before the stream is
3870    closed. If gpgrt_fcancel is used, the cancellation of internal
3871    buffers is done before the notifications.  The notification handler
3872    may not call any estream function for STREAM, neither direct nor
3873    indirectly. */
3874 int
_gpgrt_onclose(estream_t stream,int mode,void (* fnc)(estream_t,void *),void * fnc_value)3875 _gpgrt_onclose (estream_t stream, int mode,
3876                 void (*fnc) (estream_t, void*), void *fnc_value)
3877 {
3878   int err;
3879 
3880   lock_stream (stream);
3881   err = do_onclose (stream, mode, fnc, fnc_value);
3882   unlock_stream (stream);
3883 
3884   return err;
3885 }
3886 
3887 
3888 int
_gpgrt_fileno_unlocked(estream_t stream)3889 _gpgrt_fileno_unlocked (estream_t stream)
3890 {
3891   es_syshd_t syshd;
3892 
3893   if (_gpgrt_syshd_unlocked (stream, &syshd))
3894     return -1;
3895   switch (syshd.type)
3896     {
3897     case ES_SYSHD_FD:   return syshd.u.fd;
3898     case ES_SYSHD_SOCK: return syshd.u.sock;
3899     default:
3900       _set_errno (EINVAL);
3901       return -1;
3902     }
3903 }
3904 
3905 
3906 /* Return the handle of a stream which has been opened by es_sysopen.
3907    The caller needs to pass a structure which will be filled with the
3908    sys handle.  Return 0 on success or true on error and sets errno.
3909    This is the unlocked version.  */
3910 int
_gpgrt_syshd_unlocked(estream_t stream,es_syshd_t * syshd)3911 _gpgrt_syshd_unlocked (estream_t stream, es_syshd_t *syshd)
3912 {
3913   if (!stream || !syshd || stream->intern->syshd.type == ES_SYSHD_NONE)
3914     {
3915       if (syshd)
3916         syshd->type = ES_SYSHD_NONE;
3917       _set_errno (EINVAL);
3918       return -1;
3919     }
3920 
3921   *syshd = stream->intern->syshd;
3922   return 0;
3923 }
3924 
3925 
3926 void
_gpgrt_flockfile(estream_t stream)3927 _gpgrt_flockfile (estream_t stream)
3928 {
3929   lock_stream (stream);
3930 }
3931 
3932 
3933 int
_gpgrt_ftrylockfile(estream_t stream)3934 _gpgrt_ftrylockfile (estream_t stream)
3935 {
3936   return trylock_stream (stream);
3937 }
3938 
3939 
3940 void
_gpgrt_funlockfile(estream_t stream)3941 _gpgrt_funlockfile (estream_t stream)
3942 {
3943   unlock_stream (stream);
3944 }
3945 
3946 
3947 int
_gpgrt_fileno(estream_t stream)3948 _gpgrt_fileno (estream_t stream)
3949 {
3950   int ret;
3951 
3952   lock_stream (stream);
3953   ret = _gpgrt_fileno_unlocked (stream);
3954   unlock_stream (stream);
3955 
3956   return ret;
3957 }
3958 
3959 
3960 /* Return the handle of a stream which has been opened by es_sysopen.
3961    The caller needs to pass a structure which will be filled with the
3962    sys handle.  Return 0 on success or true on error and sets errno.
3963    This is the unlocked version.  */
3964 int
_gpgrt_syshd(estream_t stream,es_syshd_t * syshd)3965 _gpgrt_syshd (estream_t stream, es_syshd_t *syshd)
3966 {
3967   int ret;
3968 
3969   lock_stream (stream);
3970   ret = _gpgrt_syshd_unlocked (stream, syshd);
3971   unlock_stream (stream);
3972 
3973   return ret;
3974 }
3975 
3976 
3977 int
_gpgrt__pending_unlocked(estream_t stream)3978 _gpgrt__pending_unlocked (estream_t stream)
3979 {
3980   return check_pending (stream);
3981 }
3982 
3983 
3984 /* Return true if there is at least one byte pending for read on
3985    STREAM.  This does only work if the backend supports checking for
3986    pending bytes and is thus mostly useful with cookie based backends.
3987 
3988    Note that if this function is used with cookie based functions, the
3989    read cookie may be called with 0 for the SIZE argument.  If bytes
3990    are pending the function is expected to return -1 in this case and
3991    thus deviates from the standard behavior of read(2).   */
3992 int
_gpgrt__pending(estream_t stream)3993 _gpgrt__pending (estream_t stream)
3994 {
3995   int ret;
3996 
3997   lock_stream (stream);
3998   ret = _gpgrt__pending_unlocked (stream);
3999   unlock_stream (stream);
4000 
4001   return ret;
4002 }
4003 
4004 
4005 int
_gpgrt_feof_unlocked(estream_t stream)4006 _gpgrt_feof_unlocked (estream_t stream)
4007 {
4008   return stream->intern->indicators.eof;
4009 }
4010 
4011 
4012 int
_gpgrt_feof(estream_t stream)4013 _gpgrt_feof (estream_t stream)
4014 {
4015   int ret;
4016 
4017   lock_stream (stream);
4018   ret = _gpgrt_feof_unlocked (stream);
4019   unlock_stream (stream);
4020 
4021   return ret;
4022 }
4023 
4024 
4025 int
_gpgrt_ferror_unlocked(estream_t stream)4026 _gpgrt_ferror_unlocked (estream_t stream)
4027 {
4028   return stream->intern->indicators.err;
4029 }
4030 
4031 
4032 int
_gpgrt_ferror(estream_t stream)4033 _gpgrt_ferror (estream_t stream)
4034 {
4035   int ret;
4036 
4037   lock_stream (stream);
4038   ret = _gpgrt_ferror_unlocked (stream);
4039   unlock_stream (stream);
4040 
4041   return ret;
4042 }
4043 
4044 
4045 void
_gpgrt_clearerr_unlocked(estream_t stream)4046 _gpgrt_clearerr_unlocked (estream_t stream)
4047 {
4048   stream->intern->indicators.eof = 0;
4049   stream->intern->indicators.err = 0;
4050   /* We do not reset the HUP indicator because there is no way to
4051      get out of this state.  */
4052 }
4053 
4054 
4055 void
_gpgrt_clearerr(estream_t stream)4056 _gpgrt_clearerr (estream_t stream)
4057 {
4058   lock_stream (stream);
4059   _gpgrt_clearerr_unlocked (stream);
4060   unlock_stream (stream);
4061 }
4062 
4063 
4064 static int
do_fflush(estream_t stream)4065 do_fflush (estream_t stream)
4066 {
4067   int err;
4068 
4069   if (stream->flags.writing)
4070     err = flush_stream (stream);
4071   else
4072     {
4073       es_empty (stream);
4074       err = 0;
4075     }
4076 
4077   return err;
4078 }
4079 
4080 
4081 int
_gpgrt_fflush(estream_t stream)4082 _gpgrt_fflush (estream_t stream)
4083 {
4084   int err;
4085 
4086   if (stream)
4087     {
4088       lock_stream (stream);
4089       err = do_fflush (stream);
4090       unlock_stream (stream);
4091     }
4092   else
4093     {
4094       estream_list_t item;
4095 
4096       err = 0;
4097       lock_list ();
4098       for (item = estream_list; item; item = item->next)
4099         if (item->stream)
4100           {
4101             lock_stream (item->stream);
4102             err |= do_fflush (item->stream);
4103             unlock_stream (item->stream);
4104           }
4105       unlock_list ();
4106     }
4107   return err ? EOF : 0;
4108 }
4109 
4110 
4111 int
_gpgrt_fseek(estream_t stream,long int offset,int whence)4112 _gpgrt_fseek (estream_t stream, long int offset, int whence)
4113 {
4114   int err;
4115 
4116   lock_stream (stream);
4117   err = es_seek (stream, offset, whence, NULL);
4118   unlock_stream (stream);
4119 
4120   return err;
4121 }
4122 
4123 
4124 int
_gpgrt_fseeko(estream_t stream,gpgrt_off_t offset,int whence)4125 _gpgrt_fseeko (estream_t stream, gpgrt_off_t offset, int whence)
4126 {
4127   int err;
4128 
4129   lock_stream (stream);
4130   err = es_seek (stream, offset, whence, NULL);
4131   unlock_stream (stream);
4132 
4133   return err;
4134 }
4135 
4136 
4137 long int
_gpgrt_ftell(estream_t stream)4138 _gpgrt_ftell (estream_t stream)
4139 {
4140   long int ret;
4141 
4142   lock_stream (stream);
4143   ret = es_offset_calculate (stream);
4144   unlock_stream (stream);
4145 
4146   return ret;
4147 }
4148 
4149 
4150 gpgrt_off_t
_gpgrt_ftello(estream_t stream)4151 _gpgrt_ftello (estream_t stream)
4152 {
4153   gpgrt_off_t ret = -1;
4154 
4155   lock_stream (stream);
4156   ret = es_offset_calculate (stream);
4157   unlock_stream (stream);
4158 
4159   return ret;
4160 }
4161 
4162 
4163 void
_gpgrt_rewind(estream_t stream)4164 _gpgrt_rewind (estream_t stream)
4165 {
4166   lock_stream (stream);
4167   es_seek (stream, 0L, SEEK_SET, NULL);
4168   /* Note that es_seek already cleared the EOF flag.  */
4169   stream->intern->indicators.err = 0;
4170   unlock_stream (stream);
4171 }
4172 
4173 
4174 int
_gpgrt_ftruncate(estream_t stream,gpgrt_off_t length)4175 _gpgrt_ftruncate (estream_t stream, gpgrt_off_t length)
4176 {
4177   cookie_ioctl_function_t func_ioctl;
4178   int ret;
4179 
4180   lock_stream (stream);
4181   func_ioctl = stream->intern->func_ioctl;
4182   if (!func_ioctl)
4183     {
4184       _set_errno (EOPNOTSUPP);
4185       ret = -1;
4186     }
4187   else
4188     {
4189       ret = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_TRUNCATE,
4190                         &length, NULL);
4191     }
4192   unlock_stream (stream);
4193   return ret;
4194 }
4195 
4196 
4197 int
_gpgrt__getc_underflow(estream_t stream)4198 _gpgrt__getc_underflow (estream_t stream)
4199 {
4200   int err;
4201   unsigned char c;
4202   size_t bytes_read;
4203 
4204   err = es_readn (stream, &c, 1, &bytes_read);
4205 
4206   return (err || (! bytes_read)) ? EOF : c;
4207 }
4208 
4209 
4210 int
_gpgrt__putc_overflow(int c,estream_t stream)4211 _gpgrt__putc_overflow (int c, estream_t stream)
4212 {
4213   unsigned char d = c;
4214   int err;
4215 
4216   err = es_writen (stream, &d, 1, NULL);
4217 
4218   return err ? EOF : c;
4219 }
4220 
4221 
4222 int
_gpgrt_fgetc(estream_t stream)4223 _gpgrt_fgetc (estream_t stream)
4224 {
4225   int ret;
4226 
4227   lock_stream (stream);
4228   ret = _gpgrt_getc_unlocked (stream);
4229   unlock_stream (stream);
4230 
4231   return ret;
4232 }
4233 
4234 
4235 int
_gpgrt_fputc(int c,estream_t stream)4236 _gpgrt_fputc (int c, estream_t stream)
4237 {
4238   int ret;
4239 
4240   lock_stream (stream);
4241   ret = _gpgrt_putc_unlocked (c, stream);
4242   unlock_stream (stream);
4243 
4244   return ret;
4245 }
4246 
4247 
4248 int
_gpgrt_ungetc(int c,estream_t stream)4249 _gpgrt_ungetc (int c, estream_t stream)
4250 {
4251   unsigned char data = (unsigned char) c;
4252   size_t data_unread;
4253 
4254   lock_stream (stream);
4255   es_unreadn (stream, &data, 1, &data_unread);
4256   unlock_stream (stream);
4257 
4258   return data_unread ? c : EOF;
4259 }
4260 
4261 
4262 int
_gpgrt_read(estream_t _GPGRT__RESTRICT stream,void * _GPGRT__RESTRICT buffer,size_t bytes_to_read,size_t * _GPGRT__RESTRICT bytes_read)4263 _gpgrt_read (estream_t _GPGRT__RESTRICT stream,
4264              void *_GPGRT__RESTRICT buffer, size_t bytes_to_read,
4265              size_t *_GPGRT__RESTRICT bytes_read)
4266 {
4267   int err;
4268 
4269   if (bytes_to_read)
4270     {
4271       lock_stream (stream);
4272       err = es_readn (stream, buffer, bytes_to_read, bytes_read);
4273       unlock_stream (stream);
4274     }
4275   else
4276     err = 0;
4277 
4278   return err;
4279 }
4280 
4281 
4282 int
_gpgrt_write(estream_t _GPGRT__RESTRICT stream,const void * _GPGRT__RESTRICT buffer,size_t bytes_to_write,size_t * _GPGRT__RESTRICT bytes_written)4283 _gpgrt_write (estream_t _GPGRT__RESTRICT stream,
4284               const void *_GPGRT__RESTRICT buffer, size_t bytes_to_write,
4285               size_t *_GPGRT__RESTRICT bytes_written)
4286 {
4287   int err;
4288 
4289   if (bytes_to_write)
4290     {
4291       lock_stream (stream);
4292       err = es_writen (stream, buffer, bytes_to_write, bytes_written);
4293       unlock_stream (stream);
4294     }
4295   else
4296     err = 0;
4297 
4298   return err;
4299 }
4300 
4301 
4302 size_t
_gpgrt_fread(void * _GPGRT__RESTRICT ptr,size_t size,size_t nitems,estream_t _GPGRT__RESTRICT stream)4303 _gpgrt_fread (void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems,
4304               estream_t _GPGRT__RESTRICT stream)
4305 {
4306   size_t ret, bytes;
4307 
4308   if (size && nitems)
4309     {
4310       lock_stream (stream);
4311       es_readn (stream, ptr, size * nitems, &bytes);
4312       unlock_stream (stream);
4313 
4314       ret = bytes / size;
4315     }
4316   else
4317     ret = 0;
4318 
4319   return ret;
4320 }
4321 
4322 
4323 size_t
_gpgrt_fwrite(const void * _GPGRT__RESTRICT ptr,size_t size,size_t nitems,estream_t _GPGRT__RESTRICT stream)4324 _gpgrt_fwrite (const void *_GPGRT__RESTRICT ptr, size_t size, size_t nitems,
4325                estream_t _GPGRT__RESTRICT stream)
4326 {
4327   size_t ret, bytes;
4328 
4329   if (size && nitems)
4330     {
4331       lock_stream (stream);
4332       es_writen (stream, ptr, size * nitems, &bytes);
4333       unlock_stream (stream);
4334 
4335       ret = bytes / size;
4336     }
4337   else
4338     ret = 0;
4339 
4340   return ret;
4341 }
4342 
4343 
4344 char *
_gpgrt_fgets(char * _GPGRT__RESTRICT buffer,int length,estream_t _GPGRT__RESTRICT stream)4345 _gpgrt_fgets (char *_GPGRT__RESTRICT buffer, int length,
4346               estream_t _GPGRT__RESTRICT stream)
4347 {
4348   unsigned char *s = (unsigned char*)buffer;
4349   int c;
4350 
4351   if (!length)
4352     return NULL;
4353 
4354   c = EOF;
4355   lock_stream (stream);
4356   while (length > 1 && (c = _gpgrt_getc_unlocked (stream)) != EOF && c != '\n')
4357     {
4358       *s++ = c;
4359       length--;
4360     }
4361   unlock_stream (stream);
4362 
4363   if (c == EOF && s == (unsigned char*)buffer)
4364     return NULL; /* Nothing read.  */
4365 
4366   if (c != EOF && length > 1)
4367     *s++ = c;
4368 
4369   *s = 0;
4370   return buffer;
4371 }
4372 
4373 
4374 int
_gpgrt_fputs_unlocked(const char * _GPGRT__RESTRICT s,estream_t _GPGRT__RESTRICT stream)4375 _gpgrt_fputs_unlocked (const char *_GPGRT__RESTRICT s,
4376                        estream_t _GPGRT__RESTRICT stream)
4377 {
4378   size_t length;
4379   int err;
4380 
4381   length = strlen (s);
4382   err = es_writen (stream, s, length, NULL);
4383   return err ? EOF : 0;
4384 }
4385 
4386 int
_gpgrt_fputs(const char * _GPGRT__RESTRICT s,estream_t _GPGRT__RESTRICT stream)4387 _gpgrt_fputs (const char *_GPGRT__RESTRICT s, estream_t _GPGRT__RESTRICT stream)
4388 {
4389   size_t length;
4390   int err;
4391 
4392   length = strlen (s);
4393   lock_stream (stream);
4394   err = es_writen (stream, s, length, NULL);
4395   unlock_stream (stream);
4396 
4397   return err ? EOF : 0;
4398 }
4399 
4400 
4401 gpgrt_ssize_t
_gpgrt_getline(char * _GPGRT__RESTRICT * _GPGRT__RESTRICT lineptr,size_t * _GPGRT__RESTRICT n,estream_t _GPGRT__RESTRICT stream)4402 _gpgrt_getline (char *_GPGRT__RESTRICT *_GPGRT__RESTRICT lineptr,
4403                 size_t *_GPGRT__RESTRICT n, estream_t _GPGRT__RESTRICT stream)
4404 {
4405   char *line = NULL;
4406   size_t line_n = 0;
4407   int err;
4408 
4409   lock_stream (stream);
4410   err = doreadline (stream, 0, &line, &line_n);
4411   unlock_stream (stream);
4412   if (err)
4413     goto out;
4414 
4415   if (*n)
4416     {
4417       /* Caller wants us to use his buffer.  */
4418 
4419       if (*n < (line_n + 1))
4420 	{
4421 	  /* Provided buffer is too small -> resize.  */
4422 
4423 	  void *p;
4424 
4425 	  p = mem_realloc (*lineptr, line_n + 1);
4426 	  if (! p)
4427 	    err = -1;
4428 	  else
4429 	    {
4430 	      if (*lineptr != p)
4431 		*lineptr = p;
4432 	    }
4433 	}
4434 
4435       if (! err)
4436 	{
4437 	  memcpy (*lineptr, line, line_n + 1);
4438 	  if (*n != line_n)
4439 	    *n = line_n;
4440 	}
4441       mem_free (line);
4442     }
4443   else
4444     {
4445       /* Caller wants new buffers.  */
4446       *lineptr = line;
4447       *n = line_n;
4448     }
4449 
4450  out:
4451 
4452   return err ? err : (gpgrt_ssize_t)line_n;
4453 }
4454 
4455 
4456 
4457 /* Same as fgets() but if the provided buffer is too short a larger
4458    one will be allocated.  This is similar to getline. A line is
4459    considered a byte stream ending in a LF.
4460 
4461    If MAX_LENGTH is not NULL, it shall point to a value with the
4462    maximum allowed allocation.
4463 
4464    Returns the length of the line. EOF is indicated by a line of
4465    length zero. A truncated line is indicated my setting the value at
4466    MAX_LENGTH to 0.  If the returned value is less then 0 not enough
4467    memory was available or another error occurred; ERRNO is then set
4468    accordingly.
4469 
4470    If a line has been truncated, the file pointer is moved forward to
4471    the end of the line so that the next read starts with the next
4472    line.  Note that MAX_LENGTH must be re-initialized in this case.
4473 
4474    The caller initially needs to provide the address of a variable,
4475    initialized to NULL, at ADDR_OF_BUFFER and don't change this value
4476    anymore with the following invocations.  LENGTH_OF_BUFFER should be
4477    the address of a variable, initialized to 0, which is also
4478    maintained by this function.  Thus, both paramaters should be
4479    considered the state of this function.
4480 
4481    Note: The returned buffer is allocated with enough extra space to
4482    allow the caller to append a CR,LF,Nul.  The buffer should be
4483    released using gpgrt_free.
4484  */
4485 gpgrt_ssize_t
_gpgrt_read_line(estream_t stream,char ** addr_of_buffer,size_t * length_of_buffer,size_t * max_length)4486 _gpgrt_read_line (estream_t stream,
4487                   char **addr_of_buffer, size_t *length_of_buffer,
4488                   size_t *max_length)
4489 {
4490   int c;
4491   char  *buffer = *addr_of_buffer;
4492   size_t length = *length_of_buffer;
4493   size_t nbytes = 0;
4494   size_t maxlen = max_length? *max_length : 0;
4495   char *p;
4496 
4497   if (!buffer)
4498     {
4499       /* No buffer given - allocate a new one. */
4500       length = 256;
4501       buffer = mem_alloc (length);
4502       *addr_of_buffer = buffer;
4503       if (!buffer)
4504         {
4505           *length_of_buffer = 0;
4506           if (max_length)
4507             *max_length = 0;
4508           return -1;
4509         }
4510       *length_of_buffer = length;
4511     }
4512 
4513   if (length < 4)
4514     {
4515       /* This should never happen. If it does, the function has been
4516          called with wrong arguments. */
4517       _set_errno (EINVAL);
4518       return -1;
4519     }
4520   length -= 3; /* Reserve 3 bytes for CR,LF,EOL. */
4521 
4522   lock_stream (stream);
4523   p = buffer;
4524   while  ((c = _gpgrt_getc_unlocked (stream)) != EOF)
4525     {
4526       if (nbytes == length)
4527         {
4528           /* Enlarge the buffer. */
4529           if (maxlen && length > maxlen)
4530             {
4531               /* We are beyond our limit: Skip the rest of the line. */
4532               while (c != '\n' && (c=_gpgrt_getc_unlocked (stream)) != EOF)
4533                 ;
4534               *p++ = '\n'; /* Always append a LF (we reserved some space). */
4535               nbytes++;
4536               if (max_length)
4537                 *max_length = 0; /* Indicate truncation. */
4538               break; /* the while loop. */
4539             }
4540           length += 3; /* Adjust for the reserved bytes. */
4541           length += length < 1024? 256 : 1024;
4542           *addr_of_buffer = mem_realloc (buffer, length);
4543           if (!*addr_of_buffer)
4544             {
4545               int save_errno = errno;
4546               mem_free (buffer);
4547               *length_of_buffer = 0;
4548               if (max_length)
4549                 *max_length = 0;
4550               unlock_stream (stream);
4551               _set_errno (save_errno);
4552               return -1;
4553             }
4554           buffer = *addr_of_buffer;
4555           *length_of_buffer = length;
4556           length -= 3;
4557           p = buffer + nbytes;
4558 	}
4559       *p++ = c;
4560       nbytes++;
4561       if (c == '\n')
4562         break;
4563     }
4564   *p = 0; /* Make sure the line is a string. */
4565   unlock_stream (stream);
4566 
4567   return nbytes;
4568 }
4569 
4570 /* Wrapper around free() to match the memory allocation system used by
4571    estream.  Should be used for all buffers returned to the caller by
4572    libestream.  If a custom allocation handler has been set with
4573    gpgrt_set_alloc_func that register function may be used
4574    instead.  This function has been moved to init.c.  */
4575 /* void */
4576 /* _gpgrt_free (void *a) */
4577 /* { */
4578 /*   mem_free (a); */
4579 /* } */
4580 
4581 
4582 int
_gpgrt_vfprintf_unlocked(estream_t _GPGRT__RESTRICT stream,gpgrt_string_filter_t sf,void * sfvalue,const char * _GPGRT__RESTRICT format,va_list ap)4583 _gpgrt_vfprintf_unlocked (estream_t _GPGRT__RESTRICT stream,
4584                           gpgrt_string_filter_t sf, void *sfvalue,
4585                           const char *_GPGRT__RESTRICT format,
4586                           va_list ap)
4587 {
4588   return do_print_stream (stream, sf, sfvalue, format, ap);
4589 }
4590 
4591 
4592 int
_gpgrt_vfprintf(estream_t _GPGRT__RESTRICT stream,gpgrt_string_filter_t sf,void * sfvalue,const char * _GPGRT__RESTRICT format,va_list ap)4593 _gpgrt_vfprintf (estream_t _GPGRT__RESTRICT stream,
4594                  gpgrt_string_filter_t sf, void *sfvalue,
4595                  const char *_GPGRT__RESTRICT format,
4596                  va_list ap)
4597 {
4598   int ret;
4599 
4600   lock_stream (stream);
4601   ret = do_print_stream (stream, sf, sfvalue, format, ap);
4602   unlock_stream (stream);
4603 
4604   return ret;
4605 }
4606 
4607 
4608 int
_gpgrt_fprintf_unlocked(estream_t _GPGRT__RESTRICT stream,const char * _GPGRT__RESTRICT format,...)4609 _gpgrt_fprintf_unlocked (estream_t _GPGRT__RESTRICT stream,
4610                          const char *_GPGRT__RESTRICT format, ...)
4611 {
4612   int ret;
4613 
4614   va_list ap;
4615   va_start (ap, format);
4616   ret = do_print_stream (stream, NULL, NULL, format, ap);
4617   va_end (ap);
4618 
4619   return ret;
4620 }
4621 
4622 
4623 int
_gpgrt_fprintf(estream_t _GPGRT__RESTRICT stream,const char * _GPGRT__RESTRICT format,...)4624 _gpgrt_fprintf (estream_t _GPGRT__RESTRICT stream,
4625                 const char *_GPGRT__RESTRICT format, ...)
4626 {
4627   int ret;
4628 
4629   va_list ap;
4630   va_start (ap, format);
4631   lock_stream (stream);
4632   ret = do_print_stream (stream, NULL, NULL, format, ap);
4633   unlock_stream (stream);
4634   va_end (ap);
4635 
4636   return ret;
4637 }
4638 
4639 
4640 static int
tmpfd(void)4641 tmpfd (void)
4642 {
4643 #ifdef HAVE_W32_SYSTEM
4644   int attempts, n;
4645 #ifdef HAVE_W32CE_SYSTEM
4646   wchar_t buffer[MAX_PATH+9+12+1];
4647 # define mystrlen(a) wcslen (a)
4648   wchar_t *name, *p;
4649 #else
4650   char buffer[MAX_PATH+9+12+1];
4651 # define mystrlen(a) strlen (a)
4652   char *name, *p;
4653 #endif
4654   HANDLE file;
4655   int pid = GetCurrentProcessId ();
4656   unsigned int value;
4657   int i;
4658 
4659   n = GetTempPath (MAX_PATH+1, buffer);
4660   if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
4661     {
4662       _set_errno (ENOENT);
4663       return -1;
4664     }
4665   p = buffer + mystrlen (buffer);
4666 #ifdef HAVE_W32CE_SYSTEM
4667   wcscpy (p, L"_estream");
4668 #else
4669   strcpy (p, "_estream");
4670 #endif
4671   p += 8;
4672   /* We try to create the directory but don't care about an error as
4673      it may already exist and the CreateFile would throw an error
4674      anyway.  */
4675   CreateDirectory (buffer, NULL);
4676   *p++ = '\\';
4677   name = p;
4678   for (attempts=0; attempts < 10; attempts++)
4679     {
4680       p = name;
4681       value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
4682       for (i=0; i < 8; i++)
4683         {
4684           *p++ = tohex (((value >> 28) & 0x0f));
4685           value <<= 4;
4686         }
4687 #ifdef HAVE_W32CE_SYSTEM
4688       wcscpy (p, L".tmp");
4689 #else
4690       strcpy (p, ".tmp");
4691 #endif
4692       file = CreateFile (buffer,
4693                          GENERIC_READ | GENERIC_WRITE,
4694                          0,
4695                          NULL,
4696                          CREATE_NEW,
4697                          FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
4698                          NULL);
4699       if (file != INVALID_HANDLE_VALUE)
4700         {
4701 #ifdef HAVE_W32CE_SYSTEM
4702           int fd = (int)file;
4703 #else
4704           int fd = _open_osfhandle ((intptr_t)file, 0);
4705           if (fd == -1)
4706             {
4707               CloseHandle (file);
4708               return -1;
4709             }
4710 #endif
4711           return fd;
4712         }
4713       Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
4714     }
4715   _set_errno (ENOENT);
4716   return -1;
4717 #else /*!HAVE_W32_SYSTEM*/
4718   FILE *fp;
4719   int fp_fd;
4720   int fd;
4721 
4722   fp = NULL;
4723   fd = -1;
4724 
4725   fp = tmpfile ();
4726   if (! fp)
4727     goto out;
4728 
4729   fp_fd = fileno (fp);
4730   fd = dup (fp_fd);
4731 
4732  out:
4733 
4734   if (fp)
4735     fclose (fp);
4736 
4737   return fd;
4738 #endif /*!HAVE_W32_SYSTEM*/
4739 }
4740 
4741 estream_t
_gpgrt_tmpfile(void)4742 _gpgrt_tmpfile (void)
4743 {
4744   unsigned int modeflags;
4745   int create_called = 0;
4746   estream_t stream = NULL;
4747   void *cookie = NULL;
4748   int err;
4749   int fd;
4750   es_syshd_t syshd;
4751 
4752   modeflags = O_RDWR | O_TRUNC | O_CREAT;
4753 
4754   fd = tmpfd ();
4755   if (fd == -1)
4756     {
4757       err = -1;
4758       goto out;
4759     }
4760 
4761   err = func_fd_create (&cookie, fd, modeflags, 0);
4762   if (err)
4763     goto out;
4764 
4765   syshd.type = ES_SYSHD_FD;
4766   syshd.u.fd = fd;
4767   create_called = 1;
4768   err = create_stream (&stream, cookie, &syshd,
4769                        BACKEND_FD, estream_functions_fd,
4770                        modeflags, 0, 0);
4771 
4772  out:
4773   if (err)
4774     {
4775       if (create_called)
4776 	func_fd_destroy (cookie);
4777       else if (fd != -1)
4778 	close (fd);
4779       stream = NULL;
4780     }
4781 
4782   return stream;
4783 }
4784 
4785 
4786 int
_gpgrt_setvbuf(estream_t _GPGRT__RESTRICT stream,char * _GPGRT__RESTRICT buf,int type,size_t size)4787 _gpgrt_setvbuf (estream_t _GPGRT__RESTRICT stream,
4788                 char *_GPGRT__RESTRICT buf, int type, size_t size)
4789 {
4790   int err;
4791 
4792   if ((type == _IOFBF || type == _IOLBF || type == _IONBF)
4793       && (!buf || size || type == _IONBF))
4794     {
4795       lock_stream (stream);
4796       err = es_set_buffering (stream, buf, type, size);
4797       unlock_stream (stream);
4798     }
4799   else
4800     {
4801       _set_errno (EINVAL);
4802       err = -1;
4803     }
4804 
4805   return err;
4806 }
4807 
4808 
4809 /* Put a stream into binary mode.  This is only needed for the
4810    standard streams if they are to be used in a binary way.  On Unix
4811    systems it is never needed but MSDOS based systems require such a
4812    call.  It needs to be called before any I/O is done on STREAM.  */
4813 void
_gpgrt_set_binary(estream_t stream)4814 _gpgrt_set_binary (estream_t stream)
4815 {
4816   lock_stream (stream);
4817   if (!(stream->intern->modeflags & O_BINARY))
4818     {
4819       stream->intern->modeflags |= O_BINARY;
4820 #ifdef HAVE_DOSISH_SYSTEM
4821       if (stream->intern->func_read == func_fd_read)
4822         {
4823           estream_cookie_fd_t fd_cookie = stream->intern->cookie;
4824 
4825           if (!IS_INVALID_FD (fd_cookie->fd))
4826             setmode (fd_cookie->fd, O_BINARY);
4827         }
4828       else if (stream->intern->func_read == func_fp_read)
4829         {
4830           estream_cookie_fp_t fp_cookie = stream->intern->cookie;
4831 
4832           if (fp_cookie->fp)
4833             setmode (fileno (fp_cookie->fp), O_BINARY);
4834         }
4835 #endif
4836     }
4837   unlock_stream (stream);
4838 }
4839 
4840 
4841 /* Set non-blocking mode for STREAM.  Use true for ONOFF to enable and
4842    false to disable non-blocking mode.  Returns 0 on success or -1 on
4843    error and sets ERRNO.  Note that not all backends support
4844    non-blocking mode.
4845 
4846    In non-blocking mode a system call will not block but return an
4847    error and set errno to EAGAIN.  The estream API always uses EAGAIN
4848    and not EWOULDBLOCK.  If a buffered function like es_fgetc() or
4849    es_fgets() returns an error and both, feof() and ferror() return
4850    false the caller may assume that the error condition was EAGAIN.
4851 
4852    Switching back from non-blocking to blocking may raise problems
4853    with buffering, thus care should be taken.  Although read+write
4854    sockets are supported in theory, switching from write to read may
4855    result into problems because estream may first flush the write
4856    buffers and there is no way to handle that non-blocking (EAGAIN)
4857    case.  Explicit flushing should thus be done before before
4858    switching to read.  */
4859 int
_gpgrt_set_nonblock(estream_t stream,int onoff)4860 _gpgrt_set_nonblock (estream_t stream, int onoff)
4861 {
4862   cookie_ioctl_function_t func_ioctl;
4863   int ret;
4864 
4865   lock_stream (stream);
4866   func_ioctl = stream->intern->func_ioctl;
4867   if (!func_ioctl)
4868     {
4869       _set_errno (EOPNOTSUPP);
4870       ret = -1;
4871     }
4872   else
4873     {
4874       unsigned int save_flags = stream->intern->modeflags;
4875 
4876       if (onoff)
4877         stream->intern->modeflags |= O_NONBLOCK;
4878       else
4879         stream->intern->modeflags &= ~O_NONBLOCK;
4880 
4881       ret = func_ioctl (stream->intern->cookie, COOKIE_IOCTL_NONBLOCK,
4882                         onoff?"":NULL, NULL);
4883       if (ret)
4884         stream->intern->modeflags = save_flags;
4885     }
4886   unlock_stream (stream);
4887   return ret;
4888 }
4889 
4890 
4891 /* Return true if STREAM is in non-blocking mode.  */
4892 int
_gpgrt_get_nonblock(estream_t stream)4893 _gpgrt_get_nonblock (estream_t stream)
4894 {
4895   int ret;
4896 
4897   lock_stream (stream);
4898   ret = !!(stream->intern->modeflags & O_NONBLOCK);
4899   unlock_stream (stream);
4900   return ret;
4901 }
4902 
4903 
4904 /* A version of poll(2) working on estream handles.  Note that not all
4905    estream types work with this function.  In contrast to the standard
4906    poll function the gpgrt_poll_t object uses a set of bit flags
4907    instead of the EVENTS and REVENTS members.  An item with the IGNORE
4908    flag set is entirely ignored.  The TIMEOUT values is given in
4909    milliseconds, a value of -1 waits indefinitely, and a value of 0
4910    returns immediately.
4911 
4912    A positive return value gives the number of fds with new
4913    information.  A return value of 0 indicates a timeout and -1
4914    indicates an error in which case ERRNO is set.  */
4915 int
_gpgrt_poll(gpgrt_poll_t * fds,unsigned int nfds,int timeout)4916 _gpgrt_poll (gpgrt_poll_t *fds, unsigned int nfds, int timeout)
4917 {
4918   gpgrt_poll_t *item;
4919   int count = 0;
4920   int idx;
4921 #ifndef HAVE_W32_SYSTEM
4922 # ifdef HAVE_POLL_H
4923   struct pollfd *poll_fds = NULL;
4924   nfds_t poll_nfds;
4925 # else
4926   fd_set readfds, writefds, exceptfds;
4927   int any_readfd, any_writefd, any_exceptfd;
4928   int max_fd;
4929 #endif
4930   int fd, ret, any;
4931 #endif /*HAVE_W32_SYSTEM*/
4932 
4933   trace (("enter: nfds=%u timeout=%d", nfds, timeout));
4934 
4935   if (!fds)
4936     {
4937       _set_errno (EINVAL);
4938       count = -1;
4939       goto leave;
4940     }
4941 
4942   /* Clear all response fields (even for ignored items).  */
4943   for (item = fds, idx = 0; idx < nfds; item++, idx++)
4944     {
4945       item->got_read = 0;
4946       item->got_write = 0;
4947       item->got_oob = 0;
4948       item->got_rdhup = 0;
4949       item->got_err = 0;
4950       item->got_hup = 0;
4951       item->got_nval = 0;
4952     }
4953 
4954   /* Check for pending reads.  */
4955   for (item = fds, idx = 0; idx < nfds; item++, idx++)
4956     {
4957       if (item->ignore)
4958         continue;
4959       if (!item->want_read)
4960         continue;
4961       if (_gpgrt__pending (item->stream))
4962         {
4963           item->got_read = 1;
4964           count++;
4965         }
4966     }
4967 
4968   /* Check for space in the write buffers.  */
4969   for (item = fds, idx = 0; idx < nfds; item++, idx++)
4970     {
4971       if (item->ignore)
4972         continue;
4973       if (!item->want_write)
4974         continue;
4975       /* FIXME */
4976     }
4977 
4978   if (count)
4979     goto leave;
4980 
4981   /* Now do the real select.  */
4982 #ifdef HAVE_W32_SYSTEM
4983 
4984   _gpgrt_pre_syscall ();
4985   count = _gpgrt_w32_poll (fds, nfds, timeout);
4986   _gpgrt_post_syscall ();
4987 
4988 #else /*!HAVE_W32_SYSTEM*/
4989 # ifdef HAVE_POLL_H
4990   poll_fds = xtrymalloc (sizeof (*poll_fds)*nfds);
4991   if (!poll_fds)
4992     {
4993       count = -1;
4994       goto leave;
4995     }
4996   poll_nfds = 0;
4997   for (item = fds, idx = 0; idx < nfds; item++, idx++)
4998     {
4999       if (item->ignore)
5000         continue;
5001       fd = _gpgrt_fileno (item->stream);
5002       if (fd == -1)
5003         continue;  /* Stream does not support polling.  */
5004 
5005       if (item->want_read || item->want_write || item->want_oob)
5006         {
5007           poll_fds[poll_nfds].fd = fd;
5008           poll_fds[poll_nfds].events = ((item->want_read ? POLLIN : 0)
5009                                         |(item->want_write ? POLLOUT : 0)
5010                                         |(item->want_oob ? POLLPRI : 0));
5011           poll_fds[poll_nfds].revents = 0;
5012           poll_nfds++;
5013         }
5014     }
5015 
5016   _gpgrt_pre_syscall ();
5017   do
5018     ret = poll (poll_fds, poll_nfds, timeout);
5019   while (ret == -1 && (errno == EINTR || errno == EAGAIN));
5020   _gpgrt_post_syscall ();
5021 # else /* !HAVE_POLL_H */
5022   any_readfd = any_writefd = any_exceptfd = 0;
5023   max_fd = 0;
5024   for (item = fds, idx = 0; idx < nfds; item++, idx++)
5025     {
5026       if (item->ignore)
5027         continue;
5028       fd = _gpgrt_fileno (item->stream);
5029       if (fd == -1)
5030         continue;  /* Stream does not support polling.  */
5031 
5032       if (item->want_read)
5033         {
5034           if (!any_readfd)
5035             {
5036               FD_ZERO (&readfds);
5037               any_readfd = 1;
5038             }
5039           FD_SET (fd, &readfds);
5040           if (fd > max_fd)
5041             max_fd = fd;
5042         }
5043       if (item->want_write)
5044         {
5045           if (!any_writefd)
5046             {
5047               FD_ZERO (&writefds);
5048               any_writefd = 1;
5049             }
5050           FD_SET (fd, &writefds);
5051           if (fd > max_fd)
5052             max_fd = fd;
5053         }
5054       if (item->want_oob)
5055         {
5056           if (!any_exceptfd)
5057             {
5058               FD_ZERO (&exceptfds);
5059               any_exceptfd = 1;
5060             }
5061           FD_SET (fd, &exceptfds);
5062           if (fd > max_fd)
5063             max_fd = fd;
5064         }
5065     }
5066 
5067   _gpgrt_pre_syscall ();
5068   do
5069     {
5070       struct timeval timeout_val;
5071 
5072       timeout_val.tv_sec = timeout / 1000;
5073       timeout_val.tv_usec = (timeout % 1000) * 1000;
5074       ret = select (max_fd+1,
5075                     any_readfd?   &readfds   : NULL,
5076                     any_writefd?  &writefds  : NULL,
5077                     any_exceptfd? &exceptfds : NULL,
5078                     timeout == -1 ? NULL : &timeout_val);
5079     }
5080   while (ret == -1 && errno == EINTR);
5081   _gpgrt_post_syscall ();
5082 # endif
5083 
5084   if (ret == -1)
5085     {
5086 # ifdef HAVE_POLL_H
5087       trace_errno (1, ("poll failed: "));
5088 # else
5089       trace_errno (1, ("select failed: "));
5090 # endif
5091       count = -1;
5092       goto leave;
5093     }
5094   if (!ret)
5095     {
5096       /* Timeout.  Note that in this case we can't return got_err for
5097        * an invalid stream.  */
5098       count = 0;
5099       goto leave;
5100     }
5101 
5102 # ifdef HAVE_POLL_H
5103   poll_nfds = 0;
5104   for (item = fds, idx = 0; idx < nfds; item++, idx++)
5105     {
5106       if (item->ignore)
5107         continue;
5108       fd = _gpgrt_fileno (item->stream);
5109       if (fd == -1)
5110         {
5111           item->got_err = 1;  /* Stream does not support polling.  */
5112           count++;
5113           continue;
5114         }
5115 
5116       any = 0;
5117       if (item->stream->intern->indicators.hup)
5118         {
5119           item->got_hup = 1;
5120           any = 1;
5121         }
5122       if (item->want_read && (poll_fds[poll_nfds].revents & (POLLIN|POLLHUP)))
5123         {
5124           item->got_read = 1;
5125           any = 1;
5126         }
5127       if (item->want_write && (poll_fds[poll_nfds].revents & POLLOUT))
5128         {
5129           item->got_write = 1;
5130           any = 1;
5131         }
5132       if (item->want_oob && (poll_fds[poll_nfds].revents & ~(POLLIN|POLLOUT)))
5133         {
5134           item->got_oob = 1;
5135           any = 1;
5136         }
5137 
5138       if (item->want_read || item->want_write || item->want_oob)
5139         poll_nfds++;
5140       if (any)
5141         count++;
5142     }
5143 # else
5144   for (item = fds, idx = 0; idx < nfds; item++, idx++)
5145     {
5146       if (item->ignore)
5147         continue;
5148       fd = _gpgrt_fileno (item->stream);
5149       if (fd == -1)
5150         {
5151           item->got_err = 1;  /* Stream does not support polling.  */
5152           count++;
5153           continue;
5154         }
5155 
5156       any = 0;
5157       if (item->stream->intern->indicators.hup)
5158         {
5159           item->got_hup = 1;
5160           any = 1;
5161         }
5162       if (item->want_read && FD_ISSET (fd, &readfds))
5163         {
5164           item->got_read = 1;
5165           any = 1;
5166         }
5167       if (item->want_write && FD_ISSET (fd, &writefds))
5168         {
5169           item->got_write = 1;
5170           any = 1;
5171         }
5172       if (item->want_oob && FD_ISSET (fd, &exceptfds))
5173         {
5174           item->got_oob = 1;
5175           any = 1;
5176         }
5177 
5178       if (any)
5179         count++;
5180     }
5181 # endif
5182 #endif /*!HAVE_W32_SYSTEM*/
5183 
5184  leave:
5185 #ifndef HAVE_W32_SYSTEM
5186 # ifdef HAVE_POLL_H
5187   xfree (poll_fds);
5188 # endif
5189 #endif
5190 #ifdef ENABLE_TRACING
5191   trace (("leave: count=%d", count));
5192   if (count > 0)
5193     {
5194       for (item = fds, idx = 0; idx < nfds; item++, idx++)
5195         {
5196           trace (("     %3d  %c%c%c%c%c  %c%c%c%c%c%c%c",
5197                   idx,
5198                   fds[idx].want_read?  'r':'-',
5199                   fds[idx].want_write? 'w':'-',
5200                   fds[idx].want_oob?   'o':'-',
5201                   fds[idx].want_rdhup? 'h':'-',
5202                   fds[idx].ignore?     'i':'-',
5203                   fds[idx].got_read?   'r':'-',
5204                   fds[idx].got_write?  'w':'-',
5205                   fds[idx].got_oob?    'o':'-',
5206                   fds[idx].got_rdhup?  'h':'-',
5207                   fds[idx].got_hup?    'H':'-',
5208                   fds[idx].got_err?    'e':'-',
5209                   fds[idx].got_nval?   'n':'-'
5210                   ));
5211         }
5212     }
5213 #endif /*ENABLE_TRACING*/
5214   return count;
5215 }
5216 
5217 
5218 void
_gpgrt_opaque_set(estream_t stream,void * opaque)5219 _gpgrt_opaque_set (estream_t stream, void *opaque)
5220 {
5221   lock_stream (stream);
5222   es_opaque_ctrl (stream, opaque, NULL);
5223   unlock_stream (stream);
5224 }
5225 
5226 
5227 void *
_gpgrt_opaque_get(estream_t stream)5228 _gpgrt_opaque_get (estream_t stream)
5229 {
5230   void *opaque;
5231 
5232   lock_stream (stream);
5233   es_opaque_ctrl (stream, NULL, &opaque);
5234   unlock_stream (stream);
5235 
5236   return opaque;
5237 }
5238 
5239 
5240 static void
fname_set_internal(estream_t stream,const char * fname,int quote)5241 fname_set_internal (estream_t stream, const char *fname, int quote)
5242 {
5243   if (stream->intern->printable_fname
5244       && !stream->intern->printable_fname_inuse)
5245     {
5246       mem_free (stream->intern->printable_fname);
5247       stream->intern->printable_fname = NULL;
5248     }
5249   if (stream->intern->printable_fname)
5250     return; /* Can't change because it is in use.  */
5251 
5252   if (*fname != '[')
5253     quote = 0;
5254   else
5255     quote = !!quote;
5256 
5257   stream->intern->printable_fname = mem_alloc (strlen (fname) + quote + 1);
5258   if (quote)
5259     stream->intern->printable_fname[0] = '\\';
5260   strcpy (stream->intern->printable_fname+quote, fname);
5261 }
5262 
5263 
5264 /* Set the filename attribute of STREAM.  There is no error return.
5265    as long as STREAM is valid.  This function is called internally by
5266    functions which open a filename.  */
5267 void
_gpgrt_fname_set(estream_t stream,const char * fname)5268 _gpgrt_fname_set (estream_t stream, const char *fname)
5269 {
5270   if (fname)
5271     {
5272       lock_stream (stream);
5273       fname_set_internal (stream, fname, 1);
5274       unlock_stream (stream);
5275     }
5276 }
5277 
5278 
5279 /* Return the filename attribute of STREAM.  In case no filename has
5280    been set, "[?]" will be returned.  The returned file name is valid
5281    as long as STREAM is valid.  */
5282 const char *
_gpgrt_fname_get(estream_t stream)5283 _gpgrt_fname_get (estream_t stream)
5284 {
5285   const char *fname;
5286 
5287   lock_stream (stream);
5288   fname = stream->intern->printable_fname;
5289   if (fname)
5290     stream->intern->printable_fname_inuse = 1;
5291   unlock_stream (stream);
5292   if (!fname)
5293     fname = "[?]";
5294   return fname;
5295 }
5296 
5297 
5298 
5299 /* Print a BUFFER to STREAM while replacing all control characters and
5300    the characters in DELIMITERS by standard C escape sequences.
5301    Returns 0 on success or -1 on error.  If BYTES_WRITTEN is not NULL
5302    the number of bytes actually written are stored at this
5303    address.  */
5304 int
_gpgrt_write_sanitized(estream_t _GPGRT__RESTRICT stream,const void * _GPGRT__RESTRICT buffer,size_t length,const char * delimiters,size_t * _GPGRT__RESTRICT bytes_written)5305 _gpgrt_write_sanitized (estream_t _GPGRT__RESTRICT stream,
5306                         const void * _GPGRT__RESTRICT buffer, size_t length,
5307                         const char * delimiters,
5308                         size_t * _GPGRT__RESTRICT bytes_written)
5309 {
5310   const unsigned char *p = buffer;
5311   size_t count = 0;
5312   int ret;
5313 
5314   lock_stream (stream);
5315   for (; length; length--, p++, count++)
5316     {
5317       if (*p < 0x20
5318           || *p == 0x7f
5319           || (delimiters
5320               && (strchr (delimiters, *p) || *p == '\\')))
5321         {
5322           _gpgrt_putc_unlocked ('\\', stream);
5323           count++;
5324           if (*p == '\n')
5325             {
5326               _gpgrt_putc_unlocked ('n', stream);
5327               count++;
5328             }
5329           else if (*p == '\r')
5330             {
5331               _gpgrt_putc_unlocked ('r', stream);
5332               count++;
5333             }
5334           else if (*p == '\f')
5335             {
5336               _gpgrt_putc_unlocked ('f', stream);
5337               count++;
5338             }
5339           else if (*p == '\v')
5340             {
5341               _gpgrt_putc_unlocked ('v', stream);
5342               count++;
5343             }
5344           else if (*p == '\b')
5345             {
5346               _gpgrt_putc_unlocked ('b', stream);
5347               count++;
5348             }
5349           else if (!*p)
5350             {
5351               _gpgrt_putc_unlocked('0', stream);
5352               count++;
5353             }
5354           else
5355             {
5356               _gpgrt_fprintf_unlocked (stream, "x%02x", *p);
5357               count += 3;
5358             }
5359 	}
5360       else
5361         {
5362           _gpgrt_putc_unlocked (*p, stream);
5363           count++;
5364         }
5365     }
5366 
5367   if (bytes_written)
5368     *bytes_written = count;
5369   ret =  _gpgrt_ferror_unlocked (stream)? -1 : 0;
5370   unlock_stream (stream);
5371 
5372   return ret;
5373 }
5374 
5375 
5376 /* Write LENGTH bytes of BUFFER to STREAM as a hex encoded string.
5377    RESERVED must be 0.  Returns 0 on success or -1 on error.  If
5378    BYTES_WRITTEN is not NULL the number of bytes actually written are
5379    stored at this address.  */
5380 int
_gpgrt_write_hexstring(estream_t _GPGRT__RESTRICT stream,const void * _GPGRT__RESTRICT buffer,size_t length,int reserved,size_t * _GPGRT__RESTRICT bytes_written)5381 _gpgrt_write_hexstring (estream_t _GPGRT__RESTRICT stream,
5382                         const void *_GPGRT__RESTRICT buffer, size_t length,
5383                         int reserved, size_t *_GPGRT__RESTRICT bytes_written )
5384 {
5385   int ret;
5386   const unsigned char *s;
5387   size_t count = 0;
5388 
5389   (void)reserved;
5390 
5391 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
5392 
5393   if (!length)
5394     return 0;
5395 
5396   lock_stream (stream);
5397 
5398   for (s = buffer; length; s++, length--)
5399     {
5400       _gpgrt_putc_unlocked ( tohex ((*s>>4)&15), stream);
5401       _gpgrt_putc_unlocked ( tohex (*s&15), stream);
5402       count += 2;
5403     }
5404 
5405   if (bytes_written)
5406     *bytes_written = count;
5407   ret = _gpgrt_ferror_unlocked (stream)? -1 : 0;
5408 
5409   unlock_stream (stream);
5410 
5411   return ret;
5412 
5413 #undef tohex
5414 }
5415