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