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