added option file handling
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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/stat.h>
28 #include <unistd.h>
29
30 #include "memory.h"
31 #include "util.h"
32 #include "iobuf.h"
33
34 typedef struct {
35     FILE *fp;      /* open file handle */
36     char fname[1]; /* name of the file */
37 } file_filter_ctx_t ;
38
39 typedef struct {
40     int usage;
41     size_t size;
42     size_t count;
43     int eof;
44 } block_filter_ctx_t;
45
46 static int underflow(IOBUF a);
47
48 /****************
49  * Read data from a file into buf which has an allocated length of *LEN.
50  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
51  * the stream. A is not used.
52  * control maybe:
53  * IOBUFCTRL_INIT: called just before the function is linked into the
54  *                 list of function. This can be used to prepare internal
55  *                 data structures of the function.
56  * IOBUFCTRL_FREE: called just before the function is removed from the
57  *                  list of functions and can be used to release internal
58  *                  data structures or close a file etc.
59  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
60  *                  with new stuff. *RET_LEN is the available size of the
61  *                  buffer, and should be set to the number of bytes
62  *                  which were put into the buffer. The function
63  *                  returns 0 to indicate success, -1 on EOF and
64  *                  G10ERR_xxxxx for other errors.
65  *
66  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
67  *                  *RET_LAN is the number of bytes in BUF.
68  *
69  */
70 static int
71 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
72 {
73     file_filter_ctx_t *a = opaque;
74     FILE *fp = a->fp;
75     size_t size = *ret_len;
76     size_t nbytes = 0;
77     int c, rc = 0;
78     char *p;
79
80     if( control == IOBUFCTRL_UNDERFLOW ) {
81         assert( size ); /* need a buffer */
82         for(; size; size-- ) {
83             if( (c=getc(fp)) == EOF ) {
84                 if( ferror(fp) ) {
85                     log_error("%s: read error: %s\n",
86                                         a->fname, strerror(errno));
87                     rc = G10ERR_READ_FILE;
88                 }
89                 else if( !nbytes )
90                     rc = -1; /* okay: we can return EOF now. */
91                 break;
92             }
93             buf[nbytes++] = c & 0xff;
94         }
95         *ret_len = nbytes;
96     }
97     else if( control == IOBUFCTRL_FLUSH ) {
98         for(p=buf; nbytes < size; nbytes++, p++ ) {
99             if( putc(*p, fp) == EOF ) {
100                 log_error("%s: write error: %s\n",
101                                     a->fname, strerror(errno));
102                 rc = G10ERR_WRITE_FILE;
103                 break;
104             }
105         }
106         *ret_len = nbytes;
107     }
108     else if( control == IOBUFCTRL_INIT ) {
109     }
110     else if( control == IOBUFCTRL_DESC ) {
111         *(char**)buf = "file_filter";
112     }
113     else if( control == IOBUFCTRL_FREE ) {
114         if( fp != stdin && fp != stdout )
115             fclose(fp);
116         fp = NULL;
117         m_free(a); /* we can free our context now */
118     }
119
120     return rc;
121 }
122
123
124 /****************
125  * This is used to implement the block write mode.
126  * Block reading is done on a byte by byte basis in readbyte(),
127  * without a filter
128  */
129 static int
130 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
131 {
132     block_filter_ctx_t *a = opaque;
133     size_t size = *ret_len;
134     int c, rc = 0;
135     char *p;
136
137     if( control == IOBUFCTRL_UNDERFLOW ) {
138         size_t n=0;
139
140         p = buf;
141         assert( size ); /* need a buffer */
142         if( a->eof ) /* don't read any further */
143             rc = -1;
144         while( !rc && size ) {
145             if( !a->size ) { /* get the length bytes */
146                 c = iobuf_get(chain);
147                 a->size = c << 8;
148                 c = iobuf_get(chain);
149                 a->size |= c;
150                 if( c == -1 ) {
151                     log_error("block_filter: error reading length info\n");
152                     rc = G10ERR_READ_FILE;
153                 }
154                 if( !a->size ) {
155                     a->eof = 1;
156                     if( !n )
157                         rc = -1;
158                     break;
159                 }
160             }
161
162             for(; !rc && size && a->size; size--, a->size-- ) {
163                 if( (c=iobuf_get(chain)) == -1 ) {
164                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
165                                 a,  (ulong)size, (ulong)a->size);
166                     rc = G10ERR_READ_FILE;
167                 }
168                 else {
169                     *p++ = c;
170                     n++;
171                 }
172             }
173         }
174         *ret_len = n;
175     }
176     else if( control == IOBUFCTRL_FLUSH ) {
177         size_t avail, n;
178
179         for(p=buf; !rc && size; ) {
180             n = size;
181             avail = a->size - a->count;
182             if( !avail ) {
183                 if( n > a->size ) {
184                     iobuf_put( chain, (a->size >> 8) & 0xff );
185                     iobuf_put( chain, a->size & 0xff );
186                     avail = a->size;
187                     a->count = 0;
188                 }
189                 else {
190                     iobuf_put( chain, (n >> 8) & 0xff );
191                     iobuf_put( chain, n & 0xff );
192                     avail = n;
193                     a->count = a->size - n;
194                 }
195             }
196             if( n > avail )
197                 n = avail;
198             if( iobuf_write(chain, p, n ) )
199                 rc = G10ERR_WRITE_FILE;
200             a->count += n;
201             p += n;
202             size -= n;
203         }
204     }
205     else if( control == IOBUFCTRL_INIT ) {
206         if( DBG_IOBUF )
207             log_debug("init block_filter %p\n", a );
208         if( a->usage == 1 )
209             a->count = a->size = 0;
210         else
211             a->count = a->size; /* force first length bytes */
212         a->eof = 0;
213     }
214     else if( control == IOBUFCTRL_DESC ) {
215         *(char**)buf = "block_filter";
216     }
217     else if( control == IOBUFCTRL_FREE ) {
218         if( a->usage == 2 ) { /* write the end markers */
219             iobuf_writebyte(chain, 0);
220             iobuf_writebyte(chain, 0);
221         }
222         else if( a->size ) {
223             log_error("block_filter: pending bytes!\n");
224         }
225         if( DBG_IOBUF )
226             log_debug("free block_filter %p\n", a );
227         m_free(a); /* we can free our context now */
228     }
229
230     return rc;
231 }
232
233
234
235 /****************
236  * Allocate a new io buffer, with no function assigned.
237  * Usage is the desired usage: 1 for input, 2 for output, 3 for temp buffer
238  * BUFSIZE is a suggested buffer size.
239  */
240 IOBUF
241 iobuf_alloc(int usage, size_t bufsize)
242 {
243     IOBUF a;
244     static int number=0;
245
246     a = m_alloc_clear(sizeof *a);
247     a->usage = usage;
248     a->d.buf = m_alloc( bufsize );
249     a->d.size = bufsize;
250     a->no = ++number;
251     a->subno = 0;
252     a->opaque = NULL;
253     return a;
254 }
255
256
257 int
258 iobuf_close( IOBUF a )
259 {
260     IOBUF a2;
261     size_t dummy_len;
262     int rc=0;
263
264     for( ; a; a = a2 ) {
265         a2 = a->chain;
266         if( a->usage == 2 && (rc=iobuf_flush(a)) )
267             log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
268
269         if( DBG_IOBUF )
270             log_debug("iobuf-%d.%d: close '%s'\n", a->no, a->subno, a->desc );
271         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
272                                          a->chain, NULL, &dummy_len)) )
273             log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
274         m_free(a->d.buf);
275         m_free(a);
276     }
277     return rc;
278 }
279
280 int
281 iobuf_cancel( IOBUF a )
282 {
283     const char *s;
284
285     if( a && a->usage == 2 ) {
286         s = iobuf_get_fname(a);
287         if( s && *s )
288             remove(s);  /* remove the file. Fixme: this will fail for MSDOZE*/
289     }                   /* because the file is still open */
290     return iobuf_close(a);
291 }
292
293
294 /****************
295  * create a temporary iobuf, which can be used to collect stuff
296  * in an iobuf and later be written by iobuf_write_temp() to another
297  * iobuf.
298  */
299 IOBUF
300 iobuf_temp()
301 {
302     IOBUF a;
303
304     a = iobuf_alloc(3, 8192 );
305
306     return a;
307 }
308
309
310 /****************
311  * Create a head iobuf for reading from a file
312  * returns: NULL if an error occures and sets errno
313  */
314 IOBUF
315 iobuf_open( const char *fname )
316 {
317     IOBUF a;
318     FILE *fp;
319     file_filter_ctx_t *fcx;
320     size_t len;
321
322     if( !fname ) {
323         fp = stdin; /* fixme: set binary mode for msdoze */
324         fname = "[stdin]";
325     }
326     else if( !(fp = fopen(fname, "rb")) )
327         return NULL;
328     a = iobuf_alloc(1, 8192 );
329     fcx = m_alloc( sizeof *fcx + strlen(fname) );
330     fcx->fp = fp;
331     strcpy(fcx->fname, fname );
332     a->filter = file_filter;
333     a->filter_ov = fcx;
334     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
335     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
336     if( DBG_IOBUF )
337         log_debug("iobuf-%d.%d: open '%s'\n", a->no, a->subno, fname );
338
339     return a;
340 }
341
342 /****************
343  * create a iobuf for writing to a file; the file will be created.
344  */
345 IOBUF
346 iobuf_create( const char *fname )
347 {
348     IOBUF a;
349     FILE *fp;
350     file_filter_ctx_t *fcx;
351     size_t len;
352
353     if( !fname ) {
354         fp = stdout;
355         fname = "[stdout]";
356     }
357     else if( !(fp = fopen(fname, "wb")) )
358         return NULL;
359     a = iobuf_alloc(2, 8192 );
360     fcx = m_alloc( sizeof *fcx + strlen(fname) );
361     fcx->fp = fp;
362     strcpy(fcx->fname, fname );
363     a->filter = file_filter;
364     a->filter_ov = fcx;
365     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
366     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
367     if( DBG_IOBUF )
368         log_debug("iobuf-%d.%d: create '%s'\n", a->no, a->subno, a->desc );
369
370     return a;
371 }
372
373 /****************
374  * Register an i/o filter.
375  */
376 int
377 iobuf_push_filter( IOBUF a,
378                    int (*f)(void *opaque, int control,
379                    IOBUF chain, byte *buf, size_t *len), void *ov )
380 {
381     IOBUF b;
382     size_t dummy_len=0;
383     int rc=0;
384
385     if( a->usage == 2 && (rc=iobuf_flush(a)) )
386         return rc;
387     /* make a copy of the current stream, so that
388      * A is the new stream and B the original one.
389      * The contents of the buffers are transferred to the
390      * new stream.
391      */
392     b = m_alloc(sizeof *b);
393     memcpy(b, a, sizeof *b );
394     /* remove the filter stuff from the new stream */
395     a->filter = NULL;
396     a->filter_ov = NULL;
397     if( a->usage == 2 ) { /* allocate a fresh buffer for the original stream */
398         b->d.buf = m_alloc( a->d.size );
399         b->d.len = 0;
400         b->d.start = 0;
401     }
402     else { /* allocate a fresh buffer for the new stream */
403         a->d.buf = m_alloc( a->d.size );
404         a->d.len = 0;
405         a->d.start = 0;
406     }
407     /* disable nlimit for the new stream */
408     a->ntotal = b->ntotal + b->nbytes;
409     a->nlimit = a->nbytes = 0;
410     /* make a link from the new stream to the original stream */
411     a->chain = b;
412     a->opaque = b->opaque;
413
414     /* setup the function on the new stream */
415     a->filter = f;
416     a->filter_ov = ov;
417
418     a->subno = b->subno + 1;
419     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
420
421     if( DBG_IOBUF ) {
422         log_debug("iobuf-%d.%d: push '%s'\n", a->no, a->subno, a->desc );
423         for(b=a; b; b = b->chain )
424             log_debug("\tchain: %d.%d '%s'\n", b->no, b->subno, b->desc );
425     }
426
427     /* now we can initialize the new function if we have one */
428     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
429                        NULL, &dummy_len)) )
430         log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
431     return rc;
432 }
433
434 /****************
435  * Remove an i/o filter.
436  */
437 int
438 iobuf_pop_filter( IOBUF a, int (*f)(void *opaque, int control,
439                       IOBUF chain, byte *buf, size_t *len), void *ov )
440 {
441     IOBUF b;
442     size_t dummy_len=0;
443     int rc=0;
444
445     if( DBG_IOBUF )
446         log_debug("iobuf-%d.%d: pop '%s'\n", a->no, a->subno, a->desc );
447     if( !a->filter ) { /* this is simple */
448         b = a->chain;
449         assert(b);
450         m_free(a->d.buf);
451         memcpy(a,b, sizeof *a);
452         m_free(b);
453         return 0;
454     }
455     for(b=a ; b; b = b->chain )
456         if( b->filter == f && (!ov || b->filter_ov == ov) )
457             break;
458     if( !b )
459         log_bug("iobuf_pop_filter(): filter function not found\n");
460
461     /* flush this stream if it is an output stream */
462     if( a->usage == 2 && (rc=iobuf_flush(b)) ) {
463         log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
464         return rc;
465     }
466     /* and tell the filter to free it self */
467     if( (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
468                        NULL, &dummy_len)) ) {
469         log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
470         return rc;
471     }
472
473     /* and look how to remove it */
474     if( a == b && !b->chain )
475         log_bug("can't remove the last filter from the chain\n");
476     else if( a == b ) { /* remove the first iobuf from the chain */
477         /* everything from b is copied to a. This is save because
478          * a flush has been done on the to be removed entry
479          */
480         b = a->chain;
481         m_free(a->d.buf);
482         memcpy(a,b, sizeof *a);
483         m_free(b);
484     }
485     else if( !b->chain ) { /* remove the last iobuf from the chain */
486         log_bug("Ohh jeee, trying to a head filter\n");
487     }
488     else {  /* remove an intermediate iobuf from the chain */
489         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
490     }
491
492     return rc;
493 }
494
495
496
497 /****************
498  * read underflow: read more bytes into the buffer and return
499  * the first byte or -1 on EOF.
500  */
501 static int
502 underflow(IOBUF a)
503 {
504     size_t len;
505     int rc;
506
507   /*log_debug("iobuf-%d.%d: underflow: start=%lu len=%lu\n",
508                 a->no, a->subno, (ulong)a->d.start, (ulong)a->d.len );*/
509     assert( a->d.start == a->d.len );
510     if( a->usage == 3 )
511         return -1; /* EOF because a temp buffer can't do an underflow */
512     if( a->filter_eof ) {
513         if( DBG_IOBUF )
514             log_debug("iobuf-%d.%d: filter eof\n", a->no, a->subno );
515         return -1;
516     }
517
518     if( a->filter ) {
519         len = a->d.size;
520         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
521                         a->d.buf, &len );
522         if( a->usage == 1 && rc == -1 ) { /* EOF: we can remove the filter */
523             size_t dummy_len;
524
525             /* and tell the filter to free it self */
526             if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
527                                NULL, &dummy_len)) )
528                 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
529             a->filter = NULL;
530             a->desc = NULL;
531             a->filter_ov = NULL;
532             a->filter_eof = 1;
533         }
534
535         if( !len )
536             return -1;
537         a->d.len = len;
538         a->d.start = 0;
539         return a->d.buf[a->d.start++];
540     }
541     else
542         return -1;  /* no filter; return EOF */
543 }
544
545
546 void
547 iobuf_clear_eof(IOBUF a)
548 {
549     assert(a->usage == 1);
550
551     if( a->filter )
552         log_info("iobuf-%d.%d: clear_eof '%s' with enabled filter\n", a->no, a->subno, a->desc );
553     if( !a->filter_eof )
554         log_info("iobuf-%d.%d: clear_eof '%s' with no EOF pending\n", a->no, a->subno, a->desc );
555     iobuf_pop_filter(a, NULL, NULL);
556 }
557
558
559 int
560 iobuf_flush(IOBUF a)
561 {
562     size_t len;
563     int rc;
564
565     /*log_debug("iobuf-%d.%d: flush\n", a->no, a->subno );*/
566     if( a->usage == 3 )
567         log_bug("temp buffer too short\n");
568     else if( a->usage != 2 )
569         log_bug("flush on non-output iobuf\n");
570     else if( !a->filter )
571         log_bug("iobuf_flush: no filter\n");
572     len = a->d.len;
573     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
574     if( !rc && len != a->d.len ) {
575         log_info("iobuf_flush did not write all!\n");
576         rc = G10ERR_WRITE_FILE;
577     }
578     a->d.len = 0;
579
580     return rc;
581 }
582
583
584 /****************
585  * Read a byte from the iobuf; returns -1 on EOF
586  */
587 int
588 iobuf_readbyte(IOBUF a)
589 {
590     int c;
591
592     if( a->nlimit && a->nbytes >= a->nlimit )
593         return -1; /* forced EOF */
594
595     if( a->d.start < a->d.len ) {
596         c = a->d.buf[a->d.start++];
597     }
598     else if( (c=underflow(a)) == -1 )
599         return -1; /* EOF */
600
601     a->nbytes++;
602     return c;
603 }
604
605
606 int
607 iobuf_writebyte(IOBUF a, unsigned c)
608 {
609     if( a->d.len == a->d.size )
610         if( iobuf_flush(a) )
611             return -1;
612
613     assert( a->d.len < a->d.size );
614     a->d.buf[a->d.len++] = c;
615     return 0;
616 }
617
618
619 int
620 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
621 {
622     for( ; buflen; buflen--, buf++ )
623         if( iobuf_writebyte(a, *buf) )
624             return -1;
625     return 0;
626 }
627
628 int
629 iobuf_writestr(IOBUF a, const char *buf )
630 {
631     for( ; *buf; buf++ )
632         if( iobuf_writebyte(a, *buf) )
633             return -1;
634     return 0;
635 }
636
637
638
639 /****************
640  * copy the contents of TEMP to A.
641  */
642 int
643 iobuf_write_temp( IOBUF a, IOBUF temp )
644 {
645     return iobuf_write(a, temp->d.buf, temp->d.len );
646 }
647
648 /****************
649  * copy the contents of the temp io stream to BUFFER.
650  */
651 size_t
652 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
653 {
654     size_t n = a->d.len;
655
656     if( n > buflen )
657         n = buflen;
658     memcpy( buffer, a->d.buf, n );
659     return n;
660 }
661
662
663 /****************
664  * Set a limit, how much bytes may be read from the input stream A.
665  * Setting the limit to 0 disables this feature.
666  */
667 void
668 iobuf_set_limit( IOBUF a, unsigned long nlimit )
669 {
670     a->nlimit = nlimit;
671     a->ntotal += a->nbytes;
672     a->nbytes = 0;
673 }
674
675
676
677 /****************
678  * Return the length of an open file
679  */
680 u32
681 iobuf_get_filelength( IOBUF a )
682 {
683     struct stat st;
684
685     for( ; a; a = a->chain )
686         if( !a->chain && a->filter == file_filter ) {
687             file_filter_ctx_t *b = a->filter_ov;
688             FILE *fp = b->fp;
689
690             if( !fstat(fileno(fp), &st) )
691                 return st.st_size;
692             log_error("fstat() failed: %s\n", strerror(errno) );
693             break;
694         }
695
696     return 0;
697 }
698
699 /****************
700  * Tell the file position, where the next read will take place
701  */
702 ulong
703 iobuf_tell( IOBUF a )
704 {
705     return a->ntotal + a->nbytes;
706 }
707
708
709 int
710 iobuf_seek( IOBUF a, ulong newpos )
711 {
712
713     return -1;
714 }
715
716
717
718
719
720
721 /****************
722  * Retrieve the filename
723  */
724 const char *
725 iobuf_get_fname( IOBUF a )
726 {
727     struct stat st;
728
729     for( ; a; a = a->chain )
730         if( !a->chain && a->filter == file_filter ) {
731             file_filter_ctx_t *b = a->filter_ov;
732             return b->fname;
733         }
734
735     return NULL;
736 }
737
738 /****************
739  * Start the block write mode, see rfc1991.new for details.
740  * A value of 0 for N stops this mode (flushes and writes
741  * the end marker)
742  */
743 void
744 iobuf_set_block_mode( IOBUF a, size_t n )
745 {
746     block_filter_ctx_t *ctx = m_alloc_clear( sizeof *ctx );
747
748     assert( a->usage == 1 || a->usage == 2 );
749     ctx->usage = a->usage;
750     if( !n ) {
751         iobuf_pop_filter(a, block_filter, NULL );
752     }
753     else {
754         ctx->size = n; /* only needed for usage 2 */
755         iobuf_push_filter(a, block_filter, ctx );
756     }
757 }
758
759
760 /****************
761  * checks wether the stream is in block mode
762  */
763 int
764 iobuf_in_block_mode( IOBUF a )
765 {
766     for(; a; a = a->chain )
767         if( a->filter == block_filter )
768             return 1; /* yes */
769     return 0; /* no */
770 }
771
772
773