last local commit
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  *      Copyright (C) 1998 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
31 #include "memory.h"
32 #include "util.h"
33 #include "iobuf.h"
34
35 typedef struct {
36     FILE *fp;      /* open file handle */
37     int  print_only_name; /* flags indicating that fname is not a real file*/
38     char fname[1]; /* name of the file */
39 } file_filter_ctx_t ;
40
41 /* The first partial length header block must be of size 512
42  * to make it easier (and efficienter) we use a min. block size of 512
43  * for all chznks (but the last one) */
44 #define OP_MIN_PARTIAL_CHUNK      512
45 #define OP_MIN_PARTIAL_CHUNK_2POW 9
46
47 typedef struct {
48     int usage;
49     size_t size;
50     size_t count;
51     int partial;  /* 1 = partial header, 2 in last partial packet */
52     char *buffer;    /* used for partial header */
53     size_t buflen;   /* used size of buffer */
54     int first_c;     /* of partial header (which is > 0)*/
55     int eof;
56 } block_filter_ctx_t;
57
58
59 static int underflow(IOBUF a);
60 static const char *get_real_fname( IOBUF a );
61
62 /****************
63  * Read data from a file into buf which has an allocated length of *LEN.
64  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
65  * the stream. A is not used.
66  * control may be:
67  * IOBUFCTRL_INIT: called just before the function is linked into the
68  *                 list of function. This can be used to prepare internal
69  *                 data structures of the function.
70  * IOBUFCTRL_FREE: called just before the function is removed from the
71  *                  list of functions and can be used to release internal
72  *                  data structures or close a file etc.
73  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
74  *                  with new stuff. *RET_LEN is the available size of the
75  *                  buffer, and should be set to the number of bytes
76  *                  which were put into the buffer. The function
77  *                  returns 0 to indicate success, -1 on EOF and
78  *                  G10ERR_xxxxx for other errors.
79  *
80  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
81  *                  *RET_LAN is the number of bytes in BUF.
82  *
83  */
84 static int
85 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
86 {
87     file_filter_ctx_t *a = opaque;
88     FILE *fp = a->fp;
89     size_t size = *ret_len;
90     size_t nbytes = 0;
91     int c, rc = 0;
92     char *p;
93
94     if( control == IOBUFCTRL_UNDERFLOW ) {
95         assert( size ); /* need a buffer */
96         for(; size; size-- ) {
97             if( (c=getc(fp)) == EOF ) {
98                 if( ferror(fp) ) {
99                     log_error("%s: read error: %s\n",
100                                         a->fname, strerror(errno));
101                     rc = G10ERR_READ_FILE;
102                 }
103                 else if( !nbytes )
104                     rc = -1; /* okay: we can return EOF now. */
105                 break;
106             }
107             buf[nbytes++] = c & 0xff;
108         }
109         *ret_len = nbytes;
110     }
111     else if( control == IOBUFCTRL_FLUSH ) {
112         for(p=buf; nbytes < size; nbytes++, p++ ) {
113             if( putc(*p, fp) == EOF ) {
114                 log_error("%s: write error: %s\n",
115                                     a->fname, strerror(errno));
116                 rc = G10ERR_WRITE_FILE;
117                 break;
118             }
119         }
120         *ret_len = nbytes;
121     }
122     else if( control == IOBUFCTRL_INIT ) {
123     }
124     else if( control == IOBUFCTRL_DESC ) {
125         *(char**)buf = "file_filter";
126     }
127     else if( control == IOBUFCTRL_FREE ) {
128         if( fp != stdin && fp != stdout )
129             fclose(fp);
130         fp = NULL;
131         m_free(a); /* we can free our context now */
132     }
133
134     return rc;
135 }
136
137
138 /****************
139  * This is used to implement the block write mode.
140  * Block reading is done on a byte by byte basis in readbyte(),
141  * without a filter
142  */
143 static int
144 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
145 {
146     block_filter_ctx_t *a = opaque;
147     size_t size = *ret_len;
148     int c, rc = 0;
149     char *p;
150
151     if( control == IOBUFCTRL_UNDERFLOW ) {
152         size_t n=0;
153
154         p = buf;
155         assert( size ); /* need a buffer */
156         if( a->eof ) /* don't read any further */
157             rc = -1;
158         while( !rc && size ) {
159             if( !a->size ) { /* get the length bytes */
160                 if( a->partial == 2 ) {
161                     a->eof = 1;
162                     if( !n )
163                         rc = -1;
164                     break;
165                 }
166                 else if( a->partial ) {
167                     /* These OpenPGP introduced huffman encoded length
168                      * bytes are really a mess :-( */
169                     if( a->first_c ) {
170                         c = a->first_c;
171                         a->first_c = 0;
172                         assert( c >= 224 && c < 255 );
173                     }
174                     else if( (c = iobuf_get(chain)) == -1 ) {
175                         log_error("block_filter: 1st length byte missing\n");
176                         rc = G10ERR_READ_FILE;
177                         break;
178                     }
179                     if( c < 192 ) {
180                         a->size = c;
181                         a->partial = 2;
182                         if( !a->size ) {
183                             a->eof = 1;
184                             if( !n )
185                                 rc = -1;
186                             break;
187                         }
188                     }
189                     else if( c < 224 ) {
190                         a->size = (c - 192) * 256;
191                         if( (c = iobuf_get(chain)) == -1 ) {
192                             log_error("block_filter: 2nd length byte missing\n");
193                             rc = G10ERR_READ_FILE;
194                             break;
195                         }
196                         a->size += c + 192;
197                         a->partial = 2;
198                         if( !a->size ) {
199                             a->eof = 1;
200                             if( !n )
201                                 rc = -1;
202                             break;
203                         }
204                     }
205                     else if( c == 255 ) {
206                         a->size  = iobuf_get(chain) << 24;
207                         a->size |= iobuf_get(chain) << 16;
208                         a->size |= iobuf_get(chain) << 8;
209                         if( (c = iobuf_get(chain)) == -1 ) {
210                             log_error("block_filter: invalid 4 byte length\n");
211                             rc = G10ERR_READ_FILE;
212                             break;
213                         }
214                         a->size |= c;
215                     }
216                     else { /* next partial body length */
217                         a->size = 1 << (c & 0x1f);
218                     }
219                 }
220                 else { /* the gnupg partial length scheme - much better :-) */
221                     c = iobuf_get(chain);
222                     a->size = c << 8;
223                     c = iobuf_get(chain);
224                     a->size |= c;
225                     if( c == -1 ) {
226                         log_error("block_filter: error reading length info\n");
227                         rc = G10ERR_READ_FILE;
228                     }
229                     if( !a->size ) {
230                         a->eof = 1;
231                         if( !n )
232                             rc = -1;
233                         break;
234                     }
235                 }
236             }
237
238             for(; !rc && size && a->size; size--, a->size-- ) {
239                 if( (c=iobuf_get(chain)) == -1 ) {
240                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
241                                 a,  (ulong)size, (ulong)a->size);
242                     rc = G10ERR_READ_FILE;
243                 }
244                 else {
245                     *p++ = c;
246                     n++;
247                 }
248             }
249         }
250         *ret_len = n;
251     }
252     else if( control == IOBUFCTRL_FLUSH ) {
253         if( a->partial ) { /* the complicated openpgp scheme */
254             size_t blen, n, nbytes = size + a->buflen;
255
256             assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
257             if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
258                 /* not enough to write a partial block out , so we store it*/
259                 if( !a->buffer )
260                     a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
261                 memcpy( a->buffer + a->buflen, buf, size );
262                 a->buflen += size;
263             }
264             else { /* okay, we can write out something */
265                 /* do this in a loop to use the most efficient block lengths */
266                 p = buf;
267                 do {
268                     /* find the best matching block length - this is limited
269                      * by the size of the internal buffering */
270                     for( blen=OP_MIN_PARTIAL_CHUNK*2,
271                             c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen < nbytes;
272                                                             blen *=2, c++ )
273                         ;
274                     blen /= 2; c--;
275                     /* write the partial length header */
276                     assert( c <= 0x1f ); /*;-)*/
277                     c |= 0xe0;
278                     iobuf_put( chain, c );
279                     if( (n=a->buflen) ) { /* write stuff from the buffer */
280                         assert( n == OP_MIN_PARTIAL_CHUNK);
281                         if( iobuf_write(chain, a->buffer, n ) )
282                             rc = G10ERR_WRITE_FILE;
283                         a->buflen = 0;
284                         nbytes -= n;
285                     }
286                     if( (n = nbytes) > blen )
287                         n = blen;
288                     if( n && iobuf_write(chain, p, n ) )
289                         rc = G10ERR_WRITE_FILE;
290                     p += n;
291                     nbytes -= n;
292                 } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
293                 /* store the rest in the buffer */
294                 if( !rc && nbytes ) {
295                     assert( !a->buflen );
296                     assert( nbytes < OP_MIN_PARTIAL_CHUNK );
297                     if( !a->buffer )
298                         a->buffer = m_alloc( OP_MIN_PARTIAL_CHUNK );
299                     memcpy( a->buffer, p, nbytes );
300                     a->buflen = nbytes;
301                 }
302             }
303         }
304         else { /* the gnupg scheme */
305             size_t avail, n;
306
307             for(p=buf; !rc && size; ) {
308                 n = size;
309                 avail = a->size - a->count;
310                 if( !avail ) {
311                     if( n > a->size ) {
312                         iobuf_put( chain, (a->size >> 8) & 0xff );
313                         iobuf_put( chain, a->size & 0xff );
314                         avail = a->size;
315                         a->count = 0;
316                     }
317                     else {
318                         iobuf_put( chain, (n >> 8) & 0xff );
319                         iobuf_put( chain, n & 0xff );
320                         avail = n;
321                         a->count = a->size - n;
322                     }
323                 }
324                 if( n > avail )
325                     n = avail;
326                 if( iobuf_write(chain, p, n ) )
327                     rc = G10ERR_WRITE_FILE;
328                 a->count += n;
329                 p += n;
330                 size -= n;
331             }
332         }
333     }
334     else if( control == IOBUFCTRL_INIT ) {
335         if( DBG_IOBUF )
336             log_debug("init block_filter %p\n", a );
337         if( a->partial )
338             a->count = 0;
339         else if( a->usage == 1 )
340             a->count = a->size = 0;
341         else
342             a->count = a->size; /* force first length bytes */
343         a->eof = 0;
344         a->buffer = NULL;
345         a->buflen = 0;
346     }
347     else if( control == IOBUFCTRL_DESC ) {
348         *(char**)buf = "block_filter";
349     }
350     else if( control == IOBUFCTRL_FREE ) {
351         if( a->usage == 2 ) { /* write the end markers */
352             if( a->partial ) {
353                 u32 len;
354                 /* write out the remaining bytes without a partial header
355                  * the length of this header may be 0 - but if it is
356                  * the first block we are not allowed to use a partial header
357                  * and frankly we can't do so, because this length must be
358                  * a power of 2. This is _really_ complicated because we
359                  * have to check the possible length of a packet prior
360                  * to it's creation: a chein of filters becomes complicated
361                  * and we need a lot of code to handle compressed packets etc.
362                  *   :-(((((((
363                  */
364                 /* construct header */
365                 len = a->buflen;
366                 if( len < 192 )
367                     rc = iobuf_put(chain, len );
368                 else if( len < 8384 ) {
369                     if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
370                         rc = iobuf_put( chain, ((len-192) % 256));
371                 }
372                 else { /* use a 4 byte header */
373                     if( !(rc=iobuf_put( chain, 0xff )) )
374                         if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
375                             if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
376                                 if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
377                                     rc=iobuf_put( chain, len & 0xff );
378                 }
379                 if( !rc && len )
380                     rc = iobuf_write(chain, a->buffer, len );
381                 if( rc ) {
382                     log_error("block_filter: write error: %s\n",strerror(errno));
383                     rc = G10ERR_WRITE_FILE;
384                 }
385                 m_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
386             }
387             else {
388                 iobuf_writebyte(chain, 0);
389                 iobuf_writebyte(chain, 0);
390             }
391         }
392         else if( a->size ) {
393             log_error("block_filter: pending bytes!\n");
394         }
395         if( DBG_IOBUF )
396             log_debug("free block_filter %p\n", a );
397         m_free(a); /* we can free our context now */
398     }
399
400     return rc;
401 }
402
403
404
405 /****************
406  * Allocate a new io buffer, with no function assigned.
407  * Usage is the desired usage: 1 for input, 2 for output, 3 for temp buffer
408  * BUFSIZE is a suggested buffer size.
409  */
410 IOBUF
411 iobuf_alloc(int usage, size_t bufsize)
412 {
413     IOBUF a;
414     static int number=0;
415
416     a = m_alloc_clear(sizeof *a);
417     a->usage = usage;
418     a->d.buf = m_alloc( bufsize );
419     a->d.size = bufsize;
420     a->no = ++number;
421     a->subno = 0;
422     a->opaque = NULL;
423     return a;
424 }
425
426
427 int
428 iobuf_close( IOBUF a )
429 {
430     IOBUF a2;
431     size_t dummy_len;
432     int rc=0;
433
434     if( a->directfp ) {
435         fclose( a->directfp );
436         if( DBG_IOBUF )
437             log_debug("iobuf-close -> %p\n", a->directfp );
438         return 0;
439     }
440
441     for( ; a && !rc ; a = a2 ) {
442         a2 = a->chain;
443         if( a->usage == 2 && (rc=iobuf_flush(a)) )
444             log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
445
446         if( DBG_IOBUF )
447             log_debug("iobuf-%d.%d: close '%s'\n", a->no, a->subno, a->desc );
448         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
449                                          a->chain, NULL, &dummy_len)) )
450             log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
451         m_free(a->d.buf);
452         m_free(a);
453     }
454     return rc;
455 }
456
457 int
458 iobuf_cancel( IOBUF a )
459 {
460     const char *s;
461
462     if( a && a->usage == 2 ) {
463         s = get_real_fname(a);
464         if( s && *s )
465             remove(s);  /* remove the file. Fixme: this will fail for MSDOZE*/
466     }                   /* because the file is still open */
467     return iobuf_close(a);
468 }
469
470
471 /****************
472  * create a temporary iobuf, which can be used to collect stuff
473  * in an iobuf and later be written by iobuf_write_temp() to another
474  * iobuf.
475  */
476 IOBUF
477 iobuf_temp()
478 {
479     IOBUF a;
480
481     a = iobuf_alloc(3, 8192 );
482
483     return a;
484 }
485
486
487 /****************
488  * Create a head iobuf for reading from a file
489  * returns: NULL if an error occures and sets errno
490  */
491 IOBUF
492 iobuf_open( const char *fname )
493 {
494     IOBUF a;
495     FILE *fp;
496     file_filter_ctx_t *fcx;
497     size_t len;
498     int print_only = 0;
499
500     if( !fname || (*fname=='-' && !fname[1])  ) {
501         fp = stdin; /* fixme: set binary mode for msdoze */
502         fname = "[stdin]";
503         print_only = 1;
504     }
505     else if( !(fp = fopen(fname, "rb")) )
506         return NULL;
507     a = iobuf_alloc(1, 8192 );
508     fcx = m_alloc( sizeof *fcx + strlen(fname) );
509     fcx->fp = fp;
510     fcx->print_only_name = print_only;
511     strcpy(fcx->fname, fname );
512     a->filter = file_filter;
513     a->filter_ov = fcx;
514     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
515     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
516     if( DBG_IOBUF )
517         log_debug("iobuf-%d.%d: open '%s'\n", a->no, a->subno, fname );
518
519     return a;
520 }
521
522 /****************
523  * create an iobuf for writing to a file; the file will be created.
524  */
525 IOBUF
526 iobuf_create( const char *fname )
527 {
528     IOBUF a;
529     FILE *fp;
530     file_filter_ctx_t *fcx;
531     size_t len;
532     int print_only = 0;
533
534     if( !fname || (*fname=='-' && !fname[1]) ) {
535         fp = stdout;
536         fname = "[stdout]";
537         print_only = 1;
538     }
539     else if( !(fp = fopen(fname, "wb")) )
540         return NULL;
541     a = iobuf_alloc(2, 8192 );
542     fcx = m_alloc( sizeof *fcx + strlen(fname) );
543     fcx->fp = fp;
544     fcx->print_only_name = print_only;
545     strcpy(fcx->fname, fname );
546     a->filter = file_filter;
547     a->filter_ov = fcx;
548     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
549     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
550     if( DBG_IOBUF )
551         log_debug("iobuf-%d.%d: create '%s'\n", a->no, a->subno, a->desc );
552
553     return a;
554 }
555
556 /****************
557  * append to an iobuf; if the file does not exist, create it.
558  * cannot be used for stdout.
559  */
560 IOBUF
561 iobuf_append( const char *fname )
562 {
563     IOBUF a;
564     FILE *fp;
565     file_filter_ctx_t *fcx;
566     size_t len;
567
568     if( !fname )
569         return NULL;
570     else if( !(fp = fopen(fname, "ab")) )
571         return NULL;
572     a = iobuf_alloc(2, 8192 );
573     fcx = m_alloc( sizeof *fcx + strlen(fname) );
574     fcx->fp = fp;
575     strcpy(fcx->fname, fname );
576     a->filter = file_filter;
577     a->filter_ov = fcx;
578     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
579     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
580     if( DBG_IOBUF )
581         log_debug("iobuf-%d.%d: append '%s'\n", a->no, a->subno, a->desc );
582
583     return a;
584 }
585
586 IOBUF
587 iobuf_openrw( const char *fname )
588 {
589     IOBUF a;
590     FILE *fp;
591     file_filter_ctx_t *fcx;
592     size_t len;
593
594     if( !fname )
595         return NULL;
596     else if( !(fp = fopen(fname, "r+b")) )
597         return NULL;
598     a = iobuf_alloc(2, 8192 );
599     fcx = m_alloc( sizeof *fcx + strlen(fname) );
600     fcx->fp = fp;
601     strcpy(fcx->fname, fname );
602     a->filter = file_filter;
603     a->filter_ov = fcx;
604     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
605     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
606     if( DBG_IOBUF )
607         log_debug("iobuf-%d.%d: openrw '%s'\n", a->no, a->subno, a->desc );
608
609     return a;
610 }
611
612
613
614 /****************
615  * You can overwrite the normal iobuf behaviour by using this function.
616  * If used, the crwated iobuf is a simple wrapper around stdio.
617  * NULL if an error occures and sets errno
618  */
619 IOBUF
620 iobuf_fopen( const char *fname, const char *mode )
621 {
622     IOBUF a;
623     FILE *fp;
624     int print_only = 0;
625
626     if( !fname || (*fname=='-' && !fname[1])  ) {
627         fp = stdin; /* fixme: set binary mode for msdoze */
628         fname = "[stdin]";
629         print_only = 1;
630     }
631     else if( !(fp = fopen(fname, mode) ) )
632         return NULL;
633     a = iobuf_alloc(1, 8192 );
634     a->directfp = fp;
635
636     if( DBG_IOBUF )
637         log_debug("iobuf_fopen -> %p\n", a->directfp );
638
639     return a;
640 }
641
642
643
644
645 /****************
646  * Register an i/o filter.
647  */
648 int
649 iobuf_push_filter( IOBUF a,
650                    int (*f)(void *opaque, int control,
651                    IOBUF chain, byte *buf, size_t *len), void *ov )
652 {
653     IOBUF b;
654     size_t dummy_len=0;
655     int rc=0;
656
657     if( a->directfp )
658         BUG();
659
660     if( a->usage == 2 && (rc=iobuf_flush(a)) )
661         return rc;
662     /* make a copy of the current stream, so that
663      * A is the new stream and B the original one.
664      * The contents of the buffers are transferred to the
665      * new stream.
666      */
667     b = m_alloc(sizeof *b);
668     memcpy(b, a, sizeof *b );
669     /* remove the filter stuff from the new stream */
670     a->filter = NULL;
671     a->filter_ov = NULL;
672     a->filter_eof = 0;
673     if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
674         b->d.buf = m_alloc( a->d.size );
675         b->d.len = 0;
676         b->d.start = 0;
677     }
678     else { /* allocate a fresh buffer for the new stream */
679         a->d.buf = m_alloc( a->d.size );
680         a->d.len = 0;
681         a->d.start = 0;
682     }
683     /* disable nlimit for the new stream */
684     a->ntotal = b->ntotal + b->nbytes;
685     a->nlimit = a->nbytes = 0;
686     a->nofast &= ~1;
687     /* make a link from the new stream to the original stream */
688     a->chain = b;
689     a->opaque = b->opaque;
690
691     /* setup the function on the new stream */
692     a->filter = f;
693     a->filter_ov = ov;
694
695     a->subno = b->subno + 1;
696     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
697
698     if( DBG_IOBUF ) {
699         log_debug("iobuf-%d.%d: push '%s'\n", a->no, a->subno, a->desc );
700         for(b=a; b; b = b->chain )
701             log_debug("\tchain: %d.%d '%s'\n", b->no, b->subno, b->desc );
702     }
703
704     /* now we can initialize the new function if we have one */
705     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
706                        NULL, &dummy_len)) )
707         log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
708     return rc;
709 }
710
711 /****************
712  * Remove an i/o filter.
713  */
714 int
715 iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
716                       IOBUF chain, byte *buf, size_t *len), void *ov )
717 {
718     IOBUF b;
719     size_t dummy_len=0;
720     int rc=0;
721
722     if( a->directfp )
723         BUG();
724
725     if( DBG_IOBUF )
726         log_debug("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, a->desc );
727     if( !a->filter ) { /* this is simple */
728         b = a->chain;
729         assert(b);
730         m_free(a->d.buf);
731         memcpy(a,b, sizeof *a);
732         m_free(b);
733         return 0;
734     }
735     for(b=a ; b; b = b->chain )
736         if( b->filter == f && (!ov || b->filter_ov == ov) )
737             break;
738     if( !b )
739         log_bug("iobuf_pop_filter(): filter function not found\n");
740
741     /* flush this stream if it is an output stream */
742     if( a->usage == 2 && (rc=iobuf_flush(b)) ) {
743         log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
744         return rc;
745     }
746     /* and tell the filter to free it self */
747     if( (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
748                        NULL, &dummy_len)) ) {
749         log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
750         return rc;
751     }
752
753     /* and see how to remove it */
754     if( a == b && !b->chain )
755         log_bug("can't remove the last filter from the chain\n");
756     else if( a == b ) { /* remove the first iobuf from the chain */
757         /* everything from b is copied to a. This is save because
758          * a flush has been done on the to be removed entry
759          */
760         b = a->chain;
761         m_free(a->d.buf);
762         memcpy(a,b, sizeof *a);
763         m_free(b);
764         if( DBG_IOBUF )
765            log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
766     }
767     else if( !b->chain ) { /* remove the last iobuf from the chain */
768         log_bug("Ohh jeee, trying to remove a head filter\n");
769     }
770     else {  /* remove an intermediate iobuf from the chain */
771         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
772     }
773
774     return rc;
775 }
776
777
778
779 /****************
780  * read underflow: read more bytes into the buffer and return
781  * the first byte or -1 on EOF.
782  */
783 static int
784 underflow(IOBUF a)
785 {
786     size_t len;
787     int rc;
788
789   /*log_debug("iobuf-%d.%d: underflow: start=%lu len=%lu\n",
790                 a->no, a->subno, (ulong)a->d.start, (ulong)a->d.len );*/
791     assert( a->d.start == a->d.len );
792     if( a->usage == 3 )
793         return -1; /* EOF because a temp buffer can't do an underflow */
794
795     if( a->filter_eof ) {
796         if( DBG_IOBUF )
797             log_debug("iobuf-%d.%d: filter eof\n", a->no, a->subno );
798         return -1;
799     }
800     if( a->error ) {
801         if( DBG_IOBUF )
802             log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
803         return -1;
804     }
805
806     if( a->directfp ) {
807         FILE *fp = a->directfp;
808
809         len = fread( a->d.buf, 1, a->d.size, fp);
810         if( len < a->d.size ) {
811             if( ferror(fp) )
812                 a->error = 1;
813             else if( feof( fp ) )
814                 a->filter_eof = 1;
815         }
816         a->d.len = len;
817         a->d.start = 0;
818         return len? a->d.buf[a->d.start++] : -1;
819     }
820
821
822     if( a->filter ) {
823         len = a->d.size;
824         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
825                         a->d.buf, &len );
826         if( a->usage == 1 && rc == -1 ) { /* EOF: we can remove the filter */
827             size_t dummy_len;
828
829             /* and tell the filter to free it self */
830             if( a->filter != file_filter ) {
831                 if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
832                                    NULL, &dummy_len)) )
833                     log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
834                 a->filter = NULL;
835                 a->desc = NULL;
836                 a->filter_ov = NULL;
837             }
838             a->filter_eof = 1;
839         }
840         else if( rc )
841             a->error = 1;
842
843         if( !len )
844             return -1;
845         a->d.len = len;
846         a->d.start = 0;
847         return a->d.buf[a->d.start++];
848     }
849     else
850         return -1;  /* no filter; return EOF */
851 }
852
853
854 void
855 iobuf_clear_eof(IOBUF a)
856 {
857     if( a->directfp )
858         return;
859
860     assert(a->usage == 1);
861
862     if( a->filter )
863         log_info("iobuf-%d.%d: clear_eof '%s' with enabled filter\n", a->no, a->subno, a->desc );
864     if( !a->filter_eof )
865         log_info("iobuf-%d.%d: clear_eof '%s' with no EOF pending\n", a->no, a->subno, a->desc );
866     iobuf_pop_filter(a, NULL, NULL);
867 }
868
869
870 int
871 iobuf_flush(IOBUF a)
872 {
873     size_t len;
874     int rc;
875
876     if( a->directfp )
877         return 0;
878
879     /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
880     if( a->usage == 3 )
881         log_bug("temp buffer too short\n");
882     else if( a->usage != 2 )
883         log_bug("flush on non-output iobuf\n");
884     else if( !a->filter )
885         log_bug("iobuf_flush: no filter\n");
886     len = a->d.len;
887     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
888     if( !rc && len != a->d.len ) {
889         log_info("iobuf_flush did not write all!\n");
890         rc = G10ERR_WRITE_FILE;
891     }
892     else if( rc )
893         a->error = 1;
894     a->d.len = 0;
895
896     return rc;
897 }
898
899
900 /****************
901  * Read a byte from the iobuf; returns -1 on EOF
902  */
903 int
904 iobuf_readbyte(IOBUF a)
905 {
906     int c;
907
908     /* nlimit does not work together with unget */
909     /* nbytes is also not valid! */
910     if( a->unget.buf ) {
911         if( a->unget.start < a->unget.len )
912             return a->unget.buf[a->unget.start++];
913         m_free(a->unget.buf);
914         a->unget.buf = NULL;
915         a->nofast &= ~2;
916     }
917
918     if( a->nlimit && a->nbytes >= a->nlimit )
919         return -1; /* forced EOF */
920
921     if( a->d.start < a->d.len ) {
922         c = a->d.buf[a->d.start++];
923     }
924     else if( (c=underflow(a)) == -1 )
925         return -1; /* EOF */
926
927     a->nbytes++;
928     return c;
929 }
930
931
932 int
933 iobuf_read(IOBUF a, byte *buf, unsigned buflen )
934 {
935     int c, n;
936
937     if( a->unget.buf || a->nlimit ) {
938         /* handle special cases */
939         for(n=0 ; n < buflen; n++, buf++ ) {
940             if( (c = iobuf_readbyte(a)) == -1 ) {
941                 if( !n )
942                     return -1; /* eof */
943                 break;
944             }
945             else
946                 *buf = c;
947         }
948         return n;
949     }
950
951     n = 0;
952     do {
953         for( ; n < buflen && a->d.start < a->d.len; n++ )
954             *buf++ = a->d.buf[a->d.start++];
955         if( n < buflen ) {
956             if( (c=underflow(a)) == -1 ) {
957                 a->nbytes += n;
958                 return n? n : -1/*EOF*/;
959             }
960             *buf++ = c; n++;
961         }
962     } while( n < buflen );
963     a->nbytes += n;
964     return n;
965 }
966
967
968 /****************
969  * Have a look at the iobuf.
970  * NOTE: This only works in special cases.
971  */
972 int
973 iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
974 {
975     int n=0;
976
977     if( a->filter_eof )
978         return -1;
979     if( !(a->d.start < a->d.len) ) {
980         if( underflow(a) == -1 )
981             return -1;
982         /* and unget this character */
983         assert(a->d.start == 1);
984         a->d.start = 0;
985     }
986
987     for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
988         *buf = a->d.buf[n];
989     return n;
990 }
991
992
993
994
995 int
996 iobuf_writebyte(IOBUF a, unsigned c)
997 {
998
999     if( a->directfp )
1000         BUG();
1001
1002     if( a->d.len == a->d.size )
1003         if( iobuf_flush(a) )
1004             return -1;
1005
1006     assert( a->d.len < a->d.size );
1007     a->d.buf[a->d.len++] = c;
1008     return 0;
1009 }
1010
1011
1012 int
1013 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
1014 {
1015
1016     if( a->directfp )
1017         BUG();
1018
1019     do {
1020         for( ; buflen && a->d.len < a->d.size; buflen--, buf++ )
1021             a->d.buf[a->d.len++] = *buf;
1022         if( buflen ) {
1023             if( iobuf_flush(a) )
1024                 return -1;
1025         }
1026     } while( buflen );
1027     return 0;
1028 }
1029
1030
1031 int
1032 iobuf_writestr(IOBUF a, const char *buf )
1033 {
1034     for( ; *buf; buf++ )
1035         if( iobuf_writebyte(a, *buf) )
1036             return -1;
1037     return 0;
1038 }
1039
1040
1041
1042 /****************
1043  * copy the contents of TEMP to A.
1044  */
1045 int
1046 iobuf_write_temp( IOBUF a, IOBUF temp )
1047 {
1048     return iobuf_write(a, temp->d.buf, temp->d.len );
1049 }
1050
1051 /****************
1052  * copy the contents of the temp io stream to BUFFER.
1053  */
1054 size_t
1055 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
1056 {
1057     size_t n = a->d.len;
1058
1059     if( n > buflen )
1060         n = buflen;
1061     memcpy( buffer, a->d.buf, n );
1062     return n;
1063 }
1064
1065 /****************
1066  * unget the contents of the temp io stream to A and close temp
1067  * Could be optimized!!
1068  */
1069 void
1070 iobuf_unget_and_close_temp( IOBUF a, IOBUF temp )
1071 {
1072     if( a->unget.buf ) {
1073         if( a->unget.start < a->unget.len )
1074             log_fatal("cannot do any more ungets on this buffer\n");
1075         /* not yet cleaned up; do it now */
1076         m_free(a->unget.buf);
1077         a->unget.buf = NULL;
1078         a->nofast &= ~2;
1079     }
1080     a->unget.size = temp->d.len;
1081     a->unget.buf = m_alloc( a->unget.size );
1082     a->nofast |= 2;
1083     a->unget.len = temp->d.len;
1084     memcpy( a->unget.buf, temp->d.buf, a->unget.len );
1085     iobuf_close(temp);
1086 }
1087
1088
1089 /****************
1090  * Set a limit on how many bytes may be read from the input stream A.
1091  * Setting the limit to 0 disables this feature.
1092  */
1093 void
1094 iobuf_set_limit( IOBUF a, unsigned long nlimit )
1095 {
1096     if( nlimit )
1097         a->nofast |= 1;
1098     else
1099         a->nofast &= ~1;
1100     a->nlimit = nlimit;
1101     a->ntotal += a->nbytes;
1102     a->nbytes = 0;
1103 }
1104
1105
1106
1107 /****************
1108  * Return the length of an open file
1109  */
1110 u32
1111 iobuf_get_filelength( IOBUF a )
1112 {
1113     struct stat st;
1114
1115     if( a->directfp )  {
1116         FILE *fp = a->directfp;
1117
1118         if( !fstat(fileno(fp), &st) )
1119             return st.st_size;
1120         log_error("fstat() failed: %s\n", strerror(errno) );
1121         return 0;
1122     }
1123
1124     for( ; a; a = a->chain )
1125         if( !a->chain && a->filter == file_filter ) {
1126             file_filter_ctx_t *b = a->filter_ov;
1127             FILE *fp = b->fp;
1128
1129             if( !fstat(fileno(fp), &st) )
1130                 return st.st_size;
1131             log_error("fstat() failed: %s\n", strerror(errno) );
1132             break;
1133         }
1134
1135     return 0;
1136 }
1137
1138 /****************
1139  * Tell the file position, where the next read will take place
1140  */
1141 ulong
1142 iobuf_tell( IOBUF a )
1143 {
1144     return a->ntotal + a->nbytes;
1145 }
1146
1147
1148
1149 /****************
1150  * This is a very limited implementation. It simply discards all internal
1151  * buffering and removes all filters but the first one.
1152  */
1153 int
1154 iobuf_seek( IOBUF a, ulong newpos )
1155 {
1156     file_filter_ctx_t *b = NULL;
1157
1158     if( a->directfp ) {
1159         FILE *fp = a->directfp;
1160         if( fseek( fp, newpos, SEEK_SET ) ) {
1161             log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
1162             return -1;
1163         }
1164         clearerr(fp);
1165     }
1166     else {
1167         for( ; a; a = a->chain ) {
1168             if( !a->chain && a->filter == file_filter ) {
1169                 b = a->filter_ov;
1170                 break;
1171             }
1172         }
1173         if( !a )
1174             return -1;
1175         if( fseek( b->fp, newpos, SEEK_SET ) ) {
1176             log_error("can't seek to %lu: %s\n", newpos, strerror(errno) );
1177             return -1;
1178         }
1179     }
1180     a->d.len = 0;   /* discard buffer */
1181     a->d.start = 0;
1182     a->nbytes = 0;
1183     a->nlimit = 0;
1184     a->nofast &= ~1;
1185     a->ntotal = newpos;
1186     a->error = 0;
1187     /* remove filters, but the last */
1188     while( a->chain )
1189         iobuf_pop_filter( a, a->filter, NULL );
1190
1191     return 0;
1192 }
1193
1194
1195
1196
1197
1198
1199 /****************
1200  * Retrieve the real filename
1201  */
1202 static const char *
1203 get_real_fname( IOBUF a )
1204 {
1205     for( ; a; a = a->chain )
1206         if( !a->chain && a->filter == file_filter ) {
1207             file_filter_ctx_t *b = a->filter_ov;
1208             return b->print_only_name? NULL : b->fname;
1209         }
1210
1211     return NULL;
1212 }
1213
1214 /****************
1215  * Retrieve the filename
1216  */
1217 const char *
1218 iobuf_get_fname( IOBUF a )
1219 {
1220     for( ; a; a = a->chain )
1221         if( !a->chain && a->filter == file_filter ) {
1222             file_filter_ctx_t *b = a->filter_ov;
1223             return b->fname;
1224         }
1225
1226     return NULL;
1227 }
1228
1229 /****************
1230  * Start the block write mode, see rfc1991.new for details.
1231  * A value of 0 for N stops this mode (flushes and writes
1232  * the end marker)
1233  */
1234 void
1235 iobuf_set_block_mode( IOBUF a, size_t n )
1236 {
1237     block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
1238
1239     assert( a->usage == 1 || a->usage == 2 );
1240     ctx->usage = a->usage;
1241     if( !n ) {
1242         iobuf_pop_filter(a, block_filter, NULL );
1243     }
1244     else {
1245         ctx->size = n; /* only needed for usage 2 */
1246         iobuf_push_filter(a, block_filter, ctx );
1247     }
1248 }
1249
1250 /****************
1251  * enable partial block mode as described in the OpenPGP draft.
1252  * LEN is the first length byte on read, but ignored on writes.
1253  */
1254 void
1255 iobuf_set_partial_block_mode( IOBUF a, size_t len )
1256 {
1257     block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
1258
1259     assert( a->usage == 1 || a->usage == 2 );
1260     ctx->usage = a->usage;
1261     if( !len ) {
1262         iobuf_pop_filter(a, block_filter, NULL );
1263     }
1264     else {
1265         ctx->partial = 1;
1266         ctx->size = 0;
1267         ctx->first_c = len;
1268         iobuf_push_filter(a, block_filter, ctx );
1269     }
1270 }
1271
1272
1273 /****************
1274  * Checks whether the stream is in block mode
1275  * Note: This does not work if other filters are pushed on the stream.
1276  */
1277 int
1278 iobuf_in_block_mode( IOBUF a )
1279 {
1280     if( a && a->filter == block_filter )
1281         return 1; /* yes */
1282     return 0; /* no */
1283 }
1284
1285
1286