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