* keylist.c (list_cert_colon): Kludge to show an email address
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  *      Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <gcrypt.h>
31 #ifdef HAVE_DOSISH_SYSTEM
32   #include <fcntl.h> /* for setmode() */
33 #endif
34
35 #include "memory.h"
36 #include "util.h"
37 #include "iobuf.h"
38
39
40 #if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
41   #define fopen(a,b)  fopen64 ((a),(b))
42   #define fstat(a,b)  fstat64 ((a),(b))
43 #endif
44
45
46
47 typedef struct {
48     FILE *fp;      /* open file handle */
49     int  print_only_name; /* flags indicating that fname is not a real file*/
50     char fname[1]; /* name of the file */
51 } file_filter_ctx_t ;
52
53
54 /* The first partial length header block must be of size 512
55  * to make it easier (and efficienter) we use a min. block size of 512
56  * for all chunks (but the last one) */
57 #define OP_MIN_PARTIAL_CHUNK      512
58 #define OP_MIN_PARTIAL_CHUNK_2POW 9
59
60 typedef struct {
61     int use;
62     size_t size;
63     size_t count;
64     int partial;  /* 1 = partial header, 2 in last partial packet */
65     char *buffer;    /* used for partial header */
66     size_t buflen;   /* used size of buffer */
67     int first_c;     /* of partial header (which is > 0)*/
68     int eof;
69 } block_filter_ctx_t;
70
71
72 static int underflow(IOBUF a);
73
74 /****************
75  * Read data from a file into buf which has an allocated length of *LEN.
76  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
77  * the stream. A is not used.
78  * control may be:
79  * IOBUFCTRL_INIT: called just before the function is linked into the
80  *                 list of function. This can be used to prepare internal
81  *                 data structures of the function.
82  * IOBUFCTRL_FREE: called just before the function is removed from the
83  *                  list of functions and can be used to release internal
84  *                  data structures or close a file etc.
85  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
86  *                  with new stuff. *RET_LEN is the available size of the
87  *                  buffer, and should be set to the number of bytes
88  *                  which were put into the buffer. The function
89  *                  returns 0 to indicate success, -1 on EOF and
90  *                  GPGERR_xxxxx for other errors.
91  *
92  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
93  *                  *RET_LAN is the number of bytes in BUF.
94  *
95  * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel.  The
96  *                  filter may take appropriate action on this message.
97  */
98 static int
99 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
100 {
101     file_filter_ctx_t *a = opaque;
102     FILE *fp = a->fp;
103     size_t size = *ret_len;
104     size_t nbytes = 0;
105     int rc = 0;
106
107     if( control == IOBUFCTRL_UNDERFLOW ) {
108         assert( size ); /* need a buffer */
109         if ( feof(fp)) {        /* On terminals you could easiely read as many EOFs as you call         */
110             rc = -1;            /* fread() or fgetc() repeatly. Every call will block until you press   */
111             *ret_len = 0;       /* CTRL-D. So we catch this case before we call fread() again.          */
112         }
113         else {
114             clearerr( fp );
115             nbytes = fread( buf, 1, size, fp );
116             if( feof(fp) && !nbytes )
117                 rc = -1; /* okay: we can return EOF now. */
118             else if( ferror(fp) && errno != EPIPE  ) {
119                 log_error("%s: read error: %s\n",
120                           a->fname, strerror(errno));
121                 rc = GPGERR_READ_FILE;
122             }
123             *ret_len = nbytes;
124         }
125     }
126     else if( control == IOBUFCTRL_FLUSH ) {
127         if( size ) {
128             clearerr( fp );
129             nbytes = fwrite( buf, 1, size, fp );
130             if( ferror(fp) ) {
131                 log_error("%s: write error: %s\n", a->fname, strerror(errno));
132                 rc = GPGERR_WRITE_FILE;
133             }
134         }
135         *ret_len = nbytes;
136     }
137     else if( control == IOBUFCTRL_INIT ) {
138     }
139     else if( control == IOBUFCTRL_DESC ) {
140         *(char**)buf = "file_filter";
141     }
142     else if( control == IOBUFCTRL_FREE ) {
143         if( fp != stdin && fp != stdout ) {
144             if( DBG_IOBUF )
145                 log_debug("%s: close fd %d\n", a->fname, fileno(fp) );
146             fclose(fp);
147         }
148         fp = NULL;
149         gcry_free(a); /* we can free our context now */
150     }
151
152     return rc;
153 }
154
155
156 /****************
157  * This is used to implement the block write mode.
158  * Block reading is done on a byte by byte basis in readbyte(),
159  * without a filter
160  */
161 static int
162 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
163 {
164     block_filter_ctx_t *a = opaque;
165     size_t size = *ret_len;
166     int c, needed, rc = 0;
167     char *p;
168
169     if( control == IOBUFCTRL_UNDERFLOW ) {
170         size_t n=0;
171
172         p = buf;
173         assert( size ); /* need a buffer */
174         if( a->eof ) /* don't read any further */
175             rc = -1;
176         while( !rc && size ) {
177             if( !a->size ) { /* get the length bytes */
178                 if( a->partial == 2 ) {
179                     a->eof = 1;
180                     if( !n )
181                         rc = -1;
182                     break;
183                 }
184                 else if( a->partial ) {
185                     /* These OpenPGP introduced huffman like encoded length
186                      * bytes are really a mess :-( */
187                     if( a->first_c ) {
188                         c = a->first_c;
189                         a->first_c = 0;
190                         assert( c >= 224 && c < 255 );
191                     }
192                     else if( (c = iobuf_get(chain)) == -1 ) {
193                         log_error("block_filter: 1st length byte missing\n");
194                         rc = GPGERR_READ_FILE;
195                         break;
196                     }
197                     if( c < 192 ) {
198                         a->size = c;
199                         a->partial = 2;
200                         if( !a->size ) {
201                             a->eof = 1;
202                             if( !n )
203                                 rc = -1;
204                             break;
205                         }
206                     }
207                     else if( c < 224 ) {
208                         a->size = (c - 192) * 256;
209                         if( (c = iobuf_get(chain)) == -1 ) {
210                             log_error("block_filter: 2nd length byte missing\n");
211                             rc = GPGERR_READ_FILE;
212                             break;
213                         }
214                         a->size += c + 192;
215                         a->partial = 2;
216                         if( !a->size ) {
217                             a->eof = 1;
218                             if( !n )
219                                 rc = -1;
220                             break;
221                         }
222                     }
223                     else if( c == 255 ) {
224                         a->size  = iobuf_get(chain) << 24;
225                         a->size |= iobuf_get(chain) << 16;
226                         a->size |= iobuf_get(chain) << 8;
227                         if( (c = iobuf_get(chain)) == -1 ) {
228                             log_error("block_filter: invalid 4 byte length\n");
229                             rc = GPGERR_READ_FILE;
230                             break;
231                         }
232                         a->size |= c;
233                     }
234                     else { /* next partial body length */
235                         a->size = 1 << (c & 0x1f);
236                     }
237             /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
238                 }
239                 else { /* the gnupg partial length scheme - much better :-) */
240                     c = iobuf_get(chain);
241                     a->size = c << 8;
242                     c = iobuf_get(chain);
243                     a->size |= c;
244                     if( c == -1 ) {
245                         log_error("block_filter: error reading length info\n");
246                         rc = GPGERR_READ_FILE;
247                     }
248                     if( !a->size ) {
249                         a->eof = 1;
250                         if( !n )
251                             rc = -1;
252                         break;
253                     }
254                 }
255             }
256
257             while( !rc && size && a->size ) {
258                 needed = size < a->size ? size : a->size;
259                 c = iobuf_read( chain, p, needed );
260                 if( c < needed ) {
261                     if( c == -1 ) c = 0;
262                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
263                               a,  (ulong)size+c, (ulong)a->size+c);
264                     rc = GPGERR_READ_FILE;
265                 }
266                 else {
267                     size -= c;
268                     a->size -= c;
269                     p += c;
270                     n += c;
271                 }
272             }
273         }
274         *ret_len = n;
275     }
276     else if( control == IOBUFCTRL_FLUSH ) {
277         if( a->partial ) { /* the complicated openpgp scheme */
278             size_t blen, n, nbytes = size + a->buflen;
279
280             assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
281             if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
282                 /* not enough to write a partial block out; so we store it*/
283                 if( !a->buffer )
284                     a->buffer = gcry_xmalloc( OP_MIN_PARTIAL_CHUNK );
285                 memcpy( a->buffer + a->buflen, buf, size );
286                 a->buflen += size;
287             }
288             else { /* okay, we can write out something */
289                 /* do this in a loop to use the most efficient block lengths */
290                 p = buf;
291                 do {
292                     /* find the best matching block length - this is limited
293                      * by the size of the internal buffering */
294                     for( blen=OP_MIN_PARTIAL_CHUNK*2,
295                             c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
296                                                             blen *=2, c++ )
297                         ;
298                     blen /= 2; c--;
299                     /* write the partial length header */
300                     assert( c <= 0x1f ); /*;-)*/
301                     c |= 0xe0;
302                     iobuf_put( chain, c );
303                     if( (n=a->buflen) ) { /* write stuff from the buffer */
304                         assert( n == OP_MIN_PARTIAL_CHUNK);
305                         if( iobuf_write(chain, a->buffer, n ) )
306                             rc = GPGERR_WRITE_FILE;
307                         a->buflen = 0;
308                         nbytes -= n;
309                     }
310                     if( (n = nbytes) > blen )
311                         n = blen;
312                     if( n && iobuf_write(chain, p, n ) )
313                         rc = GPGERR_WRITE_FILE;
314                     p += n;
315                     nbytes -= n;
316                 } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
317                 /* store the rest in the buffer */
318                 if( !rc && nbytes ) {
319                     assert( !a->buflen );
320                     assert( nbytes < OP_MIN_PARTIAL_CHUNK );
321                     if( !a->buffer )
322                         a->buffer = gcry_xmalloc( OP_MIN_PARTIAL_CHUNK );
323                     memcpy( a->buffer, p, nbytes );
324                     a->buflen = nbytes;
325                 }
326             }
327         }
328         else { /* the gnupg scheme (which is not openpgp compliant) */
329             size_t avail, n;
330
331             for(p=buf; !rc && size; ) {
332                 n = size;
333                 avail = a->size - a->count;
334                 if( !avail ) {
335                     if( n > a->size ) {
336                         iobuf_put( chain, (a->size >> 8) & 0xff );
337                         iobuf_put( chain, a->size & 0xff );
338                         avail = a->size;
339                         a->count = 0;
340                     }
341                     else {
342                         iobuf_put( chain, (n >> 8) & 0xff );
343                         iobuf_put( chain, n & 0xff );
344                         avail = n;
345                         a->count = a->size - n;
346                     }
347                 }
348                 if( n > avail )
349                     n = avail;
350                 if( iobuf_write(chain, p, n ) )
351                     rc = GPGERR_WRITE_FILE;
352                 a->count += n;
353                 p += n;
354                 size -= n;
355             }
356         }
357     }
358     else if( control == IOBUFCTRL_INIT ) {
359         if( DBG_IOBUF )
360             log_debug("init block_filter %p\n", a );
361         if( a->partial )
362             a->count = 0;
363         else if( a->use == 1 )
364             a->count = a->size = 0;
365         else
366             a->count = a->size; /* force first length bytes */
367         a->eof = 0;
368         a->buffer = NULL;
369         a->buflen = 0;
370     }
371     else if( control == IOBUFCTRL_DESC ) {
372         *(char**)buf = "block_filter";
373     }
374     else if( control == IOBUFCTRL_FREE ) {
375         if( a->use == 2 ) { /* write the end markers */
376             if( a->partial ) {
377                 u32 len;
378                 /* write out the remaining bytes without a partial header
379                  * the length of this header may be 0 - but if it is
380                  * the first block we are not allowed to use a partial header
381                  * and frankly we can't do so, because this length must be
382                  * a power of 2. This is _really_ complicated because we
383                  * have to check the possible length of a packet prior
384                  * to it's creation: a chain of filters becomes complicated
385                  * and we need a lot of code to handle compressed packets etc.
386                  *   :-(((((((
387                  */
388                 /* construct header */
389                 len = a->buflen;
390                 /*log_debug("partial: remaining length=%u\n", len );*/
391                 if( len < 192 )
392                     rc = iobuf_put(chain, len );
393                 else if( len < 8384 ) {
394                     if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
395                         rc = iobuf_put( chain, ((len-192) % 256));
396                 }
397                 else { /* use a 4 byte header */
398                     if( !(rc=iobuf_put( chain, 0xff )) )
399                         if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
400                             if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
401                                 if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
402                                     rc=iobuf_put( chain, len & 0xff );
403                 }
404                 if( !rc && len )
405                     rc = iobuf_write(chain, a->buffer, len );
406                 if( rc ) {
407                     log_error("block_filter: write error: %s\n",strerror(errno));
408                     rc = GPGERR_WRITE_FILE;
409                 }
410                 gcry_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
411             }
412             else {
413                 iobuf_writebyte(chain, 0);
414                 iobuf_writebyte(chain, 0);
415             }
416         }
417         else if( a->size ) {
418             log_error("block_filter: pending bytes!\n");
419         }
420         if( DBG_IOBUF )
421             log_debug("free block_filter %p\n", a );
422         gcry_free(a); /* we can free our context now */
423     }
424
425     return rc;
426 }
427
428
429 static void
430 print_chain( IOBUF a )
431 {
432     if( !DBG_IOBUF )
433         return;
434     for(; a; a = a->chain ) {
435         size_t dummy_len = 0;
436         const char *desc = "[none]";
437
438         if( a->filter )
439             a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL,
440                                                 (byte*)&desc, &dummy_len );
441
442         log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
443                    a->no, a->subno, desc, a->filter_eof,
444                    (int)a->d.start, (int)a->d.len );
445     }
446 }
447
448 int
449 iobuf_print_chain( IOBUF a )
450 {
451     print_chain(a);
452     return 0;
453 }
454
455 /****************
456  * Allocate a new io buffer, with no function assigned.
457  * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
458  * BUFSIZE is a suggested buffer size.
459  */
460 IOBUF
461 iobuf_alloc(int use, size_t bufsize)
462 {
463     IOBUF a;
464     static int number=0;
465
466     a = gcry_xcalloc( 1,sizeof *a);
467     a->use = use;
468     a->d.buf = gcry_xmalloc( bufsize );
469     a->d.size = bufsize;
470     a->no = ++number;
471     a->subno = 0;
472     a->opaque = NULL;
473     a->real_fname = NULL;
474     return a;
475 }
476
477
478 int
479 iobuf_close( IOBUF a )
480 {
481     IOBUF a2;
482     size_t dummy_len = 0;
483     int rc=0;
484
485     if( a && a->directfp ) {
486         fclose( a->directfp );
487         gcry_free( a->real_fname );
488         if( DBG_IOBUF )
489             log_debug("iobuf_close -> %p\n", a->directfp );
490         return 0;
491     }
492
493     for( ; a && !rc ; a = a2 ) {
494         a2 = a->chain;
495         if( a->use == 2 && (rc=iobuf_flush(a)) )
496             log_error("iobuf_flush failed on close: %s\n", gpg_errstr(rc));
497
498         if( DBG_IOBUF )
499             log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno, a->desc );
500         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
501                                          a->chain, NULL, &dummy_len)) )
502             log_error("IOBUFCTRL_FREE failed on close: %s\n", gpg_errstr(rc) );
503         gcry_free(a->real_fname);
504         gcry_free(a->d.buf);
505         gcry_free(a);
506     }
507     return rc;
508 }
509
510
511 int
512 iobuf_cancel( IOBUF a )
513 {
514     const char *s;
515     IOBUF a2;
516     int rc;
517   #ifdef HAVE_DOSISH_SYSTEM
518     char *remove_name = NULL;
519   #endif
520
521     if( a && a->use == 2 ) {
522         s = iobuf_get_real_fname(a);
523         if( s && *s ) {
524           #ifdef HAVE_DOSISH_SYSTEM
525             remove_name = m_strdup ( s );
526           #else
527             remove(s);
528           #endif
529         }
530     }
531
532     /* send a cancel message to all filters */
533     for( a2 = a; a2 ; a2 = a2->chain ) {
534         size_t dummy;
535         if( a2->filter )
536             a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
537                                                          NULL, &dummy );
538     }
539
540     rc = iobuf_close(a);
541   #ifdef HAVE_DOSISH_SYSTEM
542     if ( remove_name ) {
543         /* Argg, MSDOS does not allow to remove open files.  So
544          * we have to do it here */
545         remove ( remove_name );
546         m_free ( remove_name );
547     }
548   #endif
549     return rc;
550 }
551
552 /****************
553  * create a temporary iobuf, which can be used to collect stuff
554  * in an iobuf and later be written by iobuf_write_temp() to another
555  * iobuf.
556  */
557 IOBUF
558 iobuf_temp()
559 {
560     IOBUF a;
561
562     a = iobuf_alloc(3, 8192 );
563
564     return a;
565 }
566
567 IOBUF
568 iobuf_temp_with_content( const char *buffer, size_t length )
569 {
570     IOBUF a;
571
572     a = iobuf_alloc(3, length );
573     memcpy( a->d.buf, buffer, length );
574     a->d.len = length;
575
576     return a;
577 }
578
579
580 /****************
581  * Create a head iobuf for reading from a file
582  * returns: NULL if an error occures and sets errno
583  */
584 IOBUF
585 iobuf_open( const char *fname )
586 {
587     IOBUF a;
588     FILE *fp;
589     file_filter_ctx_t *fcx;
590     size_t len;
591     int print_only = 0;
592
593     if( !fname || (*fname=='-' && !fname[1])  ) {
594         fp = stdin;
595       #ifdef HAVE_DOSISH_SYSTEM
596         setmode ( fileno(fp) , O_BINARY );
597       #endif
598         fname = "[stdin]";
599         print_only = 1;
600     }
601     else if( !(fp = fopen(fname, "rb")) )
602         return NULL;
603     a = iobuf_alloc(1, 8192 );
604     fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
605     fcx->fp = fp;
606     fcx->print_only_name = print_only;
607     strcpy(fcx->fname, fname );
608     if( !print_only )
609         a->real_fname = gcry_xstrdup( fname );
610     a->filter = file_filter;
611     a->filter_ov = fcx;
612     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
613     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
614     if( DBG_IOBUF )
615         log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
616                    a->no, a->subno, fname, fileno(fcx->fp) );
617
618     return a;
619 }
620
621 /****************
622  * Create a head iobuf for reading from a file
623  * returns: NULL if an error occures and sets errno
624  */
625 IOBUF
626 iobuf_fdopen( int fd, const char *mode )
627 {
628     IOBUF a;
629     FILE *fp;
630     file_filter_ctx_t *fcx;
631     size_t len;
632
633     if( !(fp = fdopen(fd, mode)) )
634         return NULL;
635     a = iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 );
636     fcx = gcry_xmalloc( sizeof *fcx + 20 );
637     fcx->fp = fp;
638     fcx->print_only_name = 1;
639     sprintf(fcx->fname, "[fd %d]", fd );
640     a->filter = file_filter;
641     a->filter_ov = fcx;
642     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
643     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
644     if( DBG_IOBUF )
645         log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname );
646
647     return a;
648 }
649
650 /****************
651  * create an iobuf for writing to a file; the file will be created.
652  */
653 IOBUF
654 iobuf_create( const char *fname )
655 {
656     IOBUF a;
657     FILE *fp;
658     file_filter_ctx_t *fcx;
659     size_t len;
660     int print_only = 0;
661
662     if( !fname || (*fname=='-' && !fname[1]) ) {
663         fp = stdout;
664       #ifdef HAVE_DOSISH_SYSTEM
665         setmode ( fileno(fp) , O_BINARY );
666       #endif
667         fname = "[stdout]";
668         print_only = 1;
669     }
670     else if( !(fp = fopen(fname, "wb")) )
671         return NULL;
672     a = iobuf_alloc(2, 8192 );
673     fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
674     fcx->fp = fp;
675     fcx->print_only_name = print_only;
676     strcpy(fcx->fname, fname );
677     if( !print_only )
678         a->real_fname = gcry_xstrdup( fname );
679     a->filter = file_filter;
680     a->filter_ov = fcx;
681     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
682     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
683     if( DBG_IOBUF )
684         log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno, a->desc );
685
686     return a;
687 }
688
689 /****************
690  * append to an iobuf; if the file does not exist, create it.
691  * cannot be used for stdout.
692  */
693 IOBUF
694 iobuf_append( const char *fname )
695 {
696     IOBUF a;
697     FILE *fp;
698     file_filter_ctx_t *fcx;
699     size_t len;
700
701     if( !fname )
702         return NULL;
703     else if( !(fp = fopen(fname, "ab")) )
704         return NULL;
705     a = iobuf_alloc(2, 8192 );
706     fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
707     fcx->fp = fp;
708     strcpy(fcx->fname, fname );
709     a->real_fname = gcry_xstrdup( fname );
710     a->filter = file_filter;
711     a->filter_ov = fcx;
712     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
713     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
714     if( DBG_IOBUF )
715         log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno, a->desc );
716
717     return a;
718 }
719
720 IOBUF
721 iobuf_openrw( const char *fname )
722 {
723     IOBUF a;
724     FILE *fp;
725     file_filter_ctx_t *fcx;
726     size_t len;
727
728     if( !fname )
729         return NULL;
730     else if( !(fp = fopen(fname, "r+b")) )
731         return NULL;
732     a = iobuf_alloc(2, 8192 );
733     fcx = gcry_xmalloc( sizeof *fcx + strlen(fname) );
734     fcx->fp = fp;
735     strcpy(fcx->fname, fname );
736     a->real_fname = gcry_xstrdup( fname );
737     a->filter = file_filter;
738     a->filter_ov = fcx;
739     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
740     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
741     if( DBG_IOBUF )
742         log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno, a->desc );
743
744     return a;
745 }
746
747
748
749 /****************
750  * You can overwrite the normal iobuf behaviour by using this function.
751  * If used the iobuf is a simple wrapper around stdio.
752  * NULL if an error occures and sets errno
753  */
754 IOBUF
755 iobuf_fopen( const char *fname, const char *mode )
756 {
757     IOBUF a;
758     FILE *fp;
759     int print_only = 0;
760
761     if( !fname || (*fname=='-' && !fname[1])  ) {
762         fp = stdin;
763       #ifdef HAVE_DOSISH_SYSTEM
764         setmode ( fileno(fp) , O_BINARY );
765       #endif
766         fname = "[stdin]";
767         print_only = 1;
768     }
769     else if( !(fp = fopen(fname, mode) ) )
770         return NULL;
771     a = iobuf_alloc(1, 8192 );
772     a->directfp = fp;
773     a->real_fname = gcry_xstrdup( fname );
774
775     if( DBG_IOBUF )
776         log_debug("iobuf_fopen -> %p\n", a->directfp );
777
778     return a;
779 }
780
781
782
783 /****************
784  * Register an i/o filter.
785  */
786 int
787 iobuf_push_filter( IOBUF a,
788                    int (*f)(void *opaque, int control,
789                    IOBUF chain, byte *buf, size_t *len), void *ov )
790 {
791     return iobuf_push_filter2( a, f, ov, 0 );
792 }
793
794 int
795 iobuf_push_filter2( IOBUF a,
796                     int (*f)(void *opaque, int control,
797                     IOBUF chain, byte *buf, size_t *len),
798                     void *ov, int rel_ov )
799 {
800     IOBUF b;
801     size_t dummy_len=0;
802     int rc=0;
803
804     if( a->directfp )
805         BUG();
806
807     if( a->use == 2 && (rc=iobuf_flush(a)) )
808         return rc;
809     /* make a copy of the current stream, so that
810      * A is the new stream and B the original one.
811      * The contents of the buffers are transferred to the
812      * new stream.
813      */
814     b = gcry_xmalloc(sizeof *b);
815     memcpy(b, a, sizeof *b );
816     /* fixme: it is stupid to keep a copy of the name at every level
817      * but we need the name somewhere because the name known by file_filter
818      * may have been released when we need the name of the file */
819     b->real_fname = a->real_fname? gcry_xstrdup(a->real_fname):NULL;
820     /* remove the filter stuff from the new stream */
821     a->filter = NULL;
822     a->filter_ov = NULL;
823     a->filter_ov_owner = 0;
824     a->filter_eof = 0;
825     if( a->use == 3 )
826         a->use = 2;  /* make a write stream from a temp stream */
827
828     if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
829         b->d.buf = gcry_xmalloc( a->d.size );
830         b->d.len = 0;
831         b->d.start = 0;
832     }
833     else { /* allocate a fresh buffer for the new stream */
834         a->d.buf = gcry_xmalloc( a->d.size );
835         a->d.len = 0;
836         a->d.start = 0;
837     }
838     /* disable nlimit for the new stream */
839     a->ntotal = b->ntotal + b->nbytes;
840     a->nlimit = a->nbytes = 0;
841     a->nofast &= ~1;
842     /* make a link from the new stream to the original stream */
843     a->chain = b;
844     a->opaque = b->opaque;
845
846     /* setup the function on the new stream */
847     a->filter = f;
848     a->filter_ov = ov;
849     a->filter_ov_owner = rel_ov;
850
851     a->subno = b->subno + 1;
852     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
853
854     if( DBG_IOBUF ) {
855         log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno, a->desc );
856         print_chain( a );
857     }
858
859     /* now we can initialize the new function if we have one */
860     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
861                        NULL, &dummy_len)) )
862         log_error("IOBUFCTRL_INIT failed: %s\n", gpg_errstr(rc) );
863     return rc;
864 }
865
866 /****************
867  * Remove an i/o filter.
868  */
869 int
870 pop_filter( IOBUF a, int (*f)(void *opaque, int control,
871                       IOBUF chain, byte *buf, size_t *len), void *ov )
872 {
873     IOBUF b;
874     size_t dummy_len=0;
875     int rc=0;
876
877     if( a->directfp )
878         BUG();
879
880     if( DBG_IOBUF )
881         log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno, a->desc );
882     if( !a->filter ) { /* this is simple */
883         b = a->chain;
884         assert(b);
885         gcry_free(a->d.buf);
886         gcry_free(a->real_fname);
887         memcpy(a,b, sizeof *a);
888         gcry_free(b);
889         return 0;
890     }
891     for(b=a ; b; b = b->chain )
892         if( b->filter == f && (!ov || b->filter_ov == ov) )
893             break;
894     if( !b )
895         log_bug("pop_filter(): filter function not found\n");
896
897     /* flush this stream if it is an output stream */
898     if( a->use == 2 && (rc=iobuf_flush(b)) ) {
899         log_error("iobuf_flush failed in pop_filter: %s\n", gpg_errstr(rc));
900         return rc;
901     }
902     /* and tell the filter to free it self */
903     if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
904                        NULL, &dummy_len)) ) {
905         log_error("IOBUFCTRL_FREE failed: %s\n", gpg_errstr(rc) );
906         return rc;
907     }
908     if( b->filter_ov && b->filter_ov_owner ) {
909         gcry_free( b->filter_ov );
910         b->filter_ov = NULL;
911     }
912
913
914     /* and see how to remove it */
915     if( a == b && !b->chain )
916         log_bug("can't remove the last filter from the chain\n");
917     else if( a == b ) { /* remove the first iobuf from the chain */
918         /* everything from b is copied to a. This is save because
919          * a flush has been done on the to be removed entry
920          */
921         b = a->chain;
922         gcry_free(a->d.buf);
923         gcry_free(a->real_fname);
924         memcpy(a,b, sizeof *a);
925         gcry_free(b);
926         if( DBG_IOBUF )
927            log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
928     }
929     else if( !b->chain ) { /* remove the last iobuf from the chain */
930         log_bug("Ohh jeee, trying to remove a head filter\n");
931     }
932     else {  /* remove an intermediate iobuf from the chain */
933         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
934     }
935
936     return rc;
937 }
938
939
940 /****************
941  * read underflow: read more bytes into the buffer and return
942  * the first byte or -1 on EOF.
943  */
944 static int
945 underflow(IOBUF a)
946 {
947     size_t len;
948     int rc;
949
950     assert( a->d.start == a->d.len );
951     if( a->use == 3 )
952         return -1; /* EOF because a temp buffer can't do an underflow */
953
954     if( a->filter_eof ) {
955         if( a->chain && a->filter_eof == 1 ) {
956             IOBUF b = a->chain;
957             if( DBG_IOBUF )
958                 log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
959                                         a->no, a->subno, a->desc );
960             gcry_free(a->d.buf);
961             gcry_free(a->real_fname);
962             memcpy(a, b, sizeof *a);
963             gcry_free(b);
964             print_chain(a);
965         }
966         else
967             a->filter_eof = 0;
968         if( DBG_IOBUF )
969             log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
970                                                     a->no, a->subno );
971         return -1; /* return one(!) EOF */
972     }
973     if( a->error ) {
974         if( DBG_IOBUF )
975             log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
976         return -1;
977     }
978
979     if( a->directfp ) {
980         FILE *fp = a->directfp;
981
982         len = fread( a->d.buf, 1, a->d.size, fp);
983         if( len < a->d.size ) {
984             if( ferror(fp) )
985                 a->error = 1;
986         }
987         a->d.len = len;
988         a->d.start = 0;
989         return len? a->d.buf[a->d.start++] : -1;
990     }
991
992
993     if( a->filter ) {
994         len = a->d.size;
995         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
996                         a->d.buf, &len );
997         if( DBG_IOBUF ) {
998             log_debug("iobuf-%d.%d: underflow: req=%lu got=%lu rc=%d\n",
999                     a->no, a->subno, (ulong)a->d.size, (ulong)len, rc );
1000           #if 0
1001             if( a->no == 7 ) {
1002                 print_string(stderr, a->d.buf, len, 0 );
1003                 putc('\n', stderr );
1004             }
1005           #endif
1006
1007         }
1008         if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
1009             size_t dummy_len=0;
1010
1011             /* and tell the filter to free itself */
1012             if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
1013                                NULL, &dummy_len)) )
1014                 log_error("IOBUFCTRL_FREE failed: %s\n", gpg_errstr(rc) );
1015             if( a->filter_ov && a->filter_ov_owner ) {
1016                 gcry_free( a->filter_ov );
1017                 a->filter_ov = NULL;
1018             }
1019             a->filter = NULL;
1020             a->desc = NULL;
1021             a->filter_ov = NULL;
1022             a->filter_eof = 1;
1023             if( !len && a->chain ) {
1024                 IOBUF b = a->chain;
1025                 if( DBG_IOBUF )
1026                     log_debug("iobuf-%d.%d: pop `%s' in underflow (!len)\n",
1027                                                a->no, a->subno, a->desc );
1028                 print_chain(a);
1029                 gcry_free(a->d.buf);
1030                 gcry_free(a->real_fname);
1031                 memcpy(a,b, sizeof *a);
1032                 gcry_free(b);
1033                 print_chain(a);
1034             }
1035         }
1036         else if( rc )
1037             a->error = 1;
1038
1039         if( !len ) {
1040             if( DBG_IOBUF )
1041                 log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno );
1042             return -1;
1043         }
1044         a->d.len = len;
1045         a->d.start = 0;
1046         return a->d.buf[a->d.start++];
1047     }
1048     else {
1049         if( DBG_IOBUF )
1050             log_debug("iobuf-%d.%d: underflow: eof (no filter)\n",
1051                                                     a->no, a->subno );
1052         return -1;  /* no filter; return EOF */
1053     }
1054 }
1055
1056
1057 int
1058 iobuf_flush(IOBUF a)
1059 {
1060     size_t len;
1061     int rc;
1062
1063     if( a->directfp )
1064         return 0;
1065
1066     /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
1067     if( a->use == 3 ) { /* increase the temp buffer */
1068         char *newbuf;
1069         size_t newsize = a->d.size + 8192;
1070
1071         log_debug("increasing temp iobuf from %lu to %lu\n",
1072                     (ulong)a->d.size, (ulong)newsize );
1073         newbuf = gcry_xmalloc( newsize );
1074         memcpy( newbuf, a->d.buf, a->d.len );
1075         gcry_free(a->d.buf);
1076         a->d.buf = newbuf;
1077         a->d.size = newsize;
1078         return 0;
1079     }
1080     else if( a->use != 2 )
1081         log_bug("flush on non-output iobuf\n");
1082     else if( !a->filter )
1083         log_bug("iobuf_flush: no filter\n");
1084     len = a->d.len;
1085     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
1086     if( !rc && len != a->d.len ) {
1087         log_info("iobuf_flush did not write all!\n");
1088         rc = GPGERR_WRITE_FILE;
1089     }
1090     else if( rc )
1091         a->error = 1;
1092     a->d.len = 0;
1093
1094     return rc;
1095 }
1096
1097
1098 /****************
1099  * Read a byte from the iobuf; returns -1 on EOF
1100  */
1101 int
1102 iobuf_readbyte(IOBUF a)
1103 {
1104     int c;
1105
1106     /* nlimit does not work together with unget */
1107     /* nbytes is also not valid! */
1108     if( a->unget.buf ) {
1109         if( a->unget.start < a->unget.len )
1110             return a->unget.buf[a->unget.start++];
1111         gcry_free(a->unget.buf);
1112         a->unget.buf = NULL;
1113         a->nofast &= ~2;
1114     }
1115
1116     if( a->nlimit && a->nbytes >= a->nlimit )
1117         return -1; /* forced EOF */
1118
1119     if( a->d.start < a->d.len ) {
1120         c = a->d.buf[a->d.start++];
1121     }
1122     else if( (c=underflow(a)) == -1 )
1123         return -1; /* EOF */
1124
1125     a->nbytes++;
1126     return c;
1127 }
1128
1129
1130 int
1131 iobuf_read(IOBUF a, byte *buf, unsigned buflen )
1132 {
1133     int c, n;
1134
1135     if( a->unget.buf || a->nlimit ) {
1136         /* handle special cases */
1137         for(n=0 ; n < buflen; n++ ) {
1138             if( (c = iobuf_readbyte(a)) == -1 ) {
1139                 if( !n )
1140                     return -1; /* eof */
1141                 break;
1142             }
1143             else
1144                 if( buf ) *buf = c;
1145             if( buf ) buf++;
1146         }
1147         return n;
1148     }
1149
1150     n = 0;
1151     do {
1152         if( n < buflen && a->d.start < a->d.len ) {
1153             unsigned size = a->d.len - a->d.start;
1154             if( size > buflen - n )
1155                 size = buflen - n;
1156             if( buf )
1157                 memcpy( buf, a->d.buf + a->d.start, size );
1158             n += size;
1159             a->d.start += size;
1160             if( buf )
1161                 buf += size;
1162         }
1163         if( n < buflen ) {
1164             if( (c=underflow(a)) == -1 ) {
1165                 a->nbytes += n;
1166                 return n? n : -1/*EOF*/;
1167             }
1168             if( buf )
1169                 *buf++ = c;
1170             n++;
1171         }
1172     } while( n < buflen );
1173     a->nbytes += n;
1174     return n;
1175 }
1176
1177
1178 /****************
1179  * Have a look at the iobuf.
1180  * NOTE: This only works in special cases.
1181  */
1182 int
1183 iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
1184 {
1185     int n=0;
1186
1187     if( a->filter_eof )
1188         return -1;
1189
1190     if( !(a->d.start < a->d.len) ) {
1191         if( underflow(a) == -1 )
1192             return -1;
1193         /* and unget this character */
1194         assert(a->d.start == 1);
1195         a->d.start = 0;
1196     }
1197
1198     for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
1199         *buf = a->d.buf[n];
1200     return n;
1201 }
1202
1203
1204
1205
1206 int
1207 iobuf_writebyte(IOBUF a, unsigned c)
1208 {
1209
1210     if( a->directfp )
1211         BUG();
1212
1213     if( a->d.len == a->d.size )
1214         if( iobuf_flush(a) )
1215             return -1;
1216
1217     assert( a->d.len < a->d.size );
1218     a->d.buf[a->d.len++] = c;
1219     return 0;
1220 }
1221
1222
1223 int
1224 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
1225 {
1226
1227     if( a->directfp )
1228         BUG();
1229
1230     do {
1231         if( buflen && a->d.len < a->d.size ) {
1232             unsigned size = a->d.size - a->d.len;
1233             if( size > buflen ) size = buflen;
1234             memcpy( a->d.buf + a->d.len, buf, size );
1235             buflen -= size;
1236             buf += size;
1237             a->d.len += size;
1238         }
1239         if( buflen ) {
1240             if( iobuf_flush(a) )
1241                 return -1;
1242         }
1243     } while( buflen );
1244     return 0;
1245 }
1246
1247
1248 int
1249 iobuf_writestr(IOBUF a, const char *buf )
1250 {
1251     for( ; *buf; buf++ )
1252         if( iobuf_writebyte(a, *buf) )
1253             return -1;
1254     return 0;
1255 }
1256
1257
1258
1259 /****************
1260  * copy the contents of TEMP to A.
1261  */
1262 int
1263 iobuf_write_temp( IOBUF a, IOBUF temp )
1264 {
1265     while( temp->chain )
1266         pop_filter( temp, temp->filter, NULL );
1267     return iobuf_write(a, temp->d.buf, temp->d.len );
1268 }
1269
1270 /****************
1271  * copy the contents of the temp io stream to BUFFER.
1272  */
1273 size_t
1274 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
1275 {
1276     size_t n = a->d.len;
1277
1278     if( n > buflen )
1279         n = buflen;
1280     memcpy( buffer, a->d.buf, n );
1281     return n;
1282 }
1283
1284
1285 /****************
1286  * Call this function to terminate processing of the temp stream
1287  * without closing it.  This removes all filters from the stream
1288  * makes sure that iobuf_get_temp_{buffer,length}() returns correct
1289  * values.
1290  */
1291 void
1292 iobuf_flush_temp( IOBUF temp )
1293 {
1294     while( temp->chain )
1295         pop_filter( temp, temp->filter, NULL );
1296 }
1297
1298
1299 /****************
1300  * Set a limit on how many bytes may be read from the input stream A.
1301  * Setting the limit to 0 disables this feature.
1302  */
1303 void
1304 iobuf_set_limit( IOBUF a, unsigned long nlimit )
1305 {
1306     if( nlimit )
1307         a->nofast |= 1;
1308     else
1309         a->nofast &= ~1;
1310     a->nlimit = nlimit;
1311     a->ntotal += a->nbytes;
1312     a->nbytes = 0;
1313 }
1314
1315
1316
1317 /****************
1318  * Return the length of an open file
1319  */
1320 u32
1321 iobuf_get_filelength( IOBUF a )
1322 {
1323 #if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
1324     struct stat64 st;
1325 #else
1326     struct stat st;
1327 #endif
1328
1329     if( a->directfp )  {
1330         FILE *fp = a->directfp;
1331
1332         if( !fstat(fileno(fp), &st) ) {
1333           #if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
1334             if( st.st_size >= IOBUF_FILELENGTH_LIMIT )
1335                 return IOBUF_FILELENGTH_LIMIT;
1336           #endif
1337             return (u32)st.st_size;
1338         }
1339         log_error("fstat() failed: %s\n", strerror(errno) );
1340         return 0;
1341     }
1342
1343
1344     /* Hmmm: file_filter may have already been removed */
1345     for( ; a; a = a->chain )
1346         if( !a->chain && a->filter == file_filter ) {
1347             file_filter_ctx_t *b = a->filter_ov;
1348             FILE *fp = b->fp;
1349
1350             if( !fstat(fileno(fp), &st) ) {
1351               #if defined (HAVE_FOPEN64) && defined (HAVE_FSTAT64)
1352                 if( st.st_size >= IOBUF_FILELENGTH_LIMIT )
1353                     return IOBUF_FILELENGTH_LIMIT;
1354               #endif
1355                 return st.st_size;
1356             }
1357             log_error("fstat() failed: %s\n", strerror(errno) );
1358             break;
1359         }
1360
1361     return 0;
1362 }
1363
1364 /****************
1365  * Tell the file position, where the next read will take place
1366  */
1367 ulong
1368 iobuf_tell( IOBUF a )
1369 {
1370     return a->ntotal + a->nbytes;
1371 }
1372
1373
1374
1375 /****************
1376  * This is a very limited implementation. It simply discards all internal
1377  * buffering and removes all filters but the first one.
1378  */
1379 int
1380 iobuf_seek( IOBUF a, ulong newpos )
1381 {
1382     file_filter_ctx_t *b = NULL;
1383
1384     if( a->directfp ) {
1385         FILE *fp = a->directfp;
1386         if( fseek( fp, newpos, SEEK_SET ) ) {
1387             log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
1388             return -1;
1389         }
1390         clearerr(fp);
1391     }
1392     else {
1393         for( ; a; a = a->chain ) {
1394             if( !a->chain && a->filter == file_filter ) {
1395                 b = a->filter_ov;
1396                 break;
1397             }
1398         }
1399         if( !a )
1400             return -1;
1401         if( fseek( b->fp, newpos, SEEK_SET ) ) {
1402             log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
1403             return -1;
1404         }
1405     }
1406     a->d.len = 0;   /* discard buffer */
1407     a->d.start = 0;
1408     a->nbytes = 0;
1409     a->nlimit = 0;
1410     a->nofast &= ~1;
1411     a->ntotal = newpos;
1412     a->error = 0;
1413     /* remove filters, but the last */
1414     if( a->chain )
1415         log_debug("pop_filter called in iobuf_seek - please report\n");
1416     while( a->chain )
1417        pop_filter( a, a->filter, NULL );
1418
1419     return 0;
1420 }
1421
1422
1423
1424
1425
1426
1427 /****************
1428  * Retrieve the real filename
1429  */
1430 const char *
1431 iobuf_get_real_fname( IOBUF a )
1432 {
1433     if( a->real_fname )
1434         return a->real_fname;
1435
1436     /* the old solution */
1437     for( ; a; a = a->chain )
1438         if( !a->chain && a->filter == file_filter ) {
1439             file_filter_ctx_t *b = a->filter_ov;
1440             return b->print_only_name? NULL : b->fname;
1441         }
1442
1443     return NULL;
1444 }
1445
1446
1447 /****************
1448  * Retrieve the filename
1449  */
1450 const char *
1451 iobuf_get_fname( IOBUF a )
1452 {
1453     for( ; a; a = a->chain )
1454         if( !a->chain && a->filter == file_filter ) {
1455             file_filter_ctx_t *b = a->filter_ov;
1456             return b->fname;
1457         }
1458
1459     return NULL;
1460 }
1461
1462 /****************
1463  * Start the block write mode, see rfc1991.new for details.
1464  * A value of 0 for N stops this mode (flushes and writes
1465  * the end marker)
1466  */
1467 void
1468 iobuf_set_block_mode( IOBUF a, size_t n )
1469 {
1470     block_filter_ctx_t *ctx = gcry_xcalloc( 1, sizeof *ctx );
1471
1472     assert( a->use == 1 || a->use == 2 );
1473     ctx->use = a->use;
1474     if( !n ) {
1475         if( a->use == 1 )
1476             log_debug("pop_filter called in set_block_mode - please report\n");
1477         pop_filter(a, block_filter, NULL );
1478     }
1479     else {
1480         ctx->size = n; /* only needed for use 2 */
1481         iobuf_push_filter(a, block_filter, ctx );
1482     }
1483 }
1484
1485 /****************
1486  * enable partial block mode as described in the OpenPGP draft.
1487  * LEN is the first length byte on read, but ignored on writes.
1488  */
1489 void
1490 iobuf_set_partial_block_mode( IOBUF a, size_t len )
1491 {
1492     block_filter_ctx_t *ctx = gcry_xcalloc( 1, sizeof *ctx );
1493
1494     assert( a->use == 1 || a->use == 2 );
1495     ctx->use = a->use;
1496     if( !len ) {
1497         if( a->use == 1 )
1498             log_debug("pop_filter called in set_partial_block_mode"
1499                                                     " - please report\n");
1500         pop_filter(a, block_filter, NULL );
1501     }
1502     else {
1503         ctx->partial = 1;
1504         ctx->size = 0;
1505         ctx->first_c = len;
1506         iobuf_push_filter(a, block_filter, ctx );
1507     }
1508 }
1509
1510
1511 /****************
1512  * Checks whether the stream is in block mode
1513  * Note: This does not work if other filters are pushed on the stream.
1514  */
1515 int
1516 iobuf_in_block_mode( IOBUF a )
1517 {
1518     if( a && a->filter == block_filter )
1519         return 1; /* yes */
1520     return 0; /* no */
1521 }
1522
1523
1524 /****************
1525  * Same as fgets() but if the buffer is too short a larger one will
1526  * be allocated up to some limit *max_length.
1527  * A line is considered a byte stream ending in a LF.
1528  * Returns the length of the line. EOF is indicated by a line of
1529  * length zero. The last LF may be missing due to an EOF.
1530  * is max_length is zero on return, the line has been truncated.
1531  *
1532  * Note: The buffer is allocated with enough space to append a CR,LF,EOL
1533  */
1534 unsigned
1535 iobuf_read_line( IOBUF a, byte **addr_of_buffer,
1536                           unsigned *length_of_buffer, unsigned *max_length )
1537 {
1538     int c;
1539     char *buffer = *addr_of_buffer;
1540     unsigned length = *length_of_buffer;
1541     unsigned nbytes = 0;
1542     unsigned maxlen = *max_length;
1543     char *p;
1544
1545     if( !buffer ) { /* must allocate a new buffer */
1546         length = 256;
1547         buffer = gcry_xmalloc( length );
1548         *addr_of_buffer = buffer;
1549         *length_of_buffer = length;
1550     }
1551
1552     length -= 3; /* reserve 3 bytes (cr,lf,eol) */
1553     p = buffer;
1554     while( (c=iobuf_get(a)) != -1 ) {
1555         if( nbytes == length ) { /* increase the buffer */
1556             if( length > maxlen  ) { /* this is out limit */
1557                 /* skip the rest of the line */
1558                 while( c != '\n' && (c=iobuf_get(a)) != -1 )
1559                     ;
1560                 *p++ = '\n'; /* always append a LF (we have reserved space) */
1561                 nbytes++;
1562                 *max_length = 0; /* indicate truncation */
1563                 break;
1564             }
1565             length += 3; /* correct for the reserved byte */
1566             length += length < 1024? 256 : 1024;
1567             buffer = gcry_xrealloc( buffer, length );
1568             *addr_of_buffer = buffer;
1569             *length_of_buffer = length;
1570             length -= 3; /* and reserve again */
1571             p = buffer + nbytes;
1572         }
1573         *p++ = c;
1574         nbytes++;
1575         if( c == '\n' )
1576             break;
1577     }
1578     *p = 0; /* make sure the line is a string */
1579
1580     return nbytes;
1581 }
1582