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

Contents of /trunk/Gnupg/iobuf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show 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 /* 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