Line data Source code
1 : /* iobuf.c - File Handling for OpenPGP.
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008,
3 : * 2009, 2010, 2011 Free Software Foundation, Inc.
4 : * Copyright (C) 2015 g10 Code GmbH
5 : *
6 : * This file is part of GnuPG.
7 : *
8 : * This file is free software; you can redistribute it and/or modify
9 : * it under the terms of either
10 : *
11 : * - the GNU Lesser General Public License as published by the Free
12 : * Software Foundation; either version 3 of the License, or (at
13 : * your option) any later version.
14 : *
15 : * or
16 : *
17 : * - the GNU General Public License as published by the Free
18 : * Software Foundation; either version 2 of the License, or (at
19 : * your option) any later version.
20 : *
21 : * or both in parallel, as here.
22 : *
23 : * This file is distributed in the hope that it will be useful,
24 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 : * GNU General Public License for more details.
27 : *
28 : * You should have received a copy of the GNU General Public License
29 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
30 : */
31 :
32 : #include <config.h>
33 : #include <stdio.h>
34 : #include <stdlib.h>
35 : #include <string.h>
36 : #include <errno.h>
37 : #include <ctype.h>
38 : #include <assert.h>
39 : #include <sys/types.h>
40 : #include <sys/stat.h>
41 : #include <fcntl.h>
42 : #include <unistd.h>
43 : #ifdef HAVE_W32_SYSTEM
44 : # ifdef HAVE_WINSOCK2_H
45 : # include <winsock2.h>
46 : # endif
47 : # include <windows.h>
48 : #endif
49 : #ifdef __riscos__
50 : # include <kernel.h>
51 : # include <swis.h>
52 : #endif /* __riscos__ */
53 :
54 : #include <assuan.h>
55 :
56 : #include "util.h"
57 : #include "sysutils.h"
58 : #include "iobuf.h"
59 :
60 : /*-- Begin configurable part. --*/
61 :
62 : /* The size of the internal buffers.
63 : NOTE: If you change this value you MUST also adjust the regression
64 : test "armored_key_8192" in armor.test! */
65 : #define IOBUF_BUFFER_SIZE 8192
66 :
67 : /* To avoid a potential DoS with compression packets we better limit
68 : the number of filters in a chain. */
69 : #define MAX_NESTING_FILTER 64
70 :
71 : /*-- End configurable part. --*/
72 :
73 :
74 : #ifdef HAVE_W32_SYSTEM
75 : # ifdef HAVE_W32CE_SYSTEM
76 : # define FD_FOR_STDIN (es_fileno (es_stdin))
77 : # define FD_FOR_STDOUT (es_fileno (es_stdout))
78 : # else
79 : # define FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE))
80 : # define FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
81 : # endif
82 : #else /*!HAVE_W32_SYSTEM*/
83 : # define FD_FOR_STDIN (0)
84 : # define FD_FOR_STDOUT (1)
85 : #endif /*!HAVE_W32_SYSTEM*/
86 :
87 :
88 : /* The context used by the file filter. */
89 : typedef struct
90 : {
91 : gnupg_fd_t fp; /* Open file pointer or handle. */
92 : int keep_open;
93 : int no_cache;
94 : int eof_seen;
95 : int print_only_name; /* Flags indicating that fname is not a real file. */
96 : char fname[1]; /* Name of the file. */
97 : } file_filter_ctx_t;
98 :
99 : /* The context used by the estream filter. */
100 : typedef struct
101 : {
102 : estream_t fp; /* Open estream handle. */
103 : int keep_open;
104 : int no_cache;
105 : int eof_seen;
106 : int print_only_name; /* Flags indicating that fname is not a real file. */
107 : char fname[1]; /* Name of the file. */
108 : } file_es_filter_ctx_t;
109 :
110 :
111 : /* Object to control the "close cache". */
112 : struct close_cache_s
113 : {
114 : struct close_cache_s *next;
115 : gnupg_fd_t fp;
116 : char fname[1];
117 : };
118 : typedef struct close_cache_s *close_cache_t;
119 : static close_cache_t close_cache;
120 :
121 :
122 :
123 : #ifdef HAVE_W32_SYSTEM
124 : typedef struct
125 : {
126 : int sock;
127 : int keep_open;
128 : int no_cache;
129 : int eof_seen;
130 : int print_only_name; /* Flag indicating that fname is not a real file. */
131 : char fname[1]; /* Name of the file */
132 :
133 : } sock_filter_ctx_t;
134 : #endif /*HAVE_W32_SYSTEM*/
135 :
136 : /* The first partial length header block must be of size 512 to make
137 : * it easier (and more efficient) we use a min. block size of 512 for
138 : * all chunks (but the last one) */
139 : #define OP_MIN_PARTIAL_CHUNK 512
140 : #define OP_MIN_PARTIAL_CHUNK_2POW 9
141 :
142 : /* The context we use for the block filter (used to handle OpenPGP
143 : length information header). */
144 : typedef struct
145 : {
146 : int use;
147 : size_t size;
148 : size_t count;
149 : int partial; /* 1 = partial header, 2 in last partial packet. */
150 : char *buffer; /* Used for partial header. */
151 : size_t buflen; /* Used size of buffer. */
152 : int first_c; /* First character of a partial header (which is > 0). */
153 : int eof;
154 : }
155 : block_filter_ctx_t;
156 :
157 :
158 : /* Global flag to tell whether special file names are enabled. See
159 : gpg.c for an explanation of these file names. FIXME: This does not
160 : belong in the iobuf subsystem. */
161 : static int special_names_enabled;
162 :
163 : /* Local prototypes. */
164 : static int underflow (iobuf_t a, int clear_pending_eof);
165 : static int underflow_target (iobuf_t a, int clear_pending_eof, size_t target);
166 : static int translate_file_handle (int fd, int for_write);
167 :
168 : /* Sends any pending data to the filter's FILTER function. Note: this
169 : works on the filter and not on the whole pipeline. That is,
170 : iobuf_flush doesn't necessarily cause data to be written to any
171 : underlying file; it just causes any data buffered at the filter A
172 : to be sent to A's filter function.
173 :
174 : If A is a IOBUF_OUTPUT_TEMP filter, then this also enlarges the
175 : buffer by IOBUF_BUFFER_SIZE.
176 :
177 : May only be called on an IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP filters. */
178 : static int filter_flush (iobuf_t a);
179 :
180 :
181 :
182 : /* This is a replacement for strcmp. Under W32 it does not
183 : distinguish between backslash and slash. */
184 : static int
185 483 : fd_cache_strcmp (const char *a, const char *b)
186 : {
187 : #ifdef HAVE_DOSISH_SYSTEM
188 : for (; *a && *b; a++, b++)
189 : {
190 : if (*a != *b && !((*a == '/' && *b == '\\')
191 : || (*a == '\\' && *b == '/')) )
192 : break;
193 : }
194 : return *(const unsigned char *)a - *(const unsigned char *)b;
195 : #else
196 483 : return strcmp (a, b);
197 : #endif
198 : }
199 :
200 : /*
201 : * Invalidate (i.e. close) a cached iobuf
202 : */
203 : static int
204 574 : fd_cache_invalidate (const char *fname)
205 : {
206 : close_cache_t cc;
207 574 : int rc = 0;
208 :
209 574 : assert (fname);
210 574 : if (DBG_IOBUF)
211 0 : log_debug ("fd_cache_invalidate (%s)\n", fname);
212 :
213 856 : for (cc = close_cache; cc; cc = cc->next)
214 : {
215 282 : if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
216 : {
217 39 : if (DBG_IOBUF)
218 0 : log_debug (" did (%s)\n", cc->fname);
219 : #ifdef HAVE_W32_SYSTEM
220 : if (!CloseHandle (cc->fp))
221 : rc = -1;
222 : #else
223 39 : rc = close (cc->fp);
224 : #endif
225 39 : cc->fp = GNUPG_INVALID_FD;
226 : }
227 : }
228 574 : return rc;
229 : }
230 :
231 :
232 : /* Try to sync changes to the disk. This is to avoid data loss during
233 : a system crash in write/close/rename cycle on some file
234 : systems. */
235 : static int
236 0 : fd_cache_synchronize (const char *fname)
237 : {
238 0 : int err = 0;
239 :
240 : #ifdef HAVE_FSYNC
241 : close_cache_t cc;
242 :
243 0 : if (DBG_IOBUF)
244 0 : log_debug ("fd_cache_synchronize (%s)\n", fname);
245 :
246 0 : for (cc=close_cache; cc; cc = cc->next )
247 : {
248 0 : if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
249 : {
250 0 : if (DBG_IOBUF)
251 0 : log_debug (" did (%s)\n", cc->fname);
252 :
253 0 : err = fsync (cc->fp);
254 : }
255 : }
256 : #else
257 : (void)fname;
258 : #endif /*HAVE_FSYNC*/
259 :
260 0 : return err;
261 : }
262 :
263 :
264 : static gnupg_fd_t
265 2055 : direct_open (const char *fname, const char *mode, int mode700)
266 : {
267 : #ifdef HAVE_W32_SYSTEM
268 : unsigned long da, cd, sm;
269 : HANDLE hfile;
270 :
271 : (void)mode700;
272 : /* Note, that we do not handle all mode combinations */
273 :
274 : /* According to the ReactOS source it seems that open() of the
275 : * standard MSW32 crt does open the file in shared mode which is
276 : * something new for MS applications ;-)
277 : */
278 : if (strchr (mode, '+'))
279 : {
280 : if (fd_cache_invalidate (fname))
281 : return GNUPG_INVALID_FD;
282 : da = GENERIC_READ | GENERIC_WRITE;
283 : cd = OPEN_EXISTING;
284 : sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
285 : }
286 : else if (strchr (mode, 'w'))
287 : {
288 : if (fd_cache_invalidate (fname))
289 : return GNUPG_INVALID_FD;
290 : da = GENERIC_WRITE;
291 : cd = CREATE_ALWAYS;
292 : sm = FILE_SHARE_WRITE;
293 : }
294 : else
295 : {
296 : da = GENERIC_READ;
297 : cd = OPEN_EXISTING;
298 : sm = FILE_SHARE_READ;
299 : }
300 :
301 : #ifdef HAVE_W32CE_SYSTEM
302 : {
303 : wchar_t *wfname = utf8_to_wchar (fname);
304 : if (wfname)
305 : {
306 : hfile = CreateFile (wfname, da, sm, NULL, cd,
307 : FILE_ATTRIBUTE_NORMAL, NULL);
308 : xfree (wfname);
309 : }
310 : else
311 : hfile = INVALID_HANDLE_VALUE;
312 : }
313 : #else
314 : hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
315 : #endif
316 : return hfile;
317 :
318 : #else /*!HAVE_W32_SYSTEM*/
319 :
320 : int oflag;
321 2055 : int cflag = S_IRUSR | S_IWUSR;
322 :
323 2055 : if (!mode700)
324 2051 : cflag |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
325 :
326 : /* Note, that we do not handle all mode combinations */
327 2055 : if (strchr (mode, '+'))
328 : {
329 0 : if (fd_cache_invalidate (fname))
330 0 : return GNUPG_INVALID_FD;
331 0 : oflag = O_RDWR;
332 : }
333 2055 : else if (strchr (mode, 'w'))
334 : {
335 531 : if (fd_cache_invalidate (fname))
336 0 : return GNUPG_INVALID_FD;
337 531 : oflag = O_WRONLY | O_CREAT | O_TRUNC;
338 : }
339 : else
340 : {
341 1524 : oflag = O_RDONLY;
342 : }
343 : #ifdef O_BINARY
344 : if (strchr (mode, 'b'))
345 : oflag |= O_BINARY;
346 : #endif
347 :
348 : #ifdef __riscos__
349 : {
350 : struct stat buf;
351 :
352 : /* Don't allow iobufs on directories */
353 : if (!stat (fname, &buf) && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode))
354 : return __set_errno (EISDIR);
355 : }
356 : #endif
357 2055 : return open (fname, oflag, cflag);
358 :
359 : #endif /*!HAVE_W32_SYSTEM*/
360 : }
361 :
362 :
363 : /*
364 : * Instead of closing an FD we keep it open and cache it for later reuse
365 : * Note that this caching strategy only works if the process does not chdir.
366 : */
367 : static void
368 2119 : fd_cache_close (const char *fname, gnupg_fd_t fp)
369 : {
370 : close_cache_t cc;
371 :
372 2119 : assert (fp);
373 2119 : if (!fname || !*fname)
374 : {
375 : #ifdef HAVE_W32_SYSTEM
376 : CloseHandle (fp);
377 : #else
378 937 : close (fp);
379 : #endif
380 937 : if (DBG_IOBUF)
381 0 : log_debug ("fd_cache_close (%d) real\n", (int)fp);
382 937 : return;
383 : }
384 : /* try to reuse a slot */
385 1330 : for (cc = close_cache; cc; cc = cc->next)
386 : {
387 213 : if (cc->fp == GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
388 : {
389 65 : cc->fp = fp;
390 65 : if (DBG_IOBUF)
391 0 : log_debug ("fd_cache_close (%s) used existing slot\n", fname);
392 65 : return;
393 : }
394 : }
395 : /* add a new one */
396 1117 : if (DBG_IOBUF)
397 0 : log_debug ("fd_cache_close (%s) new slot created\n", fname);
398 1117 : cc = xcalloc (1, sizeof *cc + strlen (fname));
399 1117 : strcpy (cc->fname, fname);
400 1117 : cc->fp = fp;
401 1117 : cc->next = close_cache;
402 1117 : close_cache = cc;
403 : }
404 :
405 : /*
406 : * Do a direct_open on FNAME but first try to reuse one from the fd_cache
407 : */
408 : static gnupg_fd_t
409 1588 : fd_cache_open (const char *fname, const char *mode)
410 : {
411 : close_cache_t cc;
412 :
413 1588 : assert (fname);
414 1718 : for (cc = close_cache; cc; cc = cc->next)
415 : {
416 194 : if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
417 : {
418 64 : gnupg_fd_t fp = cc->fp;
419 64 : cc->fp = GNUPG_INVALID_FD;
420 64 : if (DBG_IOBUF)
421 0 : log_debug ("fd_cache_open (%s) using cached fp\n", fname);
422 : #ifdef HAVE_W32_SYSTEM
423 : if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff)
424 : {
425 : log_error ("rewind file failed on handle %p: ec=%d\n",
426 : fp, (int) GetLastError ());
427 : fp = GNUPG_INVALID_FD;
428 : }
429 : #else
430 64 : if (lseek (fp, 0, SEEK_SET) == (off_t) - 1)
431 : {
432 0 : log_error ("can't rewind fd %d: %s\n", fp, strerror (errno));
433 0 : fp = GNUPG_INVALID_FD;
434 : }
435 : #endif
436 64 : return fp;
437 : }
438 : }
439 1524 : if (DBG_IOBUF)
440 0 : log_debug ("fd_cache_open (%s) not cached\n", fname);
441 1524 : return direct_open (fname, mode, 0);
442 : }
443 :
444 :
445 : static int
446 12046 : file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
447 : size_t * ret_len)
448 : {
449 12046 : file_filter_ctx_t *a = opaque;
450 12046 : gnupg_fd_t f = a->fp;
451 12046 : size_t size = *ret_len;
452 12046 : size_t nbytes = 0;
453 12046 : int rc = 0;
454 :
455 : (void)chain; /* Not used. */
456 :
457 12046 : if (control == IOBUFCTRL_UNDERFLOW)
458 : {
459 4857 : assert (size); /* We need a buffer. */
460 4857 : if (a->eof_seen)
461 : {
462 0 : rc = -1;
463 0 : *ret_len = 0;
464 : }
465 : else
466 : {
467 : #ifdef HAVE_W32_SYSTEM
468 : unsigned long nread;
469 :
470 : nbytes = 0;
471 : if (!ReadFile (f, buf, size, &nread, NULL))
472 : {
473 : int ec = (int) GetLastError ();
474 : if (ec != ERROR_BROKEN_PIPE)
475 : {
476 : rc = gpg_error_from_errno (ec);
477 : log_error ("%s: read error: ec=%d\n", a->fname, ec);
478 : }
479 : }
480 : else if (!nread)
481 : {
482 : a->eof_seen = 1;
483 : rc = -1;
484 : }
485 : else
486 : {
487 : nbytes = nread;
488 : }
489 :
490 : #else
491 :
492 : int n;
493 :
494 4857 : nbytes = 0;
495 : do
496 : {
497 4857 : n = read (f, buf, size);
498 : }
499 4857 : while (n == -1 && errno == EINTR);
500 4857 : if (n == -1)
501 : { /* error */
502 0 : if (errno != EPIPE)
503 : {
504 0 : rc = gpg_error_from_syserror ();
505 0 : log_error ("%s: read error: %s\n",
506 0 : a->fname, strerror (errno));
507 : }
508 : }
509 4857 : else if (!n)
510 : { /* eof */
511 1323 : a->eof_seen = 1;
512 1323 : rc = -1;
513 : }
514 : else
515 : {
516 3534 : nbytes = n;
517 : }
518 : #endif
519 4857 : *ret_len = nbytes;
520 : }
521 : }
522 7189 : else if (control == IOBUFCTRL_FLUSH)
523 : {
524 2463 : if (size)
525 : {
526 : #ifdef HAVE_W32_SYSTEM
527 : byte *p = buf;
528 : unsigned long n;
529 :
530 : nbytes = size;
531 : do
532 : {
533 : if (size && !WriteFile (f, p, nbytes, &n, NULL))
534 : {
535 : int ec = (int) GetLastError ();
536 : rc = gpg_error_from_errno (ec);
537 : log_error ("%s: write error: ec=%d\n", a->fname, ec);
538 : break;
539 : }
540 : p += n;
541 : nbytes -= n;
542 : }
543 : while (nbytes);
544 : nbytes = p - buf;
545 : #else
546 2341 : byte *p = buf;
547 : int n;
548 :
549 2341 : nbytes = size;
550 : do
551 : {
552 : do
553 : {
554 2341 : n = write (f, p, nbytes);
555 : }
556 2341 : while (n == -1 && errno == EINTR);
557 2341 : if (n > 0)
558 : {
559 2341 : p += n;
560 2341 : nbytes -= n;
561 : }
562 : }
563 2341 : while (n != -1 && nbytes);
564 2341 : if (n == -1)
565 : {
566 0 : rc = gpg_error_from_syserror ();
567 0 : log_error ("%s: write error: %s\n", a->fname, strerror (errno));
568 : }
569 2341 : nbytes = p - buf;
570 : #endif
571 : }
572 2463 : *ret_len = nbytes;
573 : }
574 4726 : else if (control == IOBUFCTRL_INIT)
575 : {
576 2363 : a->eof_seen = 0;
577 2363 : a->keep_open = 0;
578 2363 : a->no_cache = 0;
579 : }
580 2363 : else if (control == IOBUFCTRL_DESC)
581 : {
582 0 : mem2str (buf, "file_filter(fd)", *ret_len);
583 : }
584 2363 : else if (control == IOBUFCTRL_FREE)
585 : {
586 2363 : if (f != FD_FOR_STDIN && f != FD_FOR_STDOUT)
587 : {
588 2119 : if (DBG_IOBUF)
589 0 : log_debug ("%s: close fd/handle %d\n", a->fname, FD2INT (f));
590 2119 : if (!a->keep_open)
591 2119 : fd_cache_close (a->no_cache ? NULL : a->fname, f);
592 : }
593 2363 : xfree (a); /* We can free our context now. */
594 : }
595 :
596 12046 : return rc;
597 : }
598 :
599 :
600 : /* Similar to file_filter but using the estream system. */
601 : static int
602 0 : file_es_filter (void *opaque, int control, iobuf_t chain, byte * buf,
603 : size_t * ret_len)
604 : {
605 0 : file_es_filter_ctx_t *a = opaque;
606 0 : estream_t f = a->fp;
607 0 : size_t size = *ret_len;
608 0 : size_t nbytes = 0;
609 0 : int rc = 0;
610 :
611 : (void)chain; /* Not used. */
612 :
613 0 : if (control == IOBUFCTRL_UNDERFLOW)
614 : {
615 0 : assert (size); /* We need a buffer. */
616 0 : if (a->eof_seen)
617 : {
618 0 : rc = -1;
619 0 : *ret_len = 0;
620 : }
621 : else
622 : {
623 0 : nbytes = 0;
624 0 : rc = es_read (f, buf, size, &nbytes);
625 0 : if (rc == -1)
626 : { /* error */
627 0 : rc = gpg_error_from_syserror ();
628 0 : log_error ("%s: read error: %s\n", a->fname, strerror (errno));
629 : }
630 0 : else if (!nbytes)
631 : { /* eof */
632 0 : a->eof_seen = 1;
633 0 : rc = -1;
634 : }
635 0 : *ret_len = nbytes;
636 : }
637 : }
638 0 : else if (control == IOBUFCTRL_FLUSH)
639 : {
640 0 : if (size)
641 : {
642 0 : byte *p = buf;
643 : size_t nwritten;
644 :
645 0 : nbytes = size;
646 : do
647 : {
648 0 : nwritten = 0;
649 0 : if (es_write (f, p, nbytes, &nwritten))
650 : {
651 0 : rc = gpg_error_from_syserror ();
652 0 : log_error ("%s: write error: %s\n",
653 0 : a->fname, strerror (errno));
654 0 : break;
655 : }
656 0 : p += nwritten;
657 0 : nbytes -= nwritten;
658 : }
659 0 : while (nbytes);
660 0 : nbytes = p - buf;
661 : }
662 0 : *ret_len = nbytes;
663 : }
664 0 : else if (control == IOBUFCTRL_INIT)
665 : {
666 0 : a->eof_seen = 0;
667 0 : a->no_cache = 0;
668 : }
669 0 : else if (control == IOBUFCTRL_DESC)
670 : {
671 0 : mem2str (buf, "estream_filter", *ret_len);
672 : }
673 0 : else if (control == IOBUFCTRL_FREE)
674 : {
675 0 : if (f != es_stdin && f != es_stdout)
676 : {
677 0 : if (DBG_IOBUF)
678 0 : log_debug ("%s: es_fclose %p\n", a->fname, f);
679 0 : if (!a->keep_open)
680 0 : es_fclose (f);
681 : }
682 0 : f = NULL;
683 0 : xfree (a); /* We can free our context now. */
684 : }
685 :
686 0 : return rc;
687 : }
688 :
689 :
690 : #ifdef HAVE_W32_SYSTEM
691 : /* Because network sockets are special objects under Lose32 we have to
692 : use a dedicated filter for them. */
693 : static int
694 : sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
695 : size_t * ret_len)
696 : {
697 : sock_filter_ctx_t *a = opaque;
698 : size_t size = *ret_len;
699 : size_t nbytes = 0;
700 : int rc = 0;
701 :
702 : (void)chain;
703 :
704 : if (control == IOBUFCTRL_UNDERFLOW)
705 : {
706 : assert (size); /* need a buffer */
707 : if (a->eof_seen)
708 : {
709 : rc = -1;
710 : *ret_len = 0;
711 : }
712 : else
713 : {
714 : int nread;
715 :
716 : nread = recv (a->sock, buf, size, 0);
717 : if (nread == SOCKET_ERROR)
718 : {
719 : int ec = (int) WSAGetLastError ();
720 : rc = gpg_error_from_errno (ec);
721 : log_error ("socket read error: ec=%d\n", ec);
722 : }
723 : else if (!nread)
724 : {
725 : a->eof_seen = 1;
726 : rc = -1;
727 : }
728 : else
729 : {
730 : nbytes = nread;
731 : }
732 : *ret_len = nbytes;
733 : }
734 : }
735 : else if (control == IOBUFCTRL_FLUSH)
736 : {
737 : if (size)
738 : {
739 : byte *p = buf;
740 : int n;
741 :
742 : nbytes = size;
743 : do
744 : {
745 : n = send (a->sock, p, nbytes, 0);
746 : if (n == SOCKET_ERROR)
747 : {
748 : int ec = (int) WSAGetLastError ();
749 : rc = gpg_error_from_errno (ec);
750 : log_error ("socket write error: ec=%d\n", ec);
751 : break;
752 : }
753 : p += n;
754 : nbytes -= n;
755 : }
756 : while (nbytes);
757 : nbytes = p - buf;
758 : }
759 : *ret_len = nbytes;
760 : }
761 : else if (control == IOBUFCTRL_INIT)
762 : {
763 : a->eof_seen = 0;
764 : a->keep_open = 0;
765 : a->no_cache = 0;
766 : }
767 : else if (control == IOBUFCTRL_DESC)
768 : {
769 : mem2str (buf, "sock_filter", *ret_len);
770 : }
771 : else if (control == IOBUFCTRL_FREE)
772 : {
773 : if (!a->keep_open)
774 : closesocket (a->sock);
775 : xfree (a); /* we can free our context now */
776 : }
777 : return rc;
778 : }
779 : #endif /*HAVE_W32_SYSTEM*/
780 :
781 : /****************
782 : * This is used to implement the block write mode.
783 : * Block reading is done on a byte by byte basis in readbyte(),
784 : * without a filter
785 : */
786 : static int
787 4612 : block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
788 : size_t * ret_len)
789 : {
790 4612 : block_filter_ctx_t *a = opaque;
791 4612 : char *buf = (char *)buffer;
792 4612 : size_t size = *ret_len;
793 4612 : int c, needed, rc = 0;
794 : char *p;
795 :
796 4612 : if (control == IOBUFCTRL_UNDERFLOW)
797 : {
798 1644 : size_t n = 0;
799 :
800 1644 : p = buf;
801 1644 : assert (size); /* need a buffer */
802 1644 : if (a->eof) /* don't read any further */
803 313 : rc = -1;
804 5474 : while (!rc && size)
805 : {
806 2499 : if (!a->size)
807 : { /* get the length bytes */
808 2475 : if (a->partial == 2)
809 : {
810 313 : a->eof = 1;
811 313 : if (!n)
812 0 : rc = -1;
813 313 : break;
814 : }
815 2162 : else if (a->partial)
816 : {
817 : /* These OpenPGP introduced huffman like encoded length
818 : * bytes are really a mess :-( */
819 2162 : if (a->first_c)
820 : {
821 313 : c = a->first_c;
822 313 : a->first_c = 0;
823 : }
824 1849 : else if ((c = iobuf_get (chain)) == -1)
825 : {
826 0 : log_error ("block_filter: 1st length byte missing\n");
827 0 : rc = GPG_ERR_BAD_DATA;
828 0 : break;
829 : }
830 2162 : if (c < 192)
831 : {
832 95 : a->size = c;
833 95 : a->partial = 2;
834 95 : if (!a->size)
835 : {
836 0 : a->eof = 1;
837 0 : if (!n)
838 0 : rc = -1;
839 0 : break;
840 : }
841 : }
842 2067 : else if (c < 224)
843 : {
844 218 : a->size = (c - 192) * 256;
845 218 : if ((c = iobuf_get (chain)) == -1)
846 : {
847 0 : log_error
848 : ("block_filter: 2nd length byte missing\n");
849 0 : rc = GPG_ERR_BAD_DATA;
850 0 : break;
851 : }
852 218 : a->size += c + 192;
853 218 : a->partial = 2;
854 218 : if (!a->size)
855 : {
856 0 : a->eof = 1;
857 0 : if (!n)
858 0 : rc = -1;
859 0 : break;
860 : }
861 : }
862 1849 : else if (c == 255)
863 : {
864 0 : a->size = (size_t)iobuf_get (chain) << 24;
865 0 : a->size |= iobuf_get (chain) << 16;
866 0 : a->size |= iobuf_get (chain) << 8;
867 0 : if ((c = iobuf_get (chain)) == -1)
868 : {
869 0 : log_error ("block_filter: invalid 4 byte length\n");
870 0 : rc = GPG_ERR_BAD_DATA;
871 0 : break;
872 : }
873 0 : a->size |= c;
874 0 : a->partial = 2;
875 0 : if (!a->size)
876 : {
877 0 : a->eof = 1;
878 0 : if (!n)
879 0 : rc = -1;
880 0 : break;
881 : }
882 : }
883 : else
884 : { /* Next partial body length. */
885 1849 : a->size = 1 << (c & 0x1f);
886 : }
887 : /* log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */
888 : }
889 : else
890 0 : BUG ();
891 : }
892 :
893 6558 : while (!rc && size && a->size)
894 : {
895 2186 : needed = size < a->size ? size : a->size;
896 2186 : c = iobuf_read (chain, p, needed);
897 2186 : if (c < needed)
898 : {
899 0 : if (c == -1)
900 0 : c = 0;
901 0 : log_error
902 : ("block_filter %p: read error (size=%lu,a->size=%lu)\n",
903 0 : a, (ulong) size + c, (ulong) a->size + c);
904 0 : rc = GPG_ERR_BAD_DATA;
905 : }
906 : else
907 : {
908 2186 : size -= c;
909 2186 : a->size -= c;
910 2186 : p += c;
911 2186 : n += c;
912 : }
913 : }
914 : }
915 1644 : *ret_len = n;
916 : }
917 2968 : else if (control == IOBUFCTRL_FLUSH)
918 : {
919 1304 : if (a->partial)
920 : { /* the complicated openpgp scheme */
921 1304 : size_t blen, n, nbytes = size + a->buflen;
922 :
923 1304 : assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
924 1304 : if (nbytes < OP_MIN_PARTIAL_CHUNK)
925 : {
926 : /* not enough to write a partial block out; so we store it */
927 257 : if (!a->buffer)
928 257 : a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
929 257 : memcpy (a->buffer + a->buflen, buf, size);
930 257 : a->buflen += size;
931 : }
932 : else
933 : { /* okay, we can write out something */
934 : /* do this in a loop to use the most efficient block lengths */
935 1047 : p = buf;
936 : do
937 : {
938 : /* find the best matching block length - this is limited
939 : * by the size of the internal buffering */
940 7258 : for (blen = OP_MIN_PARTIAL_CHUNK * 2,
941 1193 : c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes;
942 3679 : blen *= 2, c++)
943 : ;
944 1193 : blen /= 2;
945 1193 : c--;
946 : /* write the partial length header */
947 1193 : assert (c <= 0x1f); /*;-) */
948 1193 : c |= 0xe0;
949 1193 : iobuf_put (chain, c);
950 1193 : if ((n = a->buflen))
951 : { /* write stuff from the buffer */
952 0 : assert (n == OP_MIN_PARTIAL_CHUNK);
953 0 : if (iobuf_write (chain, a->buffer, n))
954 0 : rc = gpg_error_from_syserror ();
955 0 : a->buflen = 0;
956 0 : nbytes -= n;
957 : }
958 1193 : if ((n = nbytes) > blen)
959 408 : n = blen;
960 1193 : if (n && iobuf_write (chain, p, n))
961 0 : rc = gpg_error_from_syserror ();
962 1193 : p += n;
963 1193 : nbytes -= n;
964 : }
965 1193 : while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK);
966 : /* store the rest in the buffer */
967 1047 : if (!rc && nbytes)
968 : {
969 262 : assert (!a->buflen);
970 262 : assert (nbytes < OP_MIN_PARTIAL_CHUNK);
971 262 : if (!a->buffer)
972 262 : a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
973 262 : memcpy (a->buffer, p, nbytes);
974 262 : a->buflen = nbytes;
975 : }
976 : }
977 : }
978 : else
979 0 : BUG ();
980 : }
981 1664 : else if (control == IOBUFCTRL_INIT)
982 : {
983 832 : if (DBG_IOBUF)
984 0 : log_debug ("init block_filter %p\n", a);
985 832 : if (a->partial)
986 832 : a->count = 0;
987 0 : else if (a->use == IOBUF_INPUT)
988 0 : a->count = a->size = 0;
989 : else
990 0 : a->count = a->size; /* force first length bytes */
991 832 : a->eof = 0;
992 832 : a->buffer = NULL;
993 832 : a->buflen = 0;
994 : }
995 832 : else if (control == IOBUFCTRL_DESC)
996 : {
997 0 : mem2str (buf, "block_filter", *ret_len);
998 : }
999 832 : else if (control == IOBUFCTRL_FREE)
1000 : {
1001 832 : if (a->use == IOBUF_OUTPUT)
1002 : { /* write the end markers */
1003 519 : if (a->partial)
1004 : {
1005 : u32 len;
1006 : /* write out the remaining bytes without a partial header
1007 : * the length of this header may be 0 - but if it is
1008 : * the first block we are not allowed to use a partial header
1009 : * and frankly we can't do so, because this length must be
1010 : * a power of 2. This is _really_ complicated because we
1011 : * have to check the possible length of a packet prior
1012 : * to it's creation: a chain of filters becomes complicated
1013 : * and we need a lot of code to handle compressed packets etc.
1014 : * :-(((((((
1015 : */
1016 : /* construct header */
1017 519 : len = a->buflen;
1018 : /*log_debug("partial: remaining length=%u\n", len ); */
1019 519 : if (len < 192)
1020 312 : rc = iobuf_put (chain, len);
1021 207 : else if (len < 8384)
1022 : {
1023 207 : if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192)))
1024 207 : rc = iobuf_put (chain, ((len - 192) % 256));
1025 : }
1026 : else
1027 : { /* use a 4 byte header */
1028 0 : if (!(rc = iobuf_put (chain, 0xff)))
1029 0 : if (!(rc = iobuf_put (chain, (len >> 24) & 0xff)))
1030 0 : if (!(rc = iobuf_put (chain, (len >> 16) & 0xff)))
1031 0 : if (!(rc = iobuf_put (chain, (len >> 8) & 0xff)))
1032 0 : rc = iobuf_put (chain, len & 0xff);
1033 : }
1034 519 : if (!rc && len)
1035 519 : rc = iobuf_write (chain, a->buffer, len);
1036 519 : if (rc)
1037 : {
1038 0 : log_error ("block_filter: write error: %s\n",
1039 0 : strerror (errno));
1040 0 : rc = gpg_error_from_syserror ();
1041 : }
1042 519 : xfree (a->buffer);
1043 519 : a->buffer = NULL;
1044 519 : a->buflen = 0;
1045 : }
1046 : else
1047 0 : BUG ();
1048 : }
1049 313 : else if (a->size)
1050 : {
1051 0 : log_error ("block_filter: pending bytes!\n");
1052 : }
1053 832 : if (DBG_IOBUF)
1054 0 : log_debug ("free block_filter %p\n", a);
1055 832 : xfree (a); /* we can free our context now */
1056 : }
1057 :
1058 4612 : return rc;
1059 : }
1060 :
1061 : #define MAX_IOBUF_DESC 32
1062 : /*
1063 : * Fill the buffer by the description of iobuf A.
1064 : * The buffer size should be MAX_IOBUF_DESC (or larger).
1065 : * Returns BUF as (const char *).
1066 : */
1067 : static const char *
1068 0 : iobuf_desc (iobuf_t a, byte *buf)
1069 : {
1070 0 : size_t len = MAX_IOBUF_DESC;
1071 :
1072 0 : if (! a || ! a->filter)
1073 0 : memcpy (buf, "?", 2);
1074 : else
1075 0 : a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL, buf, &len);
1076 :
1077 0 : return buf;
1078 : }
1079 :
1080 : static void
1081 1650 : print_chain (iobuf_t a)
1082 : {
1083 1650 : if (!DBG_IOBUF)
1084 3300 : return;
1085 0 : for (; a; a = a->chain)
1086 : {
1087 : byte desc[MAX_IOBUF_DESC];
1088 :
1089 0 : log_debug ("iobuf chain: %d.%d '%s' filter_eof=%d start=%d len=%d\n",
1090 : a->no, a->subno, iobuf_desc (a, desc), a->filter_eof,
1091 0 : (int) a->d.start, (int) a->d.len);
1092 : }
1093 : }
1094 :
1095 : int
1096 0 : iobuf_print_chain (iobuf_t a)
1097 : {
1098 0 : print_chain (a);
1099 0 : return 0;
1100 : }
1101 :
1102 : iobuf_t
1103 6192 : iobuf_alloc (int use, size_t bufsize)
1104 : {
1105 : iobuf_t a;
1106 : static int number = 0;
1107 :
1108 6192 : assert (use == IOBUF_INPUT || use == IOBUF_INPUT_TEMP
1109 : || use == IOBUF_OUTPUT || use == IOBUF_OUTPUT_TEMP);
1110 6192 : if (bufsize == 0)
1111 : {
1112 0 : log_bug ("iobuf_alloc() passed a bufsize of 0!\n");
1113 : bufsize = IOBUF_BUFFER_SIZE;
1114 : }
1115 :
1116 6192 : a = xcalloc (1, sizeof *a);
1117 6192 : a->use = use;
1118 6192 : a->d.buf = xmalloc (bufsize);
1119 6192 : a->d.size = bufsize;
1120 6192 : a->no = ++number;
1121 6192 : a->subno = 0;
1122 6192 : a->real_fname = NULL;
1123 6192 : return a;
1124 : }
1125 :
1126 : int
1127 14214 : iobuf_close (iobuf_t a)
1128 : {
1129 : iobuf_t a_chain;
1130 14214 : size_t dummy_len = 0;
1131 14214 : int rc = 0;
1132 :
1133 21954 : for (; a; a = a_chain)
1134 : {
1135 : byte desc[MAX_IOBUF_DESC];
1136 7740 : int rc2 = 0;
1137 :
1138 7740 : a_chain = a->chain;
1139 :
1140 7740 : if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a)))
1141 0 : log_error ("filter_flush failed on close: %s\n", gpg_strerror (rc));
1142 :
1143 7740 : if (DBG_IOBUF)
1144 0 : log_debug ("iobuf-%d.%d: close '%s'\n",
1145 : a->no, a->subno, iobuf_desc (a, desc));
1146 :
1147 7740 : if (a->filter && (rc2 = a->filter (a->filter_ov, IOBUFCTRL_FREE,
1148 : a->chain, NULL, &dummy_len)))
1149 0 : log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc));
1150 7740 : if (! rc && rc2)
1151 : /* Whoops! An error occurred. Save it in RC if we haven't
1152 : already recorded an error. */
1153 0 : rc = rc2;
1154 :
1155 7740 : xfree (a->real_fname);
1156 7740 : if (a->d.buf)
1157 : {
1158 7740 : memset (a->d.buf, 0, a->d.size); /* erase the buffer */
1159 7740 : xfree (a->d.buf);
1160 : }
1161 7740 : xfree (a);
1162 : }
1163 14214 : return rc;
1164 : }
1165 :
1166 : int
1167 7 : iobuf_cancel (iobuf_t a)
1168 : {
1169 : const char *s;
1170 : iobuf_t a2;
1171 : int rc;
1172 : #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
1173 : char *remove_name = NULL;
1174 : #endif
1175 :
1176 7 : if (a && a->use == IOBUF_OUTPUT)
1177 : {
1178 0 : s = iobuf_get_real_fname (a);
1179 0 : if (s && *s)
1180 : {
1181 : #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
1182 : remove_name = xstrdup (s);
1183 : #else
1184 0 : remove (s);
1185 : #endif
1186 : }
1187 : }
1188 :
1189 : /* send a cancel message to all filters */
1190 7 : for (a2 = a; a2; a2 = a2->chain)
1191 : {
1192 : size_t dummy;
1193 0 : if (a2->filter)
1194 0 : a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy);
1195 : }
1196 :
1197 7 : rc = iobuf_close (a);
1198 : #if defined(HAVE_W32_SYSTEM) || defined(__riscos__)
1199 : if (remove_name)
1200 : {
1201 : /* Argg, MSDOS does not allow removing open files. So
1202 : * we have to do it here */
1203 : #ifdef HAVE_W32CE_SYSTEM
1204 : wchar_t *wtmp = utf8_to_wchar (remove_name);
1205 : if (wtmp)
1206 : DeleteFile (wtmp);
1207 : xfree (wtmp);
1208 : #else
1209 : remove (remove_name);
1210 : #endif
1211 : xfree (remove_name);
1212 : }
1213 : #endif
1214 7 : return rc;
1215 : }
1216 :
1217 :
1218 : iobuf_t
1219 1171 : iobuf_temp (void)
1220 : {
1221 1171 : return iobuf_alloc (IOBUF_OUTPUT_TEMP, IOBUF_BUFFER_SIZE);
1222 : }
1223 :
1224 : iobuf_t
1225 2658 : iobuf_temp_with_content (const char *buffer, size_t length)
1226 : {
1227 : iobuf_t a;
1228 : int i;
1229 :
1230 2658 : a = iobuf_alloc (IOBUF_INPUT_TEMP, length);
1231 2658 : assert (length == a->d.size);
1232 : /* memcpy (a->d.buf, buffer, length); */
1233 2261373 : for (i=0; i < length; i++)
1234 2258715 : a->d.buf[i] = buffer[i];
1235 2658 : a->d.len = length;
1236 :
1237 2658 : return a;
1238 : }
1239 :
1240 : void
1241 0 : iobuf_enable_special_filenames (int yes)
1242 : {
1243 0 : special_names_enabled = yes;
1244 0 : }
1245 :
1246 :
1247 : /* See whether the filename has the form "-&nnnn", where n is a
1248 : non-zero number. Returns this number or -1 if it is not the
1249 : case. */
1250 : static int
1251 5601 : check_special_filename (const char *fname)
1252 : {
1253 5601 : if (special_names_enabled && fname && *fname == '-' && fname[1] == '&')
1254 : {
1255 : int i;
1256 :
1257 0 : fname += 2;
1258 0 : for (i = 0; digitp (fname+i); i++)
1259 : ;
1260 0 : if (!fname[i])
1261 0 : return atoi (fname);
1262 : }
1263 5601 : return -1;
1264 : }
1265 :
1266 :
1267 : int
1268 3880 : iobuf_is_pipe_filename (const char *fname)
1269 : {
1270 3880 : if (!fname || (*fname=='-' && !fname[1]) )
1271 398 : return 1;
1272 3482 : return check_special_filename (fname) != -1;
1273 : }
1274 :
1275 : static iobuf_t
1276 2363 : do_open (const char *fname, int special_filenames,
1277 : int use, const char *opentype, int mode700)
1278 : {
1279 : iobuf_t a;
1280 : gnupg_fd_t fp;
1281 : file_filter_ctx_t *fcx;
1282 2363 : size_t len = 0;
1283 2363 : int print_only = 0;
1284 : int fd;
1285 : byte desc[MAX_IOBUF_DESC];
1286 :
1287 2363 : assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
1288 :
1289 2363 : if (special_filenames
1290 : /* NULL or '-'. */
1291 2363 : && (!fname || (*fname == '-' && !fname[1])))
1292 : {
1293 244 : if (use == IOBUF_INPUT)
1294 : {
1295 163 : fp = FD_FOR_STDIN;
1296 163 : fname = "[stdin]";
1297 : }
1298 : else
1299 : {
1300 81 : fp = FD_FOR_STDOUT;
1301 81 : fname = "[stdout]";
1302 : }
1303 244 : print_only = 1;
1304 : }
1305 2119 : else if (!fname)
1306 0 : return NULL;
1307 2119 : else if (special_filenames && (fd = check_special_filename (fname)) != -1)
1308 0 : return iobuf_fdopen (translate_file_handle (fd, use == IOBUF_INPUT ? 0 : 1),
1309 : opentype);
1310 : else
1311 : {
1312 2119 : if (use == IOBUF_INPUT)
1313 1588 : fp = fd_cache_open (fname, opentype);
1314 : else
1315 531 : fp = direct_open (fname, opentype, mode700);
1316 2119 : if (fp == GNUPG_INVALID_FD)
1317 0 : return NULL;
1318 : }
1319 :
1320 2363 : a = iobuf_alloc (use, IOBUF_BUFFER_SIZE);
1321 2363 : fcx = xmalloc (sizeof *fcx + strlen (fname));
1322 2363 : fcx->fp = fp;
1323 2363 : fcx->print_only_name = print_only;
1324 2363 : strcpy (fcx->fname, fname);
1325 2363 : if (!print_only)
1326 2119 : a->real_fname = xstrdup (fname);
1327 2363 : a->filter = file_filter;
1328 2363 : a->filter_ov = fcx;
1329 2363 : file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1330 2363 : if (DBG_IOBUF)
1331 0 : log_debug ("iobuf-%d.%d: open '%s' desc=%s fd=%d\n",
1332 : a->no, a->subno, fname, iobuf_desc (a, desc), FD2INT (fcx->fp));
1333 :
1334 2363 : return a;
1335 : }
1336 :
1337 : iobuf_t
1338 1751 : iobuf_open (const char *fname)
1339 : {
1340 1751 : return do_open (fname, 1, IOBUF_INPUT, "rb", 0);
1341 : }
1342 :
1343 : iobuf_t
1344 612 : iobuf_create (const char *fname, int mode700)
1345 : {
1346 612 : return do_open (fname, 1, IOBUF_OUTPUT, "wb", mode700);
1347 : }
1348 :
1349 : iobuf_t
1350 0 : iobuf_openrw (const char *fname)
1351 : {
1352 0 : return do_open (fname, 0, IOBUF_OUTPUT, "r+b", 0);
1353 : }
1354 :
1355 :
1356 : static iobuf_t
1357 0 : do_iobuf_fdopen (int fd, const char *mode, int keep_open)
1358 : {
1359 : iobuf_t a;
1360 : gnupg_fd_t fp;
1361 : file_filter_ctx_t *fcx;
1362 : size_t len;
1363 :
1364 0 : fp = INT2FD (fd);
1365 :
1366 0 : a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
1367 : IOBUF_BUFFER_SIZE);
1368 0 : fcx = xmalloc (sizeof *fcx + 20);
1369 0 : fcx->fp = fp;
1370 0 : fcx->print_only_name = 1;
1371 0 : fcx->keep_open = keep_open;
1372 0 : sprintf (fcx->fname, "[fd %d]", fd);
1373 0 : a->filter = file_filter;
1374 0 : a->filter_ov = fcx;
1375 0 : file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1376 0 : if (DBG_IOBUF)
1377 0 : log_debug ("iobuf-%d.%d: fdopen%s '%s'\n",
1378 0 : a->no, a->subno, keep_open? "_nc":"", fcx->fname);
1379 0 : iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
1380 0 : return a;
1381 : }
1382 :
1383 :
1384 : iobuf_t
1385 0 : iobuf_fdopen (int fd, const char *mode)
1386 : {
1387 0 : return do_iobuf_fdopen (fd, mode, 0);
1388 : }
1389 :
1390 : iobuf_t
1391 0 : iobuf_fdopen_nc (int fd, const char *mode)
1392 : {
1393 0 : return do_iobuf_fdopen (fd, mode, 1);
1394 : }
1395 :
1396 :
1397 : iobuf_t
1398 0 : iobuf_esopen (estream_t estream, const char *mode, int keep_open)
1399 : {
1400 : iobuf_t a;
1401 : file_es_filter_ctx_t *fcx;
1402 0 : size_t len = 0;
1403 :
1404 0 : a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
1405 : IOBUF_BUFFER_SIZE);
1406 0 : fcx = xtrymalloc (sizeof *fcx + 30);
1407 0 : fcx->fp = estream;
1408 0 : fcx->print_only_name = 1;
1409 0 : fcx->keep_open = keep_open;
1410 0 : sprintf (fcx->fname, "[fd %p]", estream);
1411 0 : a->filter = file_es_filter;
1412 0 : a->filter_ov = fcx;
1413 0 : file_es_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1414 0 : if (DBG_IOBUF)
1415 0 : log_debug ("iobuf-%d.%d: esopen%s '%s'\n",
1416 0 : a->no, a->subno, keep_open? "_nc":"", fcx->fname);
1417 0 : return a;
1418 : }
1419 :
1420 :
1421 : iobuf_t
1422 0 : iobuf_sockopen (int fd, const char *mode)
1423 : {
1424 : iobuf_t a;
1425 : #ifdef HAVE_W32_SYSTEM
1426 : sock_filter_ctx_t *scx;
1427 : size_t len;
1428 :
1429 : a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
1430 : IOBUF_BUFFER_SIZE);
1431 : scx = xmalloc (sizeof *scx + 25);
1432 : scx->sock = fd;
1433 : scx->print_only_name = 1;
1434 : sprintf (scx->fname, "[sock %d]", fd);
1435 : a->filter = sock_filter;
1436 : a->filter_ov = scx;
1437 : sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len);
1438 : if (DBG_IOBUF)
1439 : log_debug ("iobuf-%d.%d: sockopen '%s'\n", a->no, a->subno, scx->fname);
1440 : iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
1441 : #else
1442 0 : a = iobuf_fdopen (fd, mode);
1443 : #endif
1444 0 : return a;
1445 : }
1446 :
1447 : int
1448 1085 : iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval)
1449 : {
1450 : byte desc[MAX_IOBUF_DESC];
1451 :
1452 1085 : if (cmd == IOBUF_IOCTL_KEEP_OPEN)
1453 : {
1454 : /* Keep system filepointer/descriptor open. This was used in
1455 : the past by http.c; this ioctl is not directly used
1456 : anymore. */
1457 0 : if (DBG_IOBUF)
1458 0 : log_debug ("iobuf-%d.%d: ioctl '%s' keep_open=%d\n",
1459 : a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc),
1460 : intval);
1461 0 : for (; a; a = a->chain)
1462 0 : if (!a->chain && a->filter == file_filter)
1463 : {
1464 0 : file_filter_ctx_t *b = a->filter_ov;
1465 0 : b->keep_open = intval;
1466 0 : return 0;
1467 : }
1468 : #ifdef HAVE_W32_SYSTEM
1469 : else if (!a->chain && a->filter == sock_filter)
1470 : {
1471 : sock_filter_ctx_t *b = a->filter_ov;
1472 : b->keep_open = intval;
1473 : return 0;
1474 : }
1475 : #endif
1476 : }
1477 1085 : else if (cmd == IOBUF_IOCTL_INVALIDATE_CACHE)
1478 : {
1479 43 : if (DBG_IOBUF)
1480 0 : log_debug ("iobuf-*.*: ioctl '%s' invalidate\n",
1481 : ptrval ? (char *) ptrval : "?");
1482 43 : if (!a && !intval && ptrval)
1483 : {
1484 43 : if (fd_cache_invalidate (ptrval))
1485 0 : return -1;
1486 43 : return 0;
1487 : }
1488 : }
1489 1042 : else if (cmd == IOBUF_IOCTL_NO_CACHE)
1490 : {
1491 1042 : if (DBG_IOBUF)
1492 0 : log_debug ("iobuf-%d.%d: ioctl '%s' no_cache=%d\n",
1493 : a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc),
1494 : intval);
1495 1042 : for (; a; a = a->chain)
1496 1042 : if (!a->chain && a->filter == file_filter)
1497 : {
1498 1042 : file_filter_ctx_t *b = a->filter_ov;
1499 1042 : b->no_cache = intval;
1500 1042 : return 0;
1501 : }
1502 : #ifdef HAVE_W32_SYSTEM
1503 : else if (!a->chain && a->filter == sock_filter)
1504 : {
1505 : sock_filter_ctx_t *b = a->filter_ov;
1506 : b->no_cache = intval;
1507 : return 0;
1508 : }
1509 : #endif
1510 : }
1511 0 : else if (cmd == IOBUF_IOCTL_FSYNC)
1512 : {
1513 : /* Do a fsync on the open fd and return any errors to the caller
1514 : of iobuf_ioctl. Note that we work on a file name here. */
1515 0 : if (DBG_IOBUF)
1516 0 : log_debug ("iobuf-*.*: ioctl '%s' fsync\n",
1517 : ptrval? (const char*)ptrval:"<null>");
1518 :
1519 0 : if (!a && !intval && ptrval)
1520 : {
1521 0 : return fd_cache_synchronize (ptrval);
1522 : }
1523 : }
1524 :
1525 :
1526 0 : return -1;
1527 : }
1528 :
1529 :
1530 : /****************
1531 : * Register an i/o filter.
1532 : */
1533 : int
1534 2153 : iobuf_push_filter (iobuf_t a,
1535 : int (*f) (void *opaque, int control,
1536 : iobuf_t chain, byte * buf, size_t * len),
1537 : void *ov)
1538 : {
1539 2153 : return iobuf_push_filter2 (a, f, ov, 0);
1540 : }
1541 :
1542 : int
1543 3253 : iobuf_push_filter2 (iobuf_t a,
1544 : int (*f) (void *opaque, int control,
1545 : iobuf_t chain, byte * buf, size_t * len),
1546 : void *ov, int rel_ov)
1547 : {
1548 : iobuf_t b;
1549 3253 : size_t dummy_len = 0;
1550 3253 : int rc = 0;
1551 :
1552 3253 : if (a->use == IOBUF_OUTPUT && (rc = filter_flush (a)))
1553 0 : return rc;
1554 :
1555 3253 : if (a->subno >= MAX_NESTING_FILTER)
1556 : {
1557 0 : log_error ("i/o filter too deeply nested - corrupted data?\n");
1558 0 : return GPG_ERR_BAD_DATA;
1559 : }
1560 :
1561 : /* We want to create a new filter and put it in front of A. A
1562 : simple implementation would do:
1563 :
1564 : b = iobuf_alloc (...);
1565 : b->chain = a;
1566 : return a;
1567 :
1568 : This is a bit problematic: A is the head of the pipeline and
1569 : there are potentially many pointers to it. Requiring the caller
1570 : to update all of these pointers is a burden.
1571 :
1572 : An alternative implementation would add a level of indirection.
1573 : For instance, we could use a pipeline object, which contains a
1574 : pointer to the first filter in the pipeline. This is not what we
1575 : do either.
1576 :
1577 : Instead, we allocate a new buffer (B) and copy the first filter's
1578 : state into that and use the initial buffer (A) for the new
1579 : filter. One limitation of this approach is that it is not
1580 : practical to maintain a pointer to a specific filter's state.
1581 :
1582 : Before:
1583 :
1584 : A
1585 : |
1586 : v 0x100 0x200
1587 : +----------+ +----------+
1588 : | filter x |--------->| filter y |---->....
1589 : +----------+ +----------+
1590 :
1591 : After: B
1592 : |
1593 : v 0x300
1594 : +----------+
1595 : A | filter x |
1596 : | +----------+
1597 : v 0x100 ^ v 0x200
1598 : +----------+ +----------+
1599 : | filter w | | filter y |---->....
1600 : +----------+ +----------+
1601 :
1602 : Note: filter x's address changed from 0x100 to 0x300, but A still
1603 : points to the head of the pipeline.
1604 : */
1605 :
1606 3253 : b = xmalloc (sizeof *b);
1607 3253 : memcpy (b, a, sizeof *b);
1608 : /* fixme: it is stupid to keep a copy of the name at every level
1609 : * but we need the name somewhere because the name known by file_filter
1610 : * may have been released when we need the name of the file */
1611 3253 : b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL;
1612 : /* remove the filter stuff from the new stream */
1613 3253 : a->filter = NULL;
1614 3253 : a->filter_ov = NULL;
1615 3253 : a->filter_ov_owner = 0;
1616 3253 : a->filter_eof = 0;
1617 3253 : if (a->use == IOBUF_OUTPUT_TEMP)
1618 : /* A TEMP filter buffers any data sent to it; it does not forward
1619 : any data down the pipeline. If we add a new filter to the
1620 : pipeline, it shouldn't also buffer data. It should send it
1621 : downstream to be buffered. Thus, the correct type for a filter
1622 : added in front of an IOBUF_OUTPUT_TEMP filter is IOBUF_OUPUT, not
1623 : IOBUF_OUTPUT_TEMP. */
1624 : {
1625 1 : a->use = IOBUF_OUTPUT;
1626 :
1627 : /* When pipeline is written to, the temp buffer's size is
1628 : increased accordingly. We don't need to allocate a 10 MB
1629 : buffer for a non-terminal filter. Just use the default
1630 : size. */
1631 1 : a->d.size = IOBUF_BUFFER_SIZE;
1632 : }
1633 3252 : else if (a->use == IOBUF_INPUT_TEMP)
1634 : /* Same idea as above. */
1635 : {
1636 4 : a->use = IOBUF_INPUT;
1637 4 : a->d.size = IOBUF_BUFFER_SIZE;
1638 : }
1639 :
1640 : /* The new filter (A) gets a new buffer.
1641 :
1642 : If the pipeline is an output or temp pipeline, then giving the
1643 : buffer to the new filter means that data that was written before
1644 : the filter was pushed gets sent to the filter. That's clearly
1645 : wrong.
1646 :
1647 : If the pipeline is an input pipeline, then giving the buffer to
1648 : the new filter (A) means that data that has read from (B), but
1649 : not yet read from the pipeline won't be processed by the new
1650 : filter (A)! That's certainly not what we want. */
1651 3253 : a->d.buf = xmalloc (a->d.size);
1652 3253 : a->d.len = 0;
1653 3253 : a->d.start = 0;
1654 :
1655 : /* disable nlimit for the new stream */
1656 3253 : a->ntotal = b->ntotal + b->nbytes;
1657 3253 : a->nlimit = a->nbytes = 0;
1658 3253 : a->nofast = 0;
1659 : /* make a link from the new stream to the original stream */
1660 3253 : a->chain = b;
1661 :
1662 : /* setup the function on the new stream */
1663 3253 : a->filter = f;
1664 3253 : a->filter_ov = ov;
1665 3253 : a->filter_ov_owner = rel_ov;
1666 :
1667 3253 : a->subno = b->subno + 1;
1668 :
1669 3253 : if (DBG_IOBUF)
1670 : {
1671 : byte desc[MAX_IOBUF_DESC];
1672 0 : log_debug ("iobuf-%d.%d: push '%s'\n",
1673 : a->no, a->subno, iobuf_desc (a, desc));
1674 0 : print_chain (a);
1675 : }
1676 :
1677 : /* now we can initialize the new function if we have one */
1678 3253 : if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain,
1679 : NULL, &dummy_len)))
1680 0 : log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc));
1681 3253 : return rc;
1682 : }
1683 :
1684 : /****************
1685 : * Remove an i/o filter.
1686 : */
1687 : int
1688 52 : iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
1689 : iobuf_t chain, byte * buf, size_t * len),
1690 : void *ov)
1691 : {
1692 : iobuf_t b;
1693 52 : size_t dummy_len = 0;
1694 52 : int rc = 0;
1695 : byte desc[MAX_IOBUF_DESC];
1696 :
1697 52 : if (DBG_IOBUF)
1698 0 : log_debug ("iobuf-%d.%d: pop '%s'\n",
1699 : a->no, a->subno, iobuf_desc (a, desc));
1700 52 : if (a->use == IOBUF_INPUT_TEMP || a->use == IOBUF_OUTPUT_TEMP)
1701 : {
1702 : /* This should be the last filter in the pipeline. */
1703 0 : assert (! a->chain);
1704 0 : return 0;
1705 : }
1706 52 : if (!a->filter)
1707 : { /* this is simple */
1708 0 : b = a->chain;
1709 0 : assert (b);
1710 0 : xfree (a->d.buf);
1711 0 : xfree (a->real_fname);
1712 0 : memcpy (a, b, sizeof *a);
1713 0 : xfree (b);
1714 0 : return 0;
1715 : }
1716 52 : for (b = a; b; b = b->chain)
1717 52 : if (b->filter == f && (!ov || b->filter_ov == ov))
1718 : break;
1719 52 : if (!b)
1720 0 : log_bug ("iobuf_pop_filter(): filter function not found\n");
1721 :
1722 : /* flush this stream if it is an output stream */
1723 52 : if (a->use == IOBUF_OUTPUT && (rc = filter_flush (b)))
1724 : {
1725 0 : log_error ("filter_flush failed in iobuf_pop_filter: %s\n",
1726 : gpg_strerror (rc));
1727 0 : return rc;
1728 : }
1729 : /* and tell the filter to free it self */
1730 52 : if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain,
1731 : NULL, &dummy_len)))
1732 : {
1733 0 : log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
1734 0 : return rc;
1735 : }
1736 52 : if (b->filter_ov && b->filter_ov_owner)
1737 : {
1738 0 : xfree (b->filter_ov);
1739 0 : b->filter_ov = NULL;
1740 : }
1741 :
1742 :
1743 : /* and see how to remove it */
1744 52 : if (a == b && !b->chain)
1745 0 : log_bug ("can't remove the last filter from the chain\n");
1746 52 : else if (a == b)
1747 : { /* remove the first iobuf from the chain */
1748 : /* everything from b is copied to a. This is save because
1749 : * a flush has been done on the to be removed entry
1750 : */
1751 52 : b = a->chain;
1752 52 : xfree (a->d.buf);
1753 52 : xfree (a->real_fname);
1754 52 : memcpy (a, b, sizeof *a);
1755 52 : xfree (b);
1756 52 : if (DBG_IOBUF)
1757 0 : log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno);
1758 : }
1759 0 : else if (!b->chain)
1760 : { /* remove the last iobuf from the chain */
1761 0 : log_bug ("Ohh jeee, trying to remove a head filter\n");
1762 : }
1763 : else
1764 : { /* remove an intermediate iobuf from the chain */
1765 0 : log_bug ("Ohh jeee, trying to remove an intermediate filter\n");
1766 : }
1767 :
1768 52 : return rc;
1769 : }
1770 :
1771 :
1772 : /****************
1773 : * read underflow: read at least one byte into the buffer and return
1774 : * the first byte or -1 on EOF.
1775 : */
1776 : static int
1777 538786 : underflow (iobuf_t a, int clear_pending_eof)
1778 : {
1779 538786 : return underflow_target (a, clear_pending_eof, 1);
1780 : }
1781 :
1782 :
1783 : /****************
1784 : * read underflow: read TARGET bytes into the buffer and return
1785 : * the first byte or -1 on EOF.
1786 : */
1787 : static int
1788 539409 : underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
1789 : {
1790 : size_t len;
1791 : int rc;
1792 :
1793 539409 : if (DBG_IOBUF)
1794 0 : log_debug ("iobuf-%d.%d: underflow: buffer size: %d; still buffered: %d => space for %d bytes\n",
1795 : a->no, a->subno,
1796 0 : (int) a->d.size, (int) (a->d.len - a->d.start),
1797 0 : (int) (a->d.size - (a->d.len - a->d.start)));
1798 :
1799 539409 : if (a->use == IOBUF_INPUT_TEMP)
1800 : /* By definition, there isn't more data to read into the
1801 : buffer. */
1802 2533 : return -1;
1803 :
1804 536876 : assert (a->use == IOBUF_INPUT);
1805 :
1806 : /* If there is still some buffered data, then move it to the start
1807 : of the buffer and try to fill the end of the buffer. (This is
1808 : useful if we are called from iobuf_peek().) */
1809 536876 : assert (a->d.start <= a->d.len);
1810 536876 : a->d.len -= a->d.start;
1811 536876 : memmove (a->d.buf, &a->d.buf[a->d.start], a->d.len);
1812 536876 : a->d.start = 0;
1813 :
1814 536876 : if (a->d.len < target && a->filter_eof)
1815 : /* The last time we tried to read from this filter, we got an EOF.
1816 : We couldn't return the EOF, because there was buffered data.
1817 : Since there is no longer any buffered data, return the
1818 : error. */
1819 : {
1820 1766 : if (DBG_IOBUF)
1821 0 : log_debug ("iobuf-%d.%d: underflow: eof (pending eof)\n",
1822 : a->no, a->subno);
1823 1766 : if (! clear_pending_eof)
1824 1 : return -1;
1825 :
1826 1765 : if (a->chain)
1827 : /* A filter follows this one. Free this filter. */
1828 : {
1829 563 : iobuf_t b = a->chain;
1830 563 : if (DBG_IOBUF)
1831 0 : log_debug ("iobuf-%d.%d: filter popped (pending EOF returned)\n",
1832 : a->no, a->subno);
1833 563 : xfree (a->d.buf);
1834 563 : xfree (a->real_fname);
1835 563 : memcpy (a, b, sizeof *a);
1836 563 : xfree (b);
1837 563 : print_chain (a);
1838 : }
1839 : else
1840 1202 : a->filter_eof = 0; /* for the top level filter */
1841 1765 : return -1; /* return one(!) EOF */
1842 : }
1843 :
1844 535110 : if (a->d.len == 0 && a->error)
1845 : /* The last time we tried to read from this filter, we got an
1846 : error. We couldn't return the error, because there was
1847 : buffered data. Since there is no longer any buffered data,
1848 : return the error. */
1849 : {
1850 0 : if (DBG_IOBUF)
1851 0 : log_debug ("iobuf-%d.%d: pending error (%s) returned\n",
1852 0 : a->no, a->subno, gpg_strerror (a->error));
1853 0 : return -1;
1854 : }
1855 :
1856 535110 : if (a->filter && ! a->filter_eof && ! a->error)
1857 : /* We have a filter function and the last time we tried to read we
1858 : didn't get an EOF or an error. Try to fill the buffer. */
1859 : {
1860 : /* Be careful to account for any buffered data. */
1861 534932 : len = a->d.size - a->d.len;
1862 534932 : if (DBG_IOBUF)
1863 0 : log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n",
1864 : a->no, a->subno, (ulong) len);
1865 534932 : if (len == 0)
1866 : /* There is no space for more data. Don't bother calling
1867 : A->FILTER. */
1868 0 : rc = 0;
1869 : else
1870 1069864 : rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
1871 534932 : &a->d.buf[a->d.len], &len);
1872 534932 : a->d.len += len;
1873 :
1874 534932 : if (DBG_IOBUF)
1875 0 : log_debug ("iobuf-%d.%d: A->FILTER() returned rc=%d (%s), read %lu bytes\n",
1876 : a->no, a->subno,
1877 0 : rc, rc == 0 ? "ok" : rc == -1 ? "EOF" : gpg_strerror (rc),
1878 : (ulong) len);
1879 : /* if( a->no == 1 ) */
1880 : /* log_hexdump (" data:", a->d.buf, len); */
1881 :
1882 534932 : if (rc == -1)
1883 : /* EOF. */
1884 : {
1885 2973 : size_t dummy_len = 0;
1886 :
1887 : /* Tell the filter to free itself */
1888 2973 : if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain,
1889 : NULL, &dummy_len)))
1890 0 : log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
1891 :
1892 : /* Free everything except for the internal buffer. */
1893 2973 : if (a->filter_ov && a->filter_ov_owner)
1894 0 : xfree (a->filter_ov);
1895 2973 : a->filter_ov = NULL;
1896 2973 : a->filter = NULL;
1897 2973 : a->filter_eof = 1;
1898 :
1899 2973 : if (clear_pending_eof && a->d.len == 0 && a->chain)
1900 : /* We don't need to keep this filter around at all:
1901 :
1902 : - we got an EOF
1903 : - we have no buffered data
1904 : - a filter follows this one.
1905 :
1906 : Unlink this filter. */
1907 : {
1908 1087 : iobuf_t b = a->chain;
1909 1087 : if (DBG_IOBUF)
1910 0 : log_debug ("iobuf-%d.%d: pop in underflow (nothing buffered, got EOF)\n",
1911 : a->no, a->subno);
1912 1087 : xfree (a->d.buf);
1913 1087 : xfree (a->real_fname);
1914 1087 : memcpy (a, b, sizeof *a);
1915 1087 : xfree (b);
1916 :
1917 1087 : print_chain (a);
1918 :
1919 3496 : return -1;
1920 : }
1921 1886 : else if (a->d.len == 0)
1922 : /* We can't unlink this filter (it is the only one in the
1923 : pipeline), but we can immediately return EOF. */
1924 1322 : return -1;
1925 : }
1926 531959 : else if (rc)
1927 : /* Record the error. */
1928 : {
1929 0 : a->error = rc;
1930 :
1931 0 : if (a->d.len == 0)
1932 : /* There is no buffered data. Immediately return EOF. */
1933 0 : return -1;
1934 : }
1935 : }
1936 :
1937 532701 : assert (a->d.start <= a->d.len);
1938 532701 : if (a->d.start < a->d.len)
1939 532521 : return a->d.buf[a->d.start++];
1940 :
1941 : /* EOF. */
1942 180 : return -1;
1943 : }
1944 :
1945 :
1946 : static int
1947 7032 : filter_flush (iobuf_t a)
1948 : {
1949 : size_t len;
1950 : int rc;
1951 :
1952 7032 : if (a->use == IOBUF_OUTPUT_TEMP)
1953 : { /* increase the temp buffer */
1954 50 : size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
1955 :
1956 50 : if (DBG_IOBUF)
1957 0 : log_debug ("increasing temp iobuf from %lu to %lu\n",
1958 : (ulong) a->d.size, (ulong) newsize);
1959 :
1960 50 : a->d.buf = xrealloc (a->d.buf, newsize);
1961 50 : a->d.size = newsize;
1962 50 : return 0;
1963 : }
1964 6982 : else if (a->use != IOBUF_OUTPUT)
1965 0 : log_bug ("flush on non-output iobuf\n");
1966 6982 : else if (!a->filter)
1967 0 : log_bug ("filter_flush: no filter\n");
1968 6982 : len = a->d.len;
1969 6982 : rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len);
1970 6982 : if (!rc && len != a->d.len)
1971 : {
1972 0 : log_info ("filter_flush did not write all!\n");
1973 0 : rc = GPG_ERR_INTERNAL;
1974 : }
1975 6982 : else if (rc)
1976 0 : a->error = rc;
1977 6982 : a->d.len = 0;
1978 :
1979 6982 : return rc;
1980 : }
1981 :
1982 :
1983 : int
1984 8840 : iobuf_readbyte (iobuf_t a)
1985 : {
1986 : int c;
1987 :
1988 8840 : if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP)
1989 : {
1990 0 : log_bug ("iobuf_readbyte called on a non-INPUT pipeline!\n");
1991 : return -1;
1992 : }
1993 :
1994 8840 : assert (a->d.start <= a->d.len);
1995 :
1996 8840 : if (a->nlimit && a->nbytes >= a->nlimit)
1997 0 : return -1; /* forced EOF */
1998 :
1999 8840 : if (a->d.start < a->d.len)
2000 : {
2001 884 : c = a->d.buf[a->d.start++];
2002 : }
2003 7956 : else if ((c = underflow (a, 1)) == -1)
2004 5012 : return -1; /* EOF */
2005 :
2006 3828 : assert (a->d.start <= a->d.len);
2007 :
2008 : /* Note: if underflow doesn't return EOF, then it returns the first
2009 : byte that was read and advances a->d.start appropriately. */
2010 :
2011 3828 : a->nbytes++;
2012 3828 : return c;
2013 : }
2014 :
2015 :
2016 : int
2017 22689 : iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
2018 : {
2019 22689 : unsigned char *buf = (unsigned char *)buffer;
2020 : int c, n;
2021 :
2022 22689 : if (a->use == IOBUF_OUTPUT || a->use == IOBUF_OUTPUT_TEMP)
2023 : {
2024 0 : log_bug ("iobuf_read called on a non-INPUT pipeline!\n");
2025 : return -1;
2026 : }
2027 :
2028 22689 : if (a->nlimit)
2029 : {
2030 : /* Handle special cases. */
2031 0 : for (n = 0; n < buflen; n++)
2032 : {
2033 0 : if ((c = iobuf_readbyte (a)) == -1)
2034 : {
2035 0 : if (!n)
2036 0 : return -1; /* eof */
2037 0 : break;
2038 : }
2039 :
2040 0 : if (buf)
2041 : {
2042 0 : *buf = c;
2043 0 : buf++;
2044 : }
2045 : }
2046 0 : return n;
2047 : }
2048 :
2049 22689 : n = 0;
2050 : do
2051 : {
2052 551643 : if (n < buflen && a->d.start < a->d.len)
2053 : /* Drain the buffer. */
2054 : {
2055 549651 : unsigned size = a->d.len - a->d.start;
2056 549651 : if (size > buflen - n)
2057 19683 : size = buflen - n;
2058 549651 : if (buf)
2059 25356 : memcpy (buf, a->d.buf + a->d.start, size);
2060 549651 : n += size;
2061 549651 : a->d.start += size;
2062 549651 : if (buf)
2063 25356 : buf += size;
2064 : }
2065 551643 : if (n < buflen)
2066 : /* Draining the internal buffer didn't fill BUFFER. Call
2067 : underflow to read more data into the filter's internal
2068 : buffer. */
2069 : {
2070 530830 : if ((c = underflow (a, 1)) == -1)
2071 : /* EOF. If we managed to read something, don't return EOF
2072 : now. */
2073 : {
2074 1875 : a->nbytes += n;
2075 1875 : return n ? n : -1 /*EOF*/;
2076 : }
2077 528955 : if (buf)
2078 4667 : *buf++ = c;
2079 528955 : n++;
2080 : }
2081 : }
2082 549768 : while (n < buflen);
2083 20814 : a->nbytes += n;
2084 20814 : return n;
2085 : }
2086 :
2087 :
2088 :
2089 : int
2090 621 : iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
2091 : {
2092 621 : int n = 0;
2093 :
2094 621 : assert (buflen > 0);
2095 621 : assert (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP);
2096 :
2097 621 : if (buflen > a->d.size)
2098 : /* We can't peek more than we can buffer. */
2099 0 : buflen = a->d.size;
2100 :
2101 : /* Try to fill the internal buffer with enough data to satisfy the
2102 : request. */
2103 1864 : while (buflen > a->d.len - a->d.start)
2104 : {
2105 623 : if (underflow_target (a, 0, buflen) == -1)
2106 : /* EOF. We can't read any more. */
2107 1 : break;
2108 :
2109 : /* Underflow consumes the first character (it's the return
2110 : value). unget() it by resetting the "file position". */
2111 622 : assert (a->d.start == 1);
2112 622 : a->d.start = 0;
2113 : }
2114 :
2115 621 : n = a->d.len - a->d.start;
2116 621 : if (n > buflen)
2117 620 : n = buflen;
2118 :
2119 621 : if (n == 0)
2120 : /* EOF. */
2121 0 : return -1;
2122 :
2123 621 : memcpy (buf, &a->d.buf[a->d.start], n);
2124 :
2125 621 : return n;
2126 : }
2127 :
2128 :
2129 :
2130 :
2131 : int
2132 967467 : iobuf_writebyte (iobuf_t a, unsigned int c)
2133 : {
2134 : int rc;
2135 :
2136 967467 : if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
2137 : {
2138 0 : log_bug ("iobuf_writebyte called on an input pipeline!\n");
2139 : return -1;
2140 : }
2141 :
2142 967467 : if (a->d.len == a->d.size)
2143 106 : if ((rc=filter_flush (a)))
2144 0 : return rc;
2145 :
2146 967467 : assert (a->d.len < a->d.size);
2147 967467 : a->d.buf[a->d.len++] = c;
2148 967467 : return 0;
2149 : }
2150 :
2151 :
2152 : int
2153 28379 : iobuf_write (iobuf_t a, const void *buffer, unsigned int buflen)
2154 : {
2155 28379 : const unsigned char *buf = (const unsigned char *)buffer;
2156 : int rc;
2157 :
2158 28379 : if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
2159 : {
2160 0 : log_bug ("iobuf_write called on an input pipeline!\n");
2161 : return -1;
2162 : }
2163 :
2164 : do
2165 : {
2166 31438 : if (buflen && a->d.len < a->d.size)
2167 : {
2168 30237 : unsigned size = a->d.size - a->d.len;
2169 30237 : if (size > buflen)
2170 27176 : size = buflen;
2171 30237 : memcpy (a->d.buf + a->d.len, buf, size);
2172 30237 : buflen -= size;
2173 30237 : buf += size;
2174 30237 : a->d.len += size;
2175 : }
2176 31438 : if (buflen)
2177 : {
2178 3059 : rc = filter_flush (a);
2179 3059 : if (rc)
2180 0 : return rc;
2181 : }
2182 : }
2183 31438 : while (buflen);
2184 28379 : return 0;
2185 : }
2186 :
2187 :
2188 : int
2189 11130 : iobuf_writestr (iobuf_t a, const char *buf)
2190 : {
2191 11130 : if (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP)
2192 : {
2193 0 : log_bug ("iobuf_writestr called on an input pipeline!\n");
2194 : return -1;
2195 : }
2196 :
2197 11130 : return iobuf_write (a, buf, strlen (buf));
2198 : }
2199 :
2200 :
2201 :
2202 : int
2203 1056 : iobuf_write_temp (iobuf_t dest, iobuf_t source)
2204 : {
2205 1056 : assert (source->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
2206 1056 : assert (dest->use == IOBUF_OUTPUT || dest->use == IOBUF_OUTPUT_TEMP);
2207 :
2208 1056 : iobuf_flush_temp (source);
2209 1056 : return iobuf_write (dest, source->d.buf, source->d.len);
2210 : }
2211 :
2212 : size_t
2213 50 : iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
2214 : {
2215 : byte desc[MAX_IOBUF_DESC];
2216 : size_t n;
2217 :
2218 : while (1)
2219 : {
2220 50 : int rc = filter_flush (a);
2221 50 : if (rc)
2222 0 : log_bug ("Flushing iobuf %d.%d (%s) from iobuf_temp_to_buffer failed. Ignoring.\n",
2223 : a->no, a->subno, iobuf_desc (a, desc));
2224 50 : if (! a->chain)
2225 49 : break;
2226 1 : a = a->chain;
2227 1 : }
2228 :
2229 49 : n = a->d.len;
2230 49 : if (n > buflen)
2231 0 : n = buflen;
2232 49 : memcpy (buffer, a->d.buf, n);
2233 49 : return n;
2234 : }
2235 :
2236 : /* Copies the data from the input iobuf SOURCE to the output iobuf
2237 : DEST until either an error is encountered or EOF is reached.
2238 : Returns the number of bytes copies. */
2239 : size_t
2240 537 : iobuf_copy (iobuf_t dest, iobuf_t source)
2241 : {
2242 : char *temp;
2243 : /* Use a 32 KB buffer. */
2244 537 : const size_t temp_size = 32 * 1024;
2245 :
2246 : size_t nread;
2247 537 : size_t nwrote = 0;
2248 : int err;
2249 :
2250 537 : assert (source->use == IOBUF_INPUT || source->use == IOBUF_INPUT_TEMP);
2251 537 : assert (dest->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
2252 :
2253 537 : if (iobuf_error (dest))
2254 0 : return -1;
2255 :
2256 537 : temp = xmalloc (temp_size);
2257 : while (1)
2258 : {
2259 1165 : nread = iobuf_read (source, temp, temp_size);
2260 1165 : if (nread == -1)
2261 : /* EOF. */
2262 537 : break;
2263 :
2264 628 : err = iobuf_write (dest, temp, nread);
2265 628 : if (err)
2266 0 : break;
2267 628 : nwrote += nread;
2268 628 : }
2269 :
2270 : /* Burn the buffer. */
2271 537 : wipememory (temp, sizeof (temp));
2272 537 : xfree (temp);
2273 :
2274 537 : return nwrote;
2275 : }
2276 :
2277 :
2278 : void
2279 1056 : iobuf_flush_temp (iobuf_t temp)
2280 : {
2281 1056 : if (temp->use == IOBUF_INPUT || temp->use == IOBUF_INPUT_TEMP)
2282 0 : log_bug ("iobuf_flush_temp called on an input pipeline!\n");
2283 2112 : while (temp->chain)
2284 0 : iobuf_pop_filter (temp, temp->filter, NULL);
2285 1056 : }
2286 :
2287 :
2288 : void
2289 0 : iobuf_set_limit (iobuf_t a, off_t nlimit)
2290 : {
2291 0 : if (nlimit)
2292 0 : a->nofast = 1;
2293 : else
2294 0 : a->nofast = 0;
2295 0 : a->nlimit = nlimit;
2296 0 : a->ntotal += a->nbytes;
2297 0 : a->nbytes = 0;
2298 0 : }
2299 :
2300 :
2301 :
2302 : off_t
2303 866 : iobuf_get_filelength (iobuf_t a, int *overflow)
2304 : {
2305 866 : if (overflow)
2306 866 : *overflow = 0;
2307 :
2308 : /* Hmmm: file_filter may have already been removed */
2309 866 : for ( ; a->chain; a = a->chain )
2310 : ;
2311 :
2312 866 : if (a->filter != file_filter)
2313 0 : return 0;
2314 :
2315 : {
2316 866 : file_filter_ctx_t *b = a->filter_ov;
2317 866 : gnupg_fd_t fp = b->fp;
2318 :
2319 : #if defined(HAVE_W32_SYSTEM)
2320 : ulong size;
2321 : static int (* __stdcall get_file_size_ex) (void *handle,
2322 : LARGE_INTEGER *r_size);
2323 : static int get_file_size_ex_initialized;
2324 :
2325 : if (!get_file_size_ex_initialized)
2326 : {
2327 : void *handle;
2328 :
2329 : handle = dlopen ("kernel32.dll", RTLD_LAZY);
2330 : if (handle)
2331 : {
2332 : get_file_size_ex = dlsym (handle, "GetFileSizeEx");
2333 : if (!get_file_size_ex)
2334 : dlclose (handle);
2335 : }
2336 : get_file_size_ex_initialized = 1;
2337 : }
2338 :
2339 : if (get_file_size_ex)
2340 : {
2341 : /* This is a newer system with GetFileSizeEx; we use this
2342 : then because it seem that GetFileSize won't return a
2343 : proper error in case a file is larger than 4GB. */
2344 : LARGE_INTEGER exsize;
2345 :
2346 : if (get_file_size_ex (fp, &exsize))
2347 : {
2348 : if (!exsize.u.HighPart)
2349 : return exsize.u.LowPart;
2350 : if (overflow)
2351 : *overflow = 1;
2352 : return 0;
2353 : }
2354 : }
2355 : else
2356 : {
2357 : if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
2358 : return size;
2359 : }
2360 : log_error ("GetFileSize for handle %p failed: %s\n",
2361 : fp, w32_strerror (0));
2362 : #else /*!HAVE_W32_SYSTEM*/
2363 : {
2364 : struct stat st;
2365 :
2366 866 : if ( !fstat (FD2INT (fp), &st) )
2367 866 : return st.st_size;
2368 0 : log_error("fstat() failed: %s\n", strerror(errno) );
2369 : }
2370 : #endif /*!HAVE_W32_SYSTEM*/
2371 : }
2372 :
2373 0 : return 0;
2374 : }
2375 :
2376 :
2377 : int
2378 1269 : iobuf_get_fd (iobuf_t a)
2379 : {
2380 1269 : for (; a->chain; a = a->chain)
2381 : ;
2382 :
2383 1269 : if (a->filter != file_filter)
2384 0 : return -1;
2385 :
2386 : {
2387 1269 : file_filter_ctx_t *b = a->filter_ov;
2388 1269 : gnupg_fd_t fp = b->fp;
2389 :
2390 1269 : return FD2INT (fp);
2391 : }
2392 : }
2393 :
2394 :
2395 : off_t
2396 922 : iobuf_tell (iobuf_t a)
2397 : {
2398 922 : return a->ntotal + a->nbytes;
2399 : }
2400 :
2401 :
2402 : #if !defined(HAVE_FSEEKO) && !defined(fseeko)
2403 :
2404 : #ifdef HAVE_LIMITS_H
2405 : # include <limits.h>
2406 : #endif
2407 : #ifndef LONG_MAX
2408 : # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
2409 : #endif
2410 : #ifndef LONG_MIN
2411 : # define LONG_MIN (-1 - LONG_MAX)
2412 : #endif
2413 :
2414 : /****************
2415 : * A substitute for fseeko, for hosts that don't have it.
2416 : */
2417 : static int
2418 : fseeko (FILE * stream, off_t newpos, int whence)
2419 : {
2420 : while (newpos != (long) newpos)
2421 : {
2422 : long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
2423 : if (fseek (stream, pos, whence) != 0)
2424 : return -1;
2425 : newpos -= pos;
2426 : whence = SEEK_CUR;
2427 : }
2428 : return fseek (stream, (long) newpos, whence);
2429 : }
2430 : #endif
2431 :
2432 : int
2433 51 : iobuf_seek (iobuf_t a, off_t newpos)
2434 : {
2435 51 : file_filter_ctx_t *b = NULL;
2436 :
2437 51 : if (a->use == IOBUF_OUTPUT || a->use == IOBUF_INPUT)
2438 : {
2439 : /* Find the last filter in the pipeline. */
2440 51 : for (; a->chain; a = a->chain)
2441 : ;
2442 :
2443 51 : if (a->filter != file_filter)
2444 0 : return -1;
2445 :
2446 51 : b = a->filter_ov;
2447 :
2448 : #ifdef HAVE_W32_SYSTEM
2449 : if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff)
2450 : {
2451 : log_error ("SetFilePointer failed on handle %p: ec=%d\n",
2452 : b->fp, (int) GetLastError ());
2453 : return -1;
2454 : }
2455 : #else
2456 51 : if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1)
2457 : {
2458 0 : log_error ("can't lseek: %s\n", strerror (errno));
2459 0 : return -1;
2460 : }
2461 : #endif
2462 : /* Discard the buffer it is not a temp stream. */
2463 51 : a->d.len = 0;
2464 : }
2465 51 : a->d.start = 0;
2466 51 : a->nbytes = 0;
2467 51 : a->nlimit = 0;
2468 51 : a->nofast = 0;
2469 51 : a->ntotal = newpos;
2470 51 : a->error = 0;
2471 :
2472 : /* It is impossible for A->CHAIN to be non-NULL. If A is an INPUT
2473 : or OUTPUT buffer, then we find the last filter, which is defined
2474 : as A->CHAIN being NULL. If A is a TEMP filter, then A must be
2475 : the only filter in the pipe: when iobuf_push_filter adds a filter
2476 : to the front of a pipeline, it sets the new filter to be an
2477 : OUTPUT filter if the pipeline is an OUTPUT or TEMP pipeline and
2478 : to be an INPUT filter if the pipeline is an INPUT pipeline.
2479 : Thus, only the last filter in a TEMP pipeline can be a */
2480 :
2481 : /* remove filters, but the last */
2482 51 : if (a->chain)
2483 0 : log_debug ("iobuf_pop_filter called in iobuf_seek - please report\n");
2484 102 : while (a->chain)
2485 0 : iobuf_pop_filter (a, a->filter, NULL);
2486 :
2487 51 : return 0;
2488 : }
2489 :
2490 :
2491 : const char *
2492 515 : iobuf_get_real_fname (iobuf_t a)
2493 : {
2494 515 : if (a->real_fname)
2495 515 : return a->real_fname;
2496 :
2497 : /* the old solution */
2498 0 : for (; a; a = a->chain)
2499 0 : if (!a->chain && a->filter == file_filter)
2500 : {
2501 0 : file_filter_ctx_t *b = a->filter_ov;
2502 0 : return b->print_only_name ? NULL : b->fname;
2503 : }
2504 :
2505 0 : return NULL;
2506 : }
2507 :
2508 : const char *
2509 3 : iobuf_get_fname (iobuf_t a)
2510 : {
2511 3 : for (; a; a = a->chain)
2512 3 : if (!a->chain && a->filter == file_filter)
2513 : {
2514 3 : file_filter_ctx_t *b = a->filter_ov;
2515 3 : return b->fname;
2516 : }
2517 0 : return NULL;
2518 : }
2519 :
2520 : const char *
2521 3 : iobuf_get_fname_nonnull (iobuf_t a)
2522 : {
2523 : const char *fname;
2524 :
2525 3 : fname = iobuf_get_fname (a);
2526 3 : return fname? fname : "[?]";
2527 : }
2528 :
2529 :
2530 : /****************
2531 : * Enable or disable partial body length mode (RFC 4880 4.2.2.4).
2532 : *
2533 : * If LEN is 0, this disables partial block mode by popping the
2534 : * partial body length filter, which which must be the most recently
2535 : * added filter.
2536 : *
2537 : * If LEN is non-zero, it pushes a partial body length filter. If
2538 : * this is a read filter, LEN must be the length byte from the first
2539 : * chunk and A should be position just after this first partial body
2540 : * length header.
2541 : */
2542 : void
2543 884 : iobuf_set_partial_body_length_mode (iobuf_t a, size_t len)
2544 : {
2545 884 : if (!len)
2546 : /* Disable partial body length mode. */
2547 : {
2548 52 : if (a->use == IOBUF_INPUT)
2549 0 : log_debug ("iobuf_pop_filter called in set_partial_block_mode"
2550 : " - please report\n");
2551 :
2552 52 : log_assert (a->filter == block_filter);
2553 52 : iobuf_pop_filter (a, block_filter, NULL);
2554 : }
2555 : else
2556 : /* Enabled partial body length mode. */
2557 : {
2558 832 : block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx);
2559 832 : ctx->use = a->use;
2560 832 : ctx->partial = 1;
2561 832 : ctx->size = 0;
2562 832 : ctx->first_c = len;
2563 832 : iobuf_push_filter (a, block_filter, ctx);
2564 : }
2565 884 : }
2566 :
2567 :
2568 :
2569 : unsigned int
2570 32372 : iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
2571 : unsigned *length_of_buffer, unsigned *max_length)
2572 : {
2573 : int c;
2574 32372 : char *buffer = (char *)*addr_of_buffer;
2575 32372 : unsigned length = *length_of_buffer;
2576 32372 : unsigned nbytes = 0;
2577 32372 : unsigned maxlen = *max_length;
2578 : char *p;
2579 :
2580 : /* The code assumes that we have space for at least a newline and a
2581 : NUL character in the buffer. This requires at least 2 bytes. We
2582 : don't complicate the code by handling the stupid corner case, but
2583 : simply assert that it can't happen. */
2584 32372 : assert (length >= 2 || maxlen >= 2);
2585 :
2586 32372 : if (!buffer || length <= 1)
2587 : /* must allocate a new buffer */
2588 : {
2589 168 : length = 256 <= maxlen ? 256 : maxlen;
2590 168 : buffer = xrealloc (buffer, length);
2591 168 : *addr_of_buffer = (unsigned char *)buffer;
2592 168 : *length_of_buffer = length;
2593 : }
2594 :
2595 32372 : p = buffer;
2596 1792326 : while ((c = iobuf_get (a)) != -1)
2597 : {
2598 1759621 : *p++ = c;
2599 1759621 : nbytes++;
2600 1759621 : if (c == '\n')
2601 32037 : break;
2602 :
2603 1727584 : if (nbytes == length - 1)
2604 : /* We don't have enough space to add a \n and a \0. Increase
2605 : the buffer size. */
2606 : {
2607 5 : if (length == maxlen)
2608 : /* We reached the buffer's size limit! */
2609 : {
2610 : /* Skip the rest of the line. */
2611 2 : while (c != '\n' && (c = iobuf_get (a)) != -1)
2612 : ;
2613 :
2614 : /* p is pointing at the last byte in the buffer. We
2615 : always terminate the line with "\n\0" so overwrite
2616 : the previous byte with a \n. */
2617 2 : assert (p > buffer);
2618 2 : p[-1] = '\n';
2619 :
2620 : /* Indicate truncation. */
2621 2 : *max_length = 0;
2622 2 : break;
2623 : }
2624 :
2625 3 : length += length < 1024 ? 256 : 1024;
2626 3 : if (length > maxlen)
2627 1 : length = maxlen;
2628 :
2629 3 : buffer = xrealloc (buffer, length);
2630 3 : *addr_of_buffer = (unsigned char *)buffer;
2631 3 : *length_of_buffer = length;
2632 3 : p = buffer + nbytes;
2633 : }
2634 : }
2635 : /* Add the terminating NUL. */
2636 32372 : *p = 0;
2637 :
2638 : /* Return the number of characters written to the buffer including
2639 : the newline, but not including the terminating NUL. */
2640 32372 : return nbytes;
2641 : }
2642 :
2643 : static int
2644 0 : translate_file_handle (int fd, int for_write)
2645 : {
2646 : #if defined(HAVE_W32CE_SYSTEM)
2647 : /* This is called only with one of the special filenames. Under
2648 : W32CE the FD here is not a file descriptor but a rendezvous id,
2649 : thus we need to finish the pipe first. */
2650 : fd = _assuan_w32ce_finish_pipe (fd, for_write);
2651 : #elif defined(HAVE_W32_SYSTEM)
2652 : {
2653 : int x;
2654 :
2655 : (void)for_write;
2656 :
2657 : if (fd == 0)
2658 : x = (int) GetStdHandle (STD_INPUT_HANDLE);
2659 : else if (fd == 1)
2660 : x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
2661 : else if (fd == 2)
2662 : x = (int) GetStdHandle (STD_ERROR_HANDLE);
2663 : else
2664 : x = fd;
2665 :
2666 : if (x == -1)
2667 : log_debug ("GetStdHandle(%d) failed: ec=%d\n",
2668 : fd, (int) GetLastError ());
2669 :
2670 : fd = x;
2671 : }
2672 : #else
2673 : (void)for_write;
2674 : #endif
2675 0 : return fd;
2676 : }
2677 :
2678 :
2679 : void
2680 14754 : iobuf_skip_rest (iobuf_t a, unsigned long n, int partial)
2681 : {
2682 14754 : if ( partial )
2683 : {
2684 : for (;;)
2685 : {
2686 0 : if (a->nofast || a->d.start >= a->d.len)
2687 : {
2688 0 : if (iobuf_readbyte (a) == -1)
2689 : {
2690 0 : break;
2691 : }
2692 : }
2693 : else
2694 : {
2695 0 : unsigned long count = a->d.len - a->d.start;
2696 0 : a->nbytes += count;
2697 0 : a->d.start = a->d.len;
2698 : }
2699 0 : }
2700 : }
2701 : else
2702 : {
2703 14754 : unsigned long remaining = n;
2704 30112 : while (remaining > 0)
2705 : {
2706 605 : if (a->nofast || a->d.start >= a->d.len)
2707 : {
2708 2 : if (iobuf_readbyte (a) == -1)
2709 : {
2710 1 : break;
2711 : }
2712 1 : --remaining;
2713 : }
2714 : else
2715 : {
2716 603 : unsigned long count = a->d.len - a->d.start;
2717 603 : if (count > remaining)
2718 : {
2719 585 : count = remaining;
2720 : }
2721 603 : a->nbytes += count;
2722 603 : a->d.start += count;
2723 603 : remaining -= count;
2724 : }
2725 : }
2726 : }
2727 14754 : }
|