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