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