/[winpt]/trunk/Gnupg/iobuf.c
ViewVC logotype

Annotation of /trunk/Gnupg/iobuf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (hide annotations)
Fri Oct 28 12:57:05 2005 UTC (19 years, 4 months ago) by werner
File MIME type: text/plain
File size: 42725 byte(s)
Second set of changes to use autotools for building.
1 werner 46 /* iobuf.c - file handling
2     * Copyright (C) 1998, 1999, 2000, 2001 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     #ifdef HAVE_CONFIG_H
22     #include <config.h>
23     #endif
24    
25     #include <stdio.h>
26     #include <stdio.h>
27     #include <stdlib.h>
28     #include <string.h>
29     #include <errno.h>
30     #include <ctype.h>
31     #include <assert.h>
32     #include <sys/types.h>
33     #include <sys/stat.h>
34     #include <fcntl.h>
35     #include <io.h>
36     #include <windows.h>
37    
38     #include "openpgp.h"
39    
40     #define my_fileno(a) (a)
41     #define my_fopen_ro(a,b) fd_cache_open ((a),(b))
42     #define my_fopen(a,b) direct_open ((a),(b))
43     typedef HANDLE FILEP_OR_FD;
44     #define INVALID_FP ((HANDLE)-1)
45     #define FILEP_OR_FD_FOR_STDIN (GetStdHandle (STD_INPUT_HANDLE))
46     #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
47     #undef USE_SETMODE
48     typedef struct {
49     FILEP_OR_FD fp; /* open file handle */
50     int keep_open;
51     int no_cache;
52     int eof_seen;
53     int print_only_name; /* flags indicating that fname is not a real file*/
54     char fname[1]; /* name of the file */
55     } file_filter_ctx_t ;
56    
57     struct close_cache_s {
58     struct close_cache_s *next;
59     FILEP_OR_FD fp;
60     char fname[1];
61     };
62     typedef struct close_cache_s *CLOSE_CACHE;
63     static CLOSE_CACHE close_cache;
64    
65     /* The first partial length header block must be of size 512
66     * to make it easier (and efficienter) we use a min. block size of 512
67     * for all chunks (but the last one) */
68     #define OP_MIN_PARTIAL_CHUNK 512
69     #define OP_MIN_PARTIAL_CHUNK_2POW 9
70    
71     typedef struct {
72     int use;
73     size_t size;
74     size_t count;
75     int partial; /* 1 = partial header, 2 in last partial packet */
76     char *buffer; /* used for partial header */
77     size_t buflen; /* used size of buffer */
78     int first_c; /* of partial header (which is > 0)*/
79     int eof;
80     } block_filter_ctx_t;
81    
82     static int special_names_enabled;
83    
84     static int underflow(gpg_iobuf_t a);
85     static int translate_file_handle ( int fd, int for_write );
86    
87     /*
88     * Invalidate (i.e. close) a cached iobuf
89     */
90     static void
91     fd_cache_invalidate (const char *fname)
92     {
93     CLOSE_CACHE cc;
94    
95     assert (fname);
96    
97     for (cc=close_cache; cc; cc = cc->next ) {
98     if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) {
99     CloseHandle (cc->fp);
100     cc->fp = INVALID_FP;
101     }
102     }
103     }
104    
105     static FILEP_OR_FD
106     direct_open (const char *fname, const char *mode)
107     {
108     unsigned long da, cd, sm;
109     HANDLE hfile;
110    
111     /* Note, that we do not handle all mode combinations */
112    
113     /* According to the ReactOS source it seems that open() of the
114     * standard MSW32 crt does open the file in share mode which is
115     * something new for MS applications ;-)
116     */
117     if ( strchr (mode, '+') ) {
118     fd_cache_invalidate (fname);
119     da = GENERIC_READ|GENERIC_WRITE;
120     cd = OPEN_EXISTING;
121     sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
122     }
123     else if ( strchr (mode, 'w') ) {
124     fd_cache_invalidate (fname);
125     da = GENERIC_WRITE;
126     cd = CREATE_ALWAYS;
127     sm = FILE_SHARE_WRITE;
128     }
129     else {
130     da = GENERIC_READ;
131     cd = OPEN_EXISTING;
132     sm = FILE_SHARE_READ;
133     }
134    
135     hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
136     return hfile;
137     }
138    
139    
140     /*
141     * Instead of closing an FD we keep it open and cache it for later reuse
142     * Note that this caching strategy only works if the process does not chdir.
143     */
144     static void
145     fd_cache_close (const char *fname, FILEP_OR_FD fp)
146     {
147     CLOSE_CACHE cc;
148    
149     assert (fp);
150     if ( !fname || !*fname ) {
151     CloseHandle (fp);
152     return;
153     }
154     /* try to reuse a slot */
155     for (cc=close_cache; cc; cc = cc->next ) {
156     if ( cc->fp == INVALID_FP && !strcmp (cc->fname, fname) ) {
157     cc->fp = fp;
158     return;
159     }
160     }
161     /* add a new one */
162     cc = calloc (1, sizeof *cc + strlen (fname));
163     strcpy (cc->fname, fname);
164     cc->fp = fp;
165     cc->next = close_cache;
166     close_cache = cc;
167     }
168    
169     /*
170     * Do an direct_open on FNAME but first try to reuse one from the fd_cache
171     */
172     static FILEP_OR_FD
173     fd_cache_open (const char *fname, const char *mode)
174     {
175     CLOSE_CACHE cc;
176    
177     assert (fname);
178     for (cc=close_cache; cc; cc = cc->next ) {
179     if ( cc->fp != INVALID_FP && !strcmp (cc->fname, fname) ) {
180     FILEP_OR_FD fp = cc->fp;
181     cc->fp = INVALID_FP;
182     if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) {
183     printf ("rewind file failed on handle %p: ec=%d\n",
184     fp, (int)GetLastError () );
185     fp = INVALID_FP;
186     }
187     return fp;
188     }
189     }
190     return direct_open (fname, mode);
191     }
192    
193    
194     /****************
195     * Read data from a file into buf which has an allocated length of *LEN.
196     * return the number of read bytes in *LEN. OPAQUE is the FILE * of
197     * the stream. A is not used.
198     * control may be:
199     * IOBUFCTRL_INIT: called just before the function is linked into the
200     * list of function. This can be used to prepare internal
201     * data structures of the function.
202     * IOBUFCTRL_FREE: called just before the function is removed from the
203     * list of functions and can be used to release internal
204     * data structures or close a file etc.
205     * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
206     * with new stuff. *RET_LEN is the available size of the
207     * buffer, and should be set to the number of bytes
208     * which were put into the buffer. The function
209     * returns 0 to indicate success, -1 on EOF and
210     * G10ERR_xxxxx for other errors.
211     *
212     * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
213     * *RET_LAN is the number of bytes in BUF.
214     *
215     * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel. The
216     * filter may take appropriate action on this message.
217     */
218     static int
219     file_filter(void *opaque, int control, gpg_iobuf_t chain, byte *buf, size_t *ret_len)
220     {
221     file_filter_ctx_t *a = opaque;
222     FILEP_OR_FD f = a->fp;
223     size_t size = *ret_len;
224     size_t nbytes = 0;
225     int rc = 0;
226    
227     if( control == IOBUFCTRL_UNDERFLOW ) {
228     assert( size ); /* need a buffer */
229     if ( a->eof_seen) {
230     rc = -1;
231     *ret_len = 0;
232     }
233     else {
234     unsigned long nread;
235    
236     nbytes = 0;
237     if ( !ReadFile ( f, buf, size, &nread, NULL ) ) {
238     int ec = (int)GetLastError ();
239     if ( ec != ERROR_BROKEN_PIPE ) {
240     printf("%s: read error: ec=%d\n", a->fname, ec);
241     rc = G10ERR_READ_FILE;
242     }
243     }
244     else if ( !nread ) {
245     a->eof_seen = 1;
246     rc = -1;
247     }
248     else {
249     nbytes = nread;
250     }
251     *ret_len = nbytes;
252     }
253     }
254     else if( control == IOBUFCTRL_FLUSH ) {
255     if( size ) {
256     byte *p = buf;
257     unsigned long n;
258    
259     nbytes = size;
260     do {
261     if ( size && !WriteFile ( f, p, nbytes, &n, NULL) ) {
262     int ec = (int)GetLastError ();
263     printf("%s: write error: ec=%d\n", a->fname, ec);
264     rc = G10ERR_WRITE_FILE;
265     break;
266     }
267     p += n;
268     nbytes -= n;
269     } while ( nbytes );
270     nbytes = p - buf;
271     }
272     *ret_len = nbytes;
273     }
274     else if ( control == IOBUFCTRL_INIT ) {
275     a->eof_seen = 0;
276     a->keep_open = 0;
277     a->no_cache = 0;
278     }
279     else if ( control == IOBUFCTRL_DESC ) {
280     *(char**)buf = "file_filter(fd)";
281     }
282     else if ( control == IOBUFCTRL_FREE ) {
283     if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) {
284     if (!a->keep_open)
285     fd_cache_close (a->no_cache?NULL:a->fname, f);
286     }
287     safe_free (a); /* we can free our context now */
288     }
289     return rc;
290     }
291    
292     /****************
293     * This is used to implement the block write mode.
294     * Block reading is done on a byte by byte basis in readbyte(),
295     * without a filter
296     */
297     static int
298     block_filter(void *opaque, int control, gpg_iobuf_t chain, byte *buf, size_t *ret_len)
299     {
300     block_filter_ctx_t *a = opaque;
301     size_t size = *ret_len;
302     int c, needed, rc = 0;
303     char *p;
304    
305     if( control == IOBUFCTRL_UNDERFLOW ) {
306     size_t n=0;
307    
308     p = buf;
309     assert( size ); /* need a buffer */
310     if( a->eof ) /* don't read any further */
311     rc = -1;
312     while( !rc && size ) {
313     if( !a->size ) { /* get the length bytes */
314     if( a->partial == 2 ) {
315     a->eof = 1;
316     if( !n )
317     rc = -1;
318     break;
319     }
320     else if( a->partial ) {
321     /* These OpenPGP introduced huffman like encoded length
322     * bytes are really a mess :-( */
323     if( a->first_c ) {
324     c = a->first_c;
325     a->first_c = 0;
326     }
327     else if( (c = gpg_iobuf_get(chain)) == -1 ) {
328     printf("block_filter: 1st length byte missing\n");
329     rc = G10ERR_READ_FILE;
330     break;
331     }
332     if( c < 192 ) {
333     a->size = c;
334     a->partial = 2;
335     if( !a->size ) {
336     a->eof = 1;
337     if( !n )
338     rc = -1;
339     break;
340     }
341     }
342     else if( c < 224 ) {
343     a->size = (c - 192) * 256;
344     if( (c = gpg_iobuf_get(chain)) == -1 ) {
345     printf("block_filter: 2nd length byte missing\n");
346     rc = G10ERR_READ_FILE;
347     break;
348     }
349     a->size += c + 192;
350     a->partial = 2;
351     if( !a->size ) {
352     a->eof = 1;
353     if( !n )
354     rc = -1;
355     break;
356     }
357     }
358     else if( c == 255 ) {
359     a->size = gpg_iobuf_get(chain) << 24;
360     a->size |= gpg_iobuf_get(chain) << 16;
361     a->size |= gpg_iobuf_get(chain) << 8;
362     if( (c = gpg_iobuf_get(chain)) == -1 ) {
363     printf("block_filter: invalid 4 byte length\n");
364     rc = G10ERR_READ_FILE;
365     break;
366     }
367     a->size |= c;
368     }
369     else { /* next partial body length */
370     a->size = 1 << (c & 0x1f);
371     }
372     /* printf("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
373     }
374     else { /* the gnupg partial length scheme - much better :-) */
375     c = gpg_iobuf_get(chain);
376     a->size = c << 8;
377     c = gpg_iobuf_get(chain);
378     a->size |= c;
379     if( c == -1 ) {
380     printf("block_filter: error reading length info\n");
381     rc = G10ERR_READ_FILE;
382     }
383     if( !a->size ) {
384     a->eof = 1;
385     if( !n )
386     rc = -1;
387     break;
388     }
389     }
390     }
391    
392     while( !rc && size && a->size ) {
393     needed = size < a->size ? size : a->size;
394     c = gpg_iobuf_read( chain, p, needed );
395     if( c < needed ) {
396     if( c == -1 ) c = 0;
397     printf("block_filter %p: read error (size=%lu,a->size=%lu)\n",
398     a, (ulong)size+c, (ulong)a->size+c);
399     rc = G10ERR_READ_FILE;
400     }
401     else {
402     size -= c;
403     a->size -= c;
404     p += c;
405     n += c;
406     }
407     }
408     }
409     *ret_len = n;
410     }
411     else if( control == IOBUFCTRL_FLUSH ) {
412     if( a->partial ) { /* the complicated openpgp scheme */
413     size_t blen, n, nbytes = size + a->buflen;
414    
415     assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
416     if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
417     /* not enough to write a partial block out; so we store it*/
418     if( !a->buffer )
419     a->buffer = malloc( OP_MIN_PARTIAL_CHUNK );
420     memcpy( a->buffer + a->buflen, buf, size );
421     a->buflen += size;
422     }
423     else { /* okay, we can write out something */
424     /* do this in a loop to use the most efficient block lengths */
425     p = buf;
426     do {
427     /* find the best matching block length - this is limited
428     * by the size of the internal buffering */
429     for( blen=OP_MIN_PARTIAL_CHUNK*2,
430     c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
431     blen *=2, c++ )
432     ;
433     blen /= 2; c--;
434     /* write the partial length header */
435     assert( c <= 0x1f ); /*;-)*/
436     c |= 0xe0;
437     gpg_iobuf_put( chain, c );
438     if( (n=a->buflen) ) { /* write stuff from the buffer */
439     assert( n == OP_MIN_PARTIAL_CHUNK);
440     if( gpg_iobuf_write(chain, a->buffer, n ) )
441     rc = G10ERR_WRITE_FILE;
442     a->buflen = 0;
443     nbytes -= n;
444     }
445     if( (n = nbytes) > blen )
446     n = blen;
447     if( n && gpg_iobuf_write(chain, p, n ) )
448     rc = G10ERR_WRITE_FILE;
449     p += n;
450     nbytes -= n;
451     } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
452     /* store the rest in the buffer */
453     if( !rc && nbytes ) {
454     assert( !a->buflen );
455     assert( nbytes < OP_MIN_PARTIAL_CHUNK );
456     if( !a->buffer )
457     a->buffer = malloc( OP_MIN_PARTIAL_CHUNK );
458     memcpy( a->buffer, p, nbytes );
459     a->buflen = nbytes;
460     }
461     }
462     }
463     else { /* the gnupg scheme (which is not openpgp compliant) */
464     size_t avail, n;
465    
466     for(p=buf; !rc && size; ) {
467     n = size;
468     avail = a->size - a->count;
469     if( !avail ) {
470     if( n > a->size ) {
471     gpg_iobuf_put( chain, (a->size >> 8) & 0xff );
472     gpg_iobuf_put( chain, a->size & 0xff );
473     avail = a->size;
474     a->count = 0;
475     }
476     else {
477     gpg_iobuf_put( chain, (n >> 8) & 0xff );
478     gpg_iobuf_put( chain, n & 0xff );
479     avail = n;
480     a->count = a->size - n;
481     }
482     }
483     if( n > avail )
484     n = avail;
485     if( gpg_iobuf_write(chain, p, n ) )
486     rc = G10ERR_WRITE_FILE;
487     a->count += n;
488     p += n;
489     size -= n;
490     }
491     }
492     }
493     else if( control == IOBUFCTRL_INIT ) {
494     if( a->partial )
495     a->count = 0;
496     else if( a->use == 1 )
497     a->count = a->size = 0;
498     else
499     a->count = a->size; /* force first length bytes */
500     a->eof = 0;
501     a->buffer = NULL;
502     a->buflen = 0;
503     }
504     else if( control == IOBUFCTRL_DESC ) {
505     *(char**)buf = "block_filter";
506     }
507     else if( control == IOBUFCTRL_FREE ) {
508     if( a->use == 2 ) { /* write the end markers */
509     if( a->partial ) {
510     u32 len;
511     /* write out the remaining bytes without a partial header
512     * the length of this header may be 0 - but if it is
513     * the first block we are not allowed to use a partial header
514     * and frankly we can't do so, because this length must be
515     * a power of 2. This is _really_ complicated because we
516     * have to check the possible length of a packet prior
517     * to it's creation: a chain of filters becomes complicated
518     * and we need a lot of code to handle compressed packets etc.
519     * :-(((((((
520     */
521     /* construct header */
522     len = a->buflen;
523     /*printf("partial: remaining length=%u\n", len );*/
524     if( len < 192 )
525     rc = gpg_iobuf_put(chain, len );
526     else if( len < 8384 ) {
527     if( !(rc=gpg_iobuf_put( chain, ((len-192) / 256) + 192)) )
528     rc = gpg_iobuf_put( chain, ((len-192) % 256));
529     }
530     else { /* use a 4 byte header */
531     if( !(rc=gpg_iobuf_put( chain, 0xff )) )
532     if( !(rc=gpg_iobuf_put( chain, (len >> 24)&0xff )) )
533     if( !(rc=gpg_iobuf_put( chain, (len >> 16)&0xff )) )
534     if( !(rc=gpg_iobuf_put( chain, (len >> 8)&0xff )))
535     rc=gpg_iobuf_put( chain, len & 0xff );
536     }
537     if( !rc && len )
538     rc = gpg_iobuf_write(chain, a->buffer, len );
539     if( rc ) {
540     printf("block_filter: write error: %s\n",strerror(errno));
541     rc = G10ERR_WRITE_FILE;
542     }
543     safe_free( a->buffer ); a->buffer = NULL; a->buflen = 0;
544     }
545     else {
546     gpg_iobuf_writebyte(chain, 0);
547     gpg_iobuf_writebyte(chain, 0);
548     }
549     }
550     else if( a->size ) {
551     printf("block_filter: pending bytes!\n");
552     }
553     safe_free(a); /* we can free our context now */
554     }
555    
556     return rc;
557     }
558    
559     /****************
560     * Allocate a new io buffer, with no function assigned.
561     * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
562     * BUFSIZE is a suggested buffer size.
563     */
564     gpg_iobuf_t
565     gpg_iobuf_alloc(int use, size_t bufsize)
566     {
567     gpg_iobuf_t a;
568     static int number=0;
569    
570     a = calloc(1, sizeof *a);
571     a->use = use;
572     a->d.buf = malloc( bufsize );
573     a->d.size = bufsize;
574     a->no = ++number;
575     a->subno = 0;
576     a->opaque = NULL;
577     a->real_fname = NULL;
578     return a;
579     }
580    
581     int
582     gpg_iobuf_close( gpg_iobuf_t a )
583     {
584     gpg_iobuf_t a2;
585     size_t dummy_len=0;
586     int rc=0;
587    
588     if( a && a->directfp ) {
589     fclose( a->directfp );
590     safe_free( a->real_fname );
591     return 0;
592     }
593    
594     for( ; a && !rc ; a = a2 ) {
595     a2 = a->chain;
596     if( a->use == 2 && (rc=gpg_iobuf_flush(a)) )
597     printf("iobuf_flush failed on close\n");
598     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
599     a->chain, NULL, &dummy_len)) )
600     printf("IOBUFCTRL_FREE failed on close\n");
601     safe_free(a->real_fname);
602     if (a->d.buf) {
603     memset (a->d.buf, 0, a->d.size); /* erase the buffer */
604     safe_free(a->d.buf);
605     }
606     safe_free(a);
607     }
608    
609     return rc;
610     }
611    
612     int
613     gpg_iobuf_cancel( gpg_iobuf_t a )
614     {
615     const char *s;
616     gpg_iobuf_t a2;
617     int rc;
618     char *remove_name = NULL;
619    
620     if( a && a->use == 2 ) {
621     s = gpg_iobuf_get_real_fname(a);
622     if( s && *s ) {
623     remove_name = strdup ( s );
624     }
625     }
626    
627     /* send a cancel message to all filters */
628     for( a2 = a; a2 ; a2 = a2->chain ) {
629     size_t dummy;
630     if( a2->filter )
631     a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
632     NULL, &dummy );
633     }
634    
635     rc = gpg_iobuf_close(a);
636     if ( remove_name ) {
637     /* Argg, MSDOS does not allow to remove open files. So
638     * we have to do it here */
639     remove ( remove_name );
640     safe_free ( remove_name );
641     }
642     return rc;
643     }
644    
645    
646     /****************
647     * create a temporary iobuf, which can be used to collect stuff
648     * in an iobuf and later be written by iobuf_write_temp() to another
649     * iobuf.
650     */
651     gpg_iobuf_t
652     gpg_iobuf_temp( void )
653     {
654     gpg_iobuf_t a;
655    
656     a = gpg_iobuf_alloc(3, 8192 );
657    
658     return a;
659     }
660    
661     gpg_iobuf_t
662     gpg_iobuf_temp_with_content( const char *buffer, size_t length )
663     {
664     gpg_iobuf_t a;
665    
666     a = gpg_iobuf_alloc(3, length );
667     memcpy( a->d.buf, buffer, length );
668     a->d.len = length;
669    
670     return a;
671     }
672    
673     void
674     gpg_iobuf_enable_special_filenames ( int yes )
675     {
676     special_names_enabled = yes;
677     }
678    
679     /*
680     * see whether the filename has the for "-&nnnn", where n is a
681     * non-zero number.
682     * Returns this number or -1 if it is not the case.
683     */
684     static int
685     check_special_filename ( const char *fname )
686     {
687     if ( special_names_enabled
688     && fname && *fname == '-' && fname[1] == '&' ) {
689     int i;
690    
691     fname += 2;
692     for (i=0; isdigit (fname[i]); i++ )
693     ;
694     if ( !fname[i] )
695     return atoi (fname);
696     }
697     return -1;
698     }
699    
700     /****************
701     * Create a head iobuf for reading from a file
702     * returns: NULL if an error occures and sets errno
703     */
704     gpg_iobuf_t
705     gpg_iobuf_open( const char *fname )
706     {
707     gpg_iobuf_t a;
708     FILEP_OR_FD fp;
709     file_filter_ctx_t *fcx;
710     size_t len;
711     int print_only = 0;
712     int fd;
713    
714     if( !fname || (*fname=='-' && !fname[1]) ) {
715     fp = FILEP_OR_FD_FOR_STDIN;
716     //setmode ( my_fileno(fp) , O_BINARY );
717     fname = "[stdin]";
718     print_only = 1;
719     }
720     else if ( (fd = check_special_filename ( fname )) != -1 )
721     return gpg_iobuf_fdopen ( translate_file_handle (fd,0), "rb" );
722     else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP )
723     return NULL;
724     a = gpg_iobuf_alloc(1, 8192 );
725     fcx = malloc( sizeof *fcx + strlen(fname) );
726     fcx->fp = fp;
727     fcx->print_only_name = print_only;
728     strcpy(fcx->fname, fname );
729     if( !print_only )
730     a->real_fname = strdup( fname );
731     a->filter = file_filter;
732     a->filter_ov = fcx;
733     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
734     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
735    
736     return a;
737     }
738    
739     /****************
740     * Create a head iobuf for reading from a file
741     * returns: NULL if an error occures and sets errno
742     */
743     gpg_iobuf_t
744     gpg_iobuf_fdopen( int fd, const char *mode )
745     {
746     gpg_iobuf_t a;
747     FILEP_OR_FD fp;
748     file_filter_ctx_t *fcx;
749     size_t len;
750    
751     fp = (FILEP_OR_FD)fd;
752     a = gpg_iobuf_alloc( strchr( mode, 'w')? 2:1, 8192 );
753     fcx = malloc( sizeof *fcx + 20 );
754     fcx->fp = fp;
755     fcx->print_only_name = 1;
756     sprintf(fcx->fname, "[fd %d]", fd );
757     a->filter = file_filter;
758     a->filter_ov = fcx;
759     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
760     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
761     gpg_iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
762     return a;
763     }
764    
765     /****************
766     * create an iobuf for writing to a file; the file will be created.
767     */
768     gpg_iobuf_t
769     gpg_iobuf_create( const char *fname )
770     {
771     gpg_iobuf_t a;
772     FILEP_OR_FD fp;
773     file_filter_ctx_t *fcx;
774     size_t len;
775     int print_only = 0;
776     int fd;
777    
778     if( !fname || (*fname=='-' && !fname[1]) ) {
779     fp = FILEP_OR_FD_FOR_STDOUT;
780     fname = "[stdout]";
781     print_only = 1;
782     }
783     else if ( (fd = check_special_filename ( fname )) != -1 )
784     return gpg_iobuf_fdopen ( translate_file_handle (fd, 1), "wb" );
785     else if( (fp = my_fopen(fname, "wb")) == INVALID_FP )
786     return NULL;
787     a = gpg_iobuf_alloc(2, 8192 );
788     fcx = malloc( sizeof *fcx + strlen(fname) );
789     fcx->fp = fp;
790     fcx->print_only_name = print_only;
791     strcpy(fcx->fname, fname );
792     if( !print_only )
793     a->real_fname = strdup( fname );
794     a->filter = file_filter;
795     a->filter_ov = fcx;
796     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
797     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
798    
799     return a;
800     }
801    
802     gpg_iobuf_t
803     gpg_iobuf_openrw( const char *fname )
804     {
805     gpg_iobuf_t a;
806     FILEP_OR_FD fp;
807     file_filter_ctx_t *fcx;
808     size_t len;
809    
810     if( !fname )
811     return NULL;
812     else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP )
813     return NULL;
814     a = gpg_iobuf_alloc(2, 8192 );
815     fcx = malloc( sizeof *fcx + strlen(fname) );
816     fcx->fp = fp;
817     strcpy(fcx->fname, fname );
818     a->real_fname = strdup( fname );
819     a->filter = file_filter;
820     a->filter_ov = fcx;
821     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
822     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
823    
824     return a;
825     }
826    
827    
828     int
829     gpg_iobuf_ioctl ( gpg_iobuf_t a, int cmd, int intval, void *ptrval )
830     {
831     if ( cmd == 1 ) { /* keep system filepointer/descriptor open */
832     for( ; a; a = a->chain )
833     if( !a->chain && a->filter == file_filter ) {
834     file_filter_ctx_t *b = a->filter_ov;
835     b->keep_open = intval;
836     return 0;
837     }
838     }
839     else if ( cmd == 2 ) { /* invalidate cache */
840     if ( !a && !intval && ptrval ) {
841     fd_cache_invalidate (ptrval);
842     return 0;
843     }
844     }
845     else if ( cmd == 3 ) { /* disallow/allow caching */
846     for( ; a; a = a->chain )
847     if( !a->chain && a->filter == file_filter ) {
848     file_filter_ctx_t *b = a->filter_ov;
849     b->no_cache = intval;
850     return 0;
851     }
852     }
853    
854     return -1;
855     }
856    
857    
858     /****************
859     * Register an i/o filter.
860     */
861     int
862     gpg_iobuf_push_filter( gpg_iobuf_t a,
863     int (*f)(void *opaque, int control,
864     gpg_iobuf_t chain, byte *buf, size_t *len), void *ov )
865     {
866     return gpg_iobuf_push_filter2( a, f, ov, 0 );
867     }
868    
869     int
870     gpg_iobuf_push_filter2( gpg_iobuf_t a,
871     int (*f)(void *opaque, int control,
872     gpg_iobuf_t chain, byte *buf, size_t *len),
873     void *ov, int rel_ov )
874     {
875     gpg_iobuf_t b;
876     size_t dummy_len=0;
877     int rc=0;
878    
879     if( a->directfp ) {
880     printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ );
881     exit( -1 );
882     }
883    
884     if( a->use == 2 && (rc=gpg_iobuf_flush(a)) )
885     return rc;
886     /* make a copy of the current stream, so that
887     * A is the new stream and B the original one.
888     * The contents of the buffers are transferred to the
889     * new stream.
890     */
891     b = malloc(sizeof *b);
892     memcpy(b, a, sizeof *b );
893     /* fixme: it is stupid to keep a copy of the name at every level
894     * but we need the name somewhere because the name known by file_filter
895     * may have been released when we need the name of the file */
896     b->real_fname = a->real_fname? strdup(a->real_fname):NULL;
897     /* remove the filter stuff from the new stream */
898     a->filter = NULL;
899     a->filter_ov = NULL;
900     a->filter_ov_owner = 0;
901     a->filter_eof = 0;
902     if( a->use == 3 )
903     a->use = 2; /* make a write stream from a temp stream */
904    
905     if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
906     b->d.buf = malloc( a->d.size );
907     b->d.len = 0;
908     b->d.start = 0;
909     }
910     else { /* allocate a fresh buffer for the new stream */
911     a->d.buf = malloc( a->d.size );
912     a->d.len = 0;
913     a->d.start = 0;
914     }
915     /* disable nlimit for the new stream */
916     a->ntotal = b->ntotal + b->nbytes;
917     a->nlimit = a->nbytes = 0;
918     a->nofast &= ~1;
919     /* make a link from the new stream to the original stream */
920     a->chain = b;
921     a->opaque = b->opaque;
922    
923     /* setup the function on the new stream */
924     a->filter = f;
925     a->filter_ov = ov;
926     a->filter_ov_owner = rel_ov;
927    
928     a->subno = b->subno + 1;
929     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
930    
931     /* now we can initialize the new function if we have one */
932     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
933     NULL, &dummy_len)) )
934     printf("IOBUFCTRL_INIT failed\n");
935     return rc;
936     }
937    
938     /****************
939     * Remove an i/o filter.
940     */
941     int
942     pop_filter( gpg_iobuf_t a, int (*f)(void *opaque, int control,
943     gpg_iobuf_t chain, byte *buf, size_t *len), void *ov )
944     {
945     gpg_iobuf_t b;
946     size_t dummy_len=0;
947     int rc=0;
948    
949     if( a->directfp ) {
950     printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ );
951     exit( -1 );
952     }
953    
954     if( !a->filter ) { /* this is simple */
955     b = a->chain;
956     assert(b);
957     safe_free(a->d.buf);
958     safe_free(a->real_fname);
959     memcpy(a,b, sizeof *a);
960     safe_free(b);
961     return 0;
962     }
963     for(b=a ; b; b = b->chain )
964     if( b->filter == f && (!ov || b->filter_ov == ov) )
965     break;
966     if( !b )
967     printf("pop_filter(): filter function not found\n");
968    
969     /* flush this stream if it is an output stream */
970     if( a->use == 2 && (rc=gpg_iobuf_flush(b)) ) {
971     printf("iobuf_flush failed in pop_filter\n");
972     return rc;
973     }
974     /* and tell the filter to free it self */
975     if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
976     NULL, &dummy_len)) ) {
977     printf("IOBUFCTRL_FREE failed\n");
978     return rc;
979     }
980     if( b->filter_ov && b->filter_ov_owner ) {
981     safe_free( b->filter_ov );
982     b->filter_ov = NULL;
983     }
984    
985    
986     /* and see how to remove it */
987     if( a == b && !b->chain )
988     printf("can't remove the last filter from the chain\n");
989     else if( a == b ) { /* remove the first iobuf from the chain */
990     /* everything from b is copied to a. This is save because
991     * a flush has been done on the to be removed entry
992     */
993     b = a->chain;
994     safe_free(a->d.buf);
995     safe_free(a->real_fname);
996     memcpy(a,b, sizeof *a);
997     safe_free(b);
998     }
999     else if( !b->chain ) { /* remove the last iobuf from the chain */
1000     printf("Ohh jeee, trying to remove a head filter\n");
1001     }
1002     else { /* remove an intermediate iobuf from the chain */
1003     printf("Ohh jeee, trying to remove an intermediate filter\n");
1004     }
1005    
1006     return rc;
1007     }
1008    
1009    
1010     /****************
1011     * read underflow: read more bytes into the buffer and return
1012     * the first byte or -1 on EOF.
1013     */
1014     static int
1015     underflow(gpg_iobuf_t a)
1016     {
1017     size_t len;
1018     int rc;
1019    
1020     assert( a->d.start == a->d.len );
1021     if( a->use == 3 )
1022     return -1; /* EOF because a temp buffer can't do an underflow */
1023    
1024     if( a->filter_eof ) {
1025     if( a->chain ) {
1026     gpg_iobuf_t b = a->chain;
1027     safe_free(a->d.buf);
1028     safe_free(a->real_fname);
1029     memcpy(a, b, sizeof *a);
1030     safe_free(b);
1031     }
1032     else
1033     a->filter_eof = 0; /* for the top level filter */
1034     return -1; /* return one(!) EOF */
1035     }
1036     if( a->error ) {
1037     return -1;
1038     }
1039    
1040     if( a->directfp ) {
1041     FILE *fp = a->directfp;
1042    
1043     len = fread( a->d.buf, 1, a->d.size, fp);
1044     if( len < a->d.size ) {
1045     if( ferror(fp) )
1046     a->error = 1;
1047     }
1048     a->d.len = len;
1049     a->d.start = 0;
1050     return len? a->d.buf[a->d.start++] : -1;
1051     }
1052    
1053    
1054     if( a->filter ) {
1055     len = a->d.size;
1056     rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
1057     a->d.buf, &len );
1058     if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
1059     size_t dummy_len=0;
1060    
1061     /* and tell the filter to free itself */
1062     if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
1063     NULL, &dummy_len)) )
1064     printf("IOBUFCTRL_FREE failed\n");
1065     if( a->filter_ov && a->filter_ov_owner ) {
1066     safe_free( a->filter_ov );
1067     a->filter_ov = NULL;
1068     }
1069     a->filter = NULL;
1070     a->desc = NULL;
1071     a->filter_ov = NULL;
1072     a->filter_eof = 1;
1073     if( !len && a->chain ) {
1074     gpg_iobuf_t b = a->chain;
1075     safe_free(a->d.buf);
1076     safe_free(a->real_fname);
1077     memcpy(a,b, sizeof *a);
1078     safe_free(b);
1079     }
1080     }
1081     else if( rc )
1082     a->error = 1;
1083    
1084     if( !len ) {
1085     return -1;
1086     }
1087     a->d.len = len;
1088     a->d.start = 0;
1089     return a->d.buf[a->d.start++];
1090     }
1091     else {
1092     return -1; /* no filter; return EOF */
1093     }
1094     }
1095    
1096    
1097     int
1098     gpg_iobuf_flush(gpg_iobuf_t a)
1099     {
1100     size_t len;
1101     int rc;
1102    
1103     if( a->directfp )
1104     return 0;
1105    
1106     if( a->use == 3 ) { /* increase the temp buffer */
1107     char *newbuf;
1108     size_t newsize = a->d.size + 8192;
1109    
1110     printf("increasing temp iobuf from %lu to %lu\n",
1111     (ulong)a->d.size, (ulong)newsize );
1112     newbuf = malloc( newsize );
1113     memcpy( newbuf, a->d.buf, a->d.len );
1114     safe_free(a->d.buf);
1115     a->d.buf = newbuf;
1116     a->d.size = newsize;
1117     return 0;
1118     }
1119     else if( a->use != 2 )
1120     printf("flush on non-output iobuf\n");
1121     else if( !a->filter )
1122     printf("iobuf_flush: no filter\n");
1123     len = a->d.len;
1124     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
1125     if( !rc && len != a->d.len ) {
1126     printf("iobuf_flush did not write all!\n");
1127     rc = G10ERR_WRITE_FILE;
1128     }
1129     else if( rc )
1130     a->error = 1;
1131     a->d.len = 0;
1132    
1133     return rc;
1134     }
1135    
1136    
1137     /****************
1138     * Read a byte from the iobuf; returns -1 on EOF
1139     */
1140     int
1141     gpg_iobuf_readbyte(gpg_iobuf_t a)
1142     {
1143     int c;
1144    
1145     /* nlimit does not work together with unget */
1146     /* nbytes is also not valid! */
1147     if( a->unget.buf ) {
1148     if( a->unget.start < a->unget.len )
1149     return a->unget.buf[a->unget.start++];
1150     safe_free(a->unget.buf);
1151     a->unget.buf = NULL;
1152     a->nofast &= ~2;
1153     }
1154    
1155     if( a->nlimit && a->nbytes >= a->nlimit )
1156     return -1; /* forced EOF */
1157    
1158     if( a->d.start < a->d.len ) {
1159     c = a->d.buf[a->d.start++];
1160     }
1161     else if( (c=underflow(a)) == -1 )
1162     return -1; /* EOF */
1163    
1164     a->nbytes++;
1165     return c;
1166     }
1167    
1168    
1169     int
1170     gpg_iobuf_read(gpg_iobuf_t a, byte *buf, unsigned buflen )
1171     {
1172     int c, n;
1173    
1174     if( a->unget.buf || a->nlimit ) {
1175     /* handle special cases */
1176     for(n=0 ; n < buflen; n++ ) {
1177     if( (c = gpg_iobuf_readbyte(a)) == -1 ) {
1178     if( !n )
1179     return -1; /* eof */
1180     break;
1181     }
1182     else
1183     if( buf ) *buf = c;
1184     if( buf ) buf++;
1185     }
1186     return n;
1187     }
1188    
1189     n = 0;
1190     do {
1191     if( n < buflen && a->d.start < a->d.len ) {
1192     unsigned size = a->d.len - a->d.start;
1193     if( size > buflen - n )
1194     size = buflen - n;
1195     if( buf )
1196     memcpy( buf, a->d.buf + a->d.start, size );
1197     n += size;
1198     a->d.start += size;
1199     if( buf )
1200     buf += size;
1201     }
1202     if( n < buflen ) {
1203     if( (c=underflow(a)) == -1 ) {
1204     a->nbytes += n;
1205     return n? n : -1/*EOF*/;
1206     }
1207     if( buf )
1208     *buf++ = c;
1209     n++;
1210     }
1211     } while( n < buflen );
1212     a->nbytes += n;
1213     return n;
1214     }
1215    
1216    
1217     /****************
1218     * Have a look at the iobuf.
1219     * NOTE: This only works in special cases.
1220     */
1221     int
1222     gpg_iobuf_peek(gpg_iobuf_t a, byte *buf, unsigned buflen )
1223     {
1224     int n=0;
1225    
1226     if( a->filter_eof )
1227     return -1;
1228    
1229     if( !(a->d.start < a->d.len) ) {
1230     if( underflow(a) == -1 )
1231     return -1;
1232     /* and unget this character */
1233     assert(a->d.start == 1);
1234     a->d.start = 0;
1235     }
1236    
1237     for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
1238     *buf = a->d.buf[n];
1239     return n;
1240     }
1241    
1242    
1243    
1244    
1245     int
1246     gpg_iobuf_writebyte(gpg_iobuf_t a, unsigned c)
1247     {
1248    
1249     if( a->directfp ) {
1250     printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ );
1251     exit( -1 );
1252     }
1253    
1254     if( a->d.len == a->d.size )
1255     if( gpg_iobuf_flush(a) )
1256     return -1;
1257    
1258     assert( a->d.len < a->d.size );
1259     a->d.buf[a->d.len++] = c;
1260     return 0;
1261     }
1262    
1263    
1264     int
1265     gpg_iobuf_write(gpg_iobuf_t a, byte *buf, unsigned buflen )
1266     {
1267    
1268     if( a->directfp ) {
1269     printf( "This is a BUG.\n%s:%d\n", __FILE__, __LINE__ );
1270     exit( -1 );
1271     }
1272    
1273     do {
1274     if( buflen && a->d.len < a->d.size ) {
1275     unsigned size = a->d.size - a->d.len;
1276     if( size > buflen ) size = buflen;
1277     memcpy( a->d.buf + a->d.len, buf, size );
1278     buflen -= size;
1279     buf += size;
1280     a->d.len += size;
1281     }
1282     if( buflen ) {
1283     if( gpg_iobuf_flush(a) )
1284     return -1;
1285     }
1286     } while( buflen );
1287     return 0;
1288     }
1289    
1290    
1291     int
1292     gpg_iobuf_writestr(gpg_iobuf_t a, const char *buf )
1293     {
1294     for( ; *buf; buf++ )
1295     if( gpg_iobuf_writebyte(a, *buf) )
1296     return -1;
1297     return 0;
1298     }
1299    
1300    
1301    
1302     /****************
1303     * copy the contents of TEMP to A.
1304     */
1305     int
1306     gpg_iobuf_write_temp( gpg_iobuf_t a, gpg_iobuf_t temp )
1307     {
1308     while( temp->chain )
1309     pop_filter( temp, temp->filter, NULL );
1310     return gpg_iobuf_write(a, temp->d.buf, temp->d.len );
1311     }
1312    
1313     /****************
1314     * copy the contents of the temp io stream to BUFFER.
1315     */
1316     size_t
1317     gpg_iobuf_temp_to_buffer( gpg_iobuf_t a, byte *buffer, size_t buflen )
1318     {
1319     size_t n = a->d.len;
1320    
1321     if( n > buflen )
1322     n = buflen;
1323     memcpy( buffer, a->d.buf, n );
1324     return n;
1325     }
1326    
1327    
1328     /****************
1329     * Call this function to terminate processing of the temp stream
1330     * without closing it. This removes all filters from the stream
1331     * makes sure that iobuf_get_temp_{buffer,length}() returns correct
1332     * values.
1333     */
1334     void
1335     gpg_iobuf_flush_temp( gpg_iobuf_t temp )
1336     {
1337     while( temp->chain )
1338     pop_filter( temp, temp->filter, NULL );
1339     }
1340    
1341    
1342     /****************
1343     * Set a limit on how many bytes may be read from the input stream A.
1344     * Setting the limit to 0 disables this feature.
1345     */
1346     void
1347     gpg_iobuf_set_limit( gpg_iobuf_t a, _off_t nlimit )
1348     {
1349     if( nlimit )
1350     a->nofast |= 1;
1351     else
1352     a->nofast &= ~1;
1353     a->nlimit = nlimit;
1354     a->ntotal += a->nbytes;
1355     a->nbytes = 0;
1356     }
1357    
1358    
1359    
1360     /****************
1361     * Return the length of an open file
1362     */
1363     _off_t
1364     gpg_iobuf_get_filelength( gpg_iobuf_t a )
1365     {
1366     struct stat st;
1367    
1368     if( a->directfp ) {
1369     FILE *fp = a->directfp;
1370    
1371     if( !fstat(fileno(fp), &st) )
1372     return st.st_size;
1373     printf("fstat() failed: %s\n", strerror(errno) );
1374     return 0;
1375     }
1376    
1377     /* Hmmm: file_filter may have already been removed */
1378     for( ; a; a = a->chain )
1379     if( !a->chain && a->filter == file_filter ) {
1380     file_filter_ctx_t *b = a->filter_ov;
1381     FILEP_OR_FD fp = b->fp;
1382    
1383     ulong size;
1384    
1385     if ( (size=GetFileSize (fp, NULL)) != 0xffffffff )
1386     return size;
1387     printf ("GetFileSize for handle %p failed: ec=%d\n",
1388     fp, (int)GetLastError () );
1389     break;
1390     }
1391    
1392     return 0;
1393     }
1394    
1395     /****************
1396     * Tell the file position, where the next read will take place
1397     */
1398     _off_t
1399     gpg_iobuf_tell( gpg_iobuf_t a )
1400     {
1401     return a->ntotal + a->nbytes;
1402     }
1403    
1404    
1405     #if !defined(HAVE_FSEEKO) && !defined(fseeko)
1406    
1407     #ifdef HAVE_LIMITS_H
1408     # include <limits.h>
1409     #endif
1410     #ifndef LONG_MAX
1411     # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
1412     #endif
1413     #ifndef LONG_MIN
1414     # define LONG_MIN (-1 - LONG_MAX)
1415     #endif
1416    
1417     /****************
1418     * A substitute for fseeko, for hosts that don't have it.
1419     */
1420     static int
1421     fseeko( FILE *stream, _off_t newpos, int whence )
1422     {
1423     while( newpos != (long) newpos ) {
1424     long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
1425     if( fseek( stream, pos, whence ) != 0 )
1426     return -1;
1427     newpos -= pos;
1428     whence = SEEK_CUR;
1429     }
1430     return fseek( stream, (long)newpos, whence );
1431     }
1432     #endif
1433    
1434     /****************
1435     * This is a very limited implementation. It simply discards all internal
1436     * buffering and removes all filters but the first one.
1437     */
1438     int
1439     gpg_iobuf_seek( gpg_iobuf_t a, _off_t newpos )
1440     {
1441     file_filter_ctx_t *b = NULL;
1442    
1443     if( a->directfp ) {
1444     FILE *fp = a->directfp;
1445     if( fseeko( fp, newpos, SEEK_SET ) ) {
1446     printf("can't seek: %s\n", strerror(errno) );
1447     return -1;
1448     }
1449     clearerr(fp);
1450     }
1451     else {
1452     for( ; a; a = a->chain ) {
1453     if( !a->chain && a->filter == file_filter ) {
1454     b = a->filter_ov;
1455     break;
1456     }
1457     }
1458     if( !a )
1459     return -1;
1460     if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) {
1461     printf ("SetFilePointer failed on handle %p: ec=%d\n",
1462     b->fp, (int)GetLastError () );
1463     return -1;
1464     }
1465     }
1466     a->d.len = 0; /* discard buffer */
1467     a->d.start = 0;
1468     a->nbytes = 0;
1469     a->nlimit = 0;
1470     a->nofast &= ~1;
1471     a->ntotal = newpos;
1472     a->error = 0;
1473     /* remove filters, but the last */
1474     if( a->chain )
1475     printf("pop_filter called in iobuf_seek - please report\n");
1476     while( a->chain )
1477     pop_filter( a, a->filter, NULL );
1478    
1479     return 0;
1480     }
1481    
1482    
1483    
1484    
1485    
1486    
1487     /****************
1488     * Retrieve the real filename
1489     */
1490     const char *
1491     gpg_iobuf_get_real_fname( gpg_iobuf_t a )
1492     {
1493     if( a->real_fname )
1494     return a->real_fname;
1495    
1496     /* the old solution */
1497     for( ; a; a = a->chain )
1498     if( !a->chain && a->filter == file_filter ) {
1499     file_filter_ctx_t *b = a->filter_ov;
1500     return b->print_only_name? NULL : b->fname;
1501     }
1502    
1503     return NULL;
1504     }
1505    
1506    
1507     /****************
1508     * Retrieve the filename
1509     */
1510     const char *
1511     gpg_iobuf_get_fname( gpg_iobuf_t a )
1512     {
1513     for( ; a; a = a->chain )
1514     if( !a->chain && a->filter == file_filter ) {
1515     file_filter_ctx_t *b = a->filter_ov;
1516     return b->fname;
1517     }
1518    
1519     return NULL;
1520     }
1521    
1522     /****************
1523     * Start the block write mode, see rfc1991.new for details.
1524     * A value of 0 for N stops this mode (flushes and writes
1525     * the end marker)
1526     */
1527     void
1528     gpg_iobuf_set_block_mode( gpg_iobuf_t a, size_t n )
1529     {
1530     block_filter_ctx_t *ctx = calloc( 1, sizeof *ctx );
1531    
1532     assert( a->use == 1 || a->use == 2 );
1533     ctx->use = a->use;
1534     if( !n ) {
1535     if( a->use == 1 )
1536     printf("pop_filter called in set_block_mode - please report\n");
1537     pop_filter(a, block_filter, NULL );
1538     }
1539     else {
1540     ctx->size = n; /* only needed for use 2 */
1541     gpg_iobuf_push_filter(a, block_filter, ctx );
1542     }
1543     }
1544    
1545     /****************
1546     * enable partial block mode as described in the OpenPGP draft.
1547     * LEN is the first length byte on read, but ignored on writes.
1548     */
1549     void
1550     gpg_iobuf_set_partial_block_mode( gpg_iobuf_t a, size_t len )
1551     {
1552     block_filter_ctx_t *ctx = calloc( 1, sizeof *ctx );
1553    
1554     assert( a->use == 1 || a->use == 2 );
1555     ctx->use = a->use;
1556     if( !len ) {
1557     if( a->use == 1 )
1558     printf("pop_filter called in set_partial_block_mode"
1559     " - please report\n");
1560     pop_filter(a, block_filter, NULL );
1561     }
1562     else {
1563     ctx->partial = 1;
1564     ctx->size = 0;
1565     ctx->first_c = len;
1566     gpg_iobuf_push_filter(a, block_filter, ctx );
1567     }
1568     }
1569    
1570    
1571     /****************
1572     * Checks whether the stream is in block mode
1573     * Note: This does not work if other filters are pushed on the stream.
1574     */
1575     int
1576     gpg_iobuf_in_block_mode( gpg_iobuf_t a )
1577     {
1578     if( a && a->filter == block_filter )
1579     return 1; /* yes */
1580     return 0; /* no */
1581     }
1582    
1583    
1584     /****************
1585     * Same as fgets() but if the buffer is too short a larger one will
1586     * be allocated up to some limit *max_length.
1587     * A line is considered a byte stream ending in a LF.
1588     * Returns the length of the line. EOF is indicated by a line of
1589     * length zero. The last LF may be missing due to an EOF.
1590     * is max_length is zero on return, the line has been truncated.
1591     *
1592     * Note: The buffer is allocated with enough space to append a CR,LF,EOL
1593     */
1594     unsigned
1595     gpg_iobuf_read_line( gpg_iobuf_t a, byte **addr_of_buffer,
1596     unsigned *length_of_buffer, unsigned *max_length )
1597     {
1598     int c;
1599     char *buffer = *addr_of_buffer;
1600     unsigned length = *length_of_buffer;
1601     unsigned nbytes = 0;
1602     unsigned maxlen = *max_length;
1603     char *p;
1604    
1605     if( !buffer ) { /* must allocate a new buffer */
1606     length = 256;
1607     buffer = (char *)malloc( length );
1608     *addr_of_buffer = buffer;
1609     *length_of_buffer = length;
1610     }
1611    
1612     length -= 3; /* reserve 3 bytes (cr,lf,eol) */
1613     p = buffer;
1614     while( (c=gpg_iobuf_get(a)) != -1 ) {
1615     if( nbytes == length ) { /* increase the buffer */
1616     if( length > maxlen ) { /* this is out limit */
1617     /* skip the rest of the line */
1618     while( c != '\n' && (c=gpg_iobuf_get(a)) != -1 )
1619     ;
1620     *p++ = '\n'; /* always append a LF (we have reserved space) */
1621     nbytes++;
1622     *max_length = 0; /* indicate truncation */
1623     break;
1624     }
1625     length += 3; /* correct for the reserved byte */
1626     length += length < 1024? 256 : 1024;
1627     buffer = realloc( buffer, length );
1628     *addr_of_buffer = buffer;
1629     *length_of_buffer = length;
1630     length -= 3; /* and reserve again */
1631     p = buffer + nbytes;
1632     }
1633     *p++ = c;
1634     nbytes++;
1635     if( c == '\n' )
1636     break;
1637     }
1638     *p = 0; /* make sure the line is a string */
1639    
1640     return nbytes;
1641     }
1642    
1643     /* This is the non iobuf specific function */
1644     int
1645     gpg_iobuf_translate_file_handle ( int fd, int for_write )
1646     {
1647     {
1648     int x;
1649    
1650     if ( fd <= 2 )
1651     return fd; /* do not do this for error, stdin, stdout, stderr */
1652    
1653     x = _open_osfhandle ( fd, for_write? 1:0 );
1654     if (x==-1 )
1655     printf ("failed to translate osfhandle %p\n", (void*)fd );
1656     else {
1657     /*log_info ("_open_osfhandle %p yields %d%s\n",
1658     (void*)fd, x, for_write? " for writing":"" );*/
1659     fd = x;
1660     }
1661     }
1662     return fd;
1663     }
1664    
1665     static int
1666     translate_file_handle ( int fd, int for_write )
1667     {
1668     {
1669     int x;
1670    
1671     if ( fd == 0 )
1672     x = (int)GetStdHandle (STD_INPUT_HANDLE);
1673     else if (fd == 1)
1674     x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
1675     else if (fd == 2)
1676     x = (int)GetStdHandle (STD_ERROR_HANDLE);
1677     else
1678     x = fd;
1679    
1680     if (x == -1)
1681     printf ("GetStdHandle(%d) failed: ec=%d\n",
1682     fd, (int)GetLastError () );
1683    
1684     fd = x;
1685     }
1686     return fd;
1687     }
1688    
1689    

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26