Add missing file and other changes.
[gnupg.git] / common / iobuf.c
1 /* iobuf.c  -  file handling
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
3  *               2004, 2006  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <ctype.h>
29 #include <assert.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #ifdef HAVE_DOSISH_SYSTEM
35 #include <windows.h>
36 #endif
37 #ifdef __riscos__
38 #include <kernel.h>
39 #include <swis.h>
40 #endif /* __riscos__ */
41
42 #include "util.h"
43 #include "iobuf.h"
44
45 /* The size of the internal buffers. 
46    NOTE: If you change this value you MUST also adjust the regression
47    test "armored_key_8192" in armor.test! */
48 #define IOBUF_BUFFER_SIZE  8192
49
50 #undef FILE_FILTER_USES_STDIO
51
52 #ifdef HAVE_DOSISH_SYSTEM
53 #define USE_SETMODE 1
54 #endif
55
56 #ifdef FILE_FILTER_USES_STDIO
57 #define my_fileno(a)  fileno ((a))
58 #define my_fopen_ro(a,b) fopen ((a),(b))
59 #define my_fopen(a,b)    fopen ((a),(b))
60 typedef FILE *FILEP_OR_FD;
61 #define INVALID_FP    NULL
62 #define FILEP_OR_FD_FOR_STDIN  (stdin)
63 #define FILEP_OR_FD_FOR_STDOUT  (stdout)
64 typedef struct
65 {
66   FILE *fp;                     /* open file handle */
67   int keep_open;
68   int no_cache;
69   int print_only_name;          /* flags indicating that fname is not a real file */
70   char fname[1];                /* name of the file */
71 }
72 file_filter_ctx_t;
73 #else
74 #define my_fileno(a)  (a)
75 #define my_fopen_ro(a,b) fd_cache_open ((a),(b))
76 #define my_fopen(a,b) direct_open ((a),(b))
77 #ifdef HAVE_DOSISH_SYSTEM
78 typedef HANDLE FILEP_OR_FD;
79 #define INVALID_FP  ((HANDLE)-1)
80 #define FILEP_OR_FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
81 #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
82 #undef USE_SETMODE
83 #else
84 typedef int FILEP_OR_FD;
85 #define INVALID_FP  (-1)
86 #define FILEP_OR_FD_FOR_STDIN  (0)
87 #define FILEP_OR_FD_FOR_STDOUT (1)
88 #endif
89 typedef struct
90 {
91   FILEP_OR_FD fp;               /* open file 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 }
98 file_filter_ctx_t;
99
100 struct close_cache_s
101 {
102   struct close_cache_s *next;
103   FILEP_OR_FD fp;
104   char fname[1];
105 };
106 typedef struct close_cache_s *CLOSE_CACHE;
107 static CLOSE_CACHE close_cache;
108 #endif
109
110 #ifdef _WIN32
111 typedef struct
112 {
113   int sock;
114   int keep_open;
115   int no_cache;
116   int eof_seen;
117   int print_only_name;          /* flags indicating that fname is not a real file */
118   char fname[1];                /* name of the file */
119 }
120 sock_filter_ctx_t;
121 #endif /*_WIN32*/
122
123 /* The first partial length header block must be of size 512
124  * to make it easier (and efficienter) we use a min. block size of 512
125  * for all chunks (but the last one) */
126 #define OP_MIN_PARTIAL_CHUNK      512
127 #define OP_MIN_PARTIAL_CHUNK_2POW 9
128
129 typedef struct
130 {
131   int use;
132   size_t size;
133   size_t count;
134   int partial;                  /* 1 = partial header, 2 in last partial packet */
135   char *buffer;                 /* used for partial header */
136   size_t buflen;                /* used size of buffer */
137   int first_c;                  /* of partial header (which is > 0) */
138   int eof;
139 }
140 block_filter_ctx_t;
141
142 static int special_names_enabled;
143
144 static int underflow (iobuf_t a);
145 static int translate_file_handle (int fd, int for_write);
146
147 #ifndef FILE_FILTER_USES_STDIO
148
149 /*
150  * Invalidate (i.e. close) a cached iobuf
151  */
152 static void
153 fd_cache_invalidate (const char *fname)
154 {
155   CLOSE_CACHE cc;
156
157   assert (fname);
158   if (DBG_IOBUF)
159     log_debug ("fd_cache_invalidate (%s)\n", fname);
160
161   for (cc = close_cache; cc; cc = cc->next)
162     {
163       if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname))
164         {
165           if (DBG_IOBUF)
166             log_debug ("                did (%s)\n", cc->fname);
167 #ifdef HAVE_DOSISH_SYSTEM
168           CloseHandle (cc->fp);
169 #else
170           close (cc->fp);
171 #endif
172           cc->fp = INVALID_FP;
173         }
174     }
175 }
176
177
178
179 static FILEP_OR_FD
180 direct_open (const char *fname, const char *mode)
181 {
182 #ifdef HAVE_DOSISH_SYSTEM
183   unsigned long da, cd, sm;
184   HANDLE hfile;
185
186   /* Note, that we do not handle all mode combinations */
187
188   /* According to the ReactOS source it seems that open() of the
189    * standard MSW32 crt does open the file in share mode which is
190    * something new for MS applications ;-)
191    */
192   if (strchr (mode, '+'))
193     {
194       fd_cache_invalidate (fname);
195       da = GENERIC_READ | GENERIC_WRITE;
196       cd = OPEN_EXISTING;
197       sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
198     }
199   else if (strchr (mode, 'w'))
200     {
201       fd_cache_invalidate (fname);
202       da = GENERIC_WRITE;
203       cd = CREATE_ALWAYS;
204       sm = FILE_SHARE_WRITE;
205     }
206   else
207     {
208       da = GENERIC_READ;
209       cd = OPEN_EXISTING;
210       sm = FILE_SHARE_READ;
211     }
212
213   hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
214   return hfile;
215 #else
216   int oflag;
217   int cflag = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
218
219   /* Note, that we do not handle all mode combinations */
220   if (strchr (mode, '+'))
221     {
222       fd_cache_invalidate (fname);
223       oflag = O_RDWR;
224     }
225   else if (strchr (mode, 'w'))
226     {
227       fd_cache_invalidate (fname);
228       oflag = O_WRONLY | O_CREAT | O_TRUNC;
229     }
230   else
231     {
232       oflag = O_RDONLY;
233     }
234 #ifdef O_BINARY
235   if (strchr (mode, 'b'))
236     oflag |= O_BINARY;
237 #endif
238 #ifndef __riscos__
239   return open (fname, oflag, cflag);
240 #else
241   {
242     struct stat buf;
243     int rc = stat (fname, &buf);
244
245     /* Don't allow iobufs on directories */
246     if (!rc && S_ISDIR (buf.st_mode) && !S_ISREG (buf.st_mode))
247       return __set_errno (EISDIR);
248     else
249       return open (fname, oflag, cflag);
250   }
251 #endif
252 #endif
253 }
254
255
256 /*
257  * Instead of closing an FD we keep it open and cache it for later reuse 
258  * Note that this caching strategy only works if the process does not chdir.
259  */
260 static void
261 fd_cache_close (const char *fname, FILEP_OR_FD fp)
262 {
263   CLOSE_CACHE cc;
264
265   assert (fp);
266   if (!fname || !*fname)
267     {
268 #ifdef HAVE_DOSISH_SYSTEM
269       CloseHandle (fp);
270 #else
271       close (fp);
272 #endif
273       if (DBG_IOBUF)
274         log_debug ("fd_cache_close (%p) real\n", (void *) fp);
275       return;
276     }
277   /* try to reuse a slot */
278   for (cc = close_cache; cc; cc = cc->next)
279     {
280       if (cc->fp == INVALID_FP && !strcmp (cc->fname, fname))
281         {
282           cc->fp = fp;
283           if (DBG_IOBUF)
284             log_debug ("fd_cache_close (%s) used existing slot\n", fname);
285           return;
286         }
287     }
288   /* add a new one */
289   if (DBG_IOBUF)
290     log_debug ("fd_cache_close (%s) new slot created\n", fname);
291   cc = xcalloc (1, sizeof *cc + strlen (fname));
292   strcpy (cc->fname, fname);
293   cc->fp = fp;
294   cc->next = close_cache;
295   close_cache = cc;
296 }
297
298 /*
299  * Do an direct_open on FNAME but first try to reuse one from the fd_cache
300  */
301 static FILEP_OR_FD
302 fd_cache_open (const char *fname, const char *mode)
303 {
304   CLOSE_CACHE cc;
305
306   assert (fname);
307   for (cc = close_cache; cc; cc = cc->next)
308     {
309       if (cc->fp != INVALID_FP && !strcmp (cc->fname, fname))
310         {
311           FILEP_OR_FD fp = cc->fp;
312           cc->fp = INVALID_FP;
313           if (DBG_IOBUF)
314             log_debug ("fd_cache_open (%s) using cached fp\n", fname);
315 #ifdef HAVE_DOSISH_SYSTEM
316           if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff)
317             {
318               log_error ("rewind file failed on handle %p: ec=%d\n",
319                          fp, (int) GetLastError ());
320               fp = INVALID_FP;
321             }
322 #else
323           if (lseek (fp, 0, SEEK_SET) == (off_t) - 1)
324             {
325               log_error ("can't rewind fd %d: %s\n", fp, strerror (errno));
326               fp = INVALID_FP;
327             }
328 #endif
329           return fp;
330         }
331     }
332   if (DBG_IOBUF)
333     log_debug ("fd_cache_open (%s) not cached\n", fname);
334   return direct_open (fname, mode);
335 }
336
337
338 #endif /*FILE_FILTER_USES_STDIO */
339
340
341 /****************
342  * Read data from a file into buf which has an allocated length of *LEN.
343  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
344  * the stream. A is not used.
345  * control may be:
346  * IOBUFCTRL_INIT: called just before the function is linked into the
347  *                 list of function. This can be used to prepare internal
348  *                 data structures of the function.
349  * IOBUFCTRL_FREE: called just before the function is removed from the
350  *                  list of functions and can be used to release internal
351  *                  data structures or close a file etc.
352  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
353  *                  with new stuff. *RET_LEN is the available size of the
354  *                  buffer, and should be set to the number of bytes
355  *                  which were put into the buffer. The function
356  *                  returns 0 to indicate success, -1 on EOF and
357  *                  GPG_ERR_xxxxx for other errors.
358  *
359  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
360  *                  *RET_LAN is the number of bytes in BUF.
361  *
362  * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel.  The
363  *                  filter may take appropriate action on this message.
364  */
365 static int
366 file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
367              size_t * ret_len)
368 {
369   file_filter_ctx_t *a = opaque;
370   FILEP_OR_FD f = a->fp;
371   size_t size = *ret_len;
372   size_t nbytes = 0;
373   int rc = 0;
374
375 #ifdef FILE_FILTER_USES_STDIO
376   if (control == IOBUFCTRL_UNDERFLOW)
377     {
378       assert (size);            /* need a buffer */
379       if (feof (f))
380         {                       /* On terminals you could easiely read as many EOFs as you call         */
381           rc = -1;              /* fread() or fgetc() repeatly. Every call will block until you press   */
382           *ret_len = 0;         /* CTRL-D. So we catch this case before we call fread() again.          */
383         }
384       else
385         {
386           clearerr (f);
387           nbytes = fread (buf, 1, size, f);
388           if (feof (f) && !nbytes)
389             {
390               rc = -1;          /* okay: we can return EOF now. */
391             }
392           else if (ferror (f) && errno != EPIPE)
393             {
394               rc = gpg_error_from_syserror ();
395               log_error ("%s: read error: %s\n", a->fname, strerror (errno));
396             }
397           *ret_len = nbytes;
398         }
399     }
400   else if (control == IOBUFCTRL_FLUSH)
401     {
402       if (size)
403         {
404           clearerr (f);
405           nbytes = fwrite (buf, 1, size, f);
406           if (ferror (f))
407             {
408               rc = gpg_error_from_syserror ();
409               log_error ("%s: write error: %s\n", a->fname, strerror (errno));
410             }
411         }
412       *ret_len = nbytes;
413     }
414   else if (control == IOBUFCTRL_INIT)
415     {
416       a->keep_open = a->no_cache = 0;
417     }
418   else if (control == IOBUFCTRL_DESC)
419     {
420       *(char **) buf = "file_filter";
421     }
422   else if (control == IOBUFCTRL_FREE)
423     {
424       if (f != stdin && f != stdout)
425         {
426           if (DBG_IOBUF)
427             log_debug ("%s: close fd %d\n", a->fname, fileno (f));
428           if (!a->keep_open)
429             fclose (f);
430         }
431       f = NULL;
432       xfree (a);                /* we can free our context now */
433     }
434 #else /* !stdio implementation */
435
436   if (control == IOBUFCTRL_UNDERFLOW)
437     {
438       assert (size);            /* need a buffer */
439       if (a->eof_seen)
440         {
441           rc = -1;
442           *ret_len = 0;
443         }
444       else
445         {
446 #ifdef HAVE_DOSISH_SYSTEM
447           unsigned long nread;
448
449           nbytes = 0;
450           if (!ReadFile (f, buf, size, &nread, NULL))
451             {
452               int ec = (int) GetLastError ();
453               if (ec != ERROR_BROKEN_PIPE)
454                 {
455                   rc = gpg_error_from_errno (ec);
456                   log_error ("%s: read error: ec=%d\n", a->fname, ec);
457                 }
458             }
459           else if (!nread)
460             {
461               a->eof_seen = 1;
462               rc = -1;
463             }
464           else
465             {
466               nbytes = nread;
467             }
468
469 #else
470
471           int n;
472
473           nbytes = 0;
474           do
475             {
476               n = read (f, buf, size);
477             }
478           while (n == -1 && errno == EINTR);
479           if (n == -1)
480             {                   /* error */
481               if (errno != EPIPE)
482                 {
483                   rc = gpg_error_from_syserror ();
484                   log_error ("%s: read error: %s\n",
485                              a->fname, strerror (errno));
486                 }
487             }
488           else if (!n)
489             {                   /* eof */
490               a->eof_seen = 1;
491               rc = -1;
492             }
493           else
494             {
495               nbytes = n;
496             }
497 #endif
498           *ret_len = nbytes;
499         }
500     }
501   else if (control == IOBUFCTRL_FLUSH)
502     {
503       if (size)
504         {
505 #ifdef HAVE_DOSISH_SYSTEM
506           byte *p = buf;
507           unsigned long n;
508
509           nbytes = size;
510           do
511             {
512               if (size && !WriteFile (f, p, nbytes, &n, NULL))
513                 {
514                   int ec = (int) GetLastError ();
515                   rc = gpg_error_from_errno (ec);
516                   log_error ("%s: write error: ec=%d\n", a->fname, ec);
517                   break;
518                 }
519               p += n;
520               nbytes -= n;
521             }
522           while (nbytes);
523           nbytes = p - buf;
524 #else
525           byte *p = buf;
526           int n;
527
528           nbytes = size;
529           do
530             {
531               do
532                 {
533                   n = write (f, p, nbytes);
534                 }
535               while (n == -1 && errno == EINTR);
536               if (n > 0)
537                 {
538                   p += n;
539                   nbytes -= n;
540                 }
541             }
542           while (n != -1 && nbytes);
543           if (n == -1)
544             {
545               rc = gpg_error_from_syserror ();
546               log_error ("%s: write error: %s\n", a->fname, strerror (errno));
547             }
548           nbytes = p - buf;
549 #endif
550         }
551       *ret_len = nbytes;
552     }
553   else if (control == IOBUFCTRL_INIT)
554     {
555       a->eof_seen = 0;
556       a->keep_open = 0;
557       a->no_cache = 0;
558     }
559   else if (control == IOBUFCTRL_DESC)
560     {
561       *(char **) buf = "file_filter(fd)";
562     }
563   else if (control == IOBUFCTRL_FREE)
564     {
565 #ifdef HAVE_DOSISH_SYSTEM
566       if (f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT)
567         {
568           if (DBG_IOBUF)
569             log_debug ("%s: close handle %p\n", a->fname, f);
570           if (!a->keep_open)
571             fd_cache_close (a->no_cache ? NULL : a->fname, f);
572         }
573 #else
574       if ((int) f != 0 && (int) f != 1)
575         {
576           if (DBG_IOBUF)
577             log_debug ("%s: close fd %d\n", a->fname, f);
578           if (!a->keep_open)
579             fd_cache_close (a->no_cache ? NULL : a->fname, f);
580         }
581       f = INVALID_FP;
582 #endif
583       xfree (a);                /* we can free our context now */
584     }
585 #endif /* !stdio implementation */
586   return rc;
587 }
588
589 #ifdef _WIN32
590 /* Becuase sockets are an special object under Lose32 we have to
591  * use a special filter */
592 static int
593 sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
594              size_t * ret_len)
595 {
596   sock_filter_ctx_t *a = opaque;
597   size_t size = *ret_len;
598   size_t nbytes = 0;
599   int rc = 0;
600
601   if (control == IOBUFCTRL_UNDERFLOW)
602     {
603       assert (size);            /* need a buffer */
604       if (a->eof_seen)
605         {
606           rc = -1;
607           *ret_len = 0;
608         }
609       else
610         {
611           int nread;
612
613           nread = recv (a->sock, buf, size, 0);
614           if (nread == SOCKET_ERROR)
615             {
616               int ec = (int) WSAGetLastError ();
617               rc = gpg_error_from_errno (ec);
618               log_error ("socket read error: ec=%d\n", ec);
619             }
620           else if (!nread)
621             {
622               a->eof_seen = 1;
623               rc = -1;
624             }
625           else
626             {
627               nbytes = nread;
628             }
629           *ret_len = nbytes;
630         }
631     }
632   else if (control == IOBUFCTRL_FLUSH)
633     {
634       if (size)
635         {
636           byte *p = buf;
637           int n;
638
639           nbytes = size;
640           do
641             {
642               n = send (a->sock, p, nbytes, 0);
643               if (n == SOCKET_ERROR)
644                 {
645                   int ec = (int) WSAGetLastError ();
646                   rc = gpg_error_from_errno (ec);
647                   log_error ("socket write error: ec=%d\n", ec);
648                   break;
649                 }
650               p += n;
651               nbytes -= n;
652             }
653           while (nbytes);
654           nbytes = p - buf;
655         }
656       *ret_len = nbytes;
657     }
658   else if (control == IOBUFCTRL_INIT)
659     {
660       a->eof_seen = 0;
661       a->keep_open = 0;
662       a->no_cache = 0;
663     }
664   else if (control == IOBUFCTRL_DESC)
665     {
666       *(char **) buf = "sock_filter";
667     }
668   else if (control == IOBUFCTRL_FREE)
669     {
670       if (!a->keep_open)
671         closesocket (a->sock);
672       xfree (a);                /* we can free our context now */
673     }
674   return rc;
675 }
676 #endif /*_WIN32*/
677
678 /****************
679  * This is used to implement the block write mode.
680  * Block reading is done on a byte by byte basis in readbyte(),
681  * without a filter
682  */
683 static int
684 block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
685               size_t * ret_len)
686 {
687   block_filter_ctx_t *a = opaque;
688   char *buf = (char *)buffer;
689   size_t size = *ret_len;
690   int c, needed, rc = 0;
691   char *p;
692
693   if (control == IOBUFCTRL_UNDERFLOW)
694     {
695       size_t n = 0;
696
697       p = buf;
698       assert (size);            /* need a buffer */
699       if (a->eof)               /* don't read any further */
700         rc = -1;
701       while (!rc && size)
702         {
703           if (!a->size)
704             {                   /* get the length bytes */
705               if (a->partial == 2)
706                 {
707                   a->eof = 1;
708                   if (!n)
709                     rc = -1;
710                   break;
711                 }
712               else if (a->partial)
713                 {
714                   /* These OpenPGP introduced huffman like encoded length
715                    * bytes are really a mess :-( */
716                   if (a->first_c)
717                     {
718                       c = a->first_c;
719                       a->first_c = 0;
720                     }
721                   else if ((c = iobuf_get (chain)) == -1)
722                     {
723                       log_error ("block_filter: 1st length byte missing\n");
724                       rc = GPG_ERR_BAD_DATA;
725                       break;
726                     }
727                   if (c < 192)
728                     {
729                       a->size = c;
730                       a->partial = 2;
731                       if (!a->size)
732                         {
733                           a->eof = 1;
734                           if (!n)
735                             rc = -1;
736                           break;
737                         }
738                     }
739                   else if (c < 224)
740                     {
741                       a->size = (c - 192) * 256;
742                       if ((c = iobuf_get (chain)) == -1)
743                         {
744                           log_error
745                             ("block_filter: 2nd length byte missing\n");
746                           rc = GPG_ERR_BAD_DATA;
747                           break;
748                         }
749                       a->size += c + 192;
750                       a->partial = 2;
751                       if (!a->size)
752                         {
753                           a->eof = 1;
754                           if (!n)
755                             rc = -1;
756                           break;
757                         }
758                     }
759                   else if (c == 255)
760                     {
761                       a->size = iobuf_get (chain) << 24;
762                       a->size |= iobuf_get (chain) << 16;
763                       a->size |= iobuf_get (chain) << 8;
764                       if ((c = iobuf_get (chain)) == -1)
765                         {
766                           log_error ("block_filter: invalid 4 byte length\n");
767                           rc = GPG_ERR_BAD_DATA;
768                           break;
769                         }
770                       a->size |= c;
771                       a->partial = 2;
772                       if (!a->size)
773                         {
774                           a->eof = 1;
775                           if (!n)
776                             rc = -1;
777                           break;
778                         }
779                     }
780                   else
781                     { /* Next partial body length. */
782                       a->size = 1 << (c & 0x1f);
783                     }
784                   /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size); */
785                 }
786               else
787                 BUG (); 
788             }
789
790           while (!rc && size && a->size)
791             {
792               needed = size < a->size ? size : a->size;
793               c = iobuf_read (chain, p, needed);
794               if (c < needed)
795                 {
796                   if (c == -1)
797                     c = 0;
798                   log_error
799                     ("block_filter %p: read error (size=%lu,a->size=%lu)\n",
800                      a, (ulong) size + c, (ulong) a->size + c);
801                   rc = GPG_ERR_BAD_DATA;
802                 }
803               else
804                 {
805                   size -= c;
806                   a->size -= c;
807                   p += c;
808                   n += c;
809                 }
810             }
811         }
812       *ret_len = n;
813     }
814   else if (control == IOBUFCTRL_FLUSH)
815     {
816       if (a->partial)
817         {                       /* the complicated openpgp scheme */
818           size_t blen, n, nbytes = size + a->buflen;
819
820           assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
821           if (nbytes < OP_MIN_PARTIAL_CHUNK)
822             {
823               /* not enough to write a partial block out; so we store it */
824               if (!a->buffer)
825                 a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
826               memcpy (a->buffer + a->buflen, buf, size);
827               a->buflen += size;
828             }
829           else
830             {                   /* okay, we can write out something */
831               /* do this in a loop to use the most efficient block lengths */
832               p = buf;
833               do
834                 {
835                   /* find the best matching block length - this is limited
836                    * by the size of the internal buffering */
837                   for (blen = OP_MIN_PARTIAL_CHUNK * 2,
838                        c = OP_MIN_PARTIAL_CHUNK_2POW + 1; blen <= nbytes;
839                        blen *= 2, c++)
840                     ;
841                   blen /= 2;
842                   c--;
843                   /* write the partial length header */
844                   assert (c <= 0x1f);   /*;-) */
845                   c |= 0xe0;
846                   iobuf_put (chain, c);
847                   if ((n = a->buflen))
848                     {           /* write stuff from the buffer */
849                       assert (n == OP_MIN_PARTIAL_CHUNK);
850                       if (iobuf_write (chain, a->buffer, n))
851                         rc = gpg_error_from_syserror ();
852                       a->buflen = 0;
853                       nbytes -= n;
854                     }
855                   if ((n = nbytes) > blen)
856                     n = blen;
857                   if (n && iobuf_write (chain, p, n))
858                     rc = gpg_error_from_syserror ();
859                   p += n;
860                   nbytes -= n;
861                 }
862               while (!rc && nbytes >= OP_MIN_PARTIAL_CHUNK);
863               /* store the rest in the buffer */
864               if (!rc && nbytes)
865                 {
866                   assert (!a->buflen);
867                   assert (nbytes < OP_MIN_PARTIAL_CHUNK);
868                   if (!a->buffer)
869                     a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
870                   memcpy (a->buffer, p, nbytes);
871                   a->buflen = nbytes;
872                 }
873             }
874         }
875       else
876         BUG ();
877     }
878   else if (control == IOBUFCTRL_INIT)
879     {
880       if (DBG_IOBUF)
881         log_debug ("init block_filter %p\n", a);
882       if (a->partial)
883         a->count = 0;
884       else if (a->use == 1)
885         a->count = a->size = 0;
886       else
887         a->count = a->size;     /* force first length bytes */
888       a->eof = 0;
889       a->buffer = NULL;
890       a->buflen = 0;
891     }
892   else if (control == IOBUFCTRL_DESC)
893     {
894       *(char **) buf = "block_filter";
895     }
896   else if (control == IOBUFCTRL_FREE)
897     {
898       if (a->use == 2)
899         {                       /* write the end markers */
900           if (a->partial)
901             {
902               u32 len;
903               /* write out the remaining bytes without a partial header
904                * the length of this header may be 0 - but if it is
905                * the first block we are not allowed to use a partial header
906                * and frankly we can't do so, because this length must be
907                * a power of 2. This is _really_ complicated because we
908                * have to check the possible length of a packet prior
909                * to it's creation: a chain of filters becomes complicated
910                * and we need a lot of code to handle compressed packets etc.
911                *   :-(((((((
912                */
913               /* construct header */
914               len = a->buflen;
915               /*log_debug("partial: remaining length=%u\n", len ); */
916               if (len < 192)
917                 rc = iobuf_put (chain, len);
918               else if (len < 8384)
919                 {
920                   if (!(rc = iobuf_put (chain, ((len - 192) / 256) + 192)))
921                     rc = iobuf_put (chain, ((len - 192) % 256));
922                 }
923               else
924                 {               /* use a 4 byte header */
925                   if (!(rc = iobuf_put (chain, 0xff)))
926                     if (!(rc = iobuf_put (chain, (len >> 24) & 0xff)))
927                       if (!(rc = iobuf_put (chain, (len >> 16) & 0xff)))
928                         if (!(rc = iobuf_put (chain, (len >> 8) & 0xff)))
929                           rc = iobuf_put (chain, len & 0xff);
930                 }
931               if (!rc && len)
932                 rc = iobuf_write (chain, a->buffer, len);
933               if (rc)
934                 {
935                   log_error ("block_filter: write error: %s\n",
936                              strerror (errno));
937                   rc = gpg_error_from_syserror ();
938                 }
939               xfree (a->buffer);
940               a->buffer = NULL;
941               a->buflen = 0;
942             }
943           else
944             BUG ();
945         }
946       else if (a->size)
947         {
948           log_error ("block_filter: pending bytes!\n");
949         }
950       if (DBG_IOBUF)
951         log_debug ("free block_filter %p\n", a);
952       xfree (a);                /* we can free our context now */
953     }
954
955   return rc;
956 }
957
958
959 static void
960 print_chain (iobuf_t a)
961 {
962   if (!DBG_IOBUF)
963     return;
964   for (; a; a = a->chain)
965     {
966       size_t dummy_len = 0;
967       const char *desc = "[none]";
968
969       if (a->filter)
970         a->filter (a->filter_ov, IOBUFCTRL_DESC, NULL,
971                    (byte *) & desc, &dummy_len);
972
973       log_debug ("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
974                  a->no, a->subno, desc, a->filter_eof,
975                  (int) a->d.start, (int) a->d.len);
976     }
977 }
978
979 int
980 iobuf_print_chain (iobuf_t a)
981 {
982   print_chain (a);
983   return 0;
984 }
985
986 /****************
987  * Allocate a new io buffer, with no function assigned.
988  * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
989  * BUFSIZE is a suggested buffer size.
990  */
991 iobuf_t
992 iobuf_alloc (int use, size_t bufsize)
993 {
994   iobuf_t a;
995   static int number = 0;
996
997   a = xcalloc (1, sizeof *a);
998   a->use = use;
999   a->d.buf = xmalloc (bufsize);
1000   a->d.size = bufsize;
1001   a->no = ++number;
1002   a->subno = 0;
1003   a->opaque = NULL;
1004   a->real_fname = NULL;
1005   return a;
1006 }
1007
1008 int
1009 iobuf_close (iobuf_t a)
1010 {
1011   iobuf_t a2;
1012   size_t dummy_len = 0;
1013   int rc = 0;
1014
1015   if (a && a->directfp)
1016     {
1017       fclose (a->directfp);
1018       xfree (a->real_fname);
1019       if (DBG_IOBUF)
1020         log_debug ("iobuf_close -> %p\n", a->directfp);
1021       return 0;
1022     }
1023
1024   for (; a && !rc; a = a2)
1025     {
1026       a2 = a->chain;
1027       if (a->use == 2 && (rc = iobuf_flush (a)))
1028         log_error ("iobuf_flush failed on close: %s\n", gpg_strerror (rc));
1029
1030       if (DBG_IOBUF)
1031         log_debug ("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc);
1032       if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_FREE,
1033                                         a->chain, NULL, &dummy_len)))
1034         log_error ("IOBUFCTRL_FREE failed on close: %s\n", gpg_strerror (rc));
1035       xfree (a->real_fname);
1036       if (a->d.buf)
1037         {
1038           memset (a->d.buf, 0, a->d.size);      /* erase the buffer */
1039           xfree (a->d.buf);
1040           xfree (a->unget.buf);
1041         }
1042       xfree (a);
1043     }
1044   return rc;
1045 }
1046
1047 int
1048 iobuf_cancel (iobuf_t a)
1049 {
1050   const char *s;
1051   iobuf_t a2;
1052   int rc;
1053 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
1054   char *remove_name = NULL;
1055 #endif
1056
1057   if (a && a->use == 2)
1058     {
1059       s = iobuf_get_real_fname (a);
1060       if (s && *s)
1061         {
1062 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
1063           remove_name = xstrdup (s);
1064 #else
1065           remove (s);
1066 #endif
1067         }
1068     }
1069
1070   /* send a cancel message to all filters */
1071   for (a2 = a; a2; a2 = a2->chain)
1072     {
1073       size_t dummy;
1074       if (a2->filter)
1075         a2->filter (a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain, NULL, &dummy);
1076     }
1077
1078   rc = iobuf_close (a);
1079 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
1080   if (remove_name)
1081     {
1082       /* Argg, MSDOS does not allow to remove open files.  So
1083        * we have to do it here */
1084       remove (remove_name);
1085       xfree (remove_name);
1086     }
1087 #endif
1088   return rc;
1089 }
1090
1091
1092 /****************
1093  * create a temporary iobuf, which can be used to collect stuff
1094  * in an iobuf and later be written by iobuf_write_temp() to another
1095  * iobuf.
1096  */
1097 iobuf_t
1098 iobuf_temp ()
1099 {
1100   iobuf_t a;
1101
1102   a = iobuf_alloc (3, 8192);
1103
1104   return a;
1105 }
1106
1107 iobuf_t
1108 iobuf_temp_with_content (const char *buffer, size_t length)
1109 {
1110   iobuf_t a;
1111
1112   a = iobuf_alloc (3, length);
1113   memcpy (a->d.buf, buffer, length);
1114   a->d.len = length;
1115
1116   return a;
1117 }
1118
1119 void
1120 iobuf_enable_special_filenames (int yes)
1121 {
1122   special_names_enabled = yes;
1123 }
1124
1125
1126 /* See whether the filename has the form "-&nnnn", where n is a
1127    non-zero number.  Returns this number or -1 if it is not the
1128    case.  */
1129 static int
1130 check_special_filename (const char *fname)
1131 {
1132   if (special_names_enabled && fname && *fname == '-' && fname[1] == '&')
1133     {
1134       int i;
1135
1136       fname += 2;
1137       for (i = 0; digitp (fname+i); i++)
1138         ;
1139       if (!fname[i])
1140         return atoi (fname);
1141     }
1142   return -1;
1143 }
1144
1145
1146 /* This fucntion returns true if FNAME indicates a PIPE (stdout or
1147    stderr) or a special file name if those are enabled. */
1148 int
1149 iobuf_is_pipe_filename (const char *fname)
1150 {
1151   if (!fname || (*fname=='-' && !fname[1]) )
1152     return 1;
1153   return check_special_filename (fname) != -1;
1154 }
1155
1156 /****************
1157  * Create a head iobuf for reading from a file
1158  * returns: NULL if an error occures and sets errno
1159  */
1160 iobuf_t
1161 iobuf_open (const char *fname)
1162 {
1163   iobuf_t a;
1164   FILEP_OR_FD fp;
1165   file_filter_ctx_t *fcx;
1166   size_t len;
1167   int print_only = 0;
1168   int fd;
1169
1170   if (!fname || (*fname == '-' && !fname[1]))
1171     {
1172       fp = FILEP_OR_FD_FOR_STDIN;
1173 #ifdef USE_SETMODE
1174       setmode (my_fileno (fp), O_BINARY);
1175 #endif
1176       fname = "[stdin]";
1177       print_only = 1;
1178     }
1179   else if ((fd = check_special_filename (fname)) != -1)
1180     return iobuf_fdopen (translate_file_handle (fd, 0), "rb");
1181   else if ((fp = my_fopen_ro (fname, "rb")) == INVALID_FP)
1182     return NULL;
1183   a = iobuf_alloc (1, 8192);
1184   fcx = xmalloc (sizeof *fcx + strlen (fname));
1185   fcx->fp = fp;
1186   fcx->print_only_name = print_only;
1187   strcpy (fcx->fname, fname);
1188   if (!print_only)
1189     a->real_fname = xstrdup (fname);
1190   a->filter = file_filter;
1191   a->filter_ov = fcx;
1192   file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
1193   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1194   if (DBG_IOBUF)
1195     log_debug ("iobuf-%d.%d: open `%s' fd=%d\n",
1196                a->no, a->subno, fname, (int) my_fileno (fcx->fp));
1197
1198   return a;
1199 }
1200
1201 /****************
1202  * Create a head iobuf for reading from a file
1203  * returns: NULL if an error occures and sets errno
1204  */
1205 iobuf_t
1206 iobuf_fdopen (int fd, const char *mode)
1207 {
1208   iobuf_t a;
1209   FILEP_OR_FD fp;
1210   file_filter_ctx_t *fcx;
1211   size_t len;
1212
1213 #ifdef FILE_FILTER_USES_STDIO
1214   if (!(fp = fdopen (fd, mode)))
1215     return NULL;
1216 #else
1217   fp = (FILEP_OR_FD) fd;
1218 #endif
1219   a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192);
1220   fcx = xmalloc (sizeof *fcx + 20);
1221   fcx->fp = fp;
1222   fcx->print_only_name = 1;
1223   sprintf (fcx->fname, "[fd %d]", fd);
1224   a->filter = file_filter;
1225   a->filter_ov = fcx;
1226   file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
1227   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1228   if (DBG_IOBUF)
1229     log_debug ("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname);
1230   iobuf_ioctl (a, 3, 1, NULL);  /* disable fd caching */
1231   return a;
1232 }
1233
1234
1235 iobuf_t
1236 iobuf_sockopen (int fd, const char *mode)
1237 {
1238   iobuf_t a;
1239 #ifdef _WIN32
1240   sock_filter_ctx_t *scx;
1241   size_t len;
1242
1243   a = iobuf_alloc (strchr (mode, 'w') ? 2 : 1, 8192);
1244   scx = xmalloc (sizeof *scx + 25);
1245   scx->sock = fd;
1246   scx->print_only_name = 1;
1247   sprintf (scx->fname, "[sock %d]", fd);
1248   a->filter = sock_filter;
1249   a->filter_ov = scx;
1250   sock_filter (scx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
1251   sock_filter (scx, IOBUFCTRL_INIT, NULL, NULL, &len);
1252   if (DBG_IOBUF)
1253     log_debug ("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
1254   iobuf_ioctl (a, 3, 1, NULL);  /* disable fd caching */
1255 #else
1256   a = iobuf_fdopen (fd, mode);
1257 #endif
1258   return a;
1259 }
1260
1261 /****************
1262  * create an iobuf for writing to a file; the file will be created.
1263  */
1264 iobuf_t
1265 iobuf_create (const char *fname)
1266 {
1267   iobuf_t a;
1268   FILEP_OR_FD fp;
1269   file_filter_ctx_t *fcx;
1270   size_t len;
1271   int print_only = 0;
1272   int fd;
1273
1274   if (!fname || (*fname == '-' && !fname[1]))
1275     {
1276       fp = FILEP_OR_FD_FOR_STDOUT;
1277 #ifdef USE_SETMODE
1278       setmode (my_fileno (fp), O_BINARY);
1279 #endif
1280       fname = "[stdout]";
1281       print_only = 1;
1282     }
1283   else if ((fd = check_special_filename (fname)) != -1)
1284     return iobuf_fdopen (translate_file_handle (fd, 1), "wb");
1285   else if ((fp = my_fopen (fname, "wb")) == INVALID_FP)
1286     return NULL;
1287   a = iobuf_alloc (2, 8192);
1288   fcx = xmalloc (sizeof *fcx + strlen (fname));
1289   fcx->fp = fp;
1290   fcx->print_only_name = print_only;
1291   strcpy (fcx->fname, fname);
1292   if (!print_only)
1293     a->real_fname = xstrdup (fname);
1294   a->filter = file_filter;
1295   a->filter_ov = fcx;
1296   file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
1297   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1298   if (DBG_IOBUF)
1299     log_debug ("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc);
1300
1301   return a;
1302 }
1303
1304 /****************
1305  * append to an iobuf; if the file does not exist, create it.
1306  * cannot be used for stdout.
1307  * Note: This is not used.
1308  */
1309 #if 0                           /* not used */
1310 iobuf_t
1311 iobuf_append (const char *fname)
1312 {
1313   iobuf_t a;
1314   FILE *fp;
1315   file_filter_ctx_t *fcx;
1316   size_t len;
1317
1318   if (!fname)
1319     return NULL;
1320   else if (!(fp = my_fopen (fname, "ab")))
1321     return NULL;
1322   a = iobuf_alloc (2, 8192);
1323   fcx = m_alloc (sizeof *fcx + strlen (fname));
1324   fcx->fp = fp;
1325   strcpy (fcx->fname, fname);
1326   a->real_fname = m_strdup (fname);
1327   a->filter = file_filter;
1328   a->filter_ov = fcx;
1329   file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
1330   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1331   if (DBG_IOBUF)
1332     log_debug ("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc);
1333
1334   return a;
1335 }
1336 #endif
1337
1338 iobuf_t
1339 iobuf_openrw (const char *fname)
1340 {
1341   iobuf_t a;
1342   FILEP_OR_FD fp;
1343   file_filter_ctx_t *fcx;
1344   size_t len;
1345
1346   if (!fname)
1347     return NULL;
1348   else if ((fp = my_fopen (fname, "r+b")) == INVALID_FP)
1349     return NULL;
1350   a = iobuf_alloc (2, 8192);
1351   fcx = xmalloc (sizeof *fcx + strlen (fname));
1352   fcx->fp = fp;
1353   strcpy (fcx->fname, fname);
1354   a->real_fname = xstrdup (fname);
1355   a->filter = file_filter;
1356   a->filter_ov = fcx;
1357   file_filter (fcx, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &len);
1358   file_filter (fcx, IOBUFCTRL_INIT, NULL, NULL, &len);
1359   if (DBG_IOBUF)
1360     log_debug ("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc);
1361
1362   return a;
1363 }
1364
1365
1366 int
1367 iobuf_ioctl (iobuf_t a, int cmd, int intval, void *ptrval)
1368 {
1369   if (cmd == 1)
1370     {                           /* keep system filepointer/descriptor open */
1371       if (DBG_IOBUF)
1372         log_debug ("iobuf-%d.%d: ioctl `%s' keep=%d\n",
1373                    a ? a->no : -1, a ? a->subno : -1, a ? a->desc : "?",
1374                    intval);
1375       for (; a; a = a->chain)
1376         if (!a->chain && a->filter == file_filter)
1377           {
1378             file_filter_ctx_t *b = a->filter_ov;
1379             b->keep_open = intval;
1380             return 0;
1381           }
1382 #ifdef _WIN32
1383         else if (!a->chain && a->filter == sock_filter)
1384           {
1385             sock_filter_ctx_t *b = a->filter_ov;
1386             b->keep_open = intval;
1387             return 0;
1388           }
1389 #endif
1390     }
1391   else if (cmd == 2)
1392     {                           /* invalidate cache */
1393       if (DBG_IOBUF)
1394         log_debug ("iobuf-*.*: ioctl `%s' invalidate\n",
1395                    ptrval ? (char *) ptrval : "?");
1396       if (!a && !intval && ptrval)
1397         {
1398 #ifndef FILE_FILTER_USES_STDIO
1399           fd_cache_invalidate (ptrval);
1400 #endif
1401           return 0;
1402         }
1403     }
1404   else if (cmd == 3)
1405     {                           /* disallow/allow caching */
1406       if (DBG_IOBUF)
1407         log_debug ("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
1408                    a ? a->no : -1, a ? a->subno : -1, a ? a->desc : "?",
1409                    intval);
1410       for (; a; a = a->chain)
1411         if (!a->chain && a->filter == file_filter)
1412           {
1413             file_filter_ctx_t *b = a->filter_ov;
1414             b->no_cache = intval;
1415             return 0;
1416           }
1417 #ifdef _WIN32
1418         else if (!a->chain && a->filter == sock_filter)
1419           {
1420             sock_filter_ctx_t *b = a->filter_ov;
1421             b->no_cache = intval;
1422             return 0;
1423           }
1424 #endif
1425     }
1426
1427   return -1;
1428 }
1429
1430
1431 /****************
1432  * Register an i/o filter.
1433  */
1434 int
1435 iobuf_push_filter (iobuf_t a,
1436                    int (*f) (void *opaque, int control,
1437                              iobuf_t chain, byte * buf, size_t * len),
1438                    void *ov)
1439 {
1440   return iobuf_push_filter2 (a, f, ov, 0);
1441 }
1442
1443 int
1444 iobuf_push_filter2 (iobuf_t a,
1445                     int (*f) (void *opaque, int control,
1446                               iobuf_t chain, byte * buf, size_t * len),
1447                     void *ov, int rel_ov)
1448 {
1449   iobuf_t b;
1450   size_t dummy_len = 0;
1451   int rc = 0;
1452
1453   if (a->directfp)
1454     BUG ();
1455
1456   if (a->use == 2 && (rc = iobuf_flush (a)))
1457     return rc;
1458   /* make a copy of the current stream, so that
1459    * A is the new stream and B the original one.
1460    * The contents of the buffers are transferred to the
1461    * new stream.
1462    */
1463   b = xmalloc (sizeof *b);
1464   memcpy (b, a, sizeof *b);
1465   /* fixme: it is stupid to keep a copy of the name at every level
1466    * but we need the name somewhere because the name known by file_filter
1467    * may have been released when we need the name of the file */
1468   b->real_fname = a->real_fname ? xstrdup (a->real_fname) : NULL;
1469   /* remove the filter stuff from the new stream */
1470   a->filter = NULL;
1471   a->filter_ov = NULL;
1472   a->filter_ov_owner = 0;
1473   a->filter_eof = 0;
1474   if (a->use == 3)
1475     a->use = 2;                 /* make a write stream from a temp stream */
1476
1477   if (a->use == 2)
1478     {                           /* allocate a fresh buffer for the
1479                                    original stream */
1480       b->d.buf = xmalloc (a->d.size);
1481       b->d.len = 0;
1482       b->d.start = 0;
1483     }
1484   else
1485     {                           /* allocate a fresh buffer for the new
1486                                    stream */
1487       a->d.buf = xmalloc (a->d.size);
1488       a->d.len = 0;
1489       a->d.start = 0;
1490     }
1491   /* disable nlimit for the new stream */
1492   a->ntotal = b->ntotal + b->nbytes;
1493   a->nlimit = a->nbytes = 0;
1494   a->nofast &= ~1;
1495   /* make a link from the new stream to the original stream */
1496   a->chain = b;
1497   a->opaque = b->opaque;
1498
1499   /* setup the function on the new stream */
1500   a->filter = f;
1501   a->filter_ov = ov;
1502   a->filter_ov_owner = rel_ov;
1503
1504   a->subno = b->subno + 1;
1505   f (ov, IOBUFCTRL_DESC, NULL, (byte *) & a->desc, &dummy_len);
1506
1507   if (DBG_IOBUF)
1508     {
1509       log_debug ("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc);
1510       print_chain (a);
1511     }
1512
1513   /* now we can initialize the new function if we have one */
1514   if (a->filter && (rc = a->filter (a->filter_ov, IOBUFCTRL_INIT, a->chain,
1515                                     NULL, &dummy_len)))
1516     log_error ("IOBUFCTRL_INIT failed: %s\n", gpg_strerror (rc));
1517   return rc;
1518 }
1519
1520 /****************
1521  * Remove an i/o filter.
1522  */
1523 static int
1524 pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
1525                                iobuf_t chain, byte * buf, size_t * len),
1526             void *ov)
1527 {
1528   iobuf_t b;
1529   size_t dummy_len = 0;
1530   int rc = 0;
1531
1532   if (a->directfp)
1533     BUG ();
1534
1535   if (DBG_IOBUF)
1536     log_debug ("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc);
1537   if (!a->filter)
1538     {                           /* this is simple */
1539       b = a->chain;
1540       assert (b);
1541       xfree (a->d.buf);
1542       xfree (a->unget.buf);
1543       xfree (a->real_fname);
1544       memcpy (a, b, sizeof *a);
1545       xfree (b);
1546       return 0;
1547     }
1548   for (b = a; b; b = b->chain)
1549     if (b->filter == f && (!ov || b->filter_ov == ov))
1550       break;
1551   if (!b)
1552     log_bug ("pop_filter(): filter function not found\n");
1553
1554   /* flush this stream if it is an output stream */
1555   if (a->use == 2 && (rc = iobuf_flush (b)))
1556     {
1557       log_error ("iobuf_flush failed in pop_filter: %s\n", gpg_strerror (rc));
1558       return rc;
1559     }
1560   /* and tell the filter to free it self */
1561   if (b->filter && (rc = b->filter (b->filter_ov, IOBUFCTRL_FREE, b->chain,
1562                                     NULL, &dummy_len)))
1563     {
1564       log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
1565       return rc;
1566     }
1567   if (b->filter_ov && b->filter_ov_owner)
1568     {
1569       xfree (b->filter_ov);
1570       b->filter_ov = NULL;
1571     }
1572
1573
1574   /* and see how to remove it */
1575   if (a == b && !b->chain)
1576     log_bug ("can't remove the last filter from the chain\n");
1577   else if (a == b)
1578     {                           /* remove the first iobuf from the chain */
1579       /* everything from b is copied to a. This is save because
1580        * a flush has been done on the to be removed entry
1581        */
1582       b = a->chain;
1583       xfree (a->d.buf);
1584       xfree (a->unget.buf);
1585       xfree (a->real_fname);
1586       memcpy (a, b, sizeof *a);
1587       xfree (b);
1588       if (DBG_IOBUF)
1589         log_debug ("iobuf-%d.%d: popped filter\n", a->no, a->subno);
1590     }
1591   else if (!b->chain)
1592     {                           /* remove the last iobuf from the chain */
1593       log_bug ("Ohh jeee, trying to remove a head filter\n");
1594     }
1595   else
1596     {                           /* remove an intermediate iobuf from the chain */
1597       log_bug ("Ohh jeee, trying to remove an intermediate filter\n");
1598     }
1599
1600   return rc;
1601 }
1602
1603
1604 /****************
1605  * read underflow: read more bytes into the buffer and return
1606  * the first byte or -1 on EOF.
1607  */
1608 static int
1609 underflow (iobuf_t a)
1610 {
1611   size_t len;
1612   int rc;
1613
1614   assert (a->d.start == a->d.len);
1615   if (a->use == 3)
1616     return -1;                  /* EOF because a temp buffer can't do an underflow */
1617
1618   if (a->filter_eof)
1619     {
1620       if (a->chain)
1621         {
1622           iobuf_t b = a->chain;
1623           if (DBG_IOBUF)
1624             log_debug ("iobuf-%d.%d: pop `%s' in underflow\n",
1625                        a->no, a->subno, a->desc);
1626           xfree (a->d.buf);
1627           xfree (a->unget.buf);
1628           xfree (a->real_fname);
1629           memcpy (a, b, sizeof *a);
1630           xfree (b);
1631           print_chain (a);
1632         }
1633       else
1634         a->filter_eof = 0;      /* for the top level filter */
1635       if (DBG_IOBUF)
1636         log_debug ("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
1637                    a->no, a->subno);
1638       return -1;                /* return one(!) EOF */
1639     }
1640   if (a->error)
1641     {
1642       if (DBG_IOBUF)
1643         log_debug ("iobuf-%d.%d: error\n", a->no, a->subno);
1644       return -1;
1645     }
1646
1647   if (a->directfp)
1648     {
1649       FILE *fp = a->directfp;
1650
1651       len = fread (a->d.buf, 1, a->d.size, fp);
1652       if (len < a->d.size)
1653         {
1654           if (ferror (fp))
1655             a->error = gpg_error_from_syserror ();
1656         }
1657       a->d.len = len;
1658       a->d.start = 0;
1659       return len ? a->d.buf[a->d.start++] : -1;
1660     }
1661
1662
1663   if (a->filter)
1664     {
1665       len = a->d.size;
1666       if (DBG_IOBUF)
1667         log_debug ("iobuf-%d.%d: underflow: req=%lu\n",
1668                    a->no, a->subno, (ulong) len);
1669       rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
1670                       a->d.buf, &len);
1671       if (DBG_IOBUF)
1672         {
1673           log_debug ("iobuf-%d.%d: underflow: got=%lu rc=%d\n",
1674                      a->no, a->subno, (ulong) len, rc);
1675 /*          if( a->no == 1 ) */
1676 /*                   log_hexdump ("     data:", a->d.buf, len); */
1677         }
1678       if (a->use == 1 && rc == -1)
1679         {                       /* EOF: we can remove the filter */
1680           size_t dummy_len = 0;
1681
1682           /* and tell the filter to free itself */
1683           if ((rc = a->filter (a->filter_ov, IOBUFCTRL_FREE, a->chain,
1684                                NULL, &dummy_len)))
1685             log_error ("IOBUFCTRL_FREE failed: %s\n", gpg_strerror (rc));
1686           if (a->filter_ov && a->filter_ov_owner)
1687             {
1688               xfree (a->filter_ov);
1689               a->filter_ov = NULL;
1690             }
1691           a->filter = NULL;
1692           a->desc = NULL;
1693           a->filter_ov = NULL;
1694           a->filter_eof = 1;
1695           if (!len && a->chain)
1696             {
1697               iobuf_t b = a->chain;
1698               if (DBG_IOBUF)
1699                 log_debug ("iobuf-%d.%d: pop `%s' in underflow (!len)\n",
1700                            a->no, a->subno, a->desc);
1701               xfree (a->d.buf);
1702               xfree (a->unget.buf);
1703               xfree (a->real_fname);
1704               memcpy (a, b, sizeof *a);
1705               xfree (b);
1706               print_chain (a);
1707             }
1708         }
1709       else if (rc)
1710         a->error = rc;
1711
1712       if (!len)
1713         {
1714           if (DBG_IOBUF)
1715             log_debug ("iobuf-%d.%d: underflow: eof\n", a->no, a->subno);
1716           return -1;
1717         }
1718       a->d.len = len;
1719       a->d.start = 0;
1720       return a->d.buf[a->d.start++];
1721     }
1722   else
1723     {
1724       if (DBG_IOBUF)
1725         log_debug ("iobuf-%d.%d: underflow: eof (no filter)\n",
1726                    a->no, a->subno);
1727       return -1;                /* no filter; return EOF */
1728     }
1729 }
1730
1731
1732 int
1733 iobuf_flush (iobuf_t a)
1734 {
1735   size_t len;
1736   int rc;
1737
1738   if (a->directfp)
1739     return 0;
1740
1741   if (a->use == 3)
1742     {                           /* increase the temp buffer */
1743       unsigned char *newbuf;
1744       size_t newsize = a->d.size + 8192;
1745
1746       if (DBG_IOBUF)
1747         log_debug ("increasing temp iobuf from %lu to %lu\n",
1748                    (ulong) a->d.size, (ulong) newsize);
1749       newbuf = xmalloc (newsize);
1750       memcpy (newbuf, a->d.buf, a->d.len);
1751       xfree (a->d.buf);
1752       a->d.buf = newbuf;
1753       a->d.size = newsize;
1754       return 0;
1755     }
1756   else if (a->use != 2)
1757     log_bug ("flush on non-output iobuf\n");
1758   else if (!a->filter)
1759     log_bug ("iobuf_flush: no filter\n");
1760   len = a->d.len;
1761   rc = a->filter (a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len);
1762   if (!rc && len != a->d.len)
1763     {
1764       log_info ("iobuf_flush did not write all!\n");
1765       rc = GPG_ERR_INTERNAL;
1766     }
1767   else if (rc)
1768     a->error = rc;
1769   a->d.len = 0;
1770
1771   return rc;
1772 }
1773
1774
1775 /****************
1776  * Read a byte from the iobuf; returns -1 on EOF
1777  */
1778 int
1779 iobuf_readbyte (iobuf_t a)
1780 {
1781   int c;
1782
1783   /* nlimit does not work together with unget */
1784   /* nbytes is also not valid! */
1785   if (a->unget.buf)
1786     {
1787       if (a->unget.start < a->unget.len)
1788         return a->unget.buf[a->unget.start++];
1789       xfree (a->unget.buf);
1790       a->unget.buf = NULL;
1791       a->nofast &= ~2;
1792     }
1793
1794   if (a->nlimit && a->nbytes >= a->nlimit)
1795     return -1;                  /* forced EOF */
1796
1797   if (a->d.start < a->d.len)
1798     {
1799       c = a->d.buf[a->d.start++];
1800     }
1801   else if ((c = underflow (a)) == -1)
1802     return -1;                  /* EOF */
1803
1804   a->nbytes++;
1805   return c;
1806 }
1807
1808
1809 int
1810 iobuf_read (iobuf_t a, void *buffer, unsigned int buflen)
1811 {
1812   unsigned char *buf = (unsigned char *)buffer;
1813   int c, n;
1814
1815   if (a->unget.buf || a->nlimit)
1816     {
1817       /* handle special cases */
1818       for (n = 0; n < buflen; n++)
1819         {
1820           if ((c = iobuf_readbyte (a)) == -1)
1821             {
1822               if (!n)
1823                 return -1;      /* eof */
1824               break;
1825             }
1826           else if (buf)
1827             *buf = c;
1828           if (buf)
1829             buf++;
1830         }
1831       return n;
1832     }
1833
1834   n = 0;
1835   do
1836     {
1837       if (n < buflen && a->d.start < a->d.len)
1838         {
1839           unsigned size = a->d.len - a->d.start;
1840           if (size > buflen - n)
1841             size = buflen - n;
1842           if (buf)
1843             memcpy (buf, a->d.buf + a->d.start, size);
1844           n += size;
1845           a->d.start += size;
1846           if (buf)
1847             buf += size;
1848         }
1849       if (n < buflen)
1850         {
1851           if ((c = underflow (a)) == -1)
1852             {
1853               a->nbytes += n;
1854               return n ? n : -1 /*EOF*/;
1855             }
1856           if (buf)
1857             *buf++ = c;
1858           n++;
1859         }
1860     }
1861   while (n < buflen);
1862   a->nbytes += n;
1863   return n;
1864 }
1865
1866
1867
1868 /* This is a verly limited unget fucntion for an iobuf.  It does only
1869    work in certain cases and should be used with care. */
1870 void
1871 iobuf_unread (iobuf_t a, const unsigned char *buf, unsigned int buflen)
1872 {
1873   unsigned int new_len;
1874   
1875   if (!buflen)
1876     return;
1877
1878   /* We always relocate the buffer, which is not optimal.  However,
1879      the code is easier to read this way, and it is not on the fast
1880      path. */
1881   if ( !a->unget.buf )
1882     a->unget.size = a->unget.start = a->unget.len = 0;
1883
1884   new_len = a->unget.len + buflen;
1885   a->unget.buf = xrealloc(a->unget.buf, new_len);
1886   memcpy(a->unget.buf + a->unget.len, buf, buflen);
1887   a->unget.len = new_len;
1888   a->nofast |= 2;
1889 }
1890
1891
1892 /****************
1893  * Have a look at the iobuf.
1894  * NOTE: This only works in special cases.
1895  */
1896 int
1897 iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
1898 {
1899   int n = 0;
1900
1901   if (a->filter_eof)
1902     return -1;
1903
1904   if (!(a->d.start < a->d.len))
1905     {
1906       if (underflow (a) == -1)
1907         return -1;
1908       /* and unget this character */
1909       assert (a->d.start == 1);
1910       a->d.start = 0;
1911     }
1912
1913   for (n = 0; n < buflen && (a->d.start + n) < a->d.len; n++, buf++)
1914     *buf = a->d.buf[n];
1915   return n;
1916 }
1917
1918
1919
1920
1921 int
1922 iobuf_writebyte (iobuf_t a, unsigned int c)
1923 {
1924   int rc;
1925
1926   if (a->directfp)
1927     BUG ();
1928
1929   if (a->d.len == a->d.size)
1930     if ((rc=iobuf_flush (a)))
1931       return rc;
1932
1933   assert (a->d.len < a->d.size);
1934   a->d.buf[a->d.len++] = c;
1935   return 0;
1936 }
1937
1938
1939 int
1940 iobuf_write (iobuf_t a, const void *buffer, unsigned int buflen)
1941 {
1942   const unsigned char *buf = (const unsigned char *)buffer;
1943   int rc;
1944
1945   if (a->directfp)
1946     BUG ();
1947
1948   do
1949     {
1950       if (buflen && a->d.len < a->d.size)
1951         {
1952           unsigned size = a->d.size - a->d.len;
1953           if (size > buflen)
1954             size = buflen;
1955           memcpy (a->d.buf + a->d.len, buf, size);
1956           buflen -= size;
1957           buf += size;
1958           a->d.len += size;
1959         }
1960       if (buflen)
1961         {
1962           rc = iobuf_flush (a);
1963           if (rc)
1964             return rc;
1965         }
1966     }
1967   while (buflen);
1968   return 0;
1969 }
1970
1971
1972 int
1973 iobuf_writestr (iobuf_t a, const char *buf)
1974 {
1975   int rc;
1976
1977   for (; *buf; buf++)
1978     if ((rc=iobuf_writebyte (a, *buf)))
1979       return rc;
1980   return 0;
1981 }
1982
1983
1984
1985 /****************
1986  * copy the contents of TEMP to A.
1987  */
1988 int
1989 iobuf_write_temp (iobuf_t a, iobuf_t temp)
1990 {
1991   while (temp->chain)
1992     pop_filter (temp, temp->filter, NULL);
1993   return iobuf_write (a, temp->d.buf, temp->d.len);
1994 }
1995
1996 /****************
1997  * copy the contents of the temp io stream to BUFFER.
1998  */
1999 size_t
2000 iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen)
2001 {
2002   size_t n = a->d.len;
2003
2004   if (n > buflen)
2005     n = buflen;
2006   memcpy (buffer, a->d.buf, n);
2007   return n;
2008 }
2009
2010
2011 /****************
2012  * Call this function to terminate processing of the temp stream
2013  * without closing it.  This removes all filters from the stream
2014  * makes sure that iobuf_get_temp_{buffer,length}() returns correct
2015  * values.
2016  */
2017 void
2018 iobuf_flush_temp (iobuf_t temp)
2019 {
2020   while (temp->chain)
2021     pop_filter (temp, temp->filter, NULL);
2022 }
2023
2024
2025 /****************
2026  * Set a limit on how many bytes may be read from the input stream A.
2027  * Setting the limit to 0 disables this feature.
2028  */
2029 void
2030 iobuf_set_limit (iobuf_t a, off_t nlimit)
2031 {
2032   if (nlimit)
2033     a->nofast |= 1;
2034   else
2035     a->nofast &= ~1;
2036   a->nlimit = nlimit;
2037   a->ntotal += a->nbytes;
2038   a->nbytes = 0;
2039 }
2040
2041
2042
2043 /* Return the length of an open file A.  IF OVERFLOW is not NULL it
2044    will be set to true if the file is larger than what off_t can cope
2045    with.  The function return 0 on error or on overflow condition.  */
2046 off_t
2047 iobuf_get_filelength (iobuf_t a, int *overflow)
2048 {
2049     struct stat st;
2050
2051     if (overflow)
2052       *overflow = 0;
2053
2054     if( a->directfp )  {
2055         FILE *fp = a->directfp;
2056
2057        if( !fstat(fileno(fp), &st) )
2058            return st.st_size;
2059         log_error("fstat() failed: %s\n", strerror(errno) );
2060         return 0;
2061     }
2062
2063     /* Hmmm: file_filter may have already been removed */
2064     for( ; a; a = a->chain )
2065         if( !a->chain && a->filter == file_filter ) {
2066             file_filter_ctx_t *b = a->filter_ov;
2067             FILEP_OR_FD fp = b->fp;
2068
2069 #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
2070             ulong size;
2071             static int (* __stdcall get_file_size_ex) 
2072               (void *handle, LARGE_INTEGER *size);
2073             static int get_file_size_ex_initialized;
2074
2075             if (!get_file_size_ex_initialized)
2076               {
2077                 void *handle;
2078                 
2079                 handle = dlopen ("kernel32.dll", RTLD_LAZY);
2080                 if (handle)
2081                   {
2082                     get_file_size_ex = dlsym (handle, "GetFileSizeEx");
2083                     if (!get_file_size_ex)
2084                     dlclose (handle);
2085                   }
2086                 get_file_size_ex_initialized = 1;
2087               }
2088
2089             if (get_file_size_ex)
2090               {
2091                 /* This is a newer system with GetFileSizeEx; we use
2092                    this then becuase it seem that GetFileSize won't
2093                    return a proper error in case a file is larger than
2094                    4GB. */
2095                 LARGE_INTEGER size;
2096                 
2097                 if (get_file_size_ex (fp, &size))
2098                   {
2099                     if (!size.u.HighPart)
2100                       return size.u.LowPart;
2101                     if (overflow)
2102                       *overflow = 1;
2103                     return 0; 
2104                   }
2105               }
2106             else
2107               {
2108                 if  ((size=GetFileSize (fp, NULL)) != 0xffffffff)
2109                   return size;
2110               }
2111             log_error ("GetFileSize for handle %p failed: %s\n",
2112                        fp, w32_strerror (0));
2113 #else
2114             if( !fstat(my_fileno(fp), &st) )
2115                 return st.st_size;
2116             log_error("fstat() failed: %s\n", strerror(errno) );
2117 #endif
2118             break;
2119         }
2120
2121     return 0;
2122 }
2123
2124
2125 /* Return the file descriptor of the underlying file or -1 if it is
2126    not available.  */
2127 int 
2128 iobuf_get_fd (iobuf_t a)
2129 {
2130   if (a->directfp)
2131     return fileno ( (FILE*)a->directfp );
2132
2133   for ( ; a; a = a->chain )
2134     if (!a->chain && a->filter == file_filter)
2135       {
2136         file_filter_ctx_t *b = a->filter_ov;
2137         FILEP_OR_FD fp = b->fp;
2138
2139         return my_fileno (fp);
2140       }
2141
2142   return -1;
2143 }
2144
2145
2146
2147 /****************
2148  * Tell the file position, where the next read will take place
2149  */
2150 off_t
2151 iobuf_tell (iobuf_t a)
2152 {
2153   return a->ntotal + a->nbytes;
2154 }
2155
2156
2157 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
2158
2159 #ifdef HAVE_LIMITS_H
2160 # include <limits.h>
2161 #endif
2162 #ifndef LONG_MAX
2163 # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
2164 #endif
2165 #ifndef LONG_MIN
2166 # define LONG_MIN (-1 - LONG_MAX)
2167 #endif
2168
2169 /****************
2170  * A substitute for fseeko, for hosts that don't have it.
2171  */
2172 static int
2173 fseeko (FILE * stream, off_t newpos, int whence)
2174 {
2175   while (newpos != (long) newpos)
2176     {
2177       long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
2178       if (fseek (stream, pos, whence) != 0)
2179         return -1;
2180       newpos -= pos;
2181       whence = SEEK_CUR;
2182     }
2183   return fseek (stream, (long) newpos, whence);
2184 }
2185 #endif
2186
2187 /****************
2188  * This is a very limited implementation. It simply discards all internal
2189  * buffering and removes all filters but the first one.
2190  */
2191 int
2192 iobuf_seek (iobuf_t a, off_t newpos)
2193 {
2194   file_filter_ctx_t *b = NULL;
2195
2196   if (a->directfp)
2197     {
2198       FILE *fp = a->directfp;
2199       if (fseeko (fp, newpos, SEEK_SET))
2200         {
2201           log_error ("can't seek: %s\n", strerror (errno));
2202           return -1;
2203         }
2204       clearerr (fp);
2205     }
2206   else
2207     {
2208       for (; a; a = a->chain)
2209         {
2210           if (!a->chain && a->filter == file_filter)
2211             {
2212               b = a->filter_ov;
2213               break;
2214             }
2215         }
2216       if (!a)
2217         return -1;
2218 #ifdef FILE_FILTER_USES_STDIO
2219       if (fseeko (b->fp, newpos, SEEK_SET))
2220         {
2221           log_error ("can't fseek: %s\n", strerror (errno));
2222           return -1;
2223         }
2224 #else
2225 #ifdef HAVE_DOSISH_SYSTEM
2226       if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff)
2227         {
2228           log_error ("SetFilePointer failed on handle %p: ec=%d\n",
2229                      b->fp, (int) GetLastError ());
2230           return -1;
2231         }
2232 #else
2233       if (lseek (b->fp, newpos, SEEK_SET) == (off_t) - 1)
2234         {
2235           log_error ("can't lseek: %s\n", strerror (errno));
2236           return -1;
2237         }
2238 #endif
2239 #endif
2240     }
2241   a->d.len = 0;                 /* discard buffer */
2242   a->d.start = 0;
2243   a->nbytes = 0;
2244   a->nlimit = 0;
2245   a->nofast &= ~1;
2246   a->ntotal = newpos;
2247   a->error = 0;
2248   /* remove filters, but the last */
2249   if (a->chain)
2250     log_debug ("pop_filter called in iobuf_seek - please report\n");
2251   while (a->chain)
2252     pop_filter (a, a->filter, NULL);
2253
2254   return 0;
2255 }
2256
2257
2258
2259
2260
2261
2262 /****************
2263  * Retrieve the real filename
2264  */
2265 const char *
2266 iobuf_get_real_fname (iobuf_t a)
2267 {
2268   if (a->real_fname)
2269     return a->real_fname;
2270
2271   /* the old solution */
2272   for (; a; a = a->chain)
2273     if (!a->chain && a->filter == file_filter)
2274       {
2275         file_filter_ctx_t *b = a->filter_ov;
2276         return b->print_only_name ? NULL : b->fname;
2277       }
2278
2279   return NULL;
2280 }
2281
2282
2283 /****************
2284  * Retrieve the filename
2285  */
2286 const char *
2287 iobuf_get_fname (iobuf_t a)
2288 {
2289   for (; a; a = a->chain)
2290     if (!a->chain && a->filter == file_filter)
2291       {
2292         file_filter_ctx_t *b = a->filter_ov;
2293         return b->fname;
2294       }
2295
2296   return NULL;
2297 }
2298
2299
2300 /****************
2301  * enable partial block mode as described in the OpenPGP draft.
2302  * LEN is the first length byte on read, but ignored on writes.
2303  */
2304 void
2305 iobuf_set_partial_block_mode (iobuf_t a, size_t len)
2306 {
2307   block_filter_ctx_t *ctx = xcalloc (1, sizeof *ctx);
2308
2309   assert (a->use == 1 || a->use == 2);
2310   ctx->use = a->use;
2311   if (!len)
2312     {
2313       if (a->use == 1)
2314         log_debug ("pop_filter called in set_partial_block_mode"
2315                    " - please report\n");
2316       pop_filter (a, block_filter, NULL);
2317     }
2318   else
2319     {
2320       ctx->partial = 1;
2321       ctx->size = 0;
2322       ctx->first_c = len;
2323       iobuf_push_filter (a, block_filter, ctx);
2324     }
2325 }
2326
2327
2328
2329 /****************
2330  * Same as fgets() but if the buffer is too short a larger one will
2331  * be allocated up to some limit *max_length.
2332  * A line is considered a byte stream ending in a LF.
2333  * Returns the length of the line. EOF is indicated by a line of
2334  * length zero. The last LF may be missing due to an EOF.
2335  * is max_length is zero on return, the line has been truncated.
2336  *
2337  * Note: The buffer is allocated with enough space to append a CR,LF,EOL
2338  */
2339 unsigned int
2340 iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
2341                  unsigned *length_of_buffer, unsigned *max_length)
2342 {
2343   int c;
2344   char *buffer = (char *)*addr_of_buffer;
2345   unsigned length = *length_of_buffer;
2346   unsigned nbytes = 0;
2347   unsigned maxlen = *max_length;
2348   char *p;
2349
2350   if (!buffer)
2351     {                           /* must allocate a new buffer */
2352       length = 256;
2353       buffer = xmalloc (length);
2354       *addr_of_buffer = (unsigned char *)buffer;
2355       *length_of_buffer = length;
2356     }
2357
2358   length -= 3;                  /* reserve 3 bytes (cr,lf,eol) */
2359   p = buffer;
2360   while ((c = iobuf_get (a)) != -1)
2361     {
2362       if (nbytes == length)
2363         {                       /* increase the buffer */
2364           if (length > maxlen)
2365             {                   /* this is out limit */
2366               /* skip the rest of the line */
2367               while (c != '\n' && (c = iobuf_get (a)) != -1)
2368                 ;
2369               *p++ = '\n';      /* always append a LF (we have reserved space) */
2370               nbytes++;
2371               *max_length = 0;  /* indicate truncation */
2372               break;
2373             }
2374           length += 3;          /* correct for the reserved byte */
2375           length += length < 1024 ? 256 : 1024;
2376           buffer = xrealloc (buffer, length);
2377           *addr_of_buffer = (unsigned char *)buffer;
2378           *length_of_buffer = length;
2379           length -= 3;          /* and reserve again */
2380           p = buffer + nbytes;
2381         }
2382       *p++ = c;
2383       nbytes++;
2384       if (c == '\n')
2385         break;
2386     }
2387   *p = 0;                       /* make sure the line is a string */
2388
2389   return nbytes;
2390 }
2391
2392 /* This is the non iobuf specific function */
2393 int
2394 iobuf_translate_file_handle (int fd, int for_write)
2395 {
2396 #ifdef _WIN32
2397   {
2398     int x;
2399
2400     if (fd <= 2)
2401       return fd;                /* do not do this for error, stdin, stdout, stderr */
2402
2403     x = _open_osfhandle (fd, for_write ? 1 : 0);
2404     if (x == -1)
2405       log_error ("failed to translate osfhandle %p\n", (void *) fd);
2406     else
2407       {
2408         /*log_info ("_open_osfhandle %p yields %d%s\n",
2409            (void*)fd, x, for_write? " for writing":"" ); */
2410         fd = x;
2411       }
2412   }
2413 #endif
2414   return fd;
2415 }
2416
2417 static int
2418 translate_file_handle (int fd, int for_write)
2419 {
2420 #ifdef _WIN32
2421 #ifdef FILE_FILTER_USES_STDIO
2422   fd = iobuf_translate_file_handle (fd, for_write);
2423 #else
2424   {
2425     int x;
2426
2427     if (fd == 0)
2428       x = (int) GetStdHandle (STD_INPUT_HANDLE);
2429     else if (fd == 1)
2430       x = (int) GetStdHandle (STD_OUTPUT_HANDLE);
2431     else if (fd == 2)
2432       x = (int) GetStdHandle (STD_ERROR_HANDLE);
2433     else
2434       x = fd;
2435
2436     if (x == -1)
2437       log_debug ("GetStdHandle(%d) failed: ec=%d\n",
2438                  fd, (int) GetLastError ());
2439
2440     fd = x;
2441   }
2442 #endif
2443 #endif
2444   return fd;
2445 }
2446
2447
2448 void
2449 iobuf_skip_rest (iobuf_t a, unsigned long n, int partial)
2450 {
2451   if ( partial )
2452     {
2453       for (;;)
2454         {
2455           if (a->nofast || a->d.start >= a->d.len) 
2456             {
2457               if (iobuf_readbyte (a) == -1)
2458                 {
2459                   break;
2460                 }
2461             } 
2462           else
2463             {
2464               unsigned long count = a->d.len - a->d.start;
2465               a->nbytes += count;
2466               a->d.start = a->d.len;
2467             }
2468         }
2469     } 
2470   else
2471     {
2472       unsigned long remaining = n;
2473       while (remaining > 0) 
2474         {
2475           if (a->nofast || a->d.start >= a->d.len)
2476             {
2477               if (iobuf_readbyte (a) == -1)
2478                 {
2479                   break;
2480                 }
2481               --remaining;
2482             } 
2483           else 
2484             {
2485               unsigned long count = a->d.len - a->d.start;
2486               if (count > remaining) 
2487                 {
2488                   count = remaining;
2489                 }
2490               a->nbytes += count;
2491               a->d.start += count;
2492               remaining -= count;
2493             }
2494         }
2495     }
2496 }