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