Obsolete option --no-sig-create-check.
[gnupg.git] / util / iobuf.c
1 /* iobuf.c  -  file handling
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2008,
3  *               2009 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #ifdef HAVE_DOSISH_SYSTEM
33 #include <windows.h>
34 #endif
35 #ifdef __riscos__
36 #include <kernel.h>
37 #include <swis.h>
38 #endif /* __riscos__ */
39
40 #include "memory.h"
41 #include "util.h"
42 #include "dynload.h"
43 #include "iobuf.h"
44
45 #ifdef __VMS
46 # include "vms.h"
47 # define open open_vms
48 #endif /* def __VMS */
49
50 /* The size of the internal buffers.
51    NOTE: If you change this value you MUST also adjust the regression
52    test "armored_key_8192" and "nopad_armored_msg" in armor.test! */
53 #define IOBUF_BUFFER_SIZE  8192
54
55
56 #undef FILE_FILTER_USES_STDIO
57
58 /* To avoid a potential DoS with compression packets we better limit
59    the number of filters in a chain.  */
60 #define MAX_NESTING_FILTER 64
61
62
63 #ifdef HAVE_DOSISH_SYSTEM
64 #define USE_SETMODE 1
65 #endif
66
67 #ifdef FILE_FILTER_USES_STDIO
68 #define my_fileno(a)  fileno ((a))
69 #define my_fopen_ro(a,b) fopen ((a),(b))
70 #define my_fopen(a,b)    fopen ((a),(b))
71 typedef FILE *FILEP_OR_FD;
72 #define INVALID_FP    NULL
73 #define FILEP_OR_FD_FOR_STDIN  (stdin)
74 #define FILEP_OR_FD_FOR_STDOUT  (stdout)
75 typedef struct {
76      FILE *fp;     /* open file handle */
77      int keep_open;
78      int no_cache;
79      int  print_only_name; /* flags indicating that fname is not a real file*/
80      char fname[1]; /* name of the file */
81  } file_filter_ctx_t ;
82 #else
83 #define my_fileno(a)  (a)
84 #define my_fopen_ro(a,b) fd_cache_open ((a),(b))
85 #define my_fopen(a,b) direct_open ((a),(b))
86 #ifdef HAVE_DOSISH_SYSTEM
87 typedef HANDLE FILEP_OR_FD;
88 #define INVALID_FP  ((HANDLE)-1)
89 #define FILEP_OR_FD_FOR_STDIN  (GetStdHandle (STD_INPUT_HANDLE))
90 #define FILEP_OR_FD_FOR_STDOUT (GetStdHandle (STD_OUTPUT_HANDLE))
91 #undef USE_SETMODE
92 #else
93 typedef int FILEP_OR_FD;
94 #define INVALID_FP  (-1)
95 #define FILEP_OR_FD_FOR_STDIN  (0)
96 #define FILEP_OR_FD_FOR_STDOUT (1)
97 #endif
98 typedef struct {
99      FILEP_OR_FD  fp;      /* open file handle */
100      int keep_open;
101      int no_cache;
102      int eof_seen;
103      int  print_only_name; /* flags indicating that fname is not a real file*/
104      char fname[1]; /* name of the file */
105  } file_filter_ctx_t ;
106
107  struct close_cache_s {
108     struct close_cache_s *next;
109     FILEP_OR_FD fp;
110     char fname[1];
111  };
112  typedef struct close_cache_s *CLOSE_CACHE;
113  static CLOSE_CACHE close_cache;
114 #endif
115
116 #ifdef _WIN32
117 typedef struct {
118     int sock;
119     int keep_open;
120     int no_cache;
121     int eof_seen;
122     int  print_only_name; /* flags indicating that fname is not a real file*/
123     char fname[1]; /* name of the file */
124 } sock_filter_ctx_t ;
125 #endif /*_WIN32*/
126
127 /* The first partial length header block must be of size 512
128  * to make it easier (and efficienter) we use a min. block size of 512
129  * for all chunks (but the last one) */
130 #define OP_MIN_PARTIAL_CHUNK      512
131 #define OP_MIN_PARTIAL_CHUNK_2POW 9
132
133 typedef struct {
134     int use;
135     size_t size;
136     size_t count;
137     int partial;  /* 1 = partial header, 2 in last partial packet */
138     char *buffer;    /* used for partial header */
139     size_t buflen;   /* used size of buffer */
140     int first_c;     /* of partial header (which is > 0)*/
141     int eof;
142 } block_filter_ctx_t;
143
144 static int special_names_enabled;
145
146 static int underflow(IOBUF a);
147 static int translate_file_handle ( int fd, int for_write );
148
149
150 \f
151 #ifndef FILE_FILTER_USES_STDIO
152
153 /* This is a replacement for strcmp.  Under W32 it does not
154    distinguish between backslash and slash.  */
155 static int
156 fd_cache_strcmp (const char *a, const char *b)
157 {
158 #ifdef HAVE_DOSISH_SYSTEM
159   for (; *a && *b; a++, b++)
160     {
161       if (*a != *b && !((*a == '/' && *b == '\\')
162                         || (*a == '\\' && *b == '/')) )
163         break;
164     }
165   return *(const unsigned char *)a - *(const unsigned char *)b;
166 #else
167   return strcmp (a, b);
168 #endif
169 }
170
171 /*
172  * Invalidate (i.e. close) a cached iobuf or all iobufs if NULL is
173  * used for FNAME.
174  */
175 static int
176 fd_cache_invalidate (const char *fname)
177 {
178     CLOSE_CACHE cc;
179     int err=0;
180
181     if (!fname) {
182         if( DBG_IOBUF )
183             log_debug ("fd_cache_invalidate (all)\n");
184
185         for (cc=close_cache; cc; cc = cc->next ) {
186             if ( cc->fp != INVALID_FP ) {
187 #ifdef HAVE_DOSISH_SYSTEM
188                 CloseHandle (cc->fp);
189 #else
190                 close(cc->fp);
191 #endif
192                 cc->fp = INVALID_FP;
193             }
194         }
195         return err;
196     }
197
198     if( DBG_IOBUF )
199         log_debug ("fd_cache_invalidate (%s)\n", fname);
200
201     for (cc=close_cache; cc; cc = cc->next ) {
202         if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
203             if( DBG_IOBUF )
204                 log_debug ("                did (%s)\n", cc->fname);
205 #ifdef HAVE_DOSISH_SYSTEM
206             if(CloseHandle (cc->fp)==0)
207               err=-1;
208 #else
209             err=close(cc->fp);
210 #endif
211             cc->fp = INVALID_FP;
212         }
213     }
214
215     return err;
216 }
217
218 static int
219 fd_cache_synchronize(const char *fname)
220 {
221   int err=0;
222
223 #ifndef HAVE_DOSISH_SYSTEM
224   CLOSE_CACHE cc;
225
226   if( DBG_IOBUF )
227     log_debug ("fd_cache_synchronize (%s)\n", fname);
228
229   for (cc=close_cache; cc; cc = cc->next )
230     {
231       if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) )
232         {
233           if( DBG_IOBUF )
234             log_debug ("                did (%s)\n", cc->fname);
235
236           err=fsync(cc->fp);
237         }
238     }
239 #endif
240
241   return err;
242 }
243
244 static FILEP_OR_FD
245 direct_open (const char *fname, const char *mode)
246 {
247 #ifdef HAVE_DOSISH_SYSTEM
248     unsigned long da, cd, sm;
249     HANDLE hfile;
250
251     /* Note, that we do not handle all mode combinations */
252
253     /* According to the ReactOS source it seems that open() of the
254      * standard MSW32 crt does open the file in share mode which is
255      * something new for MS applications ;-)
256      */
257     if ( strchr (mode, '+') ) {
258         fd_cache_invalidate (fname);
259         da = GENERIC_READ|GENERIC_WRITE;
260         cd = OPEN_EXISTING;
261         sm = FILE_SHARE_READ | FILE_SHARE_WRITE;
262     }
263     else if ( strchr (mode, 'w') ) {
264         fd_cache_invalidate (fname);
265         da = GENERIC_WRITE;
266         cd = CREATE_ALWAYS;
267         sm = FILE_SHARE_WRITE;
268     }
269     else {
270         da = GENERIC_READ;
271         cd = OPEN_EXISTING;
272         sm = FILE_SHARE_READ;
273     }
274
275     hfile = CreateFile (fname, da, sm, NULL, cd, FILE_ATTRIBUTE_NORMAL, NULL);
276     return hfile;
277 #else
278     int oflag;
279     int cflag = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
280
281     /* Note, that we do not handle all mode combinations */
282     if ( strchr (mode, '+') ) {
283         fd_cache_invalidate (fname);
284         oflag = O_RDWR;
285     }
286     else if ( strchr (mode, 'w') ) {
287         fd_cache_invalidate (fname);
288         oflag = O_WRONLY | O_CREAT | O_TRUNC;
289     }
290     else {
291         oflag = O_RDONLY;
292     }
293 #ifdef O_BINARY
294     if (strchr (mode, 'b'))
295       oflag |= O_BINARY;
296 #endif
297 #ifndef __riscos__
298     return open (fname, oflag, cflag );
299 #else
300     {
301         struct stat buf;
302         int rc = stat( fname, &buf );
303
304         /* Don't allow iobufs on directories */
305         if( !rc && S_ISDIR(buf.st_mode) && !S_ISREG(buf.st_mode) )
306             return __set_errno( EISDIR );
307         else
308             return open( fname, oflag, cflag );
309     }
310 #endif
311 #endif
312 }
313
314
315 /*
316  * Instead of closing an FD we keep it open and cache it for later reuse
317  * Note that this caching strategy only works if the process does not chdir.
318  */
319 static void
320 fd_cache_close (const char *fname, FILEP_OR_FD fp)
321 {
322     CLOSE_CACHE cc;
323
324     assert (fp);
325     if ( !fname || !*fname ) {
326 #ifdef HAVE_DOSISH_SYSTEM
327         CloseHandle (fp);
328 #else
329         close(fp);
330 #endif
331         if( DBG_IOBUF )
332           log_debug ("fd_cache_close (%d) real\n", (int)fp);
333         return;
334     }
335     /* try to reuse a slot */
336     for (cc=close_cache; cc; cc = cc->next ) {
337         if ( cc->fp == INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
338             cc->fp = fp;
339             if( DBG_IOBUF )
340                 log_debug ("fd_cache_close (%s) used existing slot\n", fname);
341             return;
342         }
343     }
344     /* add a new one */
345     if( DBG_IOBUF )
346         log_debug ("fd_cache_close (%s) new slot created\n", fname);
347     cc = xmalloc_clear (sizeof *cc + strlen (fname));
348     strcpy (cc->fname, fname);
349     cc->fp = fp;
350     cc->next = close_cache;
351     close_cache = cc;
352 }
353
354 /*
355  * Do an direct_open on FNAME but first try to reuse one from the fd_cache
356  */
357 static FILEP_OR_FD
358 fd_cache_open (const char *fname, const char *mode)
359 {
360     CLOSE_CACHE cc;
361
362     assert (fname);
363     for (cc=close_cache; cc; cc = cc->next ) {
364         if ( cc->fp != INVALID_FP && !fd_cache_strcmp (cc->fname, fname) ) {
365             FILEP_OR_FD fp = cc->fp;
366             cc->fp = INVALID_FP;
367             if( DBG_IOBUF )
368                 log_debug ("fd_cache_open (%s) using cached fp\n", fname);
369 #ifdef HAVE_DOSISH_SYSTEM
370             if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff ) {
371                 log_error ("rewind file failed on handle %p: %s\n",
372                            fp, w32_strerror (errno));
373                 fp = INVALID_FP;
374             }
375 #else
376             if ( lseek (fp, 0, SEEK_SET) == (off_t)-1 ) {
377                 log_error("can't rewind fd %d: %s\n", fp, strerror(errno) );
378                 fp = INVALID_FP;
379             }
380 #endif
381             return fp;
382         }
383     }
384     if( DBG_IOBUF )
385         log_debug ("fd_cache_open (%s) not cached\n", fname);
386     return direct_open (fname, mode);
387 }
388
389
390 #endif /*FILE_FILTER_USES_STDIO*/
391
392
393 /****************
394  * Read data from a file into buf which has an allocated length of *LEN.
395  * return the number of read bytes in *LEN. OPAQUE is the FILE * of
396  * the stream. A is not used.
397  * control may be:
398  * IOBUFCTRL_INIT: called just before the function is linked into the
399  *                 list of function. This can be used to prepare internal
400  *                 data structures of the function.
401  * IOBUFCTRL_FREE: called just before the function is removed from the
402  *                  list of functions and can be used to release internal
403  *                  data structures or close a file etc.
404  * IOBUFCTRL_UNDERFLOW: called by iobuf_underflow to fill the buffer
405  *                  with new stuff. *RET_LEN is the available size of the
406  *                  buffer, and should be set to the number of bytes
407  *                  which were put into the buffer. The function
408  *                  returns 0 to indicate success, -1 on EOF and
409  *                  G10ERR_xxxxx for other errors.
410  *
411  * IOBUFCTRL_FLUSH: called by iobuf_flush() to write out the collected stuff.
412  *                  *RET_LAN is the number of bytes in BUF.
413  *
414  * IOBUFCTRL_CANCEL: send to all filters on behalf of iobuf_cancel.  The
415  *                  filter may take appropriate action on this message.
416  */
417 static int
418 file_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
419 {
420     file_filter_ctx_t *a = opaque;
421     FILEP_OR_FD f = a->fp;
422     size_t size = *ret_len;
423     size_t nbytes = 0;
424     int rc = 0;
425
426 #ifdef FILE_FILTER_USES_STDIO
427     if( control == IOBUFCTRL_UNDERFLOW ) {
428         assert( size ); /* need a buffer */
429         if ( feof(f)) { /* On terminals you could easiely read as many EOFs as you call         */
430             rc = -1;            /* fread() or fgetc() repeatly. Every call will block until you press   */
431             *ret_len = 0;       /* CTRL-D. So we catch this case before we call fread() again.          */
432         }
433         else {
434             clearerr( f );
435             nbytes = fread( buf, 1, size, f );
436             if( feof(f) && !nbytes ) {
437                 rc = -1; /* okay: we can return EOF now. */
438             }
439             else if( ferror(f) && errno != EPIPE  ) {
440                 log_error("%s: read error: %s\n",
441                           a->fname, strerror(errno));
442                 rc = G10ERR_READ_FILE;
443             }
444             *ret_len = nbytes;
445         }
446     }
447     else if( control == IOBUFCTRL_FLUSH ) {
448         if( size ) {
449             clearerr( f );
450             nbytes = fwrite( buf, 1, size, f );
451             if( ferror(f) ) {
452                 log_error("%s: write error: %s\n", a->fname, strerror(errno));
453                 rc = G10ERR_WRITE_FILE;
454             }
455         }
456         *ret_len = nbytes;
457     }
458     else if( control == IOBUFCTRL_INIT ) {
459         a->keep_open = a->no_cache = 0;
460     }
461     else if( control == IOBUFCTRL_DESC ) {
462         *(char**)buf = "file_filter";
463     }
464     else if( control == IOBUFCTRL_FREE ) {
465         if( f != stdin && f != stdout ) {
466             if( DBG_IOBUF )
467                 log_debug("%s: close fd %d\n", a->fname, fileno(f) );
468             if (!a->keep_open)
469                 fclose(f);
470         }
471         f = NULL;
472         xfree(a); /* we can free our context now */
473     }
474 #else /* !stdio implementation */
475
476     if( control == IOBUFCTRL_UNDERFLOW ) {
477         assert( size ); /* need a buffer */
478         if ( a->eof_seen) {
479             rc = -1;
480             *ret_len = 0;
481         }
482         else {
483 #ifdef HAVE_DOSISH_SYSTEM
484             unsigned long nread;
485
486             nbytes = 0;
487             if ( !ReadFile ( f, buf, size, &nread, NULL ) ) {
488                 if ((int)GetLastError () != ERROR_BROKEN_PIPE) {
489                     log_error ("%s: read error: %s\n", a->fname,
490                                w32_strerror (0));
491                     rc = G10ERR_READ_FILE;
492                 }
493             }
494             else if ( !nread ) {
495                 a->eof_seen = 1;
496                 rc = -1;
497             }
498             else {
499                 nbytes = nread;
500             }
501
502 #else
503
504             int n;
505
506             nbytes = 0;
507             do {
508                 n = read ( f, buf, size );
509             } while (n == -1 && errno == EINTR );
510             if ( n == -1 ) { /* error */
511                 if (errno != EPIPE) {
512                     log_error("%s: read error: %s\n",
513                               a->fname, strerror(errno));
514                     rc = G10ERR_READ_FILE;
515                 }
516             }
517             else if ( !n ) { /* eof */
518                 a->eof_seen = 1;
519                 rc = -1;
520             }
521             else {
522                 nbytes = n;
523             }
524 #endif
525             *ret_len = nbytes;
526         }
527     }
528     else if( control == IOBUFCTRL_FLUSH ) {
529         if( size ) {
530 #ifdef HAVE_DOSISH_SYSTEM
531             byte *p = buf;
532             unsigned long n;
533
534             nbytes = size;
535             do {
536                 if (size && !WriteFile (f,  p, nbytes, &n, NULL)) {
537                     log_error ("%s: write error: %s\n", a->fname,
538                                w32_strerror (0));
539                     rc = G10ERR_WRITE_FILE;
540                     break;
541                 }
542                 p += n;
543                 nbytes -= n;
544             } while ( nbytes );
545             nbytes = p - buf;
546 #else
547             byte *p = buf;
548             int n;
549
550             nbytes = size;
551             do {
552                 do {
553                     n = write ( f, p, nbytes );
554                 } while ( n == -1 && errno == EINTR );
555                 if ( n > 0 ) {
556                     p += n;
557                     nbytes -= n;
558                 }
559             } while ( n != -1 && nbytes );
560             if( n == -1 ) {
561                 log_error("%s: write error: %s\n", a->fname, strerror(errno));
562                 rc = G10ERR_WRITE_FILE;
563             }
564             nbytes = p - buf;
565 #endif
566         }
567         *ret_len = nbytes;
568     }
569     else if ( control == IOBUFCTRL_INIT ) {
570         a->eof_seen = 0;
571         a->keep_open = 0;
572         a->no_cache = 0;
573     }
574     else if ( control == IOBUFCTRL_DESC ) {
575         *(char**)buf = "file_filter(fd)";
576     }
577     else if ( control == IOBUFCTRL_FREE ) {
578 #ifdef HAVE_DOSISH_SYSTEM
579         if ( f != FILEP_OR_FD_FOR_STDIN && f != FILEP_OR_FD_FOR_STDOUT ) {
580             if( DBG_IOBUF )
581                 log_debug("%s: close handle %p\n", a->fname, f );
582             if (!a->keep_open)
583                 fd_cache_close (a->no_cache?NULL:a->fname, f);
584         }
585 #else
586         if ( (int)f != 0 && (int)f != 1 ) {
587             if( DBG_IOBUF )
588                 log_debug("%s: close fd %d\n", a->fname, f );
589             if (!a->keep_open)
590                 fd_cache_close (a->no_cache?NULL:a->fname, f);
591         }
592         f = INVALID_FP;
593 #endif
594         xfree (a); /* we can free our context now */
595     }
596 #endif /* !stdio implementation */
597     return rc;
598 }
599
600 #ifdef _WIN32
601 /* Becuase sockets are an special object under Lose32 we have to
602  * use a special filter */
603 static int
604 sock_filter (void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
605 {
606     sock_filter_ctx_t *a = opaque;
607     size_t size = *ret_len;
608     size_t nbytes = 0;
609     int rc = 0;
610
611     if( control == IOBUFCTRL_UNDERFLOW ) {
612         assert( size ); /* need a buffer */
613         if ( a->eof_seen) {
614             rc = -1;
615             *ret_len = 0;
616         }
617         else {
618             int nread;
619
620             nread = recv ( a->sock, buf, size, 0 );
621             if ( nread == SOCKET_ERROR ) {
622                 int ec = (int)WSAGetLastError ();
623                 log_error("socket read error: ec=%d\n", ec);
624                 rc = G10ERR_READ_FILE;
625             }
626             else if ( !nread ) {
627                 a->eof_seen = 1;
628                 rc = -1;
629             }
630             else {
631                 nbytes = nread;
632             }
633             *ret_len = nbytes;
634         }
635     }
636     else if( control == IOBUFCTRL_FLUSH ) {
637         if( size ) {
638             byte *p = buf;
639             int n;
640
641             nbytes = size;
642             do {
643                 n = send (a->sock, p, nbytes, 0);
644                 if ( n == SOCKET_ERROR ) {
645                     int ec = (int)WSAGetLastError ();
646                     log_error("socket write error: ec=%d\n", ec);
647                     rc = G10ERR_WRITE_FILE;
648                     break;
649                 }
650                 p += n;
651                 nbytes -= n;
652             } while ( nbytes );
653             nbytes = p - buf;
654         }
655         *ret_len = nbytes;
656     }
657     else if ( control == IOBUFCTRL_INIT ) {
658         a->eof_seen = 0;
659         a->keep_open = 0;
660         a->no_cache = 0;
661     }
662     else if ( control == IOBUFCTRL_DESC ) {
663         *(char**)buf = "sock_filter";
664     }
665     else if ( control == IOBUFCTRL_FREE ) {
666         if (!a->keep_open)
667             closesocket (a->sock);
668         xfree (a); /* we can free our context now */
669     }
670     return rc;
671 }
672 #endif /*_WIN32*/
673
674 /****************
675  * This is used to implement the block write mode.
676  * Block reading is done on a byte by byte basis in readbyte(),
677  * without a filter
678  */
679 static int
680 block_filter(void *opaque, int control, IOBUF chain, byte *buf, size_t *ret_len)
681 {
682     block_filter_ctx_t *a = opaque;
683     size_t size = *ret_len;
684     int c, needed, rc = 0;
685     char *p;
686
687     if( control == IOBUFCTRL_UNDERFLOW ) {
688         size_t n=0;
689
690         p = buf;
691         assert( size ); /* need a buffer */
692         if( a->eof ) /* don't read any further */
693             rc = -1;
694         while( !rc && size ) {
695             if( !a->size ) { /* get the length bytes */
696                 if( a->partial == 2 ) {
697                     a->eof = 1;
698                     if( !n )
699                         rc = -1;
700                     break;
701                 }
702                 else if( a->partial ) {
703                     /* These OpenPGP introduced huffman like encoded length
704                      * bytes are really a mess :-( */
705                     if( a->first_c ) {
706                         c = a->first_c;
707                         a->first_c = 0;
708                     }
709                     else if( (c = iobuf_get(chain)) == -1 ) {
710                         log_error("block_filter: 1st length byte missing\n");
711                         rc = G10ERR_READ_FILE;
712                         break;
713                     }
714                     if( c < 192 ) {
715                         a->size = c;
716                         a->partial = 2;
717                         if( !a->size ) {
718                             a->eof = 1;
719                             if( !n )
720                                 rc = -1;
721                             break;
722                         }
723                     }
724                     else if( c < 224 ) {
725                         a->size = (c - 192) * 256;
726                         if( (c = iobuf_get(chain)) == -1 ) {
727                             log_error("block_filter: 2nd length byte missing\n");
728                             rc = G10ERR_READ_FILE;
729                             break;
730                         }
731                         a->size += c + 192;
732                         a->partial = 2;
733                         if( !a->size ) {
734                             a->eof = 1;
735                             if( !n )
736                                 rc = -1;
737                             break;
738                         }
739                     }
740                     else if( c == 255 ) {
741                         a->size  = iobuf_get(chain) << 24;
742                         a->size |= iobuf_get(chain) << 16;
743                         a->size |= iobuf_get(chain) << 8;
744                         if( (c = iobuf_get(chain)) == -1 ) {
745                             log_error("block_filter: invalid 4 byte length\n");
746                             rc = G10ERR_READ_FILE;
747                             break;
748                         }
749                         a->size |= c;
750                         a->partial = 2;
751                         if( !a->size ) {
752                             a->eof = 1;
753                             if( !n )
754                                 rc = -1;
755                             break;
756                         }
757                     }
758                     else { /* next partial body length */
759                         a->size = 1 << (c & 0x1f);
760                     }
761             /*  log_debug("partial: ctx=%p c=%02x size=%u\n", a, c, a->size);*/
762                 }
763                 else
764                   BUG();
765             }
766
767             while( !rc && size && a->size ) {
768                 needed = size < a->size ? size : a->size;
769                 c = iobuf_read( chain, p, needed );
770                 if( c < needed ) {
771                     if( c == -1 ) c = 0;
772                     log_error("block_filter %p: read error (size=%lu,a->size=%lu)\n",
773                               a,  (ulong)size+c, (ulong)a->size+c);
774                     rc = G10ERR_READ_FILE;
775                 }
776                 else {
777                     size -= c;
778                     a->size -= c;
779                     p += c;
780                     n += c;
781                 }
782             }
783         }
784         *ret_len = n;
785     }
786     else if( control == IOBUFCTRL_FLUSH ) {
787         if( a->partial ) { /* the complicated openpgp scheme */
788             size_t blen, n, nbytes = size + a->buflen;
789
790             assert( a->buflen <= OP_MIN_PARTIAL_CHUNK );
791             if( nbytes < OP_MIN_PARTIAL_CHUNK ) {
792                 /* not enough to write a partial block out; so we store it*/
793                 if( !a->buffer )
794                     a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
795                 memcpy( a->buffer + a->buflen, buf, size );
796                 a->buflen += size;
797             }
798             else { /* okay, we can write out something */
799                 /* do this in a loop to use the most efficient block lengths */
800                 p = buf;
801                 do {
802                     /* find the best matching block length - this is limited
803                      * by the size of the internal buffering */
804                     for( blen=OP_MIN_PARTIAL_CHUNK*2,
805                             c=OP_MIN_PARTIAL_CHUNK_2POW+1; blen <= nbytes;
806                                                             blen *=2, c++ )
807                         ;
808                     blen /= 2; c--;
809                     /* write the partial length header */
810                     assert( c <= 0x1f ); /*;-)*/
811                     c |= 0xe0;
812                     iobuf_put( chain, c );
813                     if( (n=a->buflen) ) { /* write stuff from the buffer */
814                         assert( n == OP_MIN_PARTIAL_CHUNK);
815                         if( iobuf_write(chain, a->buffer, n ) )
816                             rc = G10ERR_WRITE_FILE;
817                         a->buflen = 0;
818                         nbytes -= n;
819                     }
820                     if( (n = nbytes) > blen )
821                         n = blen;
822                     if( n && iobuf_write(chain, p, n ) )
823                         rc = G10ERR_WRITE_FILE;
824                     p += n;
825                     nbytes -= n;
826                 } while( !rc && nbytes >= OP_MIN_PARTIAL_CHUNK );
827                 /* store the rest in the buffer */
828                 if( !rc && nbytes ) {
829                     assert( !a->buflen );
830                     assert( nbytes < OP_MIN_PARTIAL_CHUNK );
831                     if( !a->buffer )
832                         a->buffer = xmalloc( OP_MIN_PARTIAL_CHUNK );
833                     memcpy( a->buffer, p, nbytes );
834                     a->buflen = nbytes;
835                 }
836             }
837         }
838         else
839           BUG();
840     }
841     else if( control == IOBUFCTRL_INIT ) {
842         if( DBG_IOBUF )
843             log_debug("init block_filter %p\n", a );
844         if( a->partial )
845             a->count = 0;
846         else if( a->use == 1 )
847             a->count = a->size = 0;
848         else
849             a->count = a->size; /* force first length bytes */
850         a->eof = 0;
851         a->buffer = NULL;
852         a->buflen = 0;
853     }
854     else if( control == IOBUFCTRL_DESC ) {
855         *(char**)buf = "block_filter";
856     }
857     else if( control == IOBUFCTRL_FREE ) {
858         if( a->use == 2 ) { /* write the end markers */
859             if( a->partial ) {
860                 u32 len;
861                 /* write out the remaining bytes without a partial header
862                  * the length of this header may be 0 - but if it is
863                  * the first block we are not allowed to use a partial header
864                  * and frankly we can't do so, because this length must be
865                  * a power of 2. This is _really_ complicated because we
866                  * have to check the possible length of a packet prior
867                  * to it's creation: a chain of filters becomes complicated
868                  * and we need a lot of code to handle compressed packets etc.
869                  *   :-(((((((
870                  */
871                 /* construct header */
872                 len = a->buflen;
873                 /*log_debug("partial: remaining length=%u\n", len );*/
874                 if( len < 192 )
875                     rc = iobuf_put(chain, len );
876                 else if( len < 8384 ) {
877                     if( !(rc=iobuf_put( chain, ((len-192) / 256) + 192)) )
878                         rc = iobuf_put( chain, ((len-192) % 256));
879                 }
880                 else { /* use a 4 byte header */
881                     if( !(rc=iobuf_put( chain, 0xff )) )
882                         if( !(rc=iobuf_put( chain, (len >> 24)&0xff )) )
883                             if( !(rc=iobuf_put( chain, (len >> 16)&0xff )) )
884                                 if( !(rc=iobuf_put( chain, (len >> 8)&0xff )))
885                                     rc=iobuf_put( chain, len & 0xff );
886                 }
887                 if( !rc && len )
888                     rc = iobuf_write(chain, a->buffer, len );
889                 if( rc ) {
890                     log_error("block_filter: write error: %s\n",strerror(errno));
891                     rc = G10ERR_WRITE_FILE;
892                 }
893                 xfree( a->buffer ); a->buffer = NULL; a->buflen = 0;
894             }
895             else
896               BUG();
897         }
898         else if( a->size ) {
899             log_error("block_filter: pending bytes!\n");
900         }
901         if( DBG_IOBUF )
902             log_debug("free block_filter %p\n", a );
903         xfree(a); /* we can free our context now */
904     }
905
906     return rc;
907 }
908
909
910 static void
911 print_chain( IOBUF a )
912 {
913     if( !DBG_IOBUF )
914         return;
915     for(; a; a = a->chain ) {
916         size_t dummy_len = 0;
917         const char *desc = "[none]";
918
919         if( a->filter )
920             a->filter( a->filter_ov, IOBUFCTRL_DESC, NULL,
921                                                 (byte*)&desc, &dummy_len );
922
923         log_debug("iobuf chain: %d.%d `%s' filter_eof=%d start=%d len=%d\n",
924                    a->no, a->subno, desc?desc:"?", a->filter_eof,
925                    (int)a->d.start, (int)a->d.len );
926     }
927 }
928
929 int
930 iobuf_print_chain( IOBUF a )
931 {
932     print_chain(a);
933     return 0;
934 }
935
936 /****************
937  * Allocate a new io buffer, with no function assigned.
938  * Use is the desired usage: 1 for input, 2 for output, 3 for temp buffer
939  * BUFSIZE is a suggested buffer size.
940  */
941 IOBUF
942 iobuf_alloc(int use, size_t bufsize)
943 {
944     IOBUF a;
945     static int number=0;
946
947     a = xmalloc_clear(sizeof *a);
948     a->use = use;
949     a->d.buf = xmalloc( bufsize );
950     a->d.size = bufsize;
951     a->no = ++number;
952     a->subno = 0;
953     a->opaque = NULL;
954     a->real_fname = NULL;
955     return a;
956 }
957
958 int
959 iobuf_close ( IOBUF a )
960 {
961     IOBUF a2;
962     size_t dummy_len=0;
963     int rc=0;
964
965     if( a && a->directfp ) {
966         fclose( a->directfp );
967         xfree( a->real_fname );
968         if( DBG_IOBUF )
969             log_debug("iobuf_close -> %p\n", a->directfp );
970         return 0;
971     }
972
973     for( ; a && !rc ; a = a2 ) {
974         a2 = a->chain;
975         if( a->use == 2 && (rc=iobuf_flush(a)) )
976             log_error("iobuf_flush failed on close: %s\n", g10_errstr(rc));
977
978         if( DBG_IOBUF )
979             log_debug("iobuf-%d.%d: close `%s'\n", a->no, a->subno,
980                       a->desc?a->desc:"?");
981         if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE,
982                                          a->chain, NULL, &dummy_len)) )
983             log_error("IOBUFCTRL_FREE failed on close: %s\n", g10_errstr(rc) );
984         xfree(a->real_fname);
985         if (a->d.buf) {
986             memset (a->d.buf, 0, a->d.size); /* erase the buffer */
987             xfree(a->d.buf);
988         }
989         xfree(a);
990     }
991     return rc;
992 }
993
994 int
995 iobuf_cancel( IOBUF a )
996 {
997     const char *s;
998     IOBUF a2;
999     int rc;
1000 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
1001     char *remove_name = NULL;
1002 #endif
1003
1004     if( a && a->use == 2 ) {
1005         s = iobuf_get_real_fname(a);
1006         if( s && *s ) {
1007 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
1008             remove_name = xstrdup ( s );
1009 #else
1010             remove(s);
1011 #endif
1012         }
1013     }
1014
1015     /* send a cancel message to all filters */
1016     for( a2 = a; a2 ; a2 = a2->chain ) {
1017         size_t dummy;
1018         if( a2->filter )
1019             a2->filter( a2->filter_ov, IOBUFCTRL_CANCEL, a2->chain,
1020                                                          NULL, &dummy );
1021     }
1022
1023     rc = iobuf_close(a);
1024 #if defined(HAVE_DOSISH_SYSTEM) || defined(__riscos__)
1025     if ( remove_name ) {
1026         /* Argg, MSDOS does not allow to remove open files.  So
1027          * we have to do it here */
1028         remove ( remove_name );
1029         xfree ( remove_name );
1030     }
1031 #endif
1032     return rc;
1033 }
1034
1035
1036 /****************
1037  * create a temporary iobuf, which can be used to collect stuff
1038  * in an iobuf and later be written by iobuf_write_temp() to another
1039  * iobuf.
1040  */
1041 IOBUF
1042 iobuf_temp()
1043 {
1044     IOBUF a;
1045
1046     a = iobuf_alloc(3, IOBUF_BUFFER_SIZE );
1047
1048     return a;
1049 }
1050
1051 IOBUF
1052 iobuf_temp_with_content( const char *buffer, size_t length )
1053 {
1054     IOBUF a;
1055
1056     a = iobuf_alloc(3, length );
1057     memcpy( a->d.buf, buffer, length );
1058     a->d.len = length;
1059
1060     return a;
1061 }
1062
1063 void
1064 iobuf_enable_special_filenames ( int yes )
1065 {
1066     special_names_enabled = yes;
1067 }
1068
1069 /*
1070  * see whether the filename has the for "-&nnnn", where n is a
1071  * non-zero number.
1072  * Returns this number or -1 if it is not the case.
1073  */
1074 static int
1075 check_special_filename ( const char *fname )
1076 {
1077     if ( special_names_enabled
1078          && fname && *fname == '-' && fname[1] == '&' ) {
1079         int i;
1080
1081         fname += 2;
1082         for (i=0; digitp (fname+i); i++ )
1083             ;
1084         if ( !fname[i] )
1085             return atoi (fname);
1086     }
1087     return -1;
1088 }
1089
1090 /* This fucntion returns true if FNAME indicates a PIPE (stdout or
1091    stderr) or a special file name if those are enabled. */
1092 int
1093 iobuf_is_pipe_filename (const char *fname)
1094 {
1095   if (!fname || (*fname=='-' && !fname[1]) )
1096     return 1;
1097   return check_special_filename (fname) != -1;
1098 }
1099
1100 /****************
1101  * Create a head iobuf for reading from a file
1102  * returns: NULL if an error occures and sets errno
1103  */
1104 IOBUF
1105 iobuf_open( const char *fname )
1106 {
1107     IOBUF a;
1108     FILEP_OR_FD fp;
1109     file_filter_ctx_t *fcx;
1110     size_t len = 0;
1111     int print_only = 0;
1112     int fd;
1113
1114     if( !fname || (*fname=='-' && !fname[1])  ) {
1115         fp = FILEP_OR_FD_FOR_STDIN;
1116 #ifdef USE_SETMODE
1117         setmode ( my_fileno(fp) , O_BINARY );
1118 #endif
1119         fname = "[stdin]";
1120         print_only = 1;
1121     }
1122     else if ( (fd = check_special_filename ( fname )) != -1 )
1123         return iobuf_fdopen ( translate_file_handle (fd,0), "rb" );
1124     else if( (fp = my_fopen_ro(fname, "rb")) == INVALID_FP )
1125         return NULL;
1126     a = iobuf_alloc(1, IOBUF_BUFFER_SIZE );
1127     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1128     fcx->fp = fp;
1129     fcx->print_only_name = print_only;
1130     strcpy(fcx->fname, fname );
1131     if( !print_only )
1132         a->real_fname = xstrdup( fname );
1133     a->filter = file_filter;
1134     a->filter_ov = fcx;
1135     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1136     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1137     if( DBG_IOBUF )
1138         log_debug("iobuf-%d.%d: open `%s' fd=%d\n",
1139                    a->no, a->subno, fname, (int)my_fileno(fcx->fp) );
1140
1141     return a;
1142 }
1143
1144 /****************
1145  * Create a head iobuf for reading from a file
1146  * returns: NULL if an error occures and sets errno
1147  */
1148 IOBUF
1149 iobuf_fdopen( int fd, const char *mode )
1150 {
1151     IOBUF a;
1152     FILEP_OR_FD fp;
1153     file_filter_ctx_t *fcx;
1154     size_t len;
1155
1156 #ifdef FILE_FILTER_USES_STDIO
1157     if( !(fp = fdopen(fd, mode)) )
1158         return NULL;
1159 #else
1160     fp = (FILEP_OR_FD)fd;
1161 #endif
1162     a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
1163     fcx = xmalloc( sizeof *fcx + 20 );
1164     fcx->fp = fp;
1165     fcx->print_only_name = 1;
1166     sprintf(fcx->fname, "[fd %d]", fd );
1167     a->filter = file_filter;
1168     a->filter_ov = fcx;
1169     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1170     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1171     if( DBG_IOBUF )
1172         log_debug("iobuf-%d.%d: fdopen `%s'\n", a->no, a->subno, fcx->fname );
1173     iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
1174     return a;
1175 }
1176
1177
1178 IOBUF
1179 iobuf_sockopen ( int fd, const char *mode )
1180 {
1181     IOBUF a;
1182 #ifdef _WIN32
1183     sock_filter_ctx_t *scx;
1184     size_t len;
1185
1186     a = iobuf_alloc( strchr( mode, 'w')? 2:1, IOBUF_BUFFER_SIZE );
1187     scx = xmalloc( sizeof *scx + 25 );
1188     scx->sock = fd;
1189     scx->print_only_name = 1;
1190     sprintf(scx->fname, "[sock %d]", fd );
1191     a->filter = sock_filter;
1192     a->filter_ov = scx;
1193     sock_filter( scx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1194     sock_filter( scx, IOBUFCTRL_INIT, NULL, NULL, &len );
1195     if( DBG_IOBUF )
1196         log_debug("iobuf-%d.%d: sockopen `%s'\n", a->no, a->subno, scx->fname);
1197     iobuf_ioctl (a,3,1,NULL); /* disable fd caching */
1198 #else
1199     a = iobuf_fdopen (fd, mode);
1200 #endif
1201     return a;
1202 }
1203
1204 /****************
1205  * create an iobuf for writing to a file; the file will be created.
1206  */
1207 IOBUF
1208 iobuf_create( const char *fname )
1209 {
1210     IOBUF a;
1211     FILEP_OR_FD fp;
1212     file_filter_ctx_t *fcx;
1213     size_t len;
1214     int print_only = 0;
1215     int fd;
1216
1217     if( !fname || (*fname=='-' && !fname[1]) ) {
1218         fp = FILEP_OR_FD_FOR_STDOUT;
1219 #ifdef USE_SETMODE
1220         setmode ( my_fileno(fp) , O_BINARY );
1221 #endif
1222         fname = "[stdout]";
1223         print_only = 1;
1224     }
1225     else if ( (fd = check_special_filename ( fname )) != -1 )
1226         return iobuf_fdopen ( translate_file_handle (fd, 1), "wb" );
1227     else if( (fp = my_fopen(fname, "wb")) == INVALID_FP )
1228         return NULL;
1229     a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
1230     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1231     fcx->fp = fp;
1232     fcx->print_only_name = print_only;
1233     strcpy(fcx->fname, fname );
1234     if( !print_only )
1235         a->real_fname = xstrdup( fname );
1236     a->filter = file_filter;
1237     a->filter_ov = fcx;
1238     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1239     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1240     if( DBG_IOBUF )
1241         log_debug("iobuf-%d.%d: create `%s'\n", a->no, a->subno,
1242                   a->desc?a->desc:"?" );
1243
1244     return a;
1245 }
1246
1247 /****************
1248  * append to an iobuf; if the file does not exist, create it.
1249  * cannot be used for stdout.
1250  * Note: This is not used.
1251  */
1252 #if 0 /* not used */
1253 IOBUF
1254 iobuf_append( const char *fname )
1255 {
1256     IOBUF a;
1257     FILE *fp;
1258     file_filter_ctx_t *fcx;
1259     size_t len;
1260
1261     if( !fname )
1262         return NULL;
1263     else if( !(fp = my_fopen(fname, "ab")) )
1264         return NULL;
1265     a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
1266     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1267     fcx->fp = fp;
1268     strcpy(fcx->fname, fname );
1269     a->real_fname = xstrdup( fname );
1270     a->filter = file_filter;
1271     a->filter_ov = fcx;
1272     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1273     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1274     if( DBG_IOBUF )
1275         log_debug("iobuf-%d.%d: append `%s'\n", a->no, a->subno,
1276                   a->desc?a->desc:"?" );
1277
1278     return a;
1279 }
1280 #endif
1281
1282 IOBUF
1283 iobuf_openrw( const char *fname )
1284 {
1285     IOBUF a;
1286     FILEP_OR_FD fp;
1287     file_filter_ctx_t *fcx;
1288     size_t len;
1289
1290     if( !fname )
1291         return NULL;
1292     else if( (fp = my_fopen(fname, "r+b")) == INVALID_FP )
1293         return NULL;
1294     a = iobuf_alloc(2, IOBUF_BUFFER_SIZE );
1295     fcx = xmalloc( sizeof *fcx + strlen(fname) );
1296     fcx->fp = fp;
1297     strcpy(fcx->fname, fname );
1298     a->real_fname = xstrdup( fname );
1299     a->filter = file_filter;
1300     a->filter_ov = fcx;
1301     file_filter( fcx, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &len );
1302     file_filter( fcx, IOBUFCTRL_INIT, NULL, NULL, &len );
1303     if( DBG_IOBUF )
1304         log_debug("iobuf-%d.%d: openrw `%s'\n", a->no, a->subno,
1305                   a->desc?a->desc:"?");
1306
1307     return a;
1308 }
1309
1310
1311 int
1312 iobuf_ioctl ( IOBUF a, int cmd, int intval, void *ptrval )
1313 {
1314     if ( cmd == 1 ) {  /* keep system filepointer/descriptor open */
1315         if( DBG_IOBUF )
1316             log_debug("iobuf-%d.%d: ioctl `%s' keep=%d\n",
1317                       a? a->no:-1, a?a->subno:-1,
1318                       a&&a->desc?a->desc:"?", intval );
1319         for( ; a; a = a->chain )
1320             if( !a->chain && a->filter == file_filter ) {
1321                 file_filter_ctx_t *b = a->filter_ov;
1322                 b->keep_open = intval;
1323                 return 0;
1324             }
1325 #ifdef _WIN32
1326             else if( !a->chain && a->filter == sock_filter ) {
1327                 sock_filter_ctx_t *b = a->filter_ov;
1328                 b->keep_open = intval;
1329                 return 0;
1330             }
1331 #endif
1332     }
1333     else if ( cmd == 2 ) {  /* invalidate cache */
1334         if( DBG_IOBUF )
1335             log_debug("iobuf-*.*: ioctl `%s' invalidate\n",
1336                       ptrval? (char*)ptrval:"[all]");
1337         if ( !a && !intval ) {
1338 #ifndef FILE_FILTER_USES_STDIO
1339             return fd_cache_invalidate (ptrval);
1340 #endif
1341             return 0;
1342          }
1343     }
1344     else if ( cmd == 3 ) {  /* disallow/allow caching */
1345         if( DBG_IOBUF )
1346             log_debug("iobuf-%d.%d: ioctl `%s' no_cache=%d\n",
1347                       a? a->no:-1, a?a->subno:-1,
1348                       a&&a->desc?a->desc:"?", intval );
1349         for( ; a; a = a->chain )
1350             if( !a->chain && a->filter == file_filter ) {
1351                 file_filter_ctx_t *b = a->filter_ov;
1352                 b->no_cache = intval;
1353                 return 0;
1354             }
1355 #ifdef _WIN32
1356             else if( !a->chain && a->filter == sock_filter ) {
1357                 sock_filter_ctx_t *b = a->filter_ov;
1358                 b->no_cache = intval;
1359                 return 0;
1360             }
1361 #endif
1362     }
1363     else if(cmd==4)
1364       {
1365         /* Do a fsync on the open fd and return any errors to the
1366            caller of iobuf_ioctl */
1367         if( DBG_IOBUF )
1368           log_debug("iobuf-*.*: ioctl `%s' fsync\n",
1369                       ptrval? (char*)ptrval:"<null>");
1370
1371         if(!a && !intval && ptrval)
1372           {
1373 #ifndef FILE_FILTER_USES_STDIO
1374             return fd_cache_synchronize (ptrval);
1375 #else
1376             return 0;
1377 #endif
1378           }
1379       }
1380
1381     return -1;
1382 }
1383
1384
1385 /****************
1386  * Register an i/o filter.
1387  */
1388 int
1389 iobuf_push_filter( IOBUF a,
1390                    int (*f)(void *opaque, int control,
1391                    IOBUF chain, byte *buf, size_t *len), void *ov )
1392 {
1393     return iobuf_push_filter2( a, f, ov, 0 );
1394 }
1395
1396 int
1397 iobuf_push_filter2( IOBUF a,
1398                     int (*f)(void *opaque, int control,
1399                     IOBUF chain, byte *buf, size_t *len),
1400                     void *ov, int rel_ov )
1401 {
1402     IOBUF b;
1403     size_t dummy_len=0;
1404     int rc=0;
1405
1406     if( a->directfp )
1407         BUG();
1408
1409     if( a->use == 2 && (rc=iobuf_flush(a)) )
1410         return rc;
1411
1412     if (a->subno >= MAX_NESTING_FILTER) {
1413         log_error ("i/o filter too deeply nested - corrupted data?\n");
1414         return G10ERR_UNEXPECTED;
1415     }
1416
1417     /* make a copy of the current stream, so that
1418      * A is the new stream and B the original one.
1419      * The contents of the buffers are transferred to the
1420      * new stream.
1421      */
1422     b = xmalloc(sizeof *b);
1423     memcpy(b, a, sizeof *b );
1424     /* fixme: it is stupid to keep a copy of the name at every level
1425      * but we need the name somewhere because the name known by file_filter
1426      * may have been released when we need the name of the file */
1427     b->real_fname = a->real_fname? xstrdup(a->real_fname):NULL;
1428     /* remove the filter stuff from the new stream */
1429     a->filter = NULL;
1430     a->filter_ov = NULL;
1431     a->filter_ov_owner = 0;
1432     a->filter_eof = 0;
1433     if( a->use == 3 )
1434         a->use = 2;  /* make a write stream from a temp stream */
1435
1436     if( a->use == 2 ) { /* allocate a fresh buffer for the original stream */
1437         b->d.buf = xmalloc( a->d.size );
1438         b->d.len = 0;
1439         b->d.start = 0;
1440     }
1441     else { /* allocate a fresh buffer for the new stream */
1442         a->d.buf = xmalloc( a->d.size );
1443         a->d.len = 0;
1444         a->d.start = 0;
1445     }
1446     /* disable nlimit for the new stream */
1447     a->ntotal = b->ntotal + b->nbytes;
1448     a->nlimit = a->nbytes = 0;
1449     a->nofast &= ~1;
1450     /* make a link from the new stream to the original stream */
1451     a->chain = b;
1452     a->opaque = b->opaque;
1453
1454     /* setup the function on the new stream */
1455     a->filter = f;
1456     a->filter_ov = ov;
1457     a->filter_ov_owner = rel_ov;
1458
1459     a->subno = b->subno + 1;
1460     f( ov, IOBUFCTRL_DESC, NULL, (byte*)&a->desc, &dummy_len );
1461
1462     if( DBG_IOBUF ) {
1463         log_debug("iobuf-%d.%d: push `%s'\n", a->no, a->subno,
1464                   a->desc?a->desc:"?" );
1465         print_chain( a );
1466     }
1467
1468     /* now we can initialize the new function if we have one */
1469     if( a->filter && (rc = a->filter(a->filter_ov, IOBUFCTRL_INIT, a->chain,
1470                        NULL, &dummy_len)) )
1471         log_error("IOBUFCTRL_INIT failed: %s\n", g10_errstr(rc) );
1472     return rc;
1473 }
1474
1475 /****************
1476  * Remove an i/o filter.
1477  */
1478 static int
1479 pop_filter( IOBUF a, int (*f)(void *opaque, int control,
1480                       IOBUF chain, byte *buf, size_t *len), void *ov )
1481 {
1482     IOBUF b;
1483     size_t dummy_len=0;
1484     int rc=0;
1485
1486     if( a->directfp )
1487         BUG();
1488
1489     if( DBG_IOBUF )
1490         log_debug("iobuf-%d.%d: pop `%s'\n", a->no, a->subno,
1491                   a->desc?a->desc:"?" );
1492     if( !a->filter ) { /* this is simple */
1493         b = a->chain;
1494         assert(b);
1495         xfree(a->d.buf);
1496         xfree(a->real_fname);
1497         memcpy(a,b, sizeof *a);
1498         xfree(b);
1499         return 0;
1500     }
1501     for(b=a ; b; b = b->chain )
1502         if( b->filter == f && (!ov || b->filter_ov == ov) )
1503             break;
1504     if( !b )
1505         log_bug("pop_filter(): filter function not found\n");
1506
1507     /* flush this stream if it is an output stream */
1508     if( a->use == 2 && (rc=iobuf_flush(b)) ) {
1509         log_error("iobuf_flush failed in pop_filter: %s\n", g10_errstr(rc));
1510         return rc;
1511     }
1512     /* and tell the filter to free it self */
1513     if( b->filter && (rc = b->filter(b->filter_ov, IOBUFCTRL_FREE, b->chain,
1514                        NULL, &dummy_len)) ) {
1515         log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
1516         return rc;
1517     }
1518     if( b->filter_ov && b->filter_ov_owner ) {
1519         xfree( b->filter_ov );
1520         b->filter_ov = NULL;
1521     }
1522
1523
1524     /* and see how to remove it */
1525     if( a == b && !b->chain )
1526         log_bug("can't remove the last filter from the chain\n");
1527     else if( a == b ) { /* remove the first iobuf from the chain */
1528         /* everything from b is copied to a. This is save because
1529          * a flush has been done on the to be removed entry
1530          */
1531         b = a->chain;
1532         xfree(a->d.buf);
1533         xfree(a->real_fname);
1534         memcpy(a,b, sizeof *a);
1535         xfree(b);
1536         if( DBG_IOBUF )
1537            log_debug("iobuf-%d.%d: popped filter\n", a->no, a->subno );
1538     }
1539     else if( !b->chain ) { /* remove the last iobuf from the chain */
1540         log_bug("Ohh jeee, trying to remove a head filter\n");
1541     }
1542     else {  /* remove an intermediate iobuf from the chain */
1543         log_bug("Ohh jeee, trying to remove an intermediate filter\n");
1544     }
1545
1546     return rc;
1547 }
1548
1549
1550 /****************
1551  * read underflow: read more bytes into the buffer and return
1552  * the first byte or -1 on EOF.
1553  */
1554 static int
1555 underflow(IOBUF a)
1556 {
1557     size_t len;
1558     int rc;
1559
1560     assert( a->d.start == a->d.len );
1561     if( a->use == 3 )
1562         return -1; /* EOF because a temp buffer can't do an underflow */
1563
1564     if( a->filter_eof ) {
1565         if( a->chain ) {
1566             IOBUF b = a->chain;
1567             if( DBG_IOBUF )
1568                 log_debug("iobuf-%d.%d: pop `%s' in underflow\n",
1569                           a->no, a->subno, a->desc?a->desc:"?" );
1570             xfree(a->d.buf);
1571             xfree(a->real_fname);
1572             memcpy(a, b, sizeof *a);
1573             xfree(b);
1574             print_chain(a);
1575         }
1576         else
1577              a->filter_eof = 0;  /* for the top level filter */
1578         if( DBG_IOBUF )
1579             log_debug("iobuf-%d.%d: underflow: eof (due to filter eof)\n",
1580                                                     a->no, a->subno );
1581         return -1; /* return one(!) EOF */
1582     }
1583     if( a->error ) {
1584         if( DBG_IOBUF )
1585             log_debug("iobuf-%d.%d: error\n", a->no, a->subno );
1586         return -1;
1587     }
1588
1589     if( a->directfp ) {
1590         FILE *fp = a->directfp;
1591
1592         len = fread( a->d.buf, 1, a->d.size, fp);
1593         if( len < a->d.size ) {
1594             if( ferror(fp) )
1595                 a->error = 1;
1596         }
1597         a->d.len = len;
1598         a->d.start = 0;
1599         return len? a->d.buf[a->d.start++] : -1;
1600     }
1601
1602
1603     if( a->filter ) {
1604         len = a->d.size;
1605         if( DBG_IOBUF )
1606             log_debug("iobuf-%d.%d: underflow: req=%lu\n",
1607                       a->no, a->subno, (ulong)len );
1608         rc = a->filter( a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
1609                         a->d.buf, &len );
1610         if( DBG_IOBUF ) {
1611             log_debug("iobuf-%d.%d: underflow: got=%lu rc=%d\n",
1612                     a->no, a->subno, (ulong)len, rc );
1613 /*          if( a->no == 1 ) */
1614 /*                   log_hexdump ("     data:", a->d.buf, len); */
1615         }
1616         if( a->use == 1 && rc == -1 ) { /* EOF: we can remove the filter */
1617             size_t dummy_len=0;
1618
1619             /* and tell the filter to free itself */
1620             if( (rc = a->filter(a->filter_ov, IOBUFCTRL_FREE, a->chain,
1621                                NULL, &dummy_len)) )
1622                 log_error("IOBUFCTRL_FREE failed: %s\n", g10_errstr(rc) );
1623             if( a->filter_ov && a->filter_ov_owner ) {
1624                 xfree( a->filter_ov );
1625                 a->filter_ov = NULL;
1626             }
1627             a->filter = NULL;
1628             a->desc = NULL;
1629             a->filter_ov = NULL;
1630             a->filter_eof = 1;
1631             if( !len && a->chain ) {
1632                 IOBUF b = a->chain;
1633                 if( DBG_IOBUF )
1634                     log_debug("iobuf-%d.%d: pop in underflow (!len)\n",
1635                               a->no, a->subno);
1636                 xfree(a->d.buf);
1637                 xfree(a->real_fname);
1638                 memcpy(a,b, sizeof *a);
1639                 xfree(b);
1640                 print_chain(a);
1641             }
1642         }
1643         else if( rc )
1644             a->error = 1;
1645
1646         if( !len ) {
1647             if( DBG_IOBUF )
1648                 log_debug("iobuf-%d.%d: underflow: eof\n", a->no, a->subno );
1649             return -1;
1650         }
1651         a->d.len = len;
1652         a->d.start = 0;
1653         return a->d.buf[a->d.start++];
1654     }
1655     else {
1656         if( DBG_IOBUF )
1657             log_debug("iobuf-%d.%d: underflow: eof (no filter)\n",
1658                                                     a->no, a->subno );
1659         return -1;  /* no filter; return EOF */
1660     }
1661 }
1662
1663
1664 int
1665 iobuf_flush(IOBUF a)
1666 {
1667     size_t len;
1668     int rc;
1669
1670     if( a->directfp )
1671         return 0;
1672
1673     if( a->use == 3 ) { /* increase the temp buffer */
1674         char *newbuf;
1675         size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
1676
1677         if( DBG_IOBUF )
1678           log_debug("increasing temp iobuf from %lu to %lu\n",
1679                     (ulong)a->d.size, (ulong)newsize );
1680         newbuf = xmalloc( newsize );
1681         memcpy( newbuf, a->d.buf, a->d.len );
1682         xfree(a->d.buf);
1683         a->d.buf = newbuf;
1684         a->d.size = newsize;
1685         return 0;
1686     }
1687     else if( a->use != 2 )
1688         log_bug("flush on non-output iobuf\n");
1689     else if( !a->filter )
1690         log_bug("iobuf_flush: no filter\n");
1691     len = a->d.len;
1692     rc = a->filter( a->filter_ov, IOBUFCTRL_FLUSH, a->chain, a->d.buf, &len );
1693     if( !rc && len != a->d.len ) {
1694         log_info("iobuf_flush did not write all!\n");
1695         rc = G10ERR_WRITE_FILE;
1696     }
1697     else if( rc )
1698         a->error = 1;
1699     a->d.len = 0;
1700
1701     return rc;
1702 }
1703
1704
1705 /****************
1706  * Read a byte from the iobuf; returns -1 on EOF
1707  */
1708 int
1709 iobuf_readbyte(IOBUF a)
1710 {
1711     int c;
1712
1713     /* nlimit does not work together with unget */
1714     /* nbytes is also not valid! */
1715     if( a->unget.buf ) {
1716         if( a->unget.start < a->unget.len )
1717             return a->unget.buf[a->unget.start++];
1718         xfree(a->unget.buf);
1719         a->unget.buf = NULL;
1720         a->nofast &= ~2;
1721     }
1722
1723     if( a->nlimit && a->nbytes >= a->nlimit )
1724         return -1; /* forced EOF */
1725
1726     if( a->d.start < a->d.len ) {
1727         c = a->d.buf[a->d.start++];
1728     }
1729     else if( (c=underflow(a)) == -1 )
1730         return -1; /* EOF */
1731
1732     a->nbytes++;
1733     return c;
1734 }
1735
1736
1737 int
1738 iobuf_read(IOBUF a, byte *buf, unsigned buflen )
1739 {
1740     int c, n;
1741
1742     if( a->unget.buf || a->nlimit ) {
1743         /* handle special cases */
1744         for(n=0 ; n < buflen; n++ ) {
1745             if( (c = iobuf_readbyte(a)) == -1 ) {
1746                 if( !n )
1747                     return -1; /* eof */
1748                 break;
1749             }
1750             else
1751                 if( buf ) *buf = c;
1752             if( buf ) buf++;
1753         }
1754         return n;
1755     }
1756
1757     n = 0;
1758     do {
1759         if( n < buflen && a->d.start < a->d.len ) {
1760             unsigned size = a->d.len - a->d.start;
1761             if( size > buflen - n )
1762                 size = buflen - n;
1763             if( buf )
1764                 memcpy( buf, a->d.buf + a->d.start, size );
1765             n += size;
1766             a->d.start += size;
1767             if( buf )
1768                 buf += size;
1769         }
1770         if( n < buflen ) {
1771             if( (c=underflow(a)) == -1 ) {
1772                 a->nbytes += n;
1773                 return n? n : -1/*EOF*/;
1774             }
1775             if( buf )
1776                 *buf++ = c;
1777             n++;
1778         }
1779     } while( n < buflen );
1780     a->nbytes += n;
1781     return n;
1782 }
1783
1784
1785 /****************
1786  * Have a look at the iobuf.
1787  * NOTE: This only works in special cases.
1788  */
1789 int
1790 iobuf_peek(IOBUF a, byte *buf, unsigned buflen )
1791 {
1792     int n=0;
1793
1794     if( a->filter_eof )
1795         return -1;
1796
1797     if( !(a->d.start < a->d.len) ) {
1798         if( underflow(a) == -1 )
1799             return -1;
1800         /* and unget this character */
1801         assert(a->d.start == 1);
1802         a->d.start = 0;
1803     }
1804
1805     for(n=0 ; n < buflen && (a->d.start+n) < a->d.len ; n++, buf++ )
1806         *buf = a->d.buf[n];
1807     return n;
1808 }
1809
1810
1811
1812
1813 int
1814 iobuf_writebyte(IOBUF a, unsigned c)
1815 {
1816
1817     if( a->directfp )
1818         BUG();
1819
1820     if( a->d.len == a->d.size )
1821         if( iobuf_flush(a) )
1822             return -1;
1823
1824     assert( a->d.len < a->d.size );
1825     a->d.buf[a->d.len++] = c;
1826     return 0;
1827 }
1828
1829
1830 int
1831 iobuf_write(IOBUF a, byte *buf, unsigned buflen )
1832 {
1833
1834     if( a->directfp )
1835         BUG();
1836
1837     do {
1838         if( buflen && a->d.len < a->d.size ) {
1839             unsigned size = a->d.size - a->d.len;
1840             if( size > buflen ) size = buflen;
1841             memcpy( a->d.buf + a->d.len, buf, size );
1842             buflen -= size;
1843             buf += size;
1844             a->d.len += size;
1845         }
1846         if( buflen ) {
1847             if( iobuf_flush(a) )
1848                 return -1;
1849         }
1850     } while( buflen );
1851     return 0;
1852 }
1853
1854
1855 int
1856 iobuf_writestr(IOBUF a, const char *buf )
1857 {
1858     for( ; *buf; buf++ )
1859         if( iobuf_writebyte(a, *buf) )
1860             return -1;
1861     return 0;
1862 }
1863
1864
1865
1866 /****************
1867  * copy the contents of TEMP to A.
1868  */
1869 int
1870 iobuf_write_temp( IOBUF a, IOBUF temp )
1871 {
1872     while( temp->chain )
1873         pop_filter( temp, temp->filter, NULL );
1874     return iobuf_write(a, temp->d.buf, temp->d.len );
1875 }
1876
1877 /****************
1878  * copy the contents of the temp io stream to BUFFER.
1879  */
1880 size_t
1881 iobuf_temp_to_buffer( IOBUF a, byte *buffer, size_t buflen )
1882 {
1883     size_t n = a->d.len;
1884
1885     if( n > buflen )
1886         n = buflen;
1887     memcpy( buffer, a->d.buf, n );
1888     return n;
1889 }
1890
1891
1892 /****************
1893  * Call this function to terminate processing of the temp stream
1894  * without closing it.  This removes all filters from the stream
1895  * makes sure that iobuf_get_temp_{buffer,length}() returns correct
1896  * values.
1897  */
1898 void
1899 iobuf_flush_temp( IOBUF temp )
1900 {
1901     while( temp->chain )
1902         pop_filter( temp, temp->filter, NULL );
1903 }
1904
1905
1906 /****************
1907  * Set a limit on how many bytes may be read from the input stream A.
1908  * Setting the limit to 0 disables this feature.
1909  */
1910 void
1911 iobuf_set_limit( IOBUF a, off_t nlimit )
1912 {
1913     if( nlimit )
1914         a->nofast |= 1;
1915     else
1916         a->nofast &= ~1;
1917     a->nlimit = nlimit;
1918     a->ntotal += a->nbytes;
1919     a->nbytes = 0;
1920 }
1921
1922
1923
1924 /* Return the length of an open file A.  IF OVERFLOW is not NULL it
1925    will be set to true if the file is larger than what off_t can cope
1926    with.  The function return 0 on error or on overflow condition.  */
1927 off_t
1928 iobuf_get_filelength (IOBUF a, int *overflow )
1929 {
1930     struct stat st;
1931
1932     if (overflow)
1933       *overflow = 0;
1934
1935     if (a->directfp)
1936       {
1937         FILE *fp = a->directfp;
1938
1939 #ifdef __VMS
1940         /* 2009-02-19 SMS.
1941          * On VMS, use a VMS-specific method to determine file size.
1942          * For some non-UNIX-like file formats, the fstat() result
1943          * will not agree with the C Standard I/O functions such as
1944          * getc() and fread(), so these must be detected and handled
1945          * specially. */
1946         return vms_file_size (fileno( fp));
1947 #else /*!__VMS */
1948         if( !fstat(fileno(fp), &st) )
1949            return st.st_size;
1950         log_error("fstat() failed: %s\n", strerror(errno) );
1951         return 0;
1952 #endif /*!__VMS */
1953     }
1954
1955     /* Hmmm: file_filter may have already been removed */
1956     for( ; a; a = a->chain )
1957         if( !a->chain && a->filter == file_filter ) {
1958             file_filter_ctx_t *b = a->filter_ov;
1959             FILEP_OR_FD fp = b->fp;
1960
1961 #if defined(HAVE_DOSISH_SYSTEM) && !defined(FILE_FILTER_USES_STDIO)
1962             ulong size;
1963             static int (* __stdcall get_file_size_ex)
1964               (void *handle, LARGE_INTEGER *size);
1965             static int get_file_size_ex_initialized;
1966
1967             if (!get_file_size_ex_initialized)
1968               {
1969                 void *handle;
1970
1971                 handle = dlopen ("kernel32.dll", RTLD_LAZY);
1972                 if (handle)
1973                   {
1974                     get_file_size_ex = dlsym (handle, "GetFileSizeEx");
1975                     if (!get_file_size_ex)
1976                     dlclose (handle);
1977                   }
1978                 get_file_size_ex_initialized = 1;
1979               }
1980
1981             if (get_file_size_ex)
1982               {
1983                 /* This is a newer system with GetFileSizeEx; we use
1984                    this then becuase it seem that GetFileSize won't
1985                    return a proper error in case a file is larger than
1986                    4GB. */
1987                 LARGE_INTEGER size;
1988
1989                 if (get_file_size_ex (fp, &size))
1990                   {
1991                     if (!size.u.HighPart)
1992                       return size.u.LowPart;
1993                     if (overflow)
1994                       *overflow = 1;
1995                     return 0;
1996                   }
1997               }
1998             else
1999               {
2000                 if  ((size=GetFileSize (fp, NULL)) != 0xffffffff)
2001                   return size;
2002               }
2003             log_error ("GetFileSize for handle %p failed: %s\n",
2004                        fp, w32_strerror (0));
2005 #elif defined(__VMS)
2006             return vms_file_size (my_fileno (fp));
2007 #else
2008             if( !fstat(my_fileno(fp), &st) )
2009                 return st.st_size;
2010             log_error("fstat() failed: %s\n", strerror(errno) );
2011 #endif
2012             break;
2013         }
2014
2015     return 0;
2016 }
2017
2018
2019 /* Return the file descriptor of the underlying file or -1 if it is
2020    not available.  */
2021 int
2022 iobuf_get_fd (IOBUF a)
2023 {
2024   if (a->directfp)
2025     return fileno ( (FILE*)a->directfp );
2026
2027   for ( ; a; a = a->chain )
2028     if (!a->chain && a->filter == file_filter)
2029       {
2030         file_filter_ctx_t *b = a->filter_ov;
2031         FILEP_OR_FD fp = b->fp;
2032
2033         return my_fileno (fp);
2034       }
2035
2036   return -1;
2037 }
2038
2039
2040 /****************
2041  * Tell the file position, where the next read will take place
2042  */
2043 off_t
2044 iobuf_tell( IOBUF a )
2045 {
2046     return a->ntotal + a->nbytes;
2047 }
2048
2049
2050 #if !defined(HAVE_FSEEKO) && !defined(fseeko)
2051
2052 #ifdef HAVE_LIMITS_H
2053 # include <limits.h>
2054 #endif
2055 #ifndef LONG_MAX
2056 # define LONG_MAX ((long) ((unsigned long) -1 >> 1))
2057 #endif
2058 #ifndef LONG_MIN
2059 # define LONG_MIN (-1 - LONG_MAX)
2060 #endif
2061
2062 /****************
2063  * A substitute for fseeko, for hosts that don't have it.
2064  */
2065 static int
2066 fseeko( FILE *stream, off_t newpos, int whence )
2067 {
2068     while( newpos != (long) newpos ) {
2069        long pos = newpos < 0 ? LONG_MIN : LONG_MAX;
2070        if( fseek( stream, pos, whence ) != 0 )
2071            return -1;
2072        newpos -= pos;
2073        whence = SEEK_CUR;
2074     }
2075     return fseek( stream, (long)newpos, whence );
2076 }
2077 #endif
2078
2079 /****************
2080  * This is a very limited implementation. It simply discards all internal
2081  * buffering and removes all filters but the first one.
2082  */
2083 int
2084 iobuf_seek( IOBUF a, off_t newpos )
2085 {
2086     file_filter_ctx_t *b = NULL;
2087
2088     if( a->directfp ) {
2089         FILE *fp = a->directfp;
2090         if( fseeko( fp, newpos, SEEK_SET ) ) {
2091             log_error("can't seek: %s\n", strerror(errno) );
2092             return -1;
2093         }
2094         clearerr(fp);
2095     }
2096     else {
2097         for( ; a; a = a->chain ) {
2098             if( !a->chain && a->filter == file_filter ) {
2099                 b = a->filter_ov;
2100                 break;
2101             }
2102         }
2103         if( !a )
2104             return -1;
2105 #ifdef FILE_FILTER_USES_STDIO
2106        if( fseeko( b->fp, newpos, SEEK_SET ) ) {
2107            log_error("can't fseek: %s\n", strerror(errno) );
2108            return -1;
2109        }
2110 #else
2111 #ifdef HAVE_DOSISH_SYSTEM
2112        if (SetFilePointer (b->fp, newpos, NULL, FILE_BEGIN) == 0xffffffff ) {
2113            log_error ("SetFilePointer failed on handle %p: %s\n",
2114                       b->fp, w32_strerror (0));
2115            return -1;
2116        }
2117 #else
2118        if ( lseek (b->fp, newpos, SEEK_SET) == (off_t)-1 ) {
2119            log_error("can't lseek: %s\n", strerror(errno) );
2120            return -1;
2121        }
2122 #endif
2123 #endif
2124     }
2125     a->d.len = 0;   /* discard buffer */
2126     a->d.start = 0;
2127     a->nbytes = 0;
2128     a->nlimit = 0;
2129     a->nofast &= ~1;
2130     a->ntotal = newpos;
2131     a->error = 0;
2132     /* remove filters, but the last */
2133     if( a->chain )
2134         log_debug("pop_filter called in iobuf_seek - please report\n");
2135     while( a->chain )
2136        pop_filter( a, a->filter, NULL );
2137
2138     return 0;
2139 }
2140
2141
2142
2143
2144
2145
2146 /****************
2147  * Retrieve the real filename
2148  */
2149 const char *
2150 iobuf_get_real_fname( IOBUF a )
2151 {
2152     if( a->real_fname )
2153         return a->real_fname;
2154
2155     /* the old solution */
2156     for( ; a; a = a->chain )
2157         if( !a->chain && a->filter == file_filter ) {
2158             file_filter_ctx_t *b = a->filter_ov;
2159             return b->print_only_name? NULL : b->fname;
2160         }
2161
2162     return NULL;
2163 }
2164
2165
2166 /****************
2167  * Retrieve the filename
2168  */
2169 const char *
2170 iobuf_get_fname( IOBUF a )
2171 {
2172     for( ; a; a = a->chain )
2173         if( !a->chain && a->filter == file_filter ) {
2174             file_filter_ctx_t *b = a->filter_ov;
2175             return b->fname;
2176         }
2177
2178     return NULL;
2179 }
2180
2181
2182 /****************
2183  * enable partial block mode as described in the OpenPGP draft.
2184  * LEN is the first length byte on read, but ignored on writes.
2185  */
2186 void
2187 iobuf_set_partial_block_mode( IOBUF a, size_t len )
2188 {
2189     block_filter_ctx_t *ctx = xmalloc_clear( sizeof *ctx );
2190
2191     assert( a->use == 1 || a->use == 2 );
2192     ctx->use = a->use;
2193     if( !len ) {
2194         if( a->use == 1 )
2195             log_debug("pop_filter called in set_partial_block_mode"
2196                                                     " - please report\n");
2197         pop_filter(a, block_filter, NULL );
2198     }
2199     else {
2200         ctx->partial = 1;
2201         ctx->size = 0;
2202         ctx->first_c = len;
2203         iobuf_push_filter(a, block_filter, ctx );
2204     }
2205 }
2206
2207
2208 /****************
2209  * Same as fgets() but if the buffer is too short a larger one will
2210  * be allocated up to some limit *max_length.
2211  * A line is considered a byte stream ending in a LF.
2212  * Returns the length of the line. EOF is indicated by a line of
2213  * length zero. The last LF may be missing due to an EOF.
2214  * is max_length is zero on return, the line has been truncated.
2215  *
2216  * Note: The buffer is allocated with enough space to append a CR,LF,EOL
2217  */
2218 unsigned
2219 iobuf_read_line( IOBUF a, byte **addr_of_buffer,
2220                           unsigned *length_of_buffer, unsigned *max_length )
2221 {
2222     int c;
2223     char *buffer = *addr_of_buffer;
2224     unsigned length = *length_of_buffer;
2225     unsigned nbytes = 0;
2226     unsigned maxlen = *max_length;
2227     char *p;
2228
2229     if( !buffer ) { /* must allocate a new buffer */
2230         length = 256;
2231         buffer = xmalloc( length );
2232         *addr_of_buffer = buffer;
2233         *length_of_buffer = length;
2234     }
2235
2236     length -= 3; /* reserve 3 bytes (cr,lf,eol) */
2237     p = buffer;
2238     while( (c=iobuf_get(a)) != -1 ) {
2239         if( nbytes == length ) { /* increase the buffer */
2240             if( length > maxlen  ) { /* this is out limit */
2241                 /* skip the rest of the line */
2242                 while( c != '\n' && (c=iobuf_get(a)) != -1 )
2243                     ;
2244                 *p++ = '\n'; /* always append a LF (we have reserved space) */
2245                 nbytes++;
2246                 *max_length = 0; /* indicate truncation */
2247                 break;
2248             }
2249             length += 3; /* correct for the reserved byte */
2250             length += length < 1024? 256 : 1024;
2251             buffer = xrealloc( buffer, length );
2252             *addr_of_buffer = buffer;
2253             *length_of_buffer = length;
2254             length -= 3; /* and reserve again */
2255             p = buffer + nbytes;
2256         }
2257         *p++ = c;
2258         nbytes++;
2259         if( c == '\n' )
2260             break;
2261     }
2262     *p = 0; /* make sure the line is a string */
2263
2264     return nbytes;
2265 }
2266
2267 /* This is the non iobuf specific function */
2268 int
2269 iobuf_translate_file_handle ( int fd, int for_write )
2270 {
2271 #ifdef _WIN32
2272     {
2273         int x;
2274
2275         if  ( fd <= 2 )
2276             return fd; /* do not do this for error, stdin, stdout, stderr */
2277
2278         x = _open_osfhandle ( fd, for_write? 1:0 );
2279         if (x==-1 )
2280             log_error ("failed to translate osfhandle %p\n", (void*)fd );
2281         else {
2282             /*log_info ("_open_osfhandle %p yields %d%s\n",
2283               (void*)fd, x, for_write? " for writing":"" );*/
2284             fd = x;
2285         }
2286     }
2287 #endif
2288     return fd;
2289 }
2290
2291 static int
2292 translate_file_handle ( int fd, int for_write )
2293 {
2294 #ifdef _WIN32
2295 #ifdef FILE_FILTER_USES_STDIO
2296     fd = iobuf_translate_file_handle (fd, for_write);
2297 #else
2298     {
2299         int x;
2300
2301         if  ( fd == 0 )
2302             x = (int)GetStdHandle (STD_INPUT_HANDLE);
2303         else if (fd == 1)
2304             x = (int)GetStdHandle (STD_OUTPUT_HANDLE);
2305         else if (fd == 2)
2306             x = (int)GetStdHandle (STD_ERROR_HANDLE);
2307         else
2308             x = fd;
2309
2310         if (x == -1)
2311             log_debug ("GetStdHandle(%d) failed: %s\n",
2312                        fd, w32_strerror (0));
2313
2314         fd = x;
2315     }
2316 #endif
2317 #endif
2318     return fd;
2319 }
2320
2321
2322 void
2323 iobuf_skip_rest(IOBUF a, unsigned long n, int partial)
2324 {
2325     if ( partial ) {
2326         for (;;) {
2327             if (a->nofast || a->d.start >= a->d.len) {
2328                 if (iobuf_readbyte (a) == -1) {
2329                     break;
2330                 }
2331             } else {
2332                 unsigned long count = a->d.len - a->d.start;
2333                 a->nbytes += count;
2334                 a->d.start = a->d.len;
2335             }
2336         }
2337     } else {
2338         unsigned long remaining = n;
2339         while (remaining > 0) {
2340             if (a->nofast || a->d.start >= a->d.len) {
2341                 if (iobuf_readbyte (a) == -1) {
2342                     break;
2343                 }
2344                 --remaining;
2345             } else {
2346                 unsigned long count = a->d.len - a->d.start;
2347                 if (count > remaining) {
2348                     count = remaining;
2349                 }
2350                 a->nbytes += count;
2351                 a->d.start += count;
2352                 remaining -= count;
2353             }
2354         }
2355     }
2356 }