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

Annotation of /trunk/Gnupg/iobuf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Mon Jan 31 11:02:21 2005 UTC (20 years, 1 month ago) by twoaday
File MIME type: text/plain
File size: 44341 byte(s)
WinPT initial checkin.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26